I develop a project which consisting of several shared libraries and build it with CMake.
Each library is built via add_subdirectory().
What is the best way to add all the API headers of the fist library to the CMakeLists.txt of the second?
Encode the include directories in the target itself:
http://www.cmake.org/cmake/help/git-master/manual/cmake-buildsystem.7.html#include-directories-and-usage-requirements
That doc is new, but the target_include_directories command exists since CMake 2.8.11. Use it with the INTERFACE or PUBLIC option.
To make an answer of steveire complete:
for the library which exports API we should write
target_include_directories("target_with_api" INTERFACE "path_to_api_includes")
and for the library which uses this API we write
target_include_directories("api_client_target_name" PRIVATE
$<TARGET_PROPERTY:"target_with_api",INTERFACE_INCLUDE_DIRECTORIES>)
where $<TARGET_PROPERTY:"target_with_api",INTERFACE_INCLUDE_DIRECTORIES>) returns us target property assigned to the library with API
Related
I have legacy c++ code that I'm trying to re-engineer.
I want to take some part of code out of the project as a ".so" shared library and load them dynamically by "dlopen".
I have written a dynamic loading mechanism which can load new modules dynamically at runtime.
Now I want to decouple existing modules from main project.
For instance I have extracted module "X" from the main project and created shared library which can be loaded later, but some part of the main project are using module X's classes directly and I can't change them yet.
I can compile the project by using module X's header files, but linker throw out "undefined reference" error.
How can I tell c++ linker that these classes will be added later by dlopen mechanism at runtime?
note: I can link and run project by copying created ".so" file of module X in "/lib" folder and use it when linking by "-lX" flag, but if I delete this file form the /lib folder the project fails on startup.
I know if you use X's classes directly you have to link X.so to your program. But if you link X.so you can use dlopen in runtime.
What you need is called an import library. They contain small wrappers for all necessary functions and thus satisfy all static linker dependencies. At runtime these wrappers will load dynamic library if it's not yet loaded and forward execution to real implementation inside library.
Import libraries is a standard feature of Windows DLLs but they are not available out-of-the-box on Linux (or any POSIX system). You can implement wrappers by hand or use Implib.so to generate them automatically.
I'm using a compiled library that I made, libexp.a. (Was compiled with PIC so its good for this use case).
I want to use it statically in my shared library and I can do that via Mixing static libraries and shared libraries.
So now I'm trying to get that working with CMake, my libexp.a is in the root directory and I do:
find_library(EXP NAMES exp PATHS ${PROJECT_SOURCE_DIR} NO_DEFAULT_PATH)
Then using it in target_link_libraries via ${EXP}, but during link time I still get a linking error of couldn't find -lexp. What is the right way to get this done? Using over 3.6
I have a problem with cmake target_link_libraries.
I have 3 libs. The first is static compiled, the second one (shared lib) link to it and the third one is an executable which use the second lib.
My problem is that my first lib is automatically added to the third lib and leads into a "object already defined" problem.
Is it possible to hide away the first lib from the third one?
I use cmake 3.4.x
Compiler: msvc 2010 x64
Thanks in advance
Tonka
Your third "lib" isn't a library, but an application. You need to add this using add_executable, not add_library.
If your shared library links in a static library, and then you want to link an application to both the static library and that shared library, you get two copies of the static library. Never link static libraries you plan to use elsewhere into a shared library, for this reason. Either make the first shared as well (the name implies that's what you want, as it is exactly what you are describing), or a workaround for this design problem could be to not explicitly link the application to the static library.
I've solved it. I can link to a library private, so f.e.
target_link_libraries(MyLib2 PRIVATE MyLib1)
will hide MyLib1 from everybody linking to MyLib2
I have a library that needs to carry some constant data injected from the content of non-source files (in this case, OpenGL shader code). To achieve this, I'm using add_custom_command() to generate include files that I can then #include into my code to initialize const static variables.
This works perfectly with regular libraries (static or shared), but now I'd like to make my library header-only. The ability of C++ to let static methods return static data without running the risk of having that data duplicated in each translation unit ("magic statics") makes this possible.
The problem however is that CMake seems to assume that an INTERFACE library (which is the CMake feature that I'm using to create header-only libraries) does not need building - which, in this case, is wrong.
(I realize that there is no actual obligation for my library to be header-only. In this particular case, the reason I want this is that I would like the library, which is doing OpenGL, to remain independent of any specific binding library [such as GLEW or GLee or the newcomer glbinding]. By keeping my library header-only, I can leave that choice to the user - all he needs to do is #include the header of the binding library before mine.)
Does anyone see a way to have CMake trigger the header-generating custom commands, at the latest when the consumer project is being built?
EDIT: I just realized that I could have the "best of both worlds" as it were by keeping my library static but still keeping all my code except for the constant data in the header files. That way, there would still be no need to choose a specific OpenGL binding library.
However, there are still advantages to having a library be header-only - simplicity of use for one - so I'm leaving my question open.
EDIT #2: Here is the relevant part of my CMakeLists.txt file (I only stripped the library dependencies - all header-only - from the end):
set(SHADER_FILES "src/vertex.glsl" "src/fragment.glsl")
add_library(libGPCGUIGLRenderer INTERFACE)
target_sources(libGPCGUIGLRenderer INTERFACE ${SHADER_FILES})
target_include_directories(libGPCGUIGLRenderer BEFORE
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Embed shader files
source_group("Shader files" FILES ${SHADER_FILES})
set(GENERATED "${CMAKE_CURRENT_BINARY_DIR}/generated")
target_include_directories(libGPCGUIGLRenderer INTERFACE ${GENERATED})
# Find the GPC Bin2C utility
find_package(GPCBin2C REQUIRED)
# Add a custom target and a dependency for each shader file
foreach(shader ${SHADER_FILES})
get_filename_component(name "${shader}" NAME)
set(shader_header "${GENERATED}/${name}.h")
add_custom_command(
OUTPUT ${shader_header}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${shader}
COMMAND GPCBin2C --input=${CMAKE_CURRENT_SOURCE_DIR}/${shader} --output=${shader_header}
)
target_sources(libGPCGUIGLRenderer INTERFACE ${shader_header})
endforeach()
Creating a static library with headers as the only sources worked for me. It is, of course, only a work-around.
Creating a static library with only header files results in an empty library. Mine says !<arch> as the only content.
CMake will automatically get the dependencies correct across sub-directories.
Since all sources are headers, you need to tell CMake which linker language should be used.
Code:
set(OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated_include")
add_custom_command(
OUTPUT "${OUTDIR}/outfile.h"
# Replace the next two lines with a proper generating script.
COMMAND mkdir -p ${OUTDIR}
COMMAND touch ${OUTDIR}/outfile.h
)
# Note, I am only adding header files to the library.
add_library(generated-headers STATIC
"${OUTDIR}/outfile.h"
)
set_target_properties(generated-headers
PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(generated-headers PUBLIC ${OUTDIR})
Use in other directories like this:
# In any other directory of the same CMake project:
add_executable(main main.cpp)
target_link_libraries(main generated-headers)
Tested on CMake 3.2, 3.8 and 3.9. Using Ninja and Make generators.
You can use target_sources in CMake 3.1 to tell consumers to compile interface files:
add_library(source_only INTERFACE)
target_sources(source_only INTERFACE foo.cpp)
http://www.cmake.org/cmake/help/v3.1/command/target_sources.html
I ran into comparable problems when trying to use glad: https://github.com/Dav1dde/glad
It uses a custom CMake command to build a binding, which means the files you need to include in the project which uses glad do not exist, so that CMake does not build glad (which would create those files)...
I did not get to try it yet, but example 3 of the following link seems to be a good solution and I believe it may work in your case:
https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/
I use find_package to include external library into my CMake project. Because I wanted to add support for static linking, I set set(BUILD_SHARED_LIBS FALSE). However, I still get libraries like libglew32.dll.a which are just wrappers that make dynamic linking easier. Instead, I want CMake to find libglew32.a which exists in the same directory. This is the module to find GLEW I use.
You can always link to an exact library using the filename. Here are the flags you would use
-l:[filename]
For cmake
target_link_libraries(target :libglew32.a)
Doing this on linux will use all static libraries
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
if you are building external libraries, usually i just include them in my target
target_link_libraries(myprogram
${LIBROCKET_LIBS_DIRS}/libRocketCore.a
${LIBROCKET_LIBS_DIRS}/libRocketControls.a)