Невозможно связать библиотеку времени выполнения C (libcmt.lib) с помощью lld-link.exe (Windows) - PullRequest
1 голос
/ 16 мая 2019

Я пишу язык, используя LLVM.Я хотел бы избежать необходимости упаковывать clang и просто использовать инструменты LLVM (например, lld, lld-link).Я пытался вызвать функцию printf из моего простого ИК-кода (testinput.ll):

; ModuleID = 'Test2'
source_filename = "entry"

@str_0 = private unnamed_addr constant [13 x i8] c"Hello world!\00"

declare i32 @printf(i8*, ...)

define i32 @main() {
entry:
  %anonymous_10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @str_0, i32 0, i32 0))
  ret i32 1234
}

Но я продолжаю получать ошибки независимо от того, что я пытаюсь:

$ clang-cl -fuse-ld=lld-link testinput.ll "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\spectre\x64\libcmt.lib"

Примечание. Я случайно выбрал ссылку "... specter \ x64 \ libcmt.lib ...", просто выполнив поиск libcmt.lib в системе.

Ошибка:

C:\Program Files\LLVM\bin\lld-link: warning: libcmt.lib(loadcfg.obj): undefined symbol: __enclave_config
error: link failed
clang-cl.exe: error: linker command failed with exit code 1 (use -v to see invocation)

Я использую Windows 10 (x64) с LLVM 5.0.Интересно, что при использовании link.exe (компоновщик Windows 'VS tools') все работает нормально (именно это и использует Clang в моем случае).

Я прочитал в эту статью :

... Как я писал ранее, __enclave_config - это переменная, которая заполняется компоновщиком, но вы должны использовать компоновщик VC и достаточно новый компоновщик, чтобы иметь возможность автоматически заполнятьэто ...Является ли версия lld-link (LLVM 5.0) несовместимой с libcmt.lib, который я использую, в этом проблема?

Редактировать : мне удалось отследить, какой лязгделает за кулисами, и нашел его с помощью следующей команды:

lld-link -out:a.exe -defaultlib:libcmt "-libpath:C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\lib\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17763.0\\ucrt\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17763.0\\um\\x64" -nologo "test.obj"

Очевидно, что он использует lld-link, и он работает.Однако, как ни странно, он без ошибок компилируется, только если входной объектный файл был скомпилирован в .LL (LLVM IR) с использованием clang (возможно, с использованием -fuse-ld=lld -v параметров?).

Что странного в этом,проверка выходного файла .LL из clang (test.ll), полное определение исходного кода (в IR) для printf (и некоторых других используемых им функций * printf) присутствует (в выходном файле .LL).

Итак, каким-то образом он получает определения printf внутри выходного файла .LL, файла ИК-кода.

Насколько я знаю, вы не можете просто $ llc libcmt.lib testinput.ll?Это будет работа компоновщика ... (ООО принимает только один позиционный аргумент)

Ошибка, которую я получаю, когда пытаюсь использовать ту же команду и аргументы lld-link с my Файл testinput.ll (не выводится из clang) выглядит следующим образом:

lld-link: error: <root>: undefined symbol: _mainCRTStartup
lld-link: error: undefined symbol: _printf

1 Ответ

3 голосов
/ 16 мая 2019

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

Я понял это, сравнив выходной LL-файл clang, и заметил странную строку в начале:

target triple = "x86_64-pc-windows-msvc"

Как только я добавил его в свой файл testinput.ll, с lld-link все работало безупречно. Ура!

...