我在徘徊,这是使用 GCC 在 Linux 上编译静态库的正确方法,这样当链接时间优化 (LTO) 应用于可执行文件时,该库是可消耗的并且可能实现最佳性能。
当库仅与-flto
可执行文件一起编译时,无论它是否使用都无法链接到它-flto
。错误是:
对“你好”的未定义引用
hello
库中定义的函数在哪里。
根据对此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
传递给链接器标志。
但是根据这个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 个变体相同的可执行文件。- 库仅使用
这是我的测试项目的最小、完整和可验证的示例,它是此Stack Overflow 问题中示例的修改版本。我正在使用 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)
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");
}