install package (library) for crosscompiler - cmake

I would like to
use the crosscompiler gcc-aarch64-linux-gnu to build a binary
link a precompiled library (e.g. libxml2.so/libxml2.a) to that binary
use cmake
I thought of the following way to achieve the above:
creating a sysroot folder (is this the correct term?)
downloading the library by apt-get download libxml2-dev:arm64
"installing" the package into the sysroot folder by dpkg-deb -x libxml2_*_arm64.deb ./sysroot/
declaring the sysroot folder in CMAKE_FIND_ROOT_PATH
using find_package() in cmake to locate the library in sysroot
Question: Is the way above a good one? Is there a better one? I am surely not the first one facing that problem, therefore I think there might be a better way.

Related

How to set up libusb dependency with CMake?

I am trying to develop an application using GreatScottGadget's Ubertooth One. To start, I need to be able to use the libusb library. I'm working with Ubuntu 20.04.
I have a simple CMakeLists.txt file that sets the module path to a path in my project that contains all the Find*.cmake files that I stole from the ubertooth repository here. I include libusb like so:
find_package(USB1 REQUIRED)
When I run CMake, this is the error I get:
Could not find package configuration file provided by "USB1" with any of the following names:
USB1Config.cmake
usb1-config.cmake
Add the installation prefix of "USB1" to CMAKE_PREFIX_PATH or set
"USB1_DIR" to a directory containing one of the above files. If "USB1"
provides a separate development package or SDK, be sure that it has been
installed.
As far as I can tell, I have libusb already installed. apt list --installed | grep libusb shows libusb-1.0.0-dev/focal,now 2:1.0.23-2build1 amd64 [installed] (among others). I can see the shared object in /usr/lib/x86_64-linux-gnu
$ ls /usr/lib/x86_64-linux-gnu | grep libusb
libusb-0.1.so.4
libusb-0.1.so.4.4.4
libusb-1.0.a
libusb-1.0.so
libusb-1.0.so.0
libusb-1.0.so.0.2.0
libusbmuxd.so.6
libusbmuxd.so.6.0.0
Additionally, I can build the host code provided in the ubertooth repository just fine. In the CMake output, I see the following:
-- Checking for module 'libusb-1.0'
-- Found libusb-1.0, version 1.0.23
-- Found LIBUSB: /usr/lib/x86_64-linux-gnu/libusb-1.0.so
Looking through the ubertooth repository, I don't see anything special they are doing to find the package. The host project adds libubertooth as a subdirectory, in in its CMakeLists.txt, it uses the same method I have to find the library. I'm not seeing any other differences.
Maybe I'm misunderstanding and the libubertooth subdirectory isn't where the library is being found. Maybe there's some global config that I'm not setting. I haven't managed to find whatever it is.
I checked the libusb homepage and downloaded the source, but I didn't find any USB1Config.cmake files, so I'm not sure how this is supposed to work.
What am I missing to be able to find the library and use it in my project?
This is because you don't have a FindUSB1.cmake in you project. You can find it on ubertooth/host/cmake/modules/FindUSB1.cmake.
BTW, don't use stole, you can find ubertooth's license, it's GPL-2.0

cmake find_package unable to find Eigen3Config.cmake spectra Windows

I am using Eigen3 with spectra (https://spectralib.org/), a library built on top of Eigen. Spectra uses find_package to find Eigen, and comes up with the error:
Could not find a package configuration file provided by "Eigen3" with any
of the following names:
Eigen3Config.cmake
eigen3-config.cmake
Looking through the directory of Eigen, I found that there were no files by those names, but rather one called Eigen3Config.cmake.in. I tried copying the file and renaming it Eigen3Config.cmake, but that gave me a different error of
find_package Error reading CMake code from "C:/Program Files
(x86)/Eigen3/cmake/Eigen3Config.cmake".
which was somewhat expected, but it does tell me that it can at least find the directory where Eigen3Config.cmake.in is. I'm assuming that either find_package is supposed to use Eigen3Config.cmake.in, or Eigen3Config.cmake.in is supposed to generate Eigen3Config.cmake, but i'm very new to cmake, so i'm not sure. How do I fix this?
There is no need to build/install Eigen to use it if you include it manually, as done in the getting started example (https://eigen.tuxfamily.org/dox/GettingStarted.html#title0)
But in order to be found by CMake, you will need to build / install it, as explained in the INSTALL file. https://gitlab.com/libeigen/eigen/-/blob/master/INSTALL
Usually, your error is followed by an hint asking you to set the variable Eigen3_DIR (or something similar) to point the build/install dir of the target project (Eigen3 here). It appears typically when you have built but not installed the project.
So:
Build Eigen
Install it (optional)
For spectra set the cmake var Eigen3_DIR to /path/to/Eigen/build . (if eigen not install or still not found)
These steps worked for me:
Install Eigen
Create a build directory for Eigen
cd into the build directory created
run "cmake ../"Your Eigen Source Directory""
After this is done, in your CMakeLists.txt of your project, you'll want to add "find_package( Eigen3 REQUIRED)" and "include_directories( ${EIGEN3_INCLUDE_DIR})".

How find_library does handle so version numbers?

How does CMake's find_library handle so version numbers like in "libFOO.so.3.2"? Some libraries have symbolic links from libFOO.so to the right version, some do not.
Does CMake find a library without the symbolic link when I just use find_library(NAMES FOO)?
What should I do to help CMake figuring out the right library?
Assuming a linux distribution, the system package manager will generally provide runtime packages and development packages. If you have installed the development package for a library (e.g. libFOO-dev), it will generally include the following three files in your /usr/lib or /usr/local/lib
libFOO.so.3.2.0 (the versioned binary)
libFOO.so.3 (soname = symlink to versioned binary)
libFOO.so (namelink = symlink to soname)
The namelink has no version details in the file name. This will be used to find the library by linker command line option, e.g. -lFOO
You should use the namelink (e.g. FOO) in the find_library cmake command.
The linker will embed the soname file into your binary.
If you have multiple versions of the library installed, be sure to symlink the namelink file to the soname file that you want to use. This is really only an issue if you have multiple major versions of the same library installed. Within a major version, APIs should be backwards compatible.
In addition to #marksisson's answer:
In case you download an SDK as a zip archive with such symlinked .so files it may happen that the symlinks are broken. Instead of real symlinks you have small text files containing the names of the linked files. As a consequence the linker complains about an unrecognizable file format.
To fix that, just recreate the symlinks after unpacking the zip file.

How can I manage the installation directory with CMake when cross-compiling?

I am cross-compiling a C library using CMake and a toolchain file. My toolchain file sets CMAKE_SYSROOT to the appropriate value so compilation works with no issues. However, when installing, the library does not install to the directory pointed to by CMAKE_SYSROOT. I can achieve that effect by running make install DESTDIR=xxx though.
I understand that there are two separate concepts here:
The cross-compilation toolchain, which consists of binaries that can be run on my local architecture
The CMAKE_SYSROOT which is the root directory of a target-architecture filesystems, containing header files and libraries, passed to e.g. gcc through the --sysroot flag.
I have two questions:
Is it a good idea to conflate the sysroot where my cross-compilation toolchain lives, with the sysroot where all my cross-compiled libraries will be installed? It feels to me like it should be the same, but am not sure, and to CMake it appears they are distinct concepts. Update: answered in the comments below, these are indeed distinct concepts.
What is the modern CMake way to specify the installation directory when cross-compiling like described above? Update: I believe this should be the same as CMAKE_SYSROOT, and I feel CMake should offer a way to only define this once somewhere.
Thanks!
There is no interference between sysroot and install directory (prefix).
Sysroot is given by CMAKE_SYSROOT variable and denotes prefix for tools used during build process.
Install directory(prefix) is given by CMAKE_INSTALL_PREFIX variable and denotes the path, where the project will be used upon installation. E.g. with install prefix /usr/local the project's executable foo expects to be run as /usr/local/bin/foo.
Note, that with default installation procedure, CMake installs files to the host machine. For install files onto the target machine, this procedure is needed to be adjusted. Parameter DESTDIR=xxx for make install is a way for install files directly to the target machine. Another way is to create a package (e.g. with CPack) on host, and install that package on target machine.
Note, that in the above paragraph it is irrelevant, whether cross-compilation took a place or not: it is possible to build the project on one machine and install it to the other, but similar one, without any cross-compilation.

Building .so module with autotools/libtool without .la and .a variants being installed

How to build and install a .so module with autotools/libtool without .la and .a libraries
being also installed into --prefix path?
Currently i am using following Makefile.am:
lib_LTLIBRARIES = libCurlDownloader.la
libCurlDownloader_la_SOURCES = Curl.cpp
libCurlDownloader_la_LDFLAGS = -module -avoid-version
It works, but in addition to libCurlDownloader.so it also installs libCurlDownloader.la and libCurlDownloader.a, what is undesirable.
Update #1
It is possible to make .a not be generated, by using either
./configure --disable-static
or
AC_ENABLE_SHARED(yes)
AC_ENABLE_STATIC(no)
in configure.ac
But it is still the question how to make .la not being installed into installation --prefix while having .so installed.
Update #2
It is possible to remove .la files from installation --prefix using
install-exec-hook: find $(DESTDIR)$(libdir) -type f -name \*.la -delete
You should not necessarily delete the .la files. The .la files contains information that is used in two situations:
Statically linking against the built library. When statically linking (i.e., .a with -static), there is no information about the dependencies of the library being linked, so libtool can use the information in the .la file to create an appropriate ld command referencing all the necessary dependencies. This is often more important on an environment like MinGW where the linker requires the same library specified multiples in a particular order to resolve recursive dependencies. This is only a concern if one intends to build a static binary.
Dynamically loading the build library on some platforms (i.e., with lt_dlopen if using libltdl). Similarly, on certain platforms, dependencies of the compile module are not encoded in the binary, so the .la file is needed so that lt_dlopen will find and load the correct dependencies. On ELF platforms (including Linux) and PE platforms (i.e., Windows), the dependencies are store in the library, so lt_dlopen will work without the .la files. The MachO format on MacOS can require .la files when building bundles.
The Debian/Ubuntu packagers have decided to exclude .la files from their packages because the second reason isn't appropriate on Linux and they would prefer you didn't build static binaries in the first place. On other platforms, which libtool is designed to support, the .la files may be needed for linking or running the program.
I stumbled upon this question because it used the term "module", which in automake/libtool speak is the term for a plugin. I have a plugin system in Finit, so I build my plugins with '-module' to avoid creating .a files. But I still get the .la files installed, which really is not even applicable in the '-module' case.
I've yet to find a documented way to skip .la files for plugins, but here is how I do it:
AM_LDFLAGS = -module -avoid-version -shared
pkglib_LTLIBRARIES = alsa-utils.la bootmisc.la
install-exec-hook:
#(cd $(DESTDIR)$(pkglibdir) && $(RM) $(pkglib_LTLIBRARIES))
To be clear, in my use-case there is nobody going to "link" against my plugin .so's, so the .la files really are of no use.