【问题标题】:CMake to produce -L<path> -l<lib> link flags for static librariesCMake 为静态库生成 -L<path> -l<lib> 链接标志
【发布时间】:2013-01-27 04:24:17
【问题描述】:

我正在使用 CMake 2.8 来构建基于 MQX OS 的应用程序(使用 CodeWarrior)。
CMake 项目基本上构建了一组静态库(比如说 LIB1 和 LIB2)。
然后我在最终的可执行 cmake 规则中引用这些库:

target_add_executable(X ${some_sources})
target_link_libraries(X LIB1 LIB2)

我的问题是一些符号在多个库中定义。
因此,像这样的链接命令:

mwldarm <args> -o <output> <objects> /path/to1/libLIB1.a /path/to2/libLIB2.a

会导致多重定义符号错误。 相反,我希望 CMake 生成如下链接命令:

mwldarm <args> -o <output> <objects> -L/path/to1 -L/path/to2 -lLIB -lLIB2

问题:如何从CMAKE中获取以下变量?

  • 库目录标志(例如: -L/path/to1 -L/path/to2)
  • 库链接标志(例如:-lLIB -lLIB2)

我已经阅读了有关 RPATH 的内容,但它似乎只涉及共享库。我对吗?

感谢您的提前。
我很感激。

【问题讨论】:

  • 尽管存在链接线问题,但拥有多个符号似乎并不是一件好事。您是否考虑过将 LIB1 和 LIB2 的公共部分重构为一个唯一的库,该库是两者的依赖项?
  • 这绝对是我的想法!我奖励你的答案,因为根据我的说法,它是正确的(我 méandres

标签: cmake static-libraries static-linking


【解决方案1】:

看来CMP0003 策略可能是您所需要的。

要使用它,请在 CMakeLists.txt 的开头附近添加以下行:

CMAKE_POLICY( SET CMP0003 OLD )

另一种可能性是直接设置依赖项和搜索路径,但这不是最干净的方式。假设你的库被称为liba.a 和libb.a,那么:

LINK_DIRECTORIES( ${paths_to_search_for} )
TARGET_ADD_EXECUTABLE(X ${some_sources} )
ADD_DEPENDENCIES(X LIB1 LIB2)
TARGET_LINK_LIBRARIES(X a b )

请注意,在这种情况下,a 和 b 不是 cmake 目标,因此需要一些机制来正确设置依赖项。

【讨论】:

  • 我在CMAKE文档中搜索过,发现和你一样。我在发布此消息之前对其进行了测试。但是,要么我没有正确使用它,要么它什么都不做,因为 cmake 生成的链接命令行是完全相同的,有和没有 CMP0003 策略(旧的或新的!)。
  • 我确认这无法完成我的工作,因为所有库都是由同一个 cmake 项目构建的。正如 CMAKE 文档在 CMP0003 策略描述中所说:当链接行上的所有项目都具有已知路径时,CMake 不会检查此策略,因此它无效。
  • 策略不是功能切换。 cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cd4fa896b 。请不要这样做,也请不要推荐其他人这样做。
【解决方案2】:

CMake 的部分设计是它与完整路径链接。为什么这是个问题?

使用策略切换行为不是正确的方法。

http://www.cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cd4fa896b

【讨论】:

    【解决方案3】:

    我想CMP0003是用来开启/关闭官方文档中描述的自动添加搜索路径的功能

    通过完整路径链接的库不再生成链接器搜索路径。

    而不是将路径名替换为-l。

    链接库时,如果库是已知的目标 CMake,则 CMake 始终将相关的 -L 和 -l 选项替换为库的路径名。这对于链接静态库可能不是问题。但是对于链接共享库的可执行文件来说,这可能是个问题。然后我找到了一个黑客方法,代码如下,解决了使用-L和`-l'而不是绝对路径链接一个线程库的问题。

    # Find out the link.txt      
    set(LINK_TXT "${CMAKE_BINARY_DIR}/${ToLinkLib}/CMakeFiles/${ToLinkLIb}.dir/link.txt")
    
    # Add the searching path into link command
    add_custom_command(TARGET ${YourTarget} PRE_BUILD
      COMMAND sed ARGS -ie "\"s;[[:blank:]]-l; -L${LIBRARY_OUTPUT_PATH} -l;\"" ${LINK_TXT}
      DEPENDS ${LINK_TXT}
      COMMENT "Hacking CMake: edit __link.txt__ to use -l instead of path to link internal library ...")
    
    # NOTE: Dont't missing the `-l'. 
    target_link_libraries(${YourTarget} -l${ToLinkLib})
    

    当然,这只是一种黑客行为,因此可能无法与所有版本的 CMake 一起正常工作。


    更新:为什么链接共享库可能是个问题?

    当我运行一个为 android 交叉编译的可执行文件,它链接一个由相同 CMake 脚本构建的共享库时,我遇到了链接失败的问题。在我使用上述黑客方法获取新版本后,我可以使用如下命令运行我的可执行文件

     $ LD_LIBRARY_PATH=. ./the_exe opts
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 2012-07-14
      相关资源
      最近更新 更多