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

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

问题描述

我试图用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屋!

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