Linker CMake自定义链接可执行命令,如何提取链接器选项?

Linker CMake自定义链接可执行命令,如何提取链接器选项?,linker,cmake,Linker,Cmake,我需要在我的CMake脚本中支持自定义可执行链接命令,即Synopsys VCS。VCS是GCC上的包装器,但它使用特殊语法传递LD选项: vcs -LDFLAGS "<LINK_FLAGS>" <LINK_LIBRARIES> <OBJECTS> 当我构建项目时,我得到了: CXXFLAGS: LINK_FLAGS: LINK_LIBRARIES: -rdynamic ../slib/libslib.a ../dlib/libdlib.so -Wl,-r

我需要在我的CMake脚本中支持自定义可执行链接命令,即Synopsys VCS。VCS是GCC上的包装器,但它使用特殊语法传递LD选项:

vcs -LDFLAGS "<LINK_FLAGS>" <LINK_LIBRARIES> <OBJECTS>
当我构建项目时,我得到了:

CXXFLAGS: 
LINK_FLAGS:
LINK_LIBRARIES: -rdynamic ../slib/libslib.a ../dlib/libdlib.so -Wl,-rpath,/home/ripopov/proj_cmake/build/dlib 
OBJECTS: CMakeFiles/sim.dir/sc_main.cpp.o
因此,所有链接器标志和库都位于
LINK\u库中

如何从
链接库
中提取链接器标志?

将我的评论转化为答案

问题 让我们看一看在中定义的Linux/GNU/GCC/CXX特定链接行:

这将给

CXXFLAGS: 
LINK_FLAGS: -Wl,-rpath,[... my binary path ...]/lib
LINK_LIBRARIES: libslib.a lib/libdlib.so 
OBJECTS: CMakeFiles/main.dir/main.cpp.o
主要问题是您是否真的需要
-rdynamic
-Wl,-rpath
选项

可以跳过第一个,请参见:

如果系统路径中有
.so
共享库,则也可以跳过后者,例如:

具体来说,它将共享库的路径编码到可执行文件(或另一个共享库)的头中。此RPATH标头值(在可执行和可链接格式标头标准中如此命名)可以覆盖或补充系统默认的动态链接搜索路径

参考资料

  • 目标属性,或者全局变量

链接标志
包含您可以使用目标属性定义的内容。您在
LINK\u LIBRARIES
中看到的其他内容来自
CMAKE\u SHARED\u LIBRARY\u LINK\u CXX\u FLAGS
CMAKE\u SHARED\u LIBRARY\u RUNTIME\u CXX\u FLAG
。所以我看到了三个选项:要么解析链接器
-Wl,
中间脚本中的选项,不要使用,但要创建变量/生成器表达式或定义。谢谢@Florian!中间脚本是一种选择,但我试图避免它。如果我回显CMAKE_SHARED_LIBRARY_RUNTIME_CXX_标志,我得到了“-Wl,-rpath”,那么rpath本身就不存在了。到目前为止,我无法在某些变量中获取rpath。基本上,CMAKE_SHARED_LIBRARY_RUNTIME_CXX_标志是用于将运行时路径传递给链接器的标志,但不是运行时路径本身。然后,您可以通过定义自己的链接器语言来尝试最后一个选项:
集(CMAKE_VCS_LINK_可执行文件“VCS-LDFLAGS\”)
。更改名为
main
的可执行目标的属性,例如:
set\u target\u properties(main properties LINKER\u LANGUAGE VCS)
谢谢@Florian,不幸的是
计算结果为空字符串。我尝试了
设置(CMAKE\u VCS\u LINK\u FLAGS${CMAKE\u CXX\u LINK\u FLAGS})
但没有效果。无论我做了什么尝试,我都无法将
-rdynamic-Wl,-rpath,/home/ripopov/proj_cmake/build/dlib
提取到某个cmake变量中。看起来额外的中间脚本是唯一的选择。谢谢你Florian。我决定使用中间脚本,因为在我的例子中,它解决了所有的问题。您的最新示例并没有解决最初的问题,但提供了一种解决方法:即将所有库放在某个预定义的目录中。不幸的是,这并不适用于所有情况:例如,如果您使用find_package()或import()导入一些每个构建的目标。@random欢迎您。我已经更新了我的答案,以提供更多关于您是否以及何时实际需要
-rdynamic
-Wl,-rpath
选项的详细信息。我认为第一个问题可以安全地删除,第二个问题是实际运行可执行文件的时间和方式。我承认我没有任何使用Synopsys VCS的经验,所以我可以稍微详细介绍一下您对链接器输出的实际操作吗?它是只在开发过程中使用还是同时生成发行版二进制文件/可执行文件?在我的使用场景中,将RPATH内置到可执行文件中非常方便,因此我不必一直处理LD_LIBRARY_PATH。我只在调试时使用它。在我的例子中,没有“释放二进制文件”,“释放”是一块带有晶体管的硅。@random只是两个想法:1。您可以切换到静态库进行开发(这就是我所做的;分发/安装也更容易)。2.您可以检查
-LDFLAGS“…”
是否可以在
VCS
命令行上多次提供,以及引号是否是必需的,因为这样您就不需要解析命令行,只需将
CMAKE\u共享库\u运行时\u CXX\u标志本身更改为
-LDFLAGS-Wl,-rpath,
。谢谢Florian。1) 在我的情况下并不总是一种选择2)是的,这是有道理的。我尝试了
CMAKE\u共享库\u运行时\u CXX\u标志
,并得出结论,它应该应用于最顶级的CMakeLists.txt。
<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> 
                     <OBJECTS> -o <TARGET> <LINK_LIBRARIES>
cmake_minimum_required(VERSION 2.8)

project(LinkerVCS CXX)

file(WRITE foo.h   "void foo();\n")
file(WRITE foo.cpp "void foo() {};\n")
file(WRITE bar.h   "void bar();\n")
file(WRITE bar.cpp "void bar() {};\n")

file(
    WRITE main.cpp 
    "#include \"foo.h\"\n"
    "#include \"bar.h\"\n"
    "int main() { foo(); bar(); return 0; }\n"
)

set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 0)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 0)

# remove the '-rdynamic'
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
# define my own search path for shared libraries
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}${CMAKE_BINARY_DIR}/lib")

set(CMAKE_CXX_LINK_EXECUTABLE "echo CXXFLAGS: ${CMAKE_CXX_FLAGS} LINK_FLAGS: <LINK_FLAGS> LINK_LIBRARIES: <LINK_LIBRARIES> OBJECTS: <OBJECTS>")

add_library(slib STATIC foo.cpp)
add_library(dlib SHARED bar.cpp)

add_executable(main main.cpp)
target_link_libraries(main slib dlib)
# remove the CMake generated '-Wl,-rpath'
set_target_properties(main PROPERTIES SKIP_BUILD_RPATH 1)
CXXFLAGS: 
LINK_FLAGS: -Wl,-rpath,[... my binary path ...]/lib
LINK_LIBRARIES: libslib.a lib/libdlib.so 
OBJECTS: CMakeFiles/main.dir/main.cpp.o
# We pass this for historical reasons.  Projects may have
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")