首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Linux上用链接时间代码生成静态库的正确方法是哪种?

在Linux上用链接时间代码生成静态库的正确方法是哪种?
EN

Stack Overflow用户
提问于 2017-10-25 13:44:44
回答 2查看 3.7K关注 0票数 3

在Linux上用GCC编译静态库的正确方法是,当将链接时间优化(LTO)应用于可执行文件时,库是可消耗的,并且有可能达到最佳性能。

当库仅用-flto编译时,无论它是否使用-flto,都不能将可执行文件链接到它。错误是:

未定义的对“`hello”的引用

其中hello是在库中定义的函数。

根据this堆栈溢出问题的答案,可能的解决方案如下:

代码语言:javascript
运行
复制
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堆栈溢出问题的答案,如果我们想要以这样的方式编译静态库,那么就必须使用-ffat-lto-objects。如果我们再次将此标志添加到库编译标志,则库可以链接到带有-flto的可执行文件,而不需要传递给链接器标志的-flto

我的问题是:

  1. 使用gcc-ar的第一个解决方案的确切含义是什么?
  2. 在用-flto编译库时,不同工作变量之间的区别是什么? 2.不需-flto即可执行。
代码语言:javascript
运行
复制
- Library is using only `gcc-ar`.
- Library is using only `-ffat-lto-objects`.
- Library is using both `gcc-ar` and `-ffat-lto-objects`

2.2可执行的-flto和相同的3个变体库。

下面是我的测试项目的最小、完整和可验证的示例,它是来自this堆栈溢出问题的示例的修改版本。我在使用GCC版本的7.2.0

CMakeLists.txt

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
extern void hello();

int main()
{
  hello();
  return 0;
}

lib/CMakeLists.txt

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
#include <stdio.h>

void hello()
{
  puts("Hello");
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-25 15:05:01

如果不将--plugin /psth/to/lto-plugin.so*添加到ar参数中,则将在链接时获得未定义的引用,并在归档创建时得到警告。或者至少这就是我想要的。您可能需要在这里添加它:

代码语言:javascript
运行
复制
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> --plugin <LTO_PLUGIN_PATH> \
  qcs <TARGET> <OBJECTS>")

(LINK_FLAGS可能不属于这里,所以我省略了它们)。

我不知道如何自动设置LTO_PLUGIN_PATH。

该插件使ar能够创建启用LTO的档案.所有其他方法要么根本不工作(存档中的非fat对象),要么实际上不会导致链接时间优化(归档中的fat对象-在这种情况下只使用传统的对象代码,LTO信息被忽略)。

票数 2
EN

Stack Overflow用户

发布于 2017-10-25 14:59:08

使用说明:

  1. 使用选项-flto -fno-fat-lto-objects编译对象文件。-fno-fat-lto-objects并不是绝对必要的,但是它确保它不是执行lto,就是失败(而不是回到非lto模式)。
  2. ar rcsT --plugin <path-to-lto-plugin> ...创建静态库,这里需要liblto_plugin.so的完整路径。选项T在这里创建一个瘦存档(不复制.o文件)。
  3. 链接到-flto标志。

示例:

代码语言:javascript
运行
复制
$ cat library.cc
namespace library {

int f(int a) {
    return a + 1;
}

}
$ cat test.cc
#include <iostream>

namespace library { int f(int); }

int main() {
    std::cout << library::f(0) << '\n';
}
$ g++ -c -Wall -Wextra -std=gnu++14 -O3 -flto -fno-fat-lto-objects -o library.o library.cc
$ ar rcsT --plugin /usr/libexec/gcc/x86_64-redhat-linux/5.3.1/liblto_plugin.so library.a library.o 
$ g++ -c -Wall -Wextra -std=gnu++14 -O3 -flto -fno-fat-lto-objects -o test.o test.cc
$ g++ -o test -flto -O3 test.o 
/tmp/ccY0l2jQ.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x37): undefined reference to `library::f(int)'
collect2: error: ld returned 1 exit status
$ g++ -o test -flto test.o library.a
$ ./test
1
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46934111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档