CMake - 项目级宏添加到应用程序级别target_link_libraries

时间:2014-07-18 04:00:10

标签: c++ c macros cmake

我的项目中有很多库,还有很多个人应用程序。我的一些库有依赖库,其中一些是外部库,我想让应用程序CMakeList.txt文件更简单。我希望使用宏来简化。

以下是一个大大减少的测试用例。例如,在我的项目中,包括我的一个库也需要include_directories,link_directories和target_link_libraries for ImageMagick,pugixml,jsoncpp,liboauthcpp等...而且,这些第三方库中的一些需要编译器标志。我的项目版本的_LIB()宏将会更长......

问题:有没有办法让下面的_LIB()宏自动向调用宏的target_link_libraries添加内容?

我不知道该怎么做,因为target_link_libraries参数1是目标名称,每个应用程序都会更改。

〜/ codeTest /的CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(codeTest)

macro(_LIB)
  include_directories(~/codeTest/lib)
  link_directories(~/codeTest/lib)
endmacro()

add_subdirectory(lib)
add_subdirectory(app)

〜/ codeTest / LIB /的CMakeLists.txt

include_directories(~/codeTest/lib)
add_library(lib lib.cpp)

〜/ codeTest / LIB / lib.h

#ifndef __LIB__
#define __LIB__

namespace LIB {

unsigned long libFunc(unsigned long inValue);

}

#endif

〜/ codeTest / LIB / lib.cpp

#include <lib.h>

namespace LIB {

unsigned long libFunc(unsigned long inValue) {
   return inValue+1;
}

}

〜/ codeTest /应用程序/的CMakeLists.txt

_LIB()
add_executable(app app.cpp)
target_link_libraries(app lib)

〜/ codeTest /应用程序/ app.cpp

#include <lib.h>
using namespace LIB;

int main() {
   unsigned long x = 1;
   unsigned long y = libFunc(x);
}

3 个答案:

答案 0 :(得分:1)

随着项目复杂性的增长,您很快就会发现,在宏中收集的多个{link,include}_directories指令是不灵活的解决方案,应该明确指定它们。

我建议您考虑模块的概念(/usr/share/cmake/Modules/):对于每个外部依赖项,使用可以在cmake modules目录中找到的Find*.cmake文件(参见上文)或包装的一个(如果其作者编写了相应的模块)。或者你可以自己写。

这些模块通常会定义一些变量(例如Boost_INCLUDE_DIRSBoost_LIBRARY_DIRS),您只会在那些真正需要的子项目中使用这些变量。

因此,对于每个子项目,您指定include_... / link_...指令显式引用模块或其他子项目中定义的变量(对于内部依赖项)。

此外,cmake中的宏和函数对于用户来说实际上是非常不可预测的,期望它们在众所周知的编程语言(CJavaRuby中表现得像传统函数, ...)当你开始向他们添加参数时;阅读有关字符串和列表之间的变量缓存,作用域和转换的信息。

答案 1 :(得分:1)

答案 2 :(得分:0)

如果您可以通过这种方式将一些依赖项分组为1个目标,我建议您创建一个INTERFACE库。

例如,

add_library(ImageMagick ...)
#...etc gather all library targets however is conviennt

add_library(CoreDependencies INTERFACE)
target_link_libraries(CoreDependencies PUBLIC ImageMagick ...)

然后在您的应用中,您可以

target_link_libraries(MyApp PRIVATE CoreDependencies)

这会带来你需要的一切。如果你真的有这么多不同的用例,你可以创建几个库的子集。

值得注意的是,这种方法需要CMake 3。 https://cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#interface-libraries