web-dev-qa-db-fra.com

Utilisation de l'optimisation du temps de liaison de GCC avec des bibliothèques liées statiques

J'essaie d'utiliser des optimisations de temps de liaison avec le -flto drapeau du GCC (6.1.1).

Bien que cela fonctionne bien avec mon code, il ne se lie pas à une bibliothèque liée statique que je construis également et que je crée un lien avec mon projet (qui est Engine et la bibliothèque est glsl-optimizer , juste pour référence).

Voici la sortie:

...
/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
...

Et après cela, bien sûr, j'obtiens plusieurs "références non définies" à certaines fonctions.

J'ai fait quelques recherches et j'ai découvert que c'était peut-être à cause de ar, et je devrais essayer d'utiliser gcc-ar, mais je ne sais pas comment je pourrais faire ça.

De plus, j'utilise CMake qui ne prend pas en charge lto (sauf sur le compilateur d'Intel sur certaines plates-formes, donc j'ai lu ...). Même si j'ai essayé d'utiliser:

set_property(TARGET glsl_optimizer PROPERTY INTERPROCEDURAL_OPTIMIZATION True)

Ce qui n'a pas fonctionné.

J'ai aussi essayé le GCC -Fuse-linker-plugin drapeau qui n'a pas fonctionné.

Je suppose que je vais devoir le faire manuellement à l'ancienne en utilisant directement gcc-ar, ou peut-être y a-t-il une autre méthode?

23
CpCd0y

Voici un projet MCVE CMake qui reproduit le problème:

$ 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");
}

La configuration est bonne:

$ 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

La construction échoue selon le problème:

$ 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

Il existe plusieurs solutions. L'une consiste à décommenter les 3 lignes commentées dans CMakeLists.txt au dessus. Alors:

$ 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

Cette correction utilise les faits suivants.

Le problème révolutionnaire:

/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

peut être résolu en donnant à ar et ranlib l'option:

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

Cependant, GNU ranlib est simplement un synonyme de ar -s, et gcc-ar est un wrapper pour ar qui fournit ce plugin.

Le modèle de construction de CMake pour une bibliothèque statique C est:

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

qui pour GNU ar est équivalent à:

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

Donc, avec ces paramètres plus:

SET(CMAKE_AR  "gcc-ar")

etait bon.

Pour un projet C++, bien sûr, définissez CMAKE_CXX_ARCHIVE_CREATE et CMAKE_CXX_ARCHIVE_FINISH

18
Mike Kinghan