I would like to build an test executable in an cmake object libray mylib. This is only a simple test setup. The lib includes an src a.c
and a header a.h
. The problem is that the cmake object lib also needs an additional header for config a_config.h
. I did not find a solution to build a executable with the additional header an the object lib.
So I have pushed the example to github: https://github.com/mgiaco/mylib/blob/master/verify/CMakeLists.txt
Folder structure:
mylib
build
include
a.h
src
a.c
verify
source
a_config.h
mylib_test.c
CMakeList.txt // one
CMakeList.txt // two
CMakeList.txt (one)
list (APPEND verify_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/source)
message("mylib")
list (APPEND verify_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/source/mylib_test.c)
add_executable(verify_exe ${verify_SOURCE} ${verify_HEADER})
target_include_directories(verify_exe PUBLIC ${verify_HEADER})
target_link_libraries(verify_exe $<TARGET_OBJECTS:mylib_obj>)
CMakeList.txt (two)
cmake_minimum_required(VERSION 3.13)
message("verify")
project(mylib VERSION 1.0.0)
add_library(${PROJECT_NAME}_obj OBJECT ${CMAKE_CURRENT_SOURCE_DIR}/src/a.c)
target_include_directories(${PROJECT_NAME}_obj
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
add_subdirectory(verify)
Run and Error
C:\workdir\io\mylib\build (master)
λ cmake.exe -DCMAKE_SH="CMAKE_SH-NOTFOUND" -G"MinGW Makefiles" ..
verify
mylib
-- Configuring done
-- Generating done
-- Build files have been written to: C:/workdir/io/mylib/build
C:\workdir\io\mylib\build (master)
λ mingw32-make.exe
[ 33%] Building C object CMakeFiles/mylib_obj.dir/src/a.c.obj
C:\workdir\io\mylib\src\a.c:10:10: fatal error: a_config.h: No such file or directory
#include "a_config.h"
^~~~~~~~~~~~
compilation terminated.
mingw32-make[2]: *** [CMakeFiles\mylib_obj.dir\build.make:63: CMakeFiles/mylib_obj.dir/src/a.c.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:95: CMakeFiles/mylib_obj.dir/all] Error 2
mingw32-make: *** [Makefile:83: all] Error 2
What am I doing wrong here?
You do not want to build your sources, then creating a library is not a solution - a library is a collection of compiled sources. Typically I do a function that allows users to easily add the library:
# mylib/CMakeList.txt
# 'a' as in the library named 'a', not as an article but as a name
set(_add_a_library_source_dir ${CMAKE_CURRENT_LIST_DIR})
function(add_a_library name)
add_library(${name} ${ARGN} ${_add_a_library_source_dir}/src/a.c)
taget_include_directories(${name}
PUBLIC
$<BUILD_INTERFACE:${_add_a_library_source_dir}/include>
)
endfunction()
Then users of the library then can do:
# mylib/verify/CMakeLists.txt
add_a_library(verify_a_library OBJECT)
# add path to a_config.h to a library
target_include_directories(verify_a_library ${CMAKE_CURRENT_SOURCE_DIR})
add_executable(verify_exe ${sources})
target_link_libraries(verify_exe verify_a_library)
even with multiple versions they need.
Notes: if you have cmake new enough, there's no need to use $<TARGET_OBJECTS
, just link with the object library.