Почему g++ выглядит в LIBRARY_PATH/../lib64 и где это документировано?

В моей переменной среды LIBRARY_PATH есть пользовательский каталог: /cs/public/lib/pkg/opencv/lib.

Но, когда я использую g++ --print-search-dirs, я получаю это вместо:

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/

Почему g++ просматривает эти альтернативы и целую кучу других системных местоположений до того, что я явно указываю в переменной LIBRARY_PATH, и где это документировано?

Я бы понял, были ли поиск по умолчанию по умолчанию в LIBRARY_PATH и LIBRARY_PATH/../lib64 и т.д., но g++ помещает LIBRARY_PATH/../lib64, затем в системные пути, затем в LIBRARY_PATH. Где зарегистрировано это упорядочение?

Моя версия g++ g++ (SUSE Linux) 4.6.2

Моя ОС openSUSE 12.1 (x86_64)

Ответ 1

Здесь был задан аналогичный вопрос: g++ ищет /lib/../lib/, затем/lib/

Эти пугающие поисковые пути определяются, по крайней мере частично, при создании самого компилятора, например, во время фазы конфигурации. Ясно, что он выходит за пределы переменных среды, поскольку можно установить несколько копий GCC и дать каждому из них разные результаты для gcc --print-search-dirs. Также отмечая, что g++ --print-search-dirs и gcc --print-search-dirs дают разные результаты, указывает, что оболочка g++ также влияет на путь поиска. Помимо различий времени конфигурирования и сборки, GCC определенно знает путь, где находится его собственный исполняемый файл, и будет искать подкаталоги этого пути. Много этой алхимии можно найти в документации 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

Насколько я знаю, самое сильное, что вы можете без компиляции своей собственной копии GCC, - это указать свои пользовательские библиотеки, используя опцию -L. Причина, по которой я говорю это, заключается в том, что -L выполняется поиск до, например, LIBRARY_PATH (см. Выше ссылку на переменные среды). Чтобы сделать его более терпимым, вы можете добавить псевдоним для g++, включая параметр -L в ваш .bashrc файл.

Если вы хотите получить окончательный ответ, то загрузка копии исходного кода GCC будет одним из способов. Например, в gcc.c появляется следующий очень наводящий комментарий комментарий:

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

Однако функция, которая следует за комментарием, не очень очевидна.

Ответ 2

Это multilib на работе - механизм, который позволяет иметь библиотеки (но и всю сборку и сборку инструментальной цепочки) для нескольких архитектур на одной машине. В этой Wiki указано, что "Суффикс multilib добавляется ко всем каталогам, которые искали библиотеки GCC и передавались через компоновщики -L в компоновщик. не имеет особых знаний о multilibs и будет продолжать консультироваться со своими каталогами поиска по умолчанию, если библиотека не найдена в путях -L. Если в одной компиляции используются несколько ортогональных вариантов изменения ABI, можно использовать несколько суффиксов multilib последовательно.".

Таким образом, согласно вышеприведенному описанию, строка маркера архитектуры или различные ее варианты добавляются к каждому пути поиска библиотеки, который получает компилятор, поскольку он не проводит различия между стандартными и настраиваемыми путями. Ваш собственный путь является первым в строке, но он проходит тот же процесс расширения, что и другие пути.

Из-за необходимости обращаться с совместимостью i386, механизмы multilib, по-видимому, теперь используются по умолчанию для большинства дистрибутивов x64, что на практике означает большинство установок там.

Ответ 3

У меня есть такая же проблема:

Fedora 17, gcc 4.7 and gcc 4.3
CentOS 6.3, gcc 4.4
Unubuntu 12, gcc 4.6

Итак, похоже, что это проблема с большинством версий gcc. Вероятно, это странное поведение впервые появилось в gcc 4.2, по крайней мере, согласно this.

Я попытался обмануть спецификации и сыграть с ними. Похоже, что спецификация *multilib используется для добавления определенных строк в зависимости от платформы. Например, мои оригинальные пространства выглядели так:

*multilib:
. !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;

Когда я изменил 64:../lib64 на 64:../lib, а вместо ../lib64 gcc добавил ../lib. Но я не мог полностью расшифровать значение *multilib или любой другой спецификации.

Ответ 4

Похоже, что это необходимо для кросс-компиляции. Из 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 - это то, что печатается с помощью флагов search-dirs. Из 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);
      }

Ответ 5

Компилятор сначала рассмотрит пути по умолчанию, а затем остальные. Как он сортируется, когда вы печатаете, я не сейчас, но он задокументирован здесь, 3.19 Переменные среды, влияющие на GCC.

Ответ 6

Пути определяются встроенными спецификациями. Спецификации определяют, как конвейер обрабатывает исходный код для получения результата. GCC просто управляет компиляцией.

Вы можете предоставить GCC свой собственный файл спецификации через -spec=, и вы можете получить встроенные спецификации с помощью -dumpspecs IIRC.

Это, вероятно, объясняется где-то в руководстве GCC.