CMakeLists.txt for third-party C files within C++

2019-07-02 19:56发布

问题:

My C++ project doggo has a doggo/external/ directory for third-party code. Currently it contains gtest and a CMakeLists.txt:

# Google gtest for unit testing.
add_subdirectory(gtest)
message("gtest include dir: ${gtest_SOURCE_DIR}")
include_directories(${gtest_SOURCE_DIR})

My top-level doggo/CMakeLists.txt contains the line add_subdirectory(external) to find and build the third-party libraries. Everything works like a charm -- I can include gtest with #include <gtest/gtest.h>. Now I'd like to add the randomkit C library to doggo/external/, as is done here: randomkit from numpy.

How can I get randomkit to build in my doggo/external/ dir? What should the doggo/external/CMakeLists.txt look like?

I should then be able to include the C headers for use in my x.cpp files by including the headers inside an extern "C" { ... } block (details here).

UPDATE: How do I install randomkit here? I've included a CMakeLists.txt entry like that above but for randomkit, and the directory looks like,

external
├── CMakeLists.txt
├── gtest
│   └── ...
└── randomkit
    ├── CMakeLists.txt
    ├── distributions.c
    ├── distributions.h
    ├── randomkit.c
    └── randomkit.h

and the randomkit/CMakeLists.txt:

project(randomkit)
file(GLOB SOURCES "*.c")
add_library(randomkit SHARED ${SOURCES})
INSTALL(
    DIRECTORY ${CMAKE_SOURCE_DIR}/
    DESTINATION "/usr/local/"
    #DESTINATION ""
    FILES_MATCHING PATTERN "*.h*")

(second DESTINATION commented out to show I tried that as well)

Yet when I run the build steps for my top-level project doggo I get an error trying to #include <randomkit/distributions.h>:

doggo/src/random_fooz.cpp:10:37: fatal error: randomkit/distributions.h: No such file or directory

UPDATE 2: doggo/CMakeLists.txt:

project(doggo)
# Find and build third-party libraries
add_subdirectory(external)
# Add source dirs to the search path so cmake can find headers
include_directories(${CMAKE_SOURCE_DIR}/include/)
# Collect source files and build
file(GLOB_RECURSE doggo_srcs ${CMAKE_SOURCE_DIR}/src/*.cpp)
add_library(doggo ${doggo_srcs})
# Setup executables
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin/)
add_subdirectory(exec)
# Tests
add_subdirectory(test)

回答1:

In the randomkit/CMakeLists.txt write:

project(randomkit)
file(GLOB SOURCES "*.c")
add_library(randomkit SHARED ${SOURCES})
target_include_directories(randomkit PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
INSTALL(
    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
    DESTINATION "include"            # this a the subdirectory with ${CMAKE_INSTALL_PREFIX}
    FILES_MATCHING PATTERN "*.h*")

In the main CMakeLists.txt, you do:

add_library(doggo ${doggo_srcs})
target_link_libraries(doggo PUBLIC randomkit)
target_include_directories(doggo PUBLIC ${CMAKE_SOURCE_DIR}/include/)

Don’t use include_directories.

Now, because the randomkit target has the PUBLIC property with the right include directories, those include directories will be automatically used when building the doggo library. And again, because the doggo library has include directories and libraries in its public interface, executables that you link to doggo will automatically be linked to these libraries, and find their include files.

Note that the INSTALL command in randomkit/CMakeLists.txt is only executed when you actually run the install target. When building, the include files must be found in the source tree.



标签: c++ c cmake