使用GCC链接时优化和静态链接库 [英] Using GCC's link-time optimization with static linked libraries
问题描述
我试图用GCC(6.1.1)的 -flto
标志来使用链接时优化。
虽然它与我的代码一起工作正常,但它不与静态链接库链接我也在构建并链接到我的项目(引擎,图书馆是 glsl-optimizer ,
以下是输出:
...
/ usr / bin / ranlib:ir_expression_flattening.cpp.o:处理lto对象所需的插件
/ usr / bin / ranlib:opt_function_inlining.cpp.o:处理lto对象所需的插件
/ usr / bin / ranlib:opt_copy_propagation_elements.cpp.o:处理lto对象所需的插件
...
之后,当然,我得到了一些函数的未定义引用。
我做了一些研究,发现这可能是因为 ar
,我应该尝试使用 gcc-ar
,但我不确定我该怎么做。
另外,我使用不支持lto的CMake(除了某些平台上的intel编译器,所以我读了...)。尽管如此,我试过使用:
set_property(TARGET glsl_optimizer PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
哪一个不行。
另外,我尝试了GCC的
-fuse-linker-plugin
标志不起作用。
我想我必须手动直接使用旧的方式
gcc-ar
,或者可能还有其他方法?
是一个 MCVE CMake项目,它重现了这个问题:
$ ls -R hellow
hellow:
CMakeLists.txt hello.c libhello.c
$ cat hellow / CMakeLists.txt
cmake_minimum_required (CMAKE_EXE_LINKER_FLAGS$ {CMAKE_EXE_LINKER_FLAGS} -flto)
SET(CMAKE_C_FLAGS$ {CMAKE_C_FLAGS} -flto)
项目(hellow)
SET (CMAKE_ARgcc-ar)
#SET(CMAKE_C_ARCHIVE_CREATE< CMAKE_AR> qcs< TAR GET>< LINK_FLAGS> < OBJECTS>)
#SET(CMAKE_C_ARCHIVE_FINISH true)
add_library(hello STATIC libhello.c)
add_executable(hello 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
void hello(void)
{
puts(Hello);
}
配置很好:
$ mkdir build_hellow
$ cd build_hellow /
$ cmake ../hellow
- C编译器标识符是GNU 5.4.0
- CXX编译器标识符是GNU 5.4.0
- 检查工作的C编译器:/ usr / bin / cc
- 检查工作的C编译器:/ usr / bin / cc - works
- 检测C编译器ABI信息
- 检测C编译器ABI信息 - done
- 检测C编译特性
- 检测C co mpile特性 - 完成
- 检查工作CXX编译器:/ usr / bin / c ++
- 检查工作CXX编译器:/ usr / bin / c ++ - works
- 检测CXX编译器ABI info
- 检测CXX编译器ABI信息 - 完成
- 检测CXX编译功能
- 检测CXX编译功能 - 完成
- 配置完成
- 生成完成的
- 生成文件已写入:/ home / imk / dev / so / build_hellow
构建按照每个问题失败:
$ make
扫描目标hello $ b的相关性$ b [25%]构建C对象CMakeFiles / hello.dir / libhello.co
[50%]链接C静态库libhello.a
/ usr / bin / ar:CMakeFiles / hello.dir / libhello.co:处理lto对象所需的插件
/ usr / bin / ranlib:libhello.co:处理lto对象所需的插件
[50%]构建目标hello
目标的扫描依赖关系hellow
[75%] Building C object CMakeFiles / hellow.dir / hello.co
[100%]链接C e xecutable hellow
/tmp/ccV0lG36.ltrans0.ltrans.o:在函数`main'中:
< artificial> :(。text + 0x5):对`hello'的未定义引用
collect2 :错误:ld返回1退出状态
CMakeFiles / hellow.dir / build.make:95:目标'hellow'失败的配方$ b $ make [2]:*** [hellow]错误1
CMakeFiles / Makefile2:67:目标配方'CMakeFiles / hellow.dir / all'失败$ b $ make [1]:*** [CMakeFiles / hellow.dir / all]错误2
Makefile: 83:目标'all'的配方失败
make:*** [all]错误2
<有多种解决方案。一种是取消注释上面的 CMakeLists.txt
中的3条注释行
。然后:
$ cmake ../hellow/
- C编译器标识是GNU 5.4.0
- CXX编译器标识为GNU 5.4.0
- 检查工作C编译器:/ usr / bin / cc
- 检查工作C编译器:/ usr / bin / cc - - works
- 检测C编译器ABI信息
- 检测C编译器ABI信息 - done
- 检测C编译特性
- 检测C编译特性 - done
- 检查工作CXX编译器:/ usr / bin / c ++
- 检查工作CXX编译器:/ usr / bin / c ++ - works
- 检测CXX编译器ABI信息
- 检测CXX编译器ABI信息 - 完成
- 检测CXX编译功能
- 检测CXX编译功能 - 完成
- 配置完成
- 生成完成
- 构建文件已写入:/ home / imk / dev / so / build_hellow
$ make
扫描目标hello的相关性
[25%] Building C对象CMakeFiles / hello.dir / libhello.co
[50%]链接C静态库l ibhello.a
[50%]构建目标hello
目标hellow的扫描依赖关系
[75%]构建C对象CMakeFiles / hellow.dir / hello.co
[100% ]链接C可执行文件hellow
[100%]构建目标hellow
$ b $ ./hellow
Hello
此修复程序利用以下事实:
构建问题:
/ usr / bin / ar:CMakeFiles / hello.dir / libhello.co:处理lto对象所需的插件
...
/ usr / bin / ranlib:libhello.co:需要处理lto对象的插件
可以通过赋值 ar
和 ranlib
选项:
- plugin = $(gcc --print-file-name = liblto_plugin.so)
然而,GNU ranlib
仅仅是 ar -s
和的同义词, gcc-ar
是提供该插件的
封装器。
CMAKE_C_ARCHIVE_CREATE(=< CMAKE_AR> qc< TARGET> < LINK_FLAGS> < OBJECTS>)
CMAKE_C_ARCHIVE_FINISH(=< CMAKE_RANLIB>< TARGET>)
这对于GNU ar
等同于:
CMAKE_C_ARCHIVE_CREATE(=< CMAKE_AR> qcs< TARGET>< LINK_FLAGS>< OBJECTS>)
CMAKE_C_ARCHIVE_FINISH(= true)#或者其他任何非操作命令
因此,使用这些设置加上:
$ p $ SET(CMAKE_ARgcc-ar )
我们很好。
当然,对于C ++项目,请设置 CMAKE_CXX_ARCHIVE_CREATE
和 CMAKE_CXX_ARCHIVE_FINISH
I'm trying to use link-time optimizations with the -flto
flag of GCC (6.1.1).
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).
Here is the output:
...
/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.
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.
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)
Which didn't work.
Also, I tried GCC's -fuse-linker-plugin
flag which didn't work.
I guess I'll have to do it manually the old way directly using gcc-ar
, or maybe there's some other method?
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");
}
Configuration is good:
$ 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
Build fails as per problem:
$ 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
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.
The build-breaking problem:
/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
can solved by giving ar
and ranlib
the option:
--plugin=$(gcc --print-file-name=liblto_plugin.so)
However, GNU ranlib
is merely a synonym for ar -s
, and gcc-ar
is a
wrapper for ar
that supplies that plugin.
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>)
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
So with these settings plus:
SET(CMAKE_AR "gcc-ar")
we're good.
For a C++ project, of course, set CMAKE_CXX_ARCHIVE_CREATE
and CMAKE_CXX_ARCHIVE_FINISH
这篇关于使用GCC链接时优化和静态链接库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!