【问题标题】:CMake - Project level macro add to application level target_link_librariesCMake - 项目级宏添加到应用程序级 target_link_libraries
【发布时间】:2014-09-09 02:52:49
【问题描述】:

我的项目中有很多库,还有很多单独的应用程序。我的一些库有依赖库,其中一些是外部库,我希望应用程序 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;
}

}

~/codeTest/app/CMakeLists.txt

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

~/codeTest/app/app.cpp

#include <lib.h>
using namespace LIB;

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

【问题讨论】:

    标签: c++ c macros cmake


    【解决方案1】:

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

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

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

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

    此外,cmake 中的宏和函数对于用户来说确实非常难以预测,他们希望它们的行为与知名编程语言(CJavaRuby、...)中的传统函数一样。开始向他们添加论据;阅读有关字符串和列表之间的变量缓存、范围和转换​​的信息。

    【讨论】:

      【解决方案2】:
      【解决方案3】:

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

      例如,

      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

      【讨论】:

        猜你喜欢
        • 2021-12-12
        • 1970-01-01
        • 2021-01-18
        • 2016-06-17
        • 2011-12-29
        • 2012-01-26
        • 2021-10-14
        • 2013-12-13
        • 1970-01-01
        相关资源
        最近更新 更多