2015-09-23 3 views
2

Альтернативное название: Почему мой dylib включает в себя дополнительные экспортированные символы при компиляции Xcode vs Makefile?Почему порядок флагов компилятора clang влияет на итоговый двоичный размер?

Наша компания строит динамическую библиотеку C++ с использованием clang, и мы недавно перенесли наш обработанный вручную Makefile в систему сборки CMake и теперь используем сгенерированные проекты Xcode. Убедившись, что все флаги компилятора/компоновщика и переменные среды точно совпадают между двумя системами, мы заметили, что dylib, созданный CMake/Xcode, был немного больше. Более тщательное обследование показало, что в нем содержатся некоторые дополнительные экспортированные символы (из шаблонных функций, которые никогда не ссылались и, следовательно, никогда не должны были быть созданы), конкретные шаблоны имели свои определения и специализации в исходных файлах, поскольку мы часто используем явные экземпляры, хотя в этом случае они не были явно созданы). Изучение разборки некоторых объектных файлов также показало небольшие различия в инструкциях. Единственное, что получило библиотеки в соответствии с размерами и символами, было именно в соответствии с порядком флагов компилятора точно. По-видимому, это демонстрирует некоторое зависящее от порядка взаимодействие между флагами компилятора, которые выглядят как ошибка компилятора или, по крайней мере, плохо документированное поведение.

Для этого конкретного вопроса, это был компилятор вызовы:

clang++ -fvisibility=hidden -fvisibility-ms-compat -c foo.cpp -o foo.o 

clang++ -fvisibility-ms-compat -fvisibility=hidden -c foo.cpp -o foo.o 

И это компоновщик призывание:

clang++ -dynamiclib -o libfoo.dylib foo.o 

Отображения экспортируемых символов с:

nm -g libfoo.dylib 

показал различия. Я представил это LLVM Bug.

Есть ли когда-нибудь какие-либо правильные ситуации, когда вопросы заказа флагов компилятора важны?

+0

Также обратите внимание, что если вы пытаетесь точно соответствовать бинарным размерам, каталог, в котором выполняется компиляция, имеет значение, если вы включаете в себя отладочные символы (-g), поскольку путь к файлу будет содержаться в объектных файлах. – jinxcat2008

ответ

1

Компиляторы Microsoft и почти все остальные традиционно имели очень разные модели для видимости символов в объектном файле. Первый уже давно использует расширения языка C и C++ для управления выбросом символов компилятором и по умолчанию не экспортирует символы.

Похоже, что -fvisibility=hidden и -fvisibility-ms-compat являются взаимоисключающими и что компилятор отмечает последний вид своей командной строки.

Справедливости ради, есть небольшая документация для -fvisibility-ms-compat, которую нужно иметь - кроме фиксации, добавляя ее к clang.

+0

Я нашел некоторую официальную документацию для -fvisibility-ms-compat [здесь] (https://developer.apple.com/library/mac/technotes/tn2185/_index.html), которая гласит: -fvisibility = hidden не действует, когда -fvisibility-ms-compat также находится в командной строке. Это указывает на то, что флаги являются взаимоисключающими, однако я до сих пор не понимаю, почему порядок флагов будет иметь какой-либо эффект. Является ли типичной практикой для компиляторов отменять флаги на основе их относительных позиций? Есть ли другие примеры, где ожидается такой тип поведения? – jinxcat2008