В настоящее время я пытаюсь скомпилировать Clang/LLVM для голой металлической цели aarch64. Компилировать Clang было просто — на самом деле я скомпилировал для нескольких архитектур, включая arm и aarch64. Для бэкэнда я использую binutils. Поскольку binutils может работать только с одной архитектурой, я создал версии для aarch64 и arm. Снова строительство казалось простым. Я собрал binutils для aarch64, используя:
mkdir build
cd build
../configure --target=aarch64-none-elf
make
из распакованного исходного пакета binutils 2.24.
Проблема, с которой я сталкиваюсь, заключается в том, что я не могу заставить мою пользовательскую сборку ld правильно обрабатывать архивные файлы. Кажется, что он находит и открывает архивные файлы без проблем, но не может найти в них неопределенные символы при компиляции окончательного двоичного файла. Вот некоторые более конкретные детали на примере:
Создайте простой файл main.s, скомпилировав:
int foo();
int main() { return foo(); }
с Clang и с использованием --target=aarch64 -S, т.е. для создания файла сборки для конкретной архитектуры.
Сделайте то же самое, чтобы создать foo.s, скомпилировав:
int foo() { return 0; }
Соберите оба файла .s в файлы .o, используя специальную сборку газа из binutils.
Создайте архив libfoo.a, запустив пользовательские сборки ar и ranlib из binutils, используя ar cr foo.a foo.s и ranlib libfoo.a.
Попробуйте связать два файла вместе, используя ld -L. -lfoo -o main.elf main.o.
Вывод показывает неопределенную ссылку на foo.
bar.cpp:(.text+0x14): undefined reference to `foo()'
Я могу запустить readelf на foo.a, и он выглядит прекрасно. В частности, я вижу общедоступный символ для foo. Если я запускаю ld с параметром --verbose, я вижу
attempt to open ./libfoo.a succeeded
но нет признаков того, что он нашел какие-либо символы.
Если я напрямую связываюсь с объектными файлами, то есть использую ld -o main.elf foo.o main.o, то я получаю хорошо сформированный файл elf. Кроме того, если я извлеку foo.o обратно из libfoo.a, я также смогу успешно скомпоновать извлеченный foo.o.
У кого-нибудь есть идеи, почему это может происходить? Я почти уверен, что моя сборка clang в порядке, так как выпущенные файлы сборки эффективно отделяют проблему от clang. Я также предполагаю, что собранные файлы .o в порядке. Таким образом, виновником остается только ar/ranlib или ld.
Чтобы попытаться устранить ar/ranlib как виновников, я пересобрал binutils для arm (те же шаги, но с использованием --target=arm-none-eabi). Если я интегрирую встроенные двоичные файлы ar/ranlib в заведомо исправную цепочку инструментов arm-eabi-none GCC, то они, похоже, будут работать правильно. Таким образом, мои подозрения на данный момент указывают на ld. Обратите внимание, что у меня возникает та же проблема с примером main/foo, что и выше, если я использую свою сборку Clang с сборкой binutils для рук.
Я также попытался интегрировать версию ld для руки в существующую хорошо известную цепочку инструментов GCC, но получил:
this linker was not configured to use sysroots
Нужно в этом разобраться. Это все еще немного загадочно для меня прямо сейчас. Это мешает мне проверить работоспособность сборки руки ld.
Вполне может быть, что я делаю что-то явно не так, но сейчас я этого не вижу.
Примечания:
Мне пришлось взломать скрипт make для binutils, чтобы добавить пару флагов -Wno-xxx. Мне нужно сделать это "правильным" способом, но я не думаю, что этот хак должен повлиять на результат.
Я создаю/размещаю все инструменты на OSX 10.9.4 64-бит.
ОБНОВЛЕНИЕ:
Ошибка по поводу sysroots проста. Ранее существовавшая цепочка инструментов была настроена с помощью флагов:
--with-prefix $SOME_INSTALL_DIR
--with-sysroot $SOME_INSTALL_DIR/arm-none-eabi
Если я пересоберу с ними, то смогу без проблем вставить свою ld-версию, и она будет работать. Я обрадовался, думая, что это могло быть моей ошибкой. Раньше я не запускал make install, так как на данном этапе меня не особо интересовала установка. Я подумал, что, возможно, моя новая сборка ld каким-то образом ссылалась на системные библиотеки/исполняемые файлы OSX (хотя я не уверен, на что именно она могла ссылаться, кроме, возможно, ar, т.е. если она запускает ar для обработки архивов) . Однако у меня все еще есть одна и та же проблема с версиями binutils как для arm, так и для arrach64, даже при такой настройке.