c++ - compile - ¿Por qué se ve g++ en LIBRARY_PATH/../ lib64 y dónde se documenta esto?
g++ mac (7)
El compilador primero mirará las rutas predeterminadas y luego las demás. Cómo se ordena cuando imprime No lo hago ahora, pero está documentado aquí, 3.19 Variables de entorno que afectan a GCC .
Mi variable de entorno LIBRARY_PATH
tiene un directorio personalizado: /cs/public/lib/pkg/opencv/lib
.
Pero, cuando uso g++ --print-search-dirs
, obtengo esto en su lugar:
libraries: =
/cs/public/lib/pkg/opencv/lib/x86_64-suse-linux/4.6/:
/cs/public/lib/pkg/opencv/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../lib64/:
/lib/x86_64-suse-linux/4.6/:
/lib/../lib64/:
/usr/lib/x86_64-suse-linux/4.6/:
/usr/lib/../lib64/:
/cs/public/lib/pkg/opencv/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../:
/lib/:
/usr/lib/
¿Por qué g ++ mira estas alternativas y un montón de otras ubicaciones del sistema antes de lo que especifico explícitamente en la variable LIBRARY_PATH
, y dónde se documenta esto?
Comprendería si se buscaran los valores predeterminados del sistema antes de LIBRARY_PATH y LIBRARY_PATH /../ lib64, etc., pero g ++ coloca LIBRARY_PATH /../ lib64, luego las rutas del sistema, luego LIBRARY_PATH. ¿Dónde está documentado este pedido?
Mi versión g ++ es g++ (SUSE Linux) 4.6.2
Mi sistema operativo es openSUSE 12.1 (x86_64)
Esta respuesta intenta resumir los comportamientos de la ruta de búsqueda para GCC y Clang.
GCC
Incluir ruta: para una línea de comandos con el siguiente formato:
CPLUS_INCLUDE_PATH=EDIR g++ -IIDIR -isystemSDIR
La siguiente lista de directorios se utiliza como rutas de búsqueda para #include <...>
:
IDIR # ''-I'' directories.
SDIR # ''-isystem'' directories.
EDIR # *_INCLUDE_PATH directories.
GCCDIR/include/c++/GCCVER # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/GCCARCH # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/backward # libstdc++ directory (C++).
GCCDIR/lib/gcc/GCCARCH/GCCVER/include # GCC arch-specific directory.
/usr/local/include/GCCARCH # Local arch-specific include directory.
/usr/local/include # Local include directory.
GCCDIR/include # GCC include directory.
GCCDIR/lib/gcc/GCCARCH/GCCVER/include-fixed # GCC include-fixed directory.
/usr/include/GCCARCH # System include arch-specific directory.
/usr/include # System include directory.
Ruta de la biblioteca: para una línea de comandos con el siguiente formato:
LIBRARY_PATH=EDIR gcc -BBDIR -LLDIR
Los siguientes argumentos se pasan al enlazador:
-LLDIR # ''-L'' directories.
-LBDIR # ''-B'' directories.
-LEDIR/../libXX # Multilib directories from LIBRARY_PATH.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER # GCC arch-specific library directory.
-LGCCDIR/libXX # GCC multilib library directory.
-L/libXX # System multilib library directory.
-L/usr/libXX # System multilib library directory.
-LEDIR # LIBRARY_PATH directories.
-LGCCDIR/lib # Other GCC libraries.
Sonido metálico
Incluir ruta: para una línea de comandos con el siguiente formato:
CPLUS_INCLUDE_PATH=EDIR clang++ --gcc-toolchain=GCCDIR -BBDIR -IIDIR -isystemSDIR
La siguiente lista de directorios se utiliza como rutas de búsqueda para #include <...>
:
IDIR # ''-I'' directories.
SDIR # ''-isystem'' directories.
EDIR # *_INCLUDE_PATH directories.
# If -stdlib=libstdc++ is used:
GCCDIR/include/c++/GCCVER # libstdc++ directory from the selected GCC toolchain (C++).
GCCDIR/include/c++/GCCVER/GCCARCH # libstdc++ directory from the selected GCC toolchain (C++).
GCCDIR/include/c++/GCCVER/backward # libstdc++ directory from the selected GCC toolchain (C++).
# If -stdlib=libc++ is used:
CLANGDIR/include/c++/v1 # libc++ directory (C++).
/usr/local/include # Local include directory.
CLANGDIR/lib/clang/CLANGVER/include # Clang include directory.
/include # System include directory.
/usr/include # System include directory.
Ruta de la biblioteca: para una línea de comandos con el siguiente formato:
LIBRARY_PATH=EDIR clang --gcc-toolchain=GCCDIR -BBDIR -LLDIR
Los siguientes argumentos se pasan al enlazador:
-LLDIR # ''-L'' directories.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER # GCC arch-specific library directory.
-LGCCDIR/libXX # GCC multilib library directory.
-L/libXX # System multilib library directory.
-L/usr/libXX # System multilib library directory.
-LGCCDIR/lib # Other GCC libraries.
-LCLANGDIR/lib # Clang libraries.
-L/lib # System library directory.
-L/usr/lib # System library directory.
-LEDIR # LIBRARY_PATH directories.
Resumen
La ruta de búsqueda para los incluidos es bastante similar tanto en GCC como en Clang. C ++: las rutas específicas se omiten si se utiliza la interfaz de C en ambos casos. Las rutas de búsqueda de bibliotecas difieren sustancialmente entre GCC y Clang, en particular la presencia de directorios -B
y la manipulación impar de LIBRARY_PATH
en la interfaz de GCC.
Las rutas de búsqueda de la biblioteca son las mismas para las interfaces de C y C ++. Otras rutas de búsqueda de bibliotecas son introducidas por el propio enlazador. El siguiente extracto proviene de la secuencia de comandos del enlazador de vainilla para GNU Binutils:
# Multilib library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/libXX");
SEARCH_DIR("BINUTILSDIR/libXX");
SEARCH_DIR("/usr/local/libXX");
SEARCH_DIR("/libXX");
SEARCH_DIR("/usr/libXX");
# Traditional library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/lib");
SEARCH_DIR("BINUTILSDIR/lib");
SEARCH_DIR("/usr/local/lib");
SEARCH_DIR("/lib");
SEARCH_DIR("/usr/lib");
También es imperativo tener en cuenta que las dependencias de las bibliotecas no se buscan dentro de los directorios mencionados anteriormente. Estos se basan exclusivamente en las -rpath
y -rpath-link
pasadas al vinculador, o bien se resuelven a partir de las rutas de la biblioteca del sistema por defecto Por lo tanto, podría ser útil producir argumentos tanto -L
como -rpath-link
para garantizar que las bibliotecas correctas estén vinculadas.
Finalmente, los archivos especiales (como los objetos CRT) se buscan solo en los directorios -B
. En Clang, los archivos especiales también se buscan dentro de la cadena de herramientas GCC seleccionada. Otros factores (archivos de especificaciones, configuración específica de la distribución) pueden cambiar algunos o todos los anteriores.
Las rutas están definidas por las especificaciones incorporadas. Las especificaciones definen cómo la canalización procesa el código fuente para obtener un resultado. GCC simplemente conduce la compilación.
Puede darle a GCC su propio archivo de especificaciones a través de -spec=
, y puede obtener las especificaciones -dumpspecs
con -dumpspecs
IIRC.
Esto probablemente se explica en alguna parte en el manual de GCC.
Parece que es necesario para la compilación cruzada. Desde el ChangeLog:
Wed Mar 29 14:53:23 1995 Jim Wilson <[email protected]>
* gcc.c (process_command): Delete code modifying gcc_exec_prefix.
(main): Put it here after last use of gcc_exec_prefix. For cross
compiler, set startfile_prefixes if gcc_exec_prefix is set and
standard_startfile_prefix is a relative path.
startfile_prefixes
es lo que se está imprimiendo con las banderas search-dirs. Desde gcc/gcc.c
:
if (print_search_dirs)
{
printf (_("install: %s%s/n"), standard_exec_prefix, machine_suffix);
printf (_("programs: %s/n"), build_search_list (&exec_prefixes, "", 0));
printf (_("libraries: %s/n"), build_search_list (&startfile_prefixes, "", 0));
return (0);
}
Se trata de multilib en funcionamiento: un mecanismo que permite tener bibliotecas (pero también toda la compilación y compilación de herramientas) para múltiples arquitecturas en una sola máquina. Este Wiki afirma que "El sufijo multilib se agrega a todos los directorios buscados por GCC y se transfiere mediante las opciones -L al vinculador. El vinculador en sí no tiene ningún conocimiento particular de multilibs, y continuará consultando sus directorios de búsqueda predeterminados si no se encuentra una biblioteca en las rutas -L. Si se usan varias opciones ortogonales de cambio de ABI en una sola compilación, se pueden usar múltiples sufijos multilib en serie ".
Por lo tanto, de acuerdo con la descripción anterior, la cadena del marcador de arquitectura o diferentes variantes de la misma se agregan a cada ruta de búsqueda de biblioteca que recibe el compilador, ya que no distingue entre rutas predeterminadas y personalizadas. Su ruta personalizada es la primera en la fila, pero sufre el mismo proceso de "expansión" que otras rutas.
Debido a la necesidad de manejar la compatibilidad con i386, parece que los mecanismos multilib ahora se usan de forma predeterminada en la mayoría de las distribuciones x64, lo que en la práctica significa la mayoría de las instalaciones disponibles.
Tengo exactamente el mismo problema en:
Fedora 17, gcc 4.7 and gcc 4.3
CentOS 6.3, gcc 4.4
Unubuntu 12, gcc 4.6
Así que parece que este es un problema con la mayoría de las versiones de gcc. Probablemente este extraño comportamiento apareció por primera vez en gcc 4.2 al menos de acuerdo con this .
Traté de engañar las especificaciones y jugar con ellos. Parece que la especificación *multilib
se usa para agregar cadenas específicas dependiendo de la plataforma. Por ejemplo, mis espacios originales parecían:
*multilib:
. !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;
Cuando cambié 64:../lib64
a 64:../lib
, en lugar de ../lib64
gcc anexado ../lib
. Pero no pude descifrar completamente el significado de *multilib
o cualquiera de las otras especificaciones.
Una pregunta similar se hizo aquí: g ++ busca /lib/../lib/, luego / lib /
Estas rutas de búsqueda de aspecto aterrador se determinan, al menos en parte, cuando el compilador se construyó, por ejemplo, durante la fase de configuración. Está claro que va más allá de las variables de entorno porque es posible tener varias copias de GCC instaladas y hacer que cada una de ellas dé resultados diferentes para gcc --print-search-dirs
. También observando que g++ --print-search-dirs
y gcc --print-search-dirs
dan diferentes resultados, señala que el contenedor g ++ también está afectando la ruta de búsqueda. Además de configurar / construir las diferencias de tiempo, GCC es definitivamente consciente de la ruta donde se encuentra su propio ejecutable, y buscará los subdirectorios de esa ruta. Mucha de esta alquimia se puede encontrar en la documentación de GCC:
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Directory-Options.html#Directory-Options
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Environment-Variables.html#Environment-Variables
Por lo que sé, lo más enérgico que puede hacer sin compilar su propia copia de GCC es especificar sus bibliotecas personalizadas con la opción -L. La razón por la que digo esto es porque antes se busca -L, por ejemplo, LIBRARY_PATH (consulte el enlace anterior sobre las variables de entorno). Para hacerlo más tolerable, puede agregar un alias para g ++ que incluya la opción -L en su archivo .bashrc.
Si desea una respuesta definitiva, descargar una copia del código fuente de GCC es una forma. Por ejemplo, en gcc.c aparece el siguiente comentario altamente sugerente:
/* Build a list of search directories from PATHS.
PREFIX is a string to prepend to the list.
If CHECK_DIR_P is true we ensure the directory exists.
If DO_MULTI is true, multilib paths are output first, then
non-multilib paths.
This is used mostly by putenv_from_prefixes so we use `collect_obstack''.
It is also used by the --print-search-dirs flag. */
Sin embargo, la función que sigue al comentario no es muy obvia.