CMAKE_SYSTEM_VERSION not updated for new kernel - cmake

I use cmake to install a linux driver. To get the kernel version I use CMAKE_SYSTEM_VERSION which should yield the output of uname -r.
However, after I installed a new kernel, I tried to reinstall the driver with cmake, just to note that it was installing to /lib/modules/<previous kernel>/... rather than to the directory for the current kernel. uname- r gives the correct result.
I use the following line in my CMakeLists.txt:
install(PROGRAMS myDevice.ko DESTINATION "/lib/modules/${CMAKE_SYSTEM_VERSION}/kernel/drivers/myDevice" COMPONENT driver)
I could not find CMAKE_SYSTEM_VERSION in the CMakeCache.txt, and just rerunning cmake .. did not do the trick either. I had to regenerate the entire build folder.
I would like to know if there is a better way, since the build folder also contains applications, that should not need rebuilding, just because there is a new kernel.

There are CMake variables, which are fixed since the first configuration. CMAKE_SYSTEM_VERSION is one of them. CMAKE_C_COMPILER is another example of "fixed" variables: changing it invalidates cache completely.
So, you need to make different builds for different kernels.
You may separate configuration and building of user-space application from kernel modules. So rebuilding kernel module doesn't force rebuilding of the applications.
Exactly that approach I have used in my projects: setting one option (introduced with option() command) builds only applications, setting another option builds only kernel modules. By default, none option is set and both kernel-space and user-space components are built.

Related

Variable interpolation in -D option

As a package manager for a Linux distribution, I want to install docs into a separate prefix. With CMake projects, the docs installation location is controlled by CMAKE_INSTALL_DOCDIR from GNUInstallDirs module. Unfortunately, unlike the other directory variables, this one contains the project name so I cannot just use cmake "-DCMAKE_INSTALL_DOCDIR=$myDocPrefix/doc".
With GNU Make, I would run make "DOCDIR=$myDocPrefix/doc/\$(PROJECT_NAME)" and have Make interpolate it but the documentation of CMake’s -D option does not mention interpolation and I understand that CMake uses much more complex system of cache entries where interpolation might be problematic (especially if the referenced variable is not yet in cache).
I could pass tailor-made CMAKE_INSTALL_DOCDIR to each CMake project but would be bothersome as I would have to do that in every package definition manually; being able to define configureCmakeProject function and have it take care of everything automatically would be better. When setting it manually, I would also want to make sure it matches the PROJECT_NAME of the respective CMake project – well, I could resign on that and just use $packageName from the package definition instead but keeping packages as close to upstream as possible is preferred.
Alternately, I could try to grep CMakeLists.txt for project command but that seems fragile and might still result in misalignments. I doubt it is possible to extract it using some CMake API since the project is not configured at the time and we actually need the value to configure the project.
Is there a way I can configure CMAKE_INSTALL_DOCDIR to use custom prefix but still keep the project name set by the CMake project?

Force CMake to install targets to architecture-specific directories?

I'm currently having this issue with the Google Protobuf Library, but it is a recurring problem and will likely occur with many if not all 3rd-party packages that I want to build and install from source.
I'm developing for Windows, and we need to be able to generate both 32-bit and 64-bit versions of our DLLs. It was relatively straightforward to get CMake to install our own modules to architecture-specific subdirectories, e.g. D:\libraries\bin\i686 and d:\libraries\lib\i686 (and sim. for bin). But I'm having trouble achieving the same thing with 3rd-party libraries such as Protobuf.
I could, of course, use distinct CMAKE_INSTALL_PREFIX and CMAKE_PREFIX_PATH combinations (e.g. D:\libraries-i686 and D:\libraries-x86_64, and will probably end up doing just that, but it bothers me that there doesn't seem to be a better alternative. The docs for find_package() clearly show that the search procedure does attempt architecture-specific search paths, so why do the CMake files of popular libraries not generally seem to support installing to architecture-specific subdirectories?
Or could it be that it is just a matter of setting the right CMAKE_XXX variable?
Thanks to #arrowd for pointing me in the right direction, I now have my answer, though it is not exactly what I had hoped for.
CMAKE_LIBRARY_OUTPUT_DIRECTORY and CMAKE_RUNTIME_OUTPUT_DIRECTORY, however, specify the build output directories, not the install directories. As it turns out though, there are variables for the install directories too, called CMAKE_INSTALL_BINDIR and CMAKE_INSTALL_LIBDIR - they are actually plainly visible (along with plenty more) in the cmake-gui interface when "Advanced" is checked.
I tried setting those two manually (to bin\i686 and lib\i686), and it works: the Protobuf INSTALL target copies the files where I wanted to have them, i.e. where the CMake script of my consumer project will find them in an architecture-safe manner.
I'm not sure how I feel about this - I would have preferred something like a CMAKE_INSTALL_ARCHITECTURE or CMAKE_ARCHITECTURE_SUBDIR variable that CMake would automatically append to relevant install paths. The solution above requires overriding defaults that I would prefer to leave untouched.
Under the circumstances, my fallback approach might still be the better option. That approach however requires that the choice of architecture be made very early on, typically when running the script that initializes the CMake-specific environment variables that will be passed to cmake when configuring build directories. And it's worse when using cmake-gui, which requires the user to set all directories manually.
In the end, I'm still undecided.

Buildroot change target directory / create "out of target" packages

I'm using buildroot to create a linux system for raspberry pi. I want to use the initramfs to enable to system to self-patch. The procedure roughly runs as follows:
Raspi boots, kernel loads initramfs
The initramfs-system (which contains busybox, zsync etc.) connects to a central server and checks if there are boot-file updates available (e.g. a new kernel)
If not, it checks if there is a system update available and downloads that if needed
The downloaded (squashfs) system image is mounted and executed via switch_root
My problem is that I need to compile a secondary busybox (and some more packages) for the initramfs which do not belong in the main system. I currently solved this by manually tinkering with the package files to install into target/initramfs, moving this folder out with pre-build and back in again with post-build, but this seems rather hacky. Additionally, different package types require different types of changes. Is there a better solution to this problem? If one could for example manually overwrite the target directory for each package, this problem would be rather easy to solve.
Create two separate buildroot configurations.
One configuration will have the kernel and the initramfs.
The other configuration only has the squashfs rootfs.
Creating a partial rootfs from a configuration is very tricky, because you have to be sure that you don't miss any shared libraries or other auxiliary files needed by some program.
Note that to speed up the build, you can use ccache and/or use an external toolchain. See the manual.

On UnsatisfiedLinkError, clarification needed

When building the project from command line using mvn clean install everything builds without any issues.
When running some tests that use precompiled C libraries from IntelliJ, tests fail with java.lang.UnsatisfiedLinkError
I may be completely off here, but does IntelliJ not see the .so file? Is so, how can it be added please?
Shared library fails to load with UnsatisfiedLinkError if:
it's not in the working directory configured in the test run configuration.
it's not in PATH environment (on Mac Terminal and GUI apps have different environment, see this answer). Run IDEA from the Terminal open -a /Applications/IntelliJ\ IDEA\ 12.app/ to make environment the same.
it's not in the location specified using -Djava.library.path VM option.
.so depends on some other library that is not found for any of the 1-3 reasons (or the dependency of that dependency is not found, etc).

How do you make it so that cpack doesn't add required libraries to an RPM?

I'm trying to convert our build system at work over to cmake and have run into an interesting problem with the RPMs that it generates (via cpack): It automatically adds all of the dependencies that it thinks your RPM has to its list of required libraries.
In general, that's great, but in my case, it's catastrophic. Unfortunately, the development packages that we build end up getting installed with one our home-grown tool that uses rpm to install them in a separate RPM database from the system one. It's stupid, but I can't change it. What this means is that all of the system libraries that any normal library will rely on (like libc or libpthread) aren't in the RPM database that is being used with our development packages. So, if an RPM for one of our development packages lists system libraries as being required, then we can't install it, as rpm will think that they're not installed (since they're listed in the normal database rather than the one that it's being told to use when installing our packages). Our current build stuff handles this just fine, because it doesn't list any system libraries as dependencies in the RPMs, but cpack automatically populates the RPM's list of required libraries and puts the system libraries in there. I need a way to stop it from doing so.
I tried setting CPACK_RPM_PACKAGE_REQUIRES to "", but that has no effect. The RPM cpack generates still ends up with the system libraries listed as being required. All I can think of doing at this point is to copy the RPM cpack generator and hack it up to do what I want and use that instead of the standard one, but I'd prefer to avoid that. Does anyone have any idea how I could get cpack to stop populating the RPM with required libraries?
See bottom of
http://www.rpm.org/max-rpm/s1-rpm-depend-auto-depend.html
The autoreqprov Tag — Disable Automatic Dependency Processing
There may be times when RPM's automatic dependency processing is not desired. In these cases, the autoreqprov tag may be used to disable it. This tag takes a yes/no or 0/1 value. For example, to disable automatic dependency processing, the following line may be used:
AutoReqProv: no
EDIT:
In order to set this in cmake, you need to do set(CPACK_RPM_PACKAGE_AUTOREQPROV " no"). The extra space seems to be required in front of (or behind) the no in order for it to work. It seems that the RPM module for cpack has a bug which makes it so that it won't let you set some its variables to anything shorter than 3 characters long.
To add to Mark Lakata's answer above, there's a snapshot of the "Maximum RPM" doc
http://www.rpm.org/max-rpm-snapshot/s1-rpm-depend-auto-depend.html
that also adds:
The autoreq and autoprov tags can be used to disable automatic processing of requirements or "provides" only, respectively.
And at least with my version of CPackRPM, there seems to be similar variables you can set e.g.
set(CPACK_RPM_PACKAGE_AUTOREQ " no")
to only disable the automatic dependency processing of 'Requires'.