使用“cmake”中的“pkg config”的正确方法是什么?
在网上,我看到了很多这样的代码:使用“cmake”中的“pkg config”的正确方法是什么?,cmake,pkg-config,Cmake,Pkg Config,在网上,我看到了很多这样的代码: include(FindPkgConfig) pkg_search_module(SDL2 REQUIRED sdl2) target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS} target_link_libraries(app ${SDL2_LIBRARIES}) 但是,这样做似乎是错误的,因为它只使用include目录和库,而忽略了pkg config可能返回的定义、库路径和其他
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS}
target_link_libraries(app ${SDL2_LIBRARIES})
但是,这样做似乎是错误的,因为它只使用include目录和库,而忽略了pkg config
可能返回的定义、库路径和其他标志
正确的方法是什么,以确保编译的应用程序使用pkg config
返回的所有编译和链接标志?有没有一个命令可以完成这一点,例如target\u use(app SDL2)
参考:
没有像target\u use
这样的命令。但我知道有几个项目编写了这样的命令供内部使用。但是每个项目都希望传递额外的标志或定义,因此在一般的CMake中使用它是没有意义的。不拥有它的另一个原因是像模板一样的C++模板库,没有库,但你只有一堆包含文件。
所描述的方法通常是正确的。对于某些库可能会有所不同,然后您必须添加\u LDFLAGS
或\u CFLAGS
。没有使用目标的另一个原因是
。如果它不适合您,请询问一个关于SDL2或任何您想要使用的库的新问题
首先,电话:
include(FindPkgConfig)
应替换为:
find_package(PkgConfig)
find_package()
调用更为灵活,并允许诸如REQUIRED
之类的选项,这些选项可以自动执行需要手动使用include()
执行的操作
其次,应尽可能避免手动调用pkg config
。CMake附带了一组丰富的包定义,可以在Linux中的/usr/share/CMake-3.0/Modules/Find*CMake
下找到。这些为用户提供了比原始调用pkg\u search\u module()
更多的选项和选择
至于前面提到的假设的target_use()
命令,CMake已经以一种带有公共|私有|接口的方式内置了该命令。像target\u include\u directories(mytarget PUBLIC…
这样的调用将导致在使用mytarget
的每个目标中自动使用include目录,例如target\u link\u库(myapp mytarget)
。但是,此机制似乎仅适用于在CMakeLists.txt
文件中创建的库,不适用于使用pkg\u search\u module()
获取的库。调用add\u 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\u CFLAGS\u OTHER
包含成功编译所需的定义和其他标志。但是,SDL2\u LIBRARY\u DIRS
和SDL2\u LDFLAGS\u OTHER
标记仍然被忽略,不知道这会成为问题的频率
此处有更多文档如果您也希望从库中添加定义,请参阅add_definitions
说明。可以找到文档,以及添加编译器标志的更多方法
以下代码段使用此指令将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})
很少有人只需要与SDL2链接。当前流行的答案是使用pkg\u search\u module()
,它检查给定的模块并使用第一个工作模块
更可能的情况是,您希望链接到SDL2和SDL2_混音器以及SDL2_TTF等pkg\u check\u 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 street creds,我只会对Grumbel的自我回答发表评论。大多数可用回答无法配置pkg config
库的标题。在冥想之后,我想出了一个解决方案,同时也提供了:
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>)
include(FindPkgConfig)
如果(未找到包装配置)
消息(致命错误“未找到pkg配置!”)
endif()
包装检查模块(需要导入的目标)
目标链接库(PkgConfig:)
(相应地,将您的目标替换为
,并将任何库替换为
。)
IMPORTED_TARGET
选项似乎很关键,使所有内容都可以在PkgConfig::
命名空间下使用。这是所有需要的,也是所有应该需要的。如果您以非常正常的方式使用cmake和pkg配置,那么这个解决方案是有效的
但是,如果某个开发目录(例如/home/me/hack/lib)中存在一个库,那么使用此处看到的其他方法无法配置链接器路径。在典型安装位置下找不到的库将导致链接器错误,如/usr/bin/ld:not find-lmy-hacking-library-1.0
。此解决方案修复了该情况下的链接器错误
另一个问题可能是pkg配置文件未安装在正常位置,需要在cmake运行时使用pkg_config_PATH环境变量添加项目的pkg配置路径(请参阅其他有关此问题的堆栈溢出问题)。假设您设置了正确的pkg配置路径,此解决方案也解决了该问题
解决方案归结为一个工作的CMakeLists.txt的最终版本:
cmake_minimum_required(VERSION 3.14)
project(ya-project C)
# the `pkg_check_modules` function is created with this call
find_package(PkgConfig REQUIRED)
# these calls create special `PkgConfig::<MODULE>` variables
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 PUBLIC
PkgConfig::MY_PKG
PkgConfig::YOUR_PKG)
cmake_最低要求(3.14版)
项目(ya项目C)
#“pkg_check_modules”函数是通过此调用创建的
查找_包(需要PkgConfig)
#这些调用创建特殊的`PkgConfig::`变量
包装检查模块(我的包装需要导入任何包装)
包装检查模块(您的包装需要导入的包装)
添加_可执行文件(程序名file.c ya.c)
目标链接库(程序名称公共)
PkgConfig::MY_PKG
PkgConfig::您的(PKG)
请注意,target\u link\u库
所做的不仅仅是改变