cmake: how to define target without linking (compilation only) - cmake

Is there any simple way to create a target where object files aren't linked?
I need additional target only for tests if everything compiles for ARM.
I don't want to create any executable (it would not link anyway), because my project will be finally a part of something much bigger, which has its own old stable make-based build system.
So I just need to compile sources. All tests are done with other, PC target compiled with gcc.

You can use an object library:
add_library(dummy OBJECT <source files>)
See also:
add_library => object-libraries
Official tutorial.

Related

Create dynamic library that implements multiple LLVM passes

I have a static library, which consists of several passes and is a part of opt. I want to make it dynamic and create one dylib file, so I could call opt, loading created .dylib and passing the desired LLVM pass. I'm using LLVM 7.0.
I created such dylib file with the help of Xcode (by adding to already existing dynamic library target additional passes), but I can't find any information, how to make it with the help of CMake.
At the moment, CMake file of the library looks like this:
add_llvm_library(MyLibrary
Pass1.cpp
Pass2.cpp
Pass3.cpp
...
PassN.cpp
DEPENDS
intrinsics_gen
)
What is expected is performing such command:
path/to/opt -load /path/to/MyLibrary.dylib -Pass3 ...
It isn't clear to me, whether it is possible to leave the structure of the library as is or if I have to modify it, by giving each pass a CMakeLists.txt file.
Tried this, faced up to the problem of multiple dependencies, which required to include several libraries. Linked libraries required required another libraries being linked. After a while, took a Hello CMakeLists.txt, which was provided in LLVM, as an example. Instead of add_llvm_library, wrote add_llvm_loadablemodule, making such CMakeLists.txt
if (WIN32 OR CYGWIN)
set(LLVM_LINK_COMPONENTS ...)
endif()
add_llvm_loadable_module(Mylib_Dylib
Pass1.cpp
Pass2.cpp
...
PassN.cpp
PLUGIN_TOOL
opt
)
It build Mylib.dylib, and it was possible to call a pass from it.
Since LLVM 8.0 the add_llvm_loadable_module CMake directive has been removed from LLVM. It has been replaced with using add_llvm_library with the MODULE argument.
if (WIN32 OR CYGWIN)
set(LLVM_LINK_COMPONENTS ...)
endif()
add_llvm_library(Mylib_Dylib MODULE
Pass1.cpp
Pass2.cpp
...
PassN.cpp
PLUGIN_TOOL
opt
)

How to create debug and release versions of libraries

I'm releasing a library which will be able to install headers and .a libraries for reuse. I would like users to be able to link either to release or debug builds of the lib if they so desire. I know that I can use DEBUG_POSTFIX like in Create a directory based on Release/Debug build type in CMake. My question is how do the users differentiate between the two? They would still put target_link_libraries(mylib), so I don't understand how a debug build would be chosen.
If MyLibTargets.cmake is correctly made they don't specify between the two. MyLibTargets.cmake should properly set IMPORTED_CONFIGURATIONS and IMPORTED_LOCATION_<CONFIG> for the target mylib. Then Debug maps to the Debug location and Release maps to the Release location. This is done automatically using the export command for multi-configuration generator. It's not really any different how a multi-configuration generator chooses Debug / Release libraries for any regular library target.

How can I "add_dependencies(..)" to an "UNKNOWN IMPORTED" library?

I want to use this way of getting googletest in my project. But there seems to be something wrong:
ninja: error: 'libsuper/test/googletest-prefix/src/googletest-build/googlemock/gtest/libgtest.a', needed by 'libdsuper/test/libsuper_test', missing and no known rule to make it
As I understand the error, there is no gtest library available when ninja tries to build the test-executable. As a consequence, I added a dependency just after the test-target:
add_executable(${PROJECT_NAME}_test ${SOURCES})
add_dependencies(${PROJECT_NAME}_test ${GTEST_LIBRARY})
But this has no effect. It seams like it's silently ignored. I guess this is because IMPORTED is meant for system libraries that need not to be compiled and are thus available from the start. In my case, this is however not true. The googletest libraries are only available after they have been compiled by the ExternalProject_Add.
Is this also linked to ninja? The site linked above does not mention problems - and I could imagine that's because googletest and libSomeOtherThingThatUsesGTest are build in sequence, as make does.
How can I instruct cmake to wait until the gtest library is truly available?
There is a little sense to be depended on IMPORTED library target - there is no actions bonded with such target, so you are actually depends on nothing.
Instead, you should depend on a target, which creates the library. In case of External Project, this is a target created for such project (the first argument to the ExternalProject_Add function's call).
In case of normal (non-IMPORTED) library target situation is quite different: actions for create such library are bonded with the target itself, so being dependent from the library target means that library should be built before the dependee. But such dependence is rarely used: instead, one links with the library target, which by itself implies the dependency from the actions, bonded with that target.
for googletest you should use:
add_executable(${PROJECT_NAME}_test ${SOURCES})
target_link_directories(${PROJECT_NAME}_test gtest)
Dependency will be automatically managed.
Also the imported target gtest already depends on googletest ExternalProject_Add according to this
I guess the errors come from the fact that the path for the imported target file location aka ${binary_dir}/googlemock/gtest/${CMAKE_FIND_LIBRARY_PREFIXES}gtest.a is wrong IMHO.

Compile gtest from source with catkin

I am trying to compile gtest from source (instead of using the existing installed version). I am working on a catkin based cmake project.
I have added the sourcecode from https://github.com/google/googletest to my workspace and included the folder with add_subdirectory.
However, I get a nameclash with the existing gtest:
CMake Error at src/test_env/GTest/googletest/cmake/internal_utils.cmake:151 (add_library):
add_library cannot create target "gtest" because another target with the
same name already exists. The existing target is a shared library created
in source directory "/usr/src/gtest". See documentation for policy CMP0002
for more details.
From other posts, and the googletest instructions itself (https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project) I understand that this should be no problem.
I think the problem might lie in how catkin handles gtest. And, admittedly, normally I could just use the installed version. But I want to make sure, that everyone uses the same (bundled) version of gtest.
Any suggestions and hints are welcomed.
Okay, so the error message is actually quite clear. A cmake "target" is "something that will be produced by the build", be it a library, or an executable, or something else. So, the problem is that you are trying to add a target named "gtest", and catkin already does the same thing. Both would produce the library "libgtest.so", and of course there can only be one of those in the same folder. You could rename "your" gtest by changing the target name in googletest/CMakelists.txt, but I would strongly advise you to not do that.
In my opinion, gtest shouldn't even be a shared library at all, especially if you are using different build flags for different projects in your repository. There is an alternative, and that is basically only including the gtest source code in a folder, and then including the header files and source files in your unittests main.cpp. googletest already comes with helpers for that, that is src/gtest-main.cc.
This is how I would structure it:
Add the gtest version you want as submodule to git (in case you use git). This way, you have a specified version for all projects in your repo, and can update it in a different branch. I will call that folder "GTEST_DIR".
Write your unittests in .cpp files, that #include <gtest/gtest.h>, one per hpp you want to test, and #include both the hpp and the cpp in your test.cpp. This enforces the separation of your tests from other classes and makes it very easy to switch out dependent classes with mocks or fake objects. You will not need a main() function, as that one is already in gtest-main.cc.
Write a cmake macro like this:
macro(add_gtest NAME FILES)
add_executable(my_gtest_$NAME
$FILES
GTEST_DIR/src/gtest.cc
GTEST_DIR/src/gtest-death-test.cc
GTEST_DIR/src/gtest-filepath.cc
GTEST_DIR/src/gtest-port.cc
GTEST_DIR/src/gtest-printers.cc
GTEST_DIR/src/gtest-test-part.cc
GTEST_DIR/src/gtest-typed-test.cc
GTEST_DIR/src/gtest-main.cc
)
target_include_directories(my_gtest_$NAME GTEST_DIR/include)
endmacro()
Of course, you can make this more complicated or less complicated, but that is the gist. Of course, compile times will be longer this way over using gtest as a shared library, but it actually makes sure your units get tested in isolation, which is very valueable in my opinion. Also, you can use ccache to greatly improve compile times in this scenario, because the gtest object files never change. Also, this will make sure gtest is compiled with exactly the flags you want it to. You could for example create 2 separate unit tests for the same class, one with exceptions enabled and one without.

CLion and CMake: only building a library without an executable?

How to only build a static library with clion without having an executable?
How does the CMakeLists.txt look like? (without add_executable)
Update: If I don't add executable to Clion, I have an
error, that an executable is required.
Here my CMakeLists.txt.
This is an old question. But I'll add the answer to your question as a help for other people. You need to replace your add_executable with add_library
add_library(target_name source_files)
Short answer: compile the library target and run any custom command as a placeholder to avoid the warning.
Long answer:
CLion lets you either build the whole project and run executables/configurations.
When running executables, you can choose a target to compile and the executable to run after compiling the target. For executable targets, they are usually the same thing. You compile the executable target and then run it.
It seems like this is not really designed for libraries, but there is a workaround. You usually set the target to be the library and the executable to be any executable that depends on this library. However, this is usually not very useful because if you wanted to run this executable you could just set this executable to be the target and the library would be built anyway.
So people probably want to just build the library (to check if everything is OK, etc) without compiling or running any extra executable targets. In this case, the workaround is to choose a custom executable to run after building the library, and the error message is gone.
You have nothing useful you need to run after building the library, just choose any cheap command as a placeholder. Something like "pwd" or "ls".