Spurious targets when installing a software with CMake - cmake

I wrote a software whose configuration, building and installation are performed by means of some CMake files. This software is developped in a continuous integration process based on unit and functional tests. I noticed that targets corresponding to these tests are built during the installation step. It is not necessary at all and I would like to understand how to prevent CMake from doing it.
After having typed
make install
I get the following output:
[ 7%] Built target arpack
[ 15%] Built target boost
[ 23%] Built target eigen
[ 31%] Built target yamlcpp
[ 34%] Built target simol-core
[ 36%] Built target simol-quantchem
[ 80%] Built target simol-statphys
[ 88%] Built target gtest
[ 91%] Built target simol_test_unit
[ 92%] Built target simol_test_functional
[ 93%] Built target test_bichainfpu
[ 94%] Built target test_dpde
[ 95%] Built target test_fluid
[ 96%] Built target test_galerkin
[ 97%] Built target test_hamiltonian
[ 98%] Built target test_langevin
[ 99%] Built target test_rotor
[100%] Built target test_trichain
The steps from 88% to 100% are definitively spurious since I do not install any tests but only the core of the software and its modules. For example, the CMake command which installs simol-statphys (80%) is
INSTALL(TARGETS simol-statphys ARCHIVE DESTINATION lib)
I have a similar command for simol-core (34%) and simol-quantchem (36%). I can understand why previous targets are built (arpack, boost, eigen, yamlcpp) because the modules of the software depend on these external libraries. But they do not depend on the tests. The reverse is true: tests obviously depend on the module. But it does not make sense to me why they should be involved in the installation step. Of course, there is no call to the INSTALL command for the tests. These tests are only defined like this:
ADD_EXECUTABLE(test_galerkin ${CMAKE_SOURCE_DIR}/test/functional/statphys/galerkin/TestGalerkin.cpp)
TARGET_LINK_LIBRARIES(test_galerkin simol-statphys)
Does anybody know what is happening here?

CMake doesn't track dependency between installed targets and their built counterpairs. Instead, whole install (pseudo-)target is made dependent from all one.
So, whatever is built during make all is built also on make install.
If you don't want to build tests on make install, exclude them from make all. The simplest way to do this is using option EXCLUDE_FROM_ALL in add_executable() invocation:
ADD_EXECUTABLE(test_galerkin EXCLUDE_FROM_ALL ...)

Related

Dependencies between Android native modules (prefab) fail to build

Our Android application consists of 40-some Android Library Modules (ALMs), each of which also builds a C++ shared library with externalNativeBuild and CMake. So far we had the dependencies between these libs set up like this:
The dependent ALM references the dependency ALM with api project(':lib')
The dependent CMake script references the dependency .so with add_library(SHARED IMPORTED lib) and set_target_properties(lib PROPERTIES IMPORTED_LOCATION ...) and a relative path.
Recently we had to upgrade to the latest Android API version. This started off a cascade because now we were getting deprecated warnings in code generated by the navigation-ktx library, but upgrading that requires upgrading Gradle and the Android Gradle plugin. After that I started getting errors like liblib.so, needed by 'project', missing and no known rule to make it.
It looks like the latest Gradle parallelizes build tasks more heavily, and this means the dependent CMake/Ninja builds are being started concurrently with their dependencies, resulting in this error because the dependency is not yet built. I figured out that what we were doing was not entirely supported, but there is a "supported" way to do that now, so I refactored our entire build to use Prefab.
Now I started getting other errors, alternating between:
1.
C++ build system [prefab] failed while executing ...
Usage: prefab [OPTIONS] PACKAGE_PATH...
Error: Invalid value for "PACKAGE_PATH": Directory ... is not readable.
ld: error: undefined symbol ...
I looked into build/intermediates and found that in the 2nd case, the cmake config script was generated incorrectly: instead of add_library(lib::lib SHARED IMPORTED ) it had add_library(lib::lib INTERFACE IMPORTED) like it it was a header only library, and there was no IMPORTED_LOCATION set in the file.
What am I doing wrong and what should I do to unbreak our build?
It looks like the toolchain support for prefab interdependencies within a project is not quite finished. Others are reporting the same kind of errors at https://issuetracker.google.com/issues/265544858:
This appears to be a race condition with generating prefab cmake files.
It says in https://issuetracker.google.com/issues/221231432 that the header-only cmake config is generated to satisfy Android Studio's IDE features (completion, etc.) before the library is actually built.
Treat as-yet-unconfigured modules as if they are Header-only libraries for Android Studio purposes. This works because Android Studio doesn't care about linker flags for the purposes of providing language services.

Building a rust library through CMake and using it as imported library target

I'm restucturing the CMake based build of a cross platform (macOS/Windows, Linux should be added soon) C++ project that has a third party rust library as dependendcy. Until now the rust lib dependency was supplied as precompiled library but I want to make its compilation part of my CMake build.
I got it working on macOS using the CMake makefile exporter by referencing the compiled library as a static imported library target and setting up a custom target with the command to build the rust library through cargo like this
add_library (rustlib STATIC IMPORTED)
add_custom_target (rustlib_cargo
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/Ext/rustlib/c-api
COMMAND cargo rustc --release -- --crate-type staticlib)
# Note: RUSTLIB_OUTPUT is set above refering to the absolute path of the produced platform specific library
set_target_properties (rustlib PROPERTIES IMPORTED_LOCATION ${RUSTLIB_OUTPUT})
add_dependencies (rustlib rustlib_cargo)
On macOS the cargo rustc command is invoked before the targets that link against my rustlib target are built and in case the rust library has been built previously this is detected by cargo and it just skips that compilation steph. But on Windows this fails with the built-in ninja exporter of Microsoft Visual Studio 2019 with an error like this:
ninja : error : '../../../Ext/rustlib/target/release/deps/rustlib.lib', needed by 'SomeTargetLinkingAgainstRustlib', missing and no known rule to make it
If I remove the line set_target_properties (rustlib PROPERTIES IMPORTED_LOCATION ${RUSTLIB_OUTPUT}) the build starts correctly, the rust build gets triggered, but as expected I end up with a linker error as the library to link against is not found. So is there any way to refer to a file that is not existent at configuration time but is guranteed to be created during compilation?

FlatBuffers with Autotools

FlatBuffers build is based on cmake, I don't have(and cant install) cmake on target system where I want to build it
FlatBuffers don't seem have support for autotools, have anyone tried to use autotools(./configure, make, make install) to build FlatBuffers?
Assuming you can build flatc on your development system (or you can generate code somewhere that is not your target system), actually building on the target system involves the generated header, and the headers in include/flatbuffers, i.e. it is header-only and as such doesn't need any build system to build it. Just point the build of your actual project to where these headers are (-I).

CMake : Relink directory and double linking

In one of my projects at work the following was noticed and asked to me.
A binary would link and then link again in a folder called the "Relink" folder.
I also checked and the binary is in two places and linking occurs twice.
CMAKE version used is 2.6 - patch 2.
I found that in the build folder, the generated cmake_install.cmake has the following entry
IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" MATCHES "^(Unspecified)$")
IF("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$")
FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/path/to/binary/file/folder/CMakeFiles/CMakeRelink.dir/<binary name>").....
If INSTALL is used in CMAKE, and COMPONENT is not created with the install command AND the build is a Debug build, then this Relink Folder is created and the binary is linked twice. The question is why does this happen?
Linking twice increases your over build time.
So what purpose does this serve.
If the Install command is omitted or the build is a Debug build, then this does not occur.
Why not and why is it relevant if the build is a Debug build or not?
I have searched documentation and this site but could not find an explanation.
example output :
.....
Linking CXX shared library lib<library-name>.so <== Linking the first time
[100%] Built target <another library name>
[ 15%] Built target <another-library-name1>
[ 92%] Built target <another-library-name2>
[ 92%] Built target <another-library-name3>
[100%] Built target <another-library-name4>
[100%] Built target <another-library-name5>
Linking CXX shared library CMakeFiles/CMakeRelink.dir/lib<library-name>.so <== Second linking.
This Relink directory shows up when the following CMAKELists entry is added
install(TARGETS <binary/library name>
RUNTIME
DESTINATION "bin")
So building this as a Debug build and non COMPONENT install shows this behaviour.
Same code when built on Jenkins does not have this because the Jenkins build is a Release/Optimized build and not a Debug build.
Looks like Relinking before installation of binaries has a lot to do with preserving the RPATH in the build.
So I tried to fulfill the initial check for COMPONENT definition and then saw the generated CMake and it shows new conditions to fulfill.
Found some relevant info here
http://public.kitware.com/pipermail/cmake/2006-October/011377.html
So, in the test project where the COMPONENT building is enabled, for INSTALL command of cmake, Re-linking again occurs with another condition to fulfill this time. In this case install_public option is checked, which has been enabled in the project.
IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" MATCHES "^(install_public)$")
IF("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$")
FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib64" TYPE SHARED_LIBRARY
#install CMakeRelink.dir/<library_name>.so.<library_version> ......
Some info here as well in the docs
https://cmake.org/Wiki/CMake_2.8.0_Docs
Search for Re-linking in the above link.
So I tested another build by changin the CMAKELists.txt and setting CMAKE_INSTALL_RPATH to OFF in the application CMAKEList.
This also stopped the double linking.

How to build library or executable binary project with dependent library project with cmake

I have two cmake projects:
BiosPatcher\CommonBase\
BiosPatcher\Bios\
First one builds a library and has ./include folder with headers.
How to build second project library(or executable) which depends on first library ./include for compilation and libCommonBase.dll for execution(in case of executable file building).
I've included header files like that
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../CommonBase/include)
And it works.
And I link library like that:
target_link_libraries (Bios libCommonBase)
But I get error message:
c:\Users\Sakhno\workspace\BiosPatcher\Bios\build>make
[ 16%] Linking CXX shared library libBios.dll
C:/mingw-w64/mingw32/bin/../lib/gcc/i686-w64-mingw32/5.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -llibCommonBase
collect2.exe: error: ld returned 1 exit status
I think i need somehow specify folder to look for the library but i don't know how.
I was able to build Bios project which depends on CommonBase project target library by adding following lines.
set(COMMON_BASE_PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../CommonBase)
...
include_directories(${COMMON_BASE_PROJECT_DIR}/include)
...
target_link_libraries (Bios ${COMMON_BASE_PROJECT_DIR}/build/libCommonBase.dll)