Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用“cmake”中的“pkg config”的正确方法是什么?_Cmake_Pkg Config - Fatal编程技术网

使用“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库
    所做的不仅仅是改变