cmake函数用于使用具有多个目标的模块化库

时间:2017-06-26 16:12:00

标签: cmake

我开发了一些库,主要是一些第三方包的接口。在我的库中,有一些核心例程需要编译,还有一组可选的例程,如果在代码中使用它,需要编译。

让我举一些例子说明。

@RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST, headers = ("content-type=multipart/*"), produces = "application/json", consumes = "image/*")

这是我项目的一棵树。我的图书馆只是一个标题。我需要编写Library |---interfaces | |---first | | |---CMakeLists.txt | | |---... | |---second | |---CMakeLists.txt | |---... |---core_routines | |---CMakeLists.txt | |---... |---dependencies.cmake 函数,可以使用它来有效地在项目中添加所需的子模块。

目前我使用自己非常难看的解决方案。也就是说,您可以在下面看到我的cmake文件的样子

dependencies.cmake

现在,当我在某些代码中使用我的库时,相应的#first interface dependencies if(first) link_directories(...) include_directories(...) add_subdirectory(${SOME_PATH}/interfaces/first "${CMAKE_CURRENT_BINARY_DIR}/first") endif() #second interface dependencies if(second) ... endif() #core routines add_subdirectory(${SOME_PATH}/core_routines/ "${CMAKE_CURRENT_BINARY_DIR}/core_routines") #function for adding required libs to new target function(add_new_target new_target) target_link_libraries( ${new_target} core_lib ) if(first) target_link_libraries( ${new_target} first_lib ) endif() if(second) target_link_libraries( ... ) endif() endfunction(add_new_target) 文件看起来像

CMakeLists.txt

我使用这种方式编译示例,因为据我所知,在添加新的可执行文件之前需要指定set(first ON) set(second ON) include(dependencies.cmake) add_executable(main.exe main.cpp) add_new_target(main.exe) link_directories,然后在include_directories之后指定所需的库它。如果我错了,请纠正我。

我的问题是,在这种情况下是否有可能写出更好的东西?我需要保持我的代码的模块化结构,因为,首先,一些接口需要使用不能安装在用户PC上的库,其次,我的库的主要用途是在包含cmake文件的项目中。不同的目标,所以我需要一些功能,可以根据用户的要求指定所需的库和接口。

2 个答案:

答案 0 :(得分:0)

ilink_directories()不是现代方式。它们太宽泛了。默认情况下,现代CMake中的几乎所有内容都基于include_directories()

每个子目录目标应该已经使用target_*target_include_directories()使用" PUBLIC"或者" INTERFACE"传递依赖性,即携带成功包含和链接它们所需的东西。

如果这些图书馆是第三方并且尚未捆绑其传递依赖关系,那么您可以使用target_link_libraries()使用" INTERFACE_INCLUDE_DIRECTORIES" AND" INTERFACE_LINK_LIBRARIES"属性。

答案 1 :(得分:0)

提供客户端程序需要链接的所有库的列表。这就像内置的FindBoost模块一样,它接收组件列表,然后为每个组件准备变量,加上BOOST_LIBRARIES,它是所有组件的列表。

set(my_component_libraries core_lib)
if(first)
    list(APPEND my_component_libraries first_lib)
endif()
# etc.

set(my_component_libraries ${my_component_libraries} PARENT_SCOPE)

这样您就可以将实际链接留给用户了。

如果您将CMake接口编写为find_package兼容,您实际上可以将COMPONENTS接口用于find_package,就像Boost一样。