Use case: I have a dependency that falls back to a subproject:
./
./subprojects/
./subprojects/mylib.wrap
src/meson.build contains:
mylib_dep = dependency('mylib') # Searches for mylib with pkg-config then fall backs to mylib.wrap.
myexec_exe = executable ('myexec', 'myexec.c', dependencies : mylib_dep)
Dependency mylib_dep provides libraries, which, if not installed on the system, make the main executable of my project unusable:
$ meson build && cd build && meson compile src/my_exec
...snip'd...
$ src/my_exec
src/my_exec: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory
My testing script build/tests/mytests.sh is configure_filed from tests/mytests.sh.in to indicate the location of myexec, and I'd like to pass to it the library paths, so that it can adjust LD_LIBRARY_PATH and run the executable. For instance, in tests/meson.build:
conf_data = configuration_data ()
conf_data.set_quoted ('MYEXEC_PATH', myexec_exe.full_path ())
conf_data.set_quoted ('MYLIB_PATH', mylib_dep.??????)
mytest_exe = configure_file (input : 'mytests.sh.in', output : 'mytests.sh', configuration : conf_data)
and in tests/mytests.sh.in:
MYEXEC_PATH=#MYEXEC_PATH#
MYLIB_PATH=#MYLIB_PATH#
export LD_LIBRARY_PATH=$(dirname "$MYLIB_PATH"):$LD_LIBRARY_PATH
$MYEXEC_PATH
Question: What should go at the ?????? above? In other words, given a dependency object, how can I extract the libraries within it, and get their full paths?
Usually in meson you wouldn't configure_file this, you'd pass the library/executable(s) to the script as arguments in the test command:
test(
'mytest',
find_program('mytest.sh')
args : [executable_target, library_target, ...],
)
It can be frustrating trying to get this sort of info out of Meson. Fortunately, if Meson used CMake to find the dependency, you may be able to get the library path from the underlying CMake variables, which are available in the Meson dependency object. Eg, something along the following lines worked for me:
mylib_dep = dependency('mylib')
if mylib_dep.found()
mylib_path = mylib_dep.get_variable(default_value : '', cmake : 'PACKAGE_LIBRARIES')
message('Library path is:', mylib_path)
endif
I am including opencv with custom build parameters in my Yocto image. For that I have an opencv_4.1.0.bbappend recipe, in which I set custom options, specifically FFMPEG. The recipe goes something like this:
DEPENDS += "ffmpeg libpng"
EXTRA_OECMAKE_append += "-DWITH_FFMPEG=ON -DWITH_GTK=OFF" # and some other options
During configure I get cmake errors and can't seem to figure out, how to satisfy the header dependencies. The errors go like this (I assume this is the reason for do_configure to fail):
CheckIncludeFile.c:1:10: fatal error: /home/janos/dev/yocto/build/tmp/work/core2-64-poky-linux/opencv/4.1.0-r0/recipe-sysroot/usr/include/libpng/png.h: No such file or directory
1 | #include </home/janos/dev/yocto/build/tmp/work/core2-64-poky-linux/opencv/4.1.0-r0/recipe-sysroot/usr/include/libpng/png.h>
CheckIncludeFile.c:1:10: fatal error: sys/videoio.h: No such file or directory
1 | #include <sys/videoio.h>
Focusing on the missing png.h header first, I am tempted to depend libpng-dev, as I also would apt install it. But there is no package for it.
When I search oe-pkgdata-util list-pkg-files -p libpng, I can find the header in a libpng-dev package:
...
libpng-dev:
/usr/bin/libpng-config
/usr/bin/libpng16-config
/usr/include/libpng16/png.h
/usr/include/libpng16/pngconf.h
/usr/include/libpng16/pnglibconf.h
/usr/include/png.h
...
...
I can also find it in libpng-src and also ffmpeg-src package (oe-pkgdata-util find-path "*png.h" was my friend). But all of these -dev and -src packages I cannot depend on in DEPENDS.
How can I get my recipe to know those headers?
Target machine is raspberrypi4-64, on which the recipe is configuring and compiling well - it fails when I build for qemux86-64, which I use for testing. Namely, my test command is MACHINE="qemux86-64" bitbake opencv.
It doesn't really answer the question which I though was the question - but this is how the opencv recipe is easily configured:
PACKAGECONFIG = "python3 libav libv4l v4l"
Looking into the opencv 4.1.0 recipe (opencv_4.1.0.bb), I could see that FFMPEG gets enabled with the libav configurable option.
As a result of depending FFMEPG, I had to whitelist "commercial" licenses in my local.conf file:
LICENSE_FLAGS_WHITELIST = "commercial"
Looking into ./build/tmp/work/aarch64-poky-linux/opencv/4.1.0-r0/temp/log.do_configure shows that opencv is correctly configured without GUI, with v4l/v4l2:, FFMPEG, python3, etc.
And so python3 in the resulting image:
import cv2
print(cv2.getBuildInformation())
Where need I to set the path to the protoc to get import standards Protocol Buffers (protobuf), like empty.proto and timestamp.proto in Windows and Dart?
When the protoc is ran:
protoc --dart_out=grpc:lib/src/protos/generated -Iprotos
protos/organization.proto
--plugin=protoc-gen-dart=D:\Users\Samuel\AppData\Roaming\Pub\Cache\bin\protoc-gen-dart.bat
The following error is presented:
google/protobuf/empty.proto: File not found. organization.proto:
Import "google/protobuf/empty.proto" was not found or had errors.
organization.proto:14:27: "google.protobuf.Empty" is not defined.
In IntelliJ Settings on Protobuf Support plugin the path is define where standard protos (*.proto) are:
Additionally this path is define in IntelliJ on Project Structure \ Global Libraries:
The code organization.proto that import google/protobuf/empty.proto to use Empty class :
syntax = "proto3";
package auge.protobuf;
import "google/protobuf/empty.proto";
service OrganizationService {
rpc GetOrganizations (google.protobuf.Empty) returns (OrganizationsResponse) {}
}
IntelliJ analyzer recognizes the import "google/protobuf/empty.proto" and Empty class on IDEA, but protoc can not find.
The environment is:
SO: Windows 7 x64
protoc: libprotoc 3.6.1
Dart: 2.2.0-edge
Say you have /some/path/to/google/protobuf/empty.proto, you need to pass --proto_path=/some/path/to/ so protoc can locate it.
use two dot before protobuf folder path
<Protobuf Include="..\Proto\protobuf.proto" ProtoRoot="Proto" />
This question is specific to avro-c, but the solution may be generalized to other packages in the OpenEmbedded BitBake system.
How do I create a do_populate_sdk task for avro-c?
I want to generate a Yocto SDK which includes avro-c. The avro-c layer in meta-openembedded is very small:
avro
├── avro-c
│ └── 0001-avro-c-Fix-build-with-clang-compiler.patch
└── avro-c_1.8.1.bb
The avro-c_1.8.1.bb recipe is only 20 lines:
SUMMARY = "Apache Avro data serialization system."
HOMEPAGE = "http://apr.apache.org/"
SECTION = "libs"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=73bdf70f268f0b3b9c5a83dd7a6f3324"
DEPENDS = "jansson zlib xz"
PV .= "+git${SRCPV}"
SRCREV = "4b3677c32b879e0e7f717eb95f9135ac654da760"
SRC_URI = "git://github.com/apache/avro \
file://0001-avro-c-Fix-build-with-clang-compiler.patch;patchdir=../../ \
"
S = "${WORKDIR}/git/lang/c"
LDFLAGS_append_libc-uclibc = " -lm"
inherit cmake
A target image which includes avro-c builds successfully, and ls /usr/bin/avro* lists the Avro functions.
However, avro-c is not included in the host SDK build. One way to troubleshoot this is to try the two commands:
$ bitbake avro-c
$ bitbake avro-c -c populate_sdk
The first command completes successfully. The second command fails with the following error messages:
ERROR: Task do_populate_sdk does not exist for target avro-c (/home/rdepew/workspace/clean1/build/../layers/meta-sporian/recipes-support/avro/avro-c_1.8.1.bb:do_populate_sdk). Close matches:
do_populate_lic
do_populate_sysroot
ERROR: Command execution failed: 1
I looked for clues in the other layers in my build system. It appeared that creating the file avro-c_%.bbappend, containing the single line
inherit nativesdk
might do the trick, but that generated two more BitBake error messages:
ERROR: Nothing PROVIDES 'virtual/x86_64-pokysdk-linux-compilerlibs' (but /home/rdepew/workspace/clean1/build/../layers/meta-sporian/recipes-support/avro/avro-c_1.8.1.bb DEPENDS on or otherwise requires it). Close matches:
virtual/nativesdk-x86_64-pokysdk-linux-compilerlibs
virtual/x86_64-pokysdk-linux-go-crosssdk
virtual/x86_64-pokysdk-linux-gcc-crosssdk
ERROR: Required build target 'avro-c' has no buildable providers.
Missing or unbuildable dependency chain was: ['avro-c', 'virtual/x86_64-pokysdk-linux-compilerlibs']
... and that's where I'm stuck. I'm not sure where to go from here.
Online places that I have researched:
I don't know if it's appropriate to list the URLS of places where I have looked for the answer. They include the GitHub repository for Avro, the Yocto Project ADT manual, and four related questions on StackOverflow. If it's appropriate, I will edit this question to include the URLs.
The right way to add something to SDK (or eSDK - Extended SDK) is via the image of your choice. So, the steps are:
Add a package to the image:
IMAGE_INSTALL_append = " avro-c"
Create Yocto SDK for an image of your choice:
bitbake core-image-full-cmdline -c populate_sdk
Create Yocto eSDK for an image of your choice:
bitbake core-image-full-cmdline -c populate_sdk_ext
Have fun! :-)
You need the following line in your recipe
BBCLASSEXTEND = "nativesdk"
This extends the same recipe to build for sdk as well. See here for more details.
EDIT:
do_populate_sdk: This task applies only for the image recipe. This handles two operations.
Target part: Compiles and installs the header and libraries for the target platform.
Host part: Installs the host part of the library and header based on SDKMACHINE
During these operations, it finds the list of packages needed for the SDK by examining the BBCLASSEXTEND variable and builds the nativesdk-<recipe_name> for combines them together in SDK.
So you have do_populate_sdk for image recipe which bundles the packages together.
See yocto manual here for more details.
From Linux, I'm using Meson (0.44.0) within Gnome Builder (3.26.4) for a console program that will use Gee and GXml. My intent is to write this in Genie.
When I use Meson within Gnome Builder it fails but the same succeeds when invoked from the command line using valac (0.38.8) as follows:
valac --pkg=gtk+-3.0 --pkg=gee-0.8 --pkg=gxml-0.16 main.gs
There is no error from the above. I've tried setting up meson.build with gee and gxml as dependency and alternatively as vala_args. Same error.
Checking pkg-config, I get the following:
$ pkg-config --libs gxml-0.16
-L/usr/local/lib64 -lgxml-0.16 -lgio-2.0 -lxml2 -lgee-0.8 -lgobject-2.0 -lglib-2.0
$ pkg-config --libs gee-0.8
-lgee-0.8 -lgobject-2.0 -lglib-2.0
$ pkg-config --libs gee-1.0
-lgee -lgobject-2.0 -lglib-2.0
Perhaps I'm doing something wrong. Here is the local meson.build file followed by the top level meson.build and the error:
example_sources = [
'main.gs'
]
example_deps = [
dependency('gio-2.0', version: '>= 2.50'),
dependency('gtk+-3.0', version: '>= 3.22'),
dependency('glib-2.0', version: '>= 2.50')
]
gnome = import('gnome')
example_sources += gnome.compile_resources(
'example-resources',
'example.gresource.xml',
c_name: 'example'
)
executable(
'example',
example_sources,
vala_args: '--target-glib=2.50 --pkg=gee-0.8 --pkg=gxml-0.16',
dependencies: example_deps,
install: true
)
with top-level meson.build:
project(
'example',
['c', 'vala'],
version: '0.1.0',
meson_version: '>= 0.40.0',
)
subdir('src')
And the error is:
uses Gee
error: The namespace name 'Gee' could not be found
I'm invoking the build from within Gnome-Builder. Can someone help me understand what is happening? I've tried to find why valac succeeds and meson fails in the documentation but cannot find a solution.
Gee and GXml should be dependencies, just like GIO, GLib and GTK+. So you should try:
example_deps = [
dependency('gio-2.0', version: '>= 2.50'),
dependency('gtk+-3.0', version: '>= 3.22'),
dependency('glib-2.0', version: '>= 2.50'),
dependency('gobject-2.0'),
dependency('gee-0.8'),
dependency('gxml-0.16'),
]
Usually you won't need to go beyond that. This makes the --pkg options in the vala_flags unnecessary. Meson does that for you. The way Meson works is it uses valac to produce C code then in a separate stage uses a C compiler to produce the binary. By using --pkg you are only telling valac which VAPI file to use, but not notifying the C compiler which pkg-config package to use for the C library.
Also notice I've added gobject-2.0 as a dependency. If I remember correctly GNOME Builder misses that and it does affect the build.
The error message, error: The namespace name 'Gee' could not be found, is troubling. This is an error from the Vala compiler and I would have thought that the compiler would be able to find the VAPI file using the vala_args method you've tried. Maybe you have Gee built from source and not installed system wide?
Meson does allow another VAPI search directory to be added:
add_project_arguments(['--vapidir',
join_paths(meson.current_source_dir(), 'vapi')
],
language: 'vala'
)
There are more details on the Vala page of the Meson Build documentation.
Genie support was added to Meson with version 0.42. So meson_version: should be >= 0.42.0.
If there are still problems then here is an MCVE using Genie, Gee and Meson. This should be compiled from the command line. Save the following Genie program as genie-gee.gs:
[indent=2]
uses Gee
init
var my_list = new ArrayList of string()
my_list.add( "one" )
my_list.add( "two" )
for item in my_list
print( item )
Then save the following Meson file as meson.build:
project('minimal-genie-gee-example',
'vala', 'c'
)
genie_gee_deps = [
dependency('glib-2.0'),
dependency('gobject-2.0'),
dependency('gee-0.8'),
]
executable('genie-gee',
'genie-gee.gs',
dependencies: genie_gee_deps
)
From the command line use Meson to set up the build directory:
meson setup builddir
This should show the dependencies have been found, for example:
Native dependency gee-0.8 found: YES 0.18.0
Then use Ninja build to build the project:
ninja -C builddir
For anyone using Fedora ninja is ninja-build.
Any problems with Meson setting up the build directory are logged to builddir/meson-logs/meson-log.txt.
If this works, but it fails in GNOME Builder, then my only other thought is that GNOME Builder has been installed using Flatpak. The sandboxed environment of Flatpak may be affecting the access to dependencies.
Update: Following the discussion in the comments it appears the runtime used by GNOME Builder was the problem. Builder has a great feature of being able to select the Flatpak runtime used to build your software. If you are following the 'traditional' way of developing by installing libraries and header files on your workstation then make sure Host Operating System is selected instead of a Flatpak runtime. It would appear the GNOME Flatpak runtime does not include libgee.
Update2: When writing a Flatpak builder manifest and a dependency is not in the Flatpak runtime/SDK then add the dependency as another module in the Flatpak builder manifest. This allows GNOME Builder to use Flatpak to build the software with the Flatpak runtime. An example manifest is given in AsymLabs answer.
Well after some exploration and AlThomas' advice above, here is what I discovered. OpenSUSE Tumbleweed provides four (or more) ways to install Gnome-Builder. These are:
1) Via Gnome Software Center. This installs org.gnome.Builder/stable in a sand boxed environment using Flatpak.
2) Via Flathub.org using Flatpak from the command line. This installs org.gnome.Builder/master (nightly) in a sand-boxed environment.
3) Via the package manager zypper and the command line. This installs a stable Gnome-Builder and related libraries system-wide.
4) Via Yast2. This provides the same as Zypper.
All three installations (same version 3.26.4 - different branches/tags - stable, master, nightly - two sand-boxed and one system wide) can be installed side by side and used as needed. During initial setup and testing, all variants yielded the same outcome - when using Gee and GXml only a Default build would work (the Flatpak Manifest would not build) but this has been resolved (it now appears that this is purely a Flatpak issue was a conflict between Flatpak and Fuse).
The Default build enables the Host runtime system. To set the Default build environment, upon opening a project within Gnome-Builder, choose Build Preferences from the upper left popover menu and select Default.
The drawback to a Default configuration is that it is not possible to Export Bundle, but local builds can utilize system-wide features.
So what is a Flatpak Manifest and why is it so important? It is the top level JSON file that contains project information. The Flatpak Manifest, in this case org.gnome.Example.json, pulls together all the features of the project so that it may be packaged for distribution. This includes the runtime, sdk, system connectivity to X11, IPC, Wayland, DBus, etc, the build system (Meson by default), cleanup directives, configuration and build options, submodule details (dependencies) and many other features. One Flatpak package can be installed in just about any Linux distribution, whether Debian, Ubuntu, Red Hat, OpenSuse or their derivatives, for example, and is sand-boxed for security and portability purposes. It will be, in future, fully cross-platform.
For instruction and testing, there are Flatpak Manifest examples to illustrate how they work. There are ways to alter the sand-box permissions using build finish directives. Flatpak documentation is excellent.
Within Gnome Builder when you first create a project, choose Vala + Gnome Application and a valid Flatpak Manifest will be installed. By default this is intended for a GUI rather than command line application; nonetheless it generates a default Flatpak Manifest that can be used as a template (Gnome Builder will allow multiple manifests - just select the build required). The following is the resulting improved Flatpak Manifest that will build submodules for both Gee and GXml (this has been tested within Gnome Builder and works):
{
"app-id": "org.gnome.Example",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "example",
"finish-args": [
"--share=network",
"--share=ipc",
"--socket=x11",
"--socket=wayland",
"--filesystem=xdg-run/dconf",
"--filesystem=~/.config/dconf:ro",
"--talk-name=ca.desrt.dconf",
"--env=DCONF_USER_CONFIG_DIR=.config/dconf"
],
"build-options": {
"cflags": "-O2 -g",
"cxxflags": "-O2 -g",
"env": {
"V": "1"
}
},
"cleanup": [
"/bin",
"/include",
"/lib",
"/lib/pkgconfig",
"/share",
"/share/vala",
"*.la",
"*.a"
],
"modules": [
{
"name": "libgee",
"buildsystem": "meson",
"config-opts": [
"--libdir=lib"
],
"builddir": true,
"sources": [
{
"type": "git",
"tag": "meson",
"url": "https://github.com/GNOME/libgee.git"
}
]
},
{
"name": "libgxml",
"buildsystem": "meson",
"config-opts": [
"--libdir=lib"
],
"builddir": true,
"sources": [
{
"type": "git",
"branch": "master",
"url": "https://gitlab.gnome.org/GNOME/gxml.git"
}
]
},
{
"name": "example",
"buildsystem": "meson",
"config-opts": [
"--libdir=lib"
],
"builddir": true,
"sources": [
{
"type": "git",
"url": "file:///home/<user>/Projects/example"
}
]
}
]
}
Hat's off to the folks who are developing this package. Combining Flatpak, Meson, Gtk3/4/5/.., Vala, Genie (and soon the Vulkan 3D graphics engine) and beautifully minimalistic UI guidlines/standards in one lightweight development platform is something magical, akin to a modern day alchemy.
As an aside, I tried using Gtk3 with a number of languages, including C/C++, D, Haskell and Python but none of these alternatives could produce stand-alone binaries that were as compact, efficient and fun to write as Vala and Genie. These are greatly underrated languages.
Concluding, anyone who needs a good starting point when trying to understand these technologies and how Gnome-Builder is bringing them together can read AlThomas' post above and this one, along with the comments. It may save a lot of time.