How to resolve target redefinition problem in diamond subproject dependency? - cmake

There are two libs libA and libB depending on libBase and including it into build process with
add_subdirectory(../libBase build/libBase)
Everything works when they are build separately. But when project prj wants to include everything into its build process:
add_subdirectory(../libA build/libA)
add_subdirectory(../libB build/libB)
Then cmake complaints about target redefinition:
add_library cannot create target "libBase" because another target with the same name already exists.
How to make such project (building all dependences in one step) correct? Is it achievable with add_subdirectory or sth else should be used to add dependencies?

Found it: include_guard() since cmake 3.10

Related

How do I remove duplicate cmake targets created by sub-cmake targets?

I have a cmake project that depends on several other cmake projects.
The cmake project that I am writing depends on 2 cmake projects that both create uninstall targets.
These duplicate targets cause errors:
add_custom_target cannot create target "uninstall" because another target
with the same name already exists. The existing target is a custom target
created in source directory
I do not need the uninstall target from either sub-cmake project. How do I exclude all targets with the name uninstall so that I don't get these errors? What other options are there available to solve this error? I am looking for a solution that is OS agnostic.
I sugguest you read the following documentation for Kitware : https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake .
The process is quite well explained.

How to build namespaced subprojects in cmake that find each other

I am trying to get a basic cmake project to work with 2 subprojects (each a library) where one depends on the other.
As such I have a self-contained project for lib1 and a self-contained project for lib2 (but that depends on lib1). Some lib2 authors could while others will not have access to lib1 source. If no access is desired, it seems that building and installing one after the other is the way to go. Is there a way to build them in one go using cmake? Currently, I am trying using an overall project, libs.
However, as the libraries are related I want to call them in a boost / poco like fashion. That is for lib2 I would like to write:
find_package(libs COMPONENTS lib1 REQUIRED)
target_link_libraries(lib2 PUBLIC libs::lib1)
I have created config files for both lib1 and lib2 and libs. However, I keep getting the same error
CMake Error at libs/lib2/CMakeLists.txt:67 (find_package):
By not providing "Findlibs.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "libs", but
CMake did not find one.
Could not find a package configuration file provided by "libs" with any of
the following names:
libsConfig.cmake
libs-config.cmake
Add the installation prefix of "libs" to CMAKE_PREFIX_PATH or set
"libs_DIR" to a directory containing one of the above files. If "libs"
provides a separate development package or SDK, be sure it has been
installed.
I don't understand where to put these files. It searches for them under prefix/ etc but at the time of building none of these libraries is yet installed. What is the proper place to put the -config.cmake files? I have put them all in
${CMAKE_BINARY_DIR}/libs
which seems similar to Poco, but the error remains. How can the libraries find each other?
// update:
From the comments I understand that lib1 first needs to be build in order to use find_package. Is there a way (in cmake) to
build lib1, install it, build lib2
or is this better to do using a bash / python / etc script?

Compiler option dependency for LLVM pass with CMake

I have a project that needs to be built with an LLVM pass. Here is the project structure:
proj/
instrumentation/
CMakeLists.txt
Instrumentation.cpp
[My project files]
CMakeLists.txt
instrumentation/CMakeLists.txt has a target to build the LLVM pass called MyPass.
I've added the following the CMakeLists.txt:
add_subdirectory(instrumentation)
add_compile_options(
"SHELL:-Xclang -load"
"SHELL:-Xclang $<TARGET_FILE:MyPass>")
Now I just need to add MyPass as a dependency for all the targets in my project. I was wondering if there was a way to force MyPass to build first so that when compiling other files, the LLVM pass would be present. Maybe there a way to add a target compile_options dependencies?
Note: I'd rather not add the dependency manually to every target because there many targets in the project.
My solution to this is to create another project to wrap the compiler executable and automatically build with the LLVM pass. Then rebuild the original project with the wrapped compiler.
AFL does this exact thing when building with a clang compiler.

Cmake sub_directory, libs dependencies needed to be build

I would like to add libraries to my current project.
The idea was to do something like this :
if(build_libs)
add_subdirectory(libs1)
add_subdirectory(libs2)
add_subdirectory(libs3)
add_subdirectory(libs4)
endif()
But, libs2 need generated files/lib from libs1 after the build. There is a cmake verification/find from libs2 finding libs1.
How can I enforce libs1 to be build before adding subdir libs2 ?
Same for libs3->2, libs4->3

Building third party library as part of CMake project

I have a top level CMakeLists.txt file which builds a library called Camellia and several executables in subdirectories which link with Camellia. I would like to add a third party library called XDMF as a dependency for Camellia under Camellia/TPL/Xdmf. Luckily, XDMF is already on a CMake build system, but when I use
add_subdirectory(TPL/Xdmf)
and then
add_library(Camellia ${LIB_SOURCES} ${HEADERS})
it builds Camellia in the build/TPL/Xdmf/bin directory rather than build as it does without the add_subdirectory(TPL/Xdmf). Why does adding a subdirectory change the build directory for Camellia, and how do I fix it? Also how do I make sure Camellia is linking with Xdmf once I get that figured out?
I think that ExternalProject_Add(...) is what you want.
Please see CMake: How to build external projects and include their targets which describes a similar issue.