cmake

cmake object library build with external aditional header file


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?


Solution

  • 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.