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

CMake - Project level macro add to application level target_link_libraries

本文关键字:link libraries target 添加 项目 应用程序      更新时间:2023-10-16

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

下面是一个简化的测试用例。例如,在我的项目中,包括我的一个库还需要包括ImageMagick、pugixml、jsoncpp、liboauthcpp等的include_directories、link_directories和target_link_libraries…而且,其中一些第三方库需要编译器标志。我的项目版本的_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;
}
}

~//app/CMakeLists.txt codeTest

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

~//app/app.cpp codeTest

#include <lib.h>
using namespace LIB;
int main() {
   unsigned long x = 1;
   unsigned long y = libFunc(x);
}

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

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

模块通常定义一些变量,(例如,Boost_INCLUDE_DIRS, Boost_LIBRARY_DIRS),你将只在那些子项目中使用,真正需要的。

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

此外,cmake中的宏和函数对于用户来说是非常不可预测的,当你开始向它们添加参数时,用户期望它们的行为像知名编程语言(C, Java, Ruby,…)中的传统函数一样;阅读变量缓存、作用域以及字符串和列表之间的转换。

考虑将使用需求编码到目标本身中,而不是使用宏。

应该是'modern cmake':

http://www.cmake.org/cmake/help/git-next/manual/cmake-buildsystem.7.html

http://www.kdab.com/modern-cmake-with-qt-and-boost/

http://www.steveire.com/WhatWhyHowCMake.pdf

http://www.cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html

我可能会建议创建一个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界面库