对静态链接库使用 GCC 的链接时优化 [英] Using GCC's link-time optimization with static linked libraries

查看:71
本文介绍了对静态链接库使用 GCC 的链接时优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 GCC (6.1.1) 的 -flto 标志使用链接时优化.

I'm trying to use link-time optimizations with the -flto flag of GCC (6.1.1).

虽然它在我的代码上运行良好,但它没有链接到我也在构建和链接到我的项目的静态链接库(即 Engine 和库是 glsl-optimizer,仅供参考)

While it works fine with my code, it doesn't link with a static linked library I'm also building and linking with my project (which is Engine and the library is glsl-optimizer, just for reference).

这是输出:

...
/usr/bin/ranlib: ir_expression_flattening.cpp.o: plugin needed to handle lto object
/usr/bin/ranlib: opt_function_inlining.cpp.o: plugin needed to handle lto object
/usr/bin/ranlib: opt_copy_propagation_elements.cpp.o: plugin needed to handle lto object
...

当然,在那之后,我得到了一些对某些函数的未定义引用".

And after that, of course, I get several "undefined references" to some functions.

我做了一些研究,发现可能是因为ar,我应该尝试使用gcc-ar,但我不确定我是如何可能会这样做.

I did some research and found out that it might be because of ar, and I should try to use gcc-ar, but I'm not sure how I might do that.

此外,我使用的 CMake 不支持 lto(某些平台上的英特尔编译器除外,所以我阅读了...).尽管如此,我尝试使用:

Also, I'm using CMake that does not support lto (except on Intel's compiler on some platforms, so I read...). Even though, I tried using:

set_property(TARGET glsl_optimizer PROPERTY INTERPROCEDURAL_OPTIMIZATION True)

没有用.

另外,我尝试了 GCC 的 -fuse-linker-plugin 标志,但它不起作用.

Also, I tried GCC's -fuse-linker-plugin flag which didn't work.

我想我必须直接使用 gcc-ar 以旧方式手动完成,或者也许还有其他方法?

I guess I'll have to do it manually the old way directly using gcc-ar, or maybe there's some other method?

推荐答案

这是一个重现问题的 MCVE CMake 项目:

Here is an MCVE CMake project that reproduces the problem:

$ ls -R hellow
hellow:
CMakeLists.txt  hello.c  libhello.c

$ cat hellow/CMakeLists.txt 
cmake_minimum_required (VERSION 2.6)
project (hellow)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
#SET(CMAKE_AR  "gcc-ar")
#SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
#SET(CMAKE_C_ARCHIVE_FINISH   true)
add_library(hello STATIC libhello.c) 
add_executable(hellow hello.c)
target_link_libraries(hellow hello)
add_dependencies(hellow hello)


$ cat hellow/hello.c 
extern void hello(void);

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

$ cat hellow/libhello.c 
#include <stdio.h>

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

配置好:

$ mkdir build_hellow
$ cd build_hellow/
$ cmake ../hellow
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/imk/dev/so/build_hellow

根据问题构建失败:

$ make
Scanning dependencies of target hello
[ 25%] Building C object CMakeFiles/hello.dir/libhello.c.o
[ 50%] Linking C static library libhello.a
/usr/bin/ar: CMakeFiles/hello.dir/libhello.c.o: plugin needed to handle lto object
/usr/bin/ranlib: libhello.c.o: plugin needed to handle lto object
[ 50%] Built target hello
Scanning dependencies of target hellow
[ 75%] Building C object CMakeFiles/hellow.dir/hello.c.o
[100%] Linking C executable hellow
/tmp/ccV0lG36.ltrans0.ltrans.o: In function `main':
<artificial>:(.text+0x5): undefined reference to `hello'
collect2: error: ld returned 1 exit status
CMakeFiles/hellow.dir/build.make:95: recipe for target 'hellow' failed
make[2]: *** [hellow] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/hellow.dir/all' failed
make[1]: *** [CMakeFiles/hellow.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

解决方案不止一种.一种是取消注释3条注释行在上面的 CMakeLists.txt 中.然后:

There is more than one solution. One is to uncomment the 3 commented lines in CMakeLists.txt above. Then:

$ cmake ../hellow/
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/imk/dev/so/build_hellow

$ make
Scanning dependencies of target hello
[ 25%] Building C object CMakeFiles/hello.dir/libhello.c.o
[ 50%] Linking C static library libhello.a
[ 50%] Built target hello
Scanning dependencies of target hellow
[ 75%] Building C object CMakeFiles/hellow.dir/hello.c.o
[100%] Linking C executable hellow
[100%] Built target hellow

$ ./hellow 
Hello

此修复利用了以下事实.

This fix makes use of the following facts.

构建破坏问题:

/usr/bin/ar: CMakeFiles/hello.dir/libhello.c.o: plugin needed to handle lto object
...
/usr/bin/ranlib: libhello.c.o: plugin needed to handle lto object

可以通过给 arranlib 选项解决:

can solved by giving ar and ranlib the option:

--plugin=$(gcc --print-file-name=liblto_plugin.so)

然而,GNU ranlib 只是 ar -s 的同义词,而 gcc-ar 是一个提供该插件的 ar 的包装器.

However, GNU ranlib is merely a synonym for ar -s, and gcc-ar is a wrapper for ar that supplies that plugin.

CMake 的 C 静态库构建模板是:

CMake's build template for a C static library is:

CMAKE_C_ARCHIVE_CREATE ( = <CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>)
CMAKE_C_ARCHIVE_FINISH ( = <CMAKE_RANLIB> <TARGET>)

对于 GNU ar 等价于:

which for GNU ar is equivalent to:

CMAKE_C_ARCHIVE_CREATE ( = <CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>)
CMAKE_C_ARCHIVE_FINISH ( = true) # Or any other no-op command

所以加上这些设置:

SET(CMAKE_AR  "gcc-ar")

我们很好.

对于C++项目,当然要设置CMAKE_CXX_ARCHIVE_CREATECMAKE_CXX_ARCHIVE_FINISH

For a C++ project, of course, set CMAKE_CXX_ARCHIVE_CREATE and CMAKE_CXX_ARCHIVE_FINISH

这篇关于对静态链接库使用 GCC 的链接时优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆