在网上浏览我看到了很多这样的代码:
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS}
target_link_libraries(app ${SDL2_LIBRARIES})
然而,这似乎是错误的方式,因为它只使用包含目录和库,但忽略了定义,库路径和pkg-config
可能返回的其他标志。
执行此操作的正确方法是什么,并确保编译的pkg-config
使用app
返回的所有编译和链接标志?是否有一个命令可以完成此任务,例如target_use(app SDL2)
?
REF:
答案 0 :(得分:35)
首先是电话:
include(FindPkgConfig)
应替换为:
find_package(PkgConfig)
find_package()
来电变得更加灵活,并且允许REQUIRED
这样的选项自动执行,而这些操作必须通过include()
手动执行。
其次,应尽可能避免手动调用pkg-config
。 CMake附带了一组丰富的包定义,可在/usr/share/cmake-3.0/Modules/Find*cmake
下的Linux中找到。与原始调用pkg_search_module()
相比,这些为用户提供了更多选项和选择。
对于上面提到的假设target_use()
命令,CMake已经以PUBLIC | PRIVATE | INTERFACE的方式内置了。像target_include_directories(mytarget PUBLIC ...)
这样的调用会导致包含目录在使用mytarget
的每个目标中自动使用,例如target_link_libraries(myapp mytarget)
。但是,此机制似乎仅适用于在CMakeLists.txt
文件中创建的库,而不适用于使用pkg_search_module()
获取的库。电话add_library(bar SHARED IMPORTED)
可能会用于此,但我还没有调查过。
至于主要问题,这在大多数情况下适用:
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
...
target_link_libraries(testapp ${SDL2_LIBRARIES})
target_include_directories(testapp PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(testapp PUBLIC ${SDL2_CFLAGS_OTHER})
SDL2_CFLAGS_OTHER
包含成功编译所需的定义和其他标志。然而,标记SDL2_LIBRARY_DIRS
和SDL2_LDFLAGS_OTHER
仍被忽略,不知道这会成为问题的频率。
此处有更多文档http://www.cmake.org/cmake/help/v3.0/module/FindPkgConfig.html
答案 1 :(得分:6)
很少人只需要与SDL2链接。目前流行的答案使用pkg_search_module()
来检查给定的模块并使用第一个工作模块。
您更有可能想要与SDL2和SDL2_Mixer以及SDL2_TTF等链接... pkg_check_modules()
检查所有给定的模块。
# sdl2 linking variables
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2 SDL2_ttf SDL2_mixer SDL2_image)
# your app
file(GLOB SRC "my_app/*.c")
add_executable(my_app ${SRC})
target_link_libraries(my_app ${SDL2_LIBRARIES})
target_include_directories(my_app PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(my_app PUBLIC ${SDL2_CFLAGS_OTHER})
免责声明:如果我有足够的街头信誉和stackoverflow,我会简单地评论一下Grumbel的自我回答。
答案 2 :(得分:1)
大多数可用答案无法配置pkg-config
库的标头。在对Documentation for FindPkgConfig进行冥想之后,我想出了一个解决方案,该解决方案还提供了以下解决方案:
include(FindPkgConfig)
if(NOT PKG_CONFIG_FOUND)
message(FATAL_ERROR "pkg-config not found!" )
endif()
pkg_check_modules(<some-lib> REQUIRED IMPORTED_TARGET <some-lib>)
target_link_libraries(<my-target> PkgConfig::<some-lib>)
(用您的目标代替<my-target>
,并用任何库代替<some-lib>
。)
IMPORTED_TARGET
选项似乎很关键,可以使所有内容在PkgConfig::
命名空间下可用。这是所有需要的,也是所有 都需要的。
答案 3 :(得分:1)
到目前为止,已接受的答案无法为在典型安装位置(例如/ usr / lib)下找不到的那些共享库配置链接器路径。导致的链接器错误为/usr/bin/ld: cannot find -llibrary-1.0
。就我而言,也没有安装pkg-config文件,并且使用PKG_CONFIG_PATH环境变量添加了项目的pkg-config路径。这是正常工作的CMakeLists.txt的简化版本:
cmake_minimum_required(VERSION 3.14)
project(ya-project C)
find_package(PkgConfig REQUIRED)
pkg_check_modules(MY_PKG REQUIRED IMPORTED_TARGET any-package)
pkg_check_modules(YOUR_PKG REQUIRED IMPORTED_TARGET ya-package)
add_executable(program-name file.c ya.c)
target_link_libraries(program-name
PkgConfig::MY_PKG
PkgConfig::YOUR_PKG)
答案 4 :(得分:0)
没有target_use
这样的命令。但我知道有几个项目已经为内部使用编写了这样的命令。但是每个项目都希望传递额外的标志或定义,因此将它放在一般的CMake中是没有意义的。没有它的另一个原因是像Eigen这样的C ++模板化库,没有库,但你只有一堆包含文件。
所描述的方式通常是正确的。某些库可能会有所不同,因此您必须添加_LDFLAGS
或_CFLAGS
。没有target_use
的另一个原因。如果它不适合您,请询问有关SDL2或您想要使用的任何库的新问题。
答案 5 :(得分:-2)
如果您还希望从库中添加定义,那么add_definitions
指令就在那里。可以找到文档here,以及添加编译器标志的更多方法。
以下代码段使用此指令将GTKGL添加到项目中:
pkg_check_modules(GTKGL REQUIRED gtkglext-1.0)
include_directories(${GTKGL_INCLUDE_DIRS})
link_directories(${GTKGL_LIBRARY_DIRS})
add_definitions(${GTKGL_CFLAGS_OTHER})
set(LIBS ${LIBS} ${GTKGL_LIBRARIES})
target_link_libraries([insert name of program] ${LIBS})