CMake:使用自定义链接器

Bre*_*ght 32 linker gcc cmake

我想用qmake设置自定义工具链.我已经设置了编译器,但我不知道如何设置链接器.报告此错误是因为cmake尝试使用编译器链接:

The C compiler "xgcc.exe" is not able to compile a simple test program.
Run Code Online (Sandbox Code Playgroud)

这里有一个我的工具链文件的片段

# specify the cross compiler
INCLUDE(CMakeForceCompiler)
SET(CMAKE_C_COMPILER   xgcc.exe)
SET(CMAKE_CXX_COMPILER xgcc.exe)
#CMAKE_FORCE_C_COMPILER(xgcc.exe GNU)
#CMAKE_FORCE_CXX_COMPILER(xgcc.exe GNU)
Run Code Online (Sandbox Code Playgroud)

我试图强制编译器,但链接器问题将无法解决.

mab*_*ham 23

链接命令行在Modules/CMake {C,CXX,Fortran} Information.cmake中设置,默认使用编译器,而不是CMAKE_LINKER(参见源代码).这可以通过替换构建链接命令行的规则来更改,该命令行位于变量CMAKE_CXX_LINK_EXECUTABLE(和朋友)中.注意,变量不指示链接器可执行文件的路径; 它说如何链接可执行文件!

一种方法是将该规则设置为使用链接器,例如

cmake -DCMAKE_LINKER=/path/to/linker -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"
Run Code Online (Sandbox Code Playgroud)

另请参阅CMake邮件列表中的这篇文章 - 这也是将链接器修饰符添加到另一个链接器的自然位置.

  • 您没有在此规则中指定任何内容。这是 cmake 构建可执行文件时遵循的规则,因此它会插入从例如您添加到 CMakeLists.txt 文件中的目标的源构建的对象。 (2认同)

use*_*610 13

我成功地做到了

add_link_options("-fuse-ld=lld")
Run Code Online (Sandbox Code Playgroud)

这是之前答案的变体。区别在于我用来设置标志的 CMake 命令。

添加它的CMAKE_CXX_FLAGS缺点是还必须添加-Wno-unused-command-line-argument,因为标志也添加到编译命令中,而不仅仅是链接命令。

的缺点CMAKE_SHARED_LINKER_FLAGS是你必须多次添加它,到_SHARED_,,_EXE_也许我忘记了什么。


FeR*_*eRD 11

正如 Mabraham 指出的那样,CMake 调用编译器来进行链接。因此,到这个最简单的办法就是让IT,而是告诉编译器运行不同的连接器调用时。

正如在另一个答案中所指出的那样——但现在它甚至是一个记录在案的选项gcc --help=common——就像:

cmake -DCMAKE_CXX_FLAGS="-fuse-ld=lld"
Run Code Online (Sandbox Code Playgroud)

g++orclang++将在每次调用时传递-fuse-ld=lld1标志,并且当他们进行任何链接时,他们将使用指定的命令而不是内置默认值。简单易行,CMake 根本不需要关心这些事情。

(顺便说一句,该选项被解析 ( -f) ( use-ld) ( =) ( lld),没有“保险丝”选项gcc。)

笔记
  1. 当使用铛,lld可以与要使用,就像任何其他的连接命令来代替ld.exeld.goldmingw32/bin/ld.exe,等。

    GCC 没有那么灵活,-fuse-ld它只接受三个可能的参数之一:lld, bfd, 或gold。它将调用它在. (感谢 bviktor 指出 GCC 对备用链接器选择的限制。)ld.fooPATH

  • @FeRD 不,我的观点是这是设置错误的变量。它_会_工作的,别误会我的意思。但是正在编译的每个编译单元都会导致未使用的命令行开关的警告。因为该开关实际上仅在链接步骤期间才相关。因此,虽然这有效,但很难被称为最佳实践。在 GNUmakefile 中,通常不会使用“CXXFLAGS”来传达链接器标志。无论如何,尽管存在缺陷,我还是赞成这个答案的普遍实用性。 (3认同)
  • 在此处提供的所有“解决方案”中,这是唯一真正对我有用的命令行解决方案(cmake 3.19.2) (2认同)
  • @0xC0000022L 我同意这不是一个理想的解决方案,但对于像我一样发现这个问题的人来说,因为他们尝试使用的 CMake 项目*确实*依赖编译器驱动程序来调用链接器,这可能是最好的解决方案此处提出的所有解决方案。 (2认同)
  • @FeRD 啊,但是有。只是您必须对要链接的每种类型的工件执行此操作。[`CMAKE_EXE_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS.html) 和 [`CMAKE_SHARED_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS) .html) 是其中两个 (2认同)

Bre*_*ght 10

我必须使用CMAKE_CXX_LINK_EXECUTABLE,CMAKE_C_LINK_EXECUTABLE变量:

SET(CMAKE_C_LINK_EXECUTABLE "c:\\MoSync\\bin\\pipe-tool.exe")
Run Code Online (Sandbox Code Playgroud)

  • 这在大多数情况下不起作用 - 该变量为整个链接命令建立规则,并且通常需要标记和参数进行链接. (18认同)

Ale*_*ing 10

CMake 仅允许您直接控制每种语言的编译器。要调用链接器,它会通过配置的编译器。这意味着在 CMake 中没有设置链接器的通用方法,您必须配置编译器以使用您想要的链接器。

需要在 CMake 的编译器检测例程运行之前设置此类标志,因为它将尝试编译测试二进制文件。最好的方法是创建一个工具链文件。在工具链文件中设置这些标志的最佳方法如下:

# e.g. to use lld with Clang
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
Run Code Online (Sandbox Code Playgroud)

这三个变量分别控制可执行文件、可加载模块和共享库的(默认)链接器标志集。这里不需要处理CMAKE_STATIC_LINKER_FLAGS_INIT(对于静态库),因为调用的是归档,而不是链接器。

然后,您可以在首次运行 CMake 时通过-DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake在命令行中进行设置来设置工具链文件。从 CMake 3.21 开始,您将能够通过传递--toolchain /path/to/toolchain.cmake(这是完全等效的,但打字要少一些)。


Gun*_*iez 5

在CMakeCache.txt或ccmake之后设置变量$ {CMAKE_LINKER}.在高级选项下.

  • 是的。在构建目录中调用 `ccmake .` 并按 't'。向下滚动,直到您点击 CMAKE_LINKER。 (2认同)
  • 我以前就是这么做的,现在不行了。就好像 cmake 根本不考虑这个变量一样:设置 CMAKE_LINKER 来完成无意义的操作并不会改变错误(或命令行)丝毫。CMake 3.14.5。 (2认同)

usr*_*567 5

从(尚未发布)版本 3.29 开始,CMake 提供了一种设置链接器的方法。

  • 将变量设置为预定义变量、、、、、或更奇特的变量之一CMAKE_LINKER_TYPE。有关更多详细信息,请查看文档LLDGOLDMOLDBFDMSVC
  • 如果预设不够,您可以设置CMAKE_<LANG>_USING_LINKER_<TYPE>链接器的路径或编译器的标志。通过设置变量CMAKE_<LANG>_USING_LINKER_MODE文档)告诉 CMake 您的选择。