我在徘徊哪种是在 Linux 上使用 GCC 编译静态库的正确方法,这样当链接时间优化 (LTO) 应用于可执行文件时,库可以使用并可能实现最佳性能。
当仅使用-flto
编译库时,无论是否使用-flto
都无法将可执行文件链接到它。错误是:
undefined reference to `hello'
其中 hello
是库中定义的函数。
根据this的回答Stack Overflow 问题一种可能的解决方案如下:
set(CMAKE_AR gcc-ar)
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH true)
然后可以使用 -flto
和不将 -flto
传递给链接器标志来将库链接到可执行文件。
但是根据this的回答Stack Overflow 问题如果我们希望以这种方式编译静态库,以便在有和没有 LTO 的情况下都可以使用,而不是我们必须使用 -ffat-lto-objects
。如果我们再次将此标志添加到库编译标志中,则可以使用 -flto
和不将 -flto
传递给链接器标志来将库链接到可执行文件。
我的问题是:
gcc-ar
的第一个解决方案的确切含义是什么?当使用
-flto
编译库时,不同工作变体之间有什么区别。2.1 无需
-flto
即可执行。- 库仅使用
gcc-ar
。 - 库仅使用
-ffat-lto-objects
。 - 库同时使用
gcc-ar
和-ffat-lto-objects
2.2 可使用
-flto
和库的相同 3 个变体执行。- 库仅使用
这是我的测试项目中的最小、完整和可验证示例,它是来自 this 的示例的修改版本堆栈溢出问题。我使用的是 GCC 版本 7.2.0
。
CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(lto)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -g -O3")
add_subdirectory(lib)
add_subdirectory(exe)
执行/CMakeLists.txt
set(TARGET_NAME exe)
add_executable(${TARGET_NAME} src/main.c)
target_link_libraries(${TARGET_NAME} lib)
option(EXE_LTO "Use link time optimizations for the executable." OFF)
if(${EXE_LTO})
target_compile_options(${TARGET_NAME} PRIVATE "-flto")
endif()
exe/src/main.c
extern void hello();
int main()
{
hello();
return 0;
}
lib/CMakeLists.txt
set(TARGET_NAME lib)
add_library(${TARGET_NAME} STATIC src/lib.c)
option(LIB_LTO "Use link time optimizations for the library." OFF)
option(LIB_FAT_LTO "Create fat LTO objects for library files." OFF)
option(LIB_USE_LTO_AR "Use another AR program for LTO objects." OFF)
if(${LIB_LTO})
target_compile_options(${TARGET_NAME} PRIVATE -flto)
endif()
if(${LIB_FAT_LTO})
target_compile_options(${TARGET_NAME} PRIVATE -ffat-lto-objects)
endif()
if(${LIB_USE_LTO_AR})
set(CMAKE_AR gcc-ar)
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH true)
endif()
lib/src/lib.c
#include <stdio.h>
void hello()
{
puts("Hello");
}
最佳答案
如果不将--plugin/psth/to/lto-plugin.so*
添加到ar
参数,您将在链接时得到 undefined reference < em>和存档创建时的警告。或者至少这就是我得到的。您可能需要在此处添加它:
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> --plugin <LTO_PLUGIN_PATH> \
qcs <TARGET> <OBJECTS>")
(LINK_FLAGS
可能不属于这里,所以我省略了它们)。
我不知道如何自动设置 LTO_PLUGIN_PATH。
该插件使 ar
能够创建支持 LTO 的存档。所有其他方法要么根本不起作用(存档中的非胖对象),要么实际上不会导致链接时间优化(存档中的胖对象——在这种情况下只使用传统的目标代码,LTO 信息被忽略)。
关于c++ - 在 Linux 上构建带有链接时间代码生成的静态库的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46934111/