Я пишу язык, используя 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