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

时间:2016-05-21 21:59:43

标签: linker cmake

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

vcs -LDFLAGS "<LINK_FLAGS>" <LINK_LIBRARIES> <OBJECTS>

链接可执行文件的规则存在于CMAKE_CXX_LINK_EXECUTABLE变量中,因此我尝试使用它:

set(CMAKE_CXX_LINK_EXECUTABLE "echo CXXFLAGS: <CMAKE_CXX_LINK_FLAGS>  LINK_FLAGS: <LINKER_FLAGS> LINK_LIBRARIES: <LINK_LIBRARIES> OBJECTS: <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_LIBRARIES

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

1 个答案:

答案 0 :(得分:3)

将我的评论转化为答案

问题

让我们来看看CMAKE_CXX_LINK_EXECUTABLE中定义的Linux / GNU / GCC / CXX特定链接:

<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> 
                     <OBJECTS> -o <TARGET> <LINK_LIBRARIES>

由于问题在于LINK_LIBRARIES扩展规则,让我们仔细研究一下(以您的示例为例)了解其内容在cmLocalGenerator::OutputLinkLibraries()中的生成方式:

LINK_LIBRARIES

但是您不希望这些链接器标记混合到LINK_LIBRARIES中,因为您的Synopsys VCS GCC包装器希望它们具有-LDFLAGS前缀/组。

你是对的“库和标志彼此不可分离。看起来生成LINK_LIBRARIES的函数是cmLocalGenerator::OutputLinkLibraries。不幸的是,它将所有标志和库放入单{{ {1}}“。

可能的解决方案

我看到五个选项(或它们的某种组合):

  1. 前缀/替换正常的gcc / ld标志及其VCS匹配
  2. 解析中间脚本中的链接器std::string选项
  3. 不要使用扩展规则,而是使用CMake变量/生成器表达式
  4. 定义您自己的链接器语言
  5. 首选动态链接库上的静态库
  6. 所以 - 在选项3的变体中 - 你需要知道为什么你在-Wl,中看到的链接器选项存在,以及如何在其他地方抑制然后重新生成它们。

    以下是我成功测试的一个示例:

    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 -rdynamic选项。

    可以跳过第一个,请参阅Linux-GNU.cmake

    -Wl,-rpath

    如果系统路径中有# 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") 个共享库,也可以跳过后者,例如, Wikipedia rpath

      

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

    <强>参考

相关问题