cmake中target_link_libraries()使用问题动态库使用绝对路径没问题,但是使用相对路径就矬了?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cmake中target_link_libraries()使用问题动态库使用绝对路径没问题,但是使用相对路径就矬了?相关的知识,希望对你有一定的参考价值。

小弟最近在做一个小项目,需要用到cmake的target_link_libraries()来链接一个已经存在的动态库文件,就像这样 myproject/libs/libcurl.so(libcurl.so是直接下载的)。我把CmakeList.txt和qiproject.xml放在另一个文件夹下,就像这样 myproject/build/cmakelist.txt. 编辑cmakelist.txt的时候使用target_link_libraries()来链接动态库 ,在make的时候发现,只有使用动态库的绝对路径才行得通,换成相对路径就不行。在此问一下大家,可能是哪里出了问题?

使用相对路径的时候,你要让cmake能够搜索到找到你动态库,就像直接使用gcc/g++来链接的时候一样,要使用-L来指定第三方库所在路径。cmake可以使用  LINK_DIRECTORIES 命令来指定第三方库所在路径,比如,你的动态库在/home/myproject/libs这个路径下,则通过命令:LINK_DIRECTORIES(/home/myproject/libs),把该路径添加到第三方库搜索路径中,这样就可以使用相对路径了,使用TARGET_LINK_LIBRARIES的时候,只需要给出动态链接库的名字就行了。

拓展:

1、CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。

2、只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。

参考技术A 使用相对路径的时候,你要让cmake能够搜索到找到你动态库,就像直接使用gcc/g++来链接的时候一样,要使用-L来指定第三方库所在路径。
cmake可以使用 LINK_DIRECTORIES 命令来指定第三方库所在路径,比如,你的动态库在
/home/myproject/libs
这个路径下,则通过命令:
LINK_DIRECTORIES(/home/myproject/libs)
把该路径添加到第三方库搜索路径中,这样就可以使用相对路径了,使用TARGET_LINK_LIBRARIES的时候,只需要给出动态链接库的名字就行了,比如:
TARGET_LINK_LIBRARIES(MyApp -lcurl )
参考技术B 程序执行时的当前路径可能不是你存放list的路径

在CMake中如何使`TARGET_LINK_LIBRARIES'禁止第三方库代码发出警告?

在CMake中,您可以将TARGET_INCLUDE_DIRECTORIES()添加包含目录作为系统包含目录(即使用-isystem),以便不会弹出以第3方代码为根的警告:

TARGET_INCLUDE_DIRECTORIES(mytarget
    SYSTEM
        ${3rdPartyLib_INCLUDE_DIR})

我更喜欢使用TARGET_LINK_LIBRARIES,它也包括来自第三方库的目录。据我所知,TARGET_LINK_LIBRARIES不支持SYSTEM修饰符将这些目录添加为系统包含目录。

我弄错了吗?

有没有办法:

TARGET_LINK_LIBRARIES(mytarget
    ${3rdPartyLib_INCLUDE_DIR})

使用-isystem? (或任何其他方式来抑制来自3rdPartyLib的警告)。

答案

我建议你创建一个名为myproject_thirdparty.h的标题,如下所示:

#ifndef myproject_thirdparty_h
#define myproject_thirdparty_h

#include "myprojectMacros.h"

CLANG_PRAGMA_PUSH
CLANG_SUPPRESS_Wfloat_equal
CLANG_PRAGMA_POP

#endif

其中myprojectMacros.h将定义有用的宏,如CLANG_PRAGMA_PUSHCLANG_PRAGMA_POPGCC_PRAGMA_PUSHGCC_PRAGMA_POP,...

例如,这种宏,请参阅https://github.com/InsightSoftwareConsortium/ITK/blob/6b41fe1cbf7a71a6003d4824e02a69b41a508cda/Modules/Core/Common/include/itkMacro.h#L69-L136

然后,在项目代码中,每次要使用库时都会包含myproject_thirdparty_h,这将有效地关闭警告而不会影响项目的剩余部分。

另一答案

我有一个similar question,我用自定义函数解决了:

function(target_link_libraries_system target)
  set(libs ${ARGN})
  foreach(lib ${libs})
    get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES)
    target_include_directories(${target} SYSTEM PRIVATE ${lib_include_dirs})
    target_link_libraries(${target} ${lib})
  endforeach(lib)
endfunction(target_link_libraries_system)

我现在可以调用target_link_libraries_system(myapp lib::lib),并从目标的属性中读取include目录。

现在可以将其扩展为指定PUBLIC|PRIVATE|INTERFACE范围,但由于我在可执行文件上使用它,现在就足够了。

以上是关于cmake中target_link_libraries()使用问题动态库使用绝对路径没问题,但是使用相对路径就矬了?的主要内容,如果未能解决你的问题,请参考以下文章

cmake中target_link_libraries()使用问题动态库使用绝对路径没问题,但是使用相对路径就矬了?

添加不存在的目标时强制 CMake target_link_libraries 失败

C++学习(四一零)cmake的target_link_libraries

[cmake][转载]cmake中的link_directories, LINK_LIBRARIES, target_link_libraries的区别

调用 `target_link_libraries(target_name, library_name_without_postfix)` 时,`Cmake` 更喜欢链接到哪个库?

CMake命令target_link_libraries链接库的顺序