将 GCC 的 link 时间优化与静态 linked 库一起使用
Using GCC's link-time optimization with static linked libraries
我正在尝试将 link 时间优化与 GCC (6.1.1) 的 -flto
标志一起使用。
虽然它适用于我的代码,但它不适用于 link 静态 linked 库,我也在构建和 linking 我的项目(这是Engine and the library is glsl-optimizer,仅供参考。
这是输出:
...
/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
...
当然,在那之后,我得到了几个 "undefined references" 的一些功能。
我做了一些研究,发现可能是因为 ar
,我应该尝试使用 gcc-ar
,但我不确定该怎么做。
此外,我使用的 CMake 不支持 lto(某些平台上的 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 (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
中。那么:
$ 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
此修复利用了以下事实。
构建中断问题:
/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
可以通过给 ar
和 ranlib
选项来解决:
--plugin=$(gcc --print-file-name=liblto_plugin.so)
但是,GNU ranlib
只是 ar -s
的同义词,而 gcc-ar
是
提供该插件的 ar
包装器。
CMake 的 C 静态库构建模板是:
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) # Or any other no-op command
因此使用这些设置加上:
SET(CMAKE_AR "gcc-ar")
我们很好。
对于C++项目,当然设置CMAKE_CXX_ARCHIVE_CREATE
和CMAKE_CXX_ARCHIVE_FINISH
移植到 g++-11 后我遇到了类似的问题。这可能是由于默认设置的更改引起的 - 使用“苗条”对象而不是“胖”对象 - 并添加 -ffat-lto-objects
解决了它。
另请参阅 this SO answer 和那里的评论。
我正在尝试将 link 时间优化与 GCC (6.1.1) 的 -flto
标志一起使用。
虽然它适用于我的代码,但它不适用于 link 静态 linked 库,我也在构建和 linking 我的项目(这是Engine and the library is glsl-optimizer,仅供参考。
这是输出:
...
/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
...
当然,在那之后,我得到了几个 "undefined references" 的一些功能。
我做了一些研究,发现可能是因为 ar
,我应该尝试使用 gcc-ar
,但我不确定该怎么做。
此外,我使用的 CMake 不支持 lto(某些平台上的 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 (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
中。那么:
$ 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
此修复利用了以下事实。
构建中断问题:
/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
可以通过给 ar
和 ranlib
选项来解决:
--plugin=$(gcc --print-file-name=liblto_plugin.so)
但是,GNU ranlib
只是 ar -s
的同义词,而 gcc-ar
是
提供该插件的 ar
包装器。
CMake 的 C 静态库构建模板是:
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) # Or any other no-op command
因此使用这些设置加上:
SET(CMAKE_AR "gcc-ar")
我们很好。
对于C++项目,当然设置CMAKE_CXX_ARCHIVE_CREATE
和CMAKE_CXX_ARCHIVE_FINISH
移植到 g++-11 后我遇到了类似的问题。这可能是由于默认设置的更改引起的 - 使用“苗条”对象而不是“胖”对象 - 并添加 -ffat-lto-objects
解决了它。
另请参阅 this SO answer 和那里的评论。