Файл CMakeList для создания файла битового кода LLVM из исходного файла C

Я пытаюсь сгенерировать файл байт-кода LLVM из исходного файла C (hello.c) с помощью CMake. А ниже мой файл CMakeLists.

###### CMakelists.txt ############
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_C_FLAGS "-emit-llvm")

project (hello)
add_executable(hello hello.c)
  1. Я новичок в CMake и не уверен, что это правильный путь. Я не смог найти никаких правил для создания *.bc в сгенерированном MakeFile. . Пожалуйста, поправьте меня здесь. Я также пробовал "-save-temps"

  2. Учитывая это для одного файла .c. Было бы очень полезно, если бы вы могли дать мне несколько советов по созданию того же самого для полного проекта C.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
2 535
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я думаю, что вы в конечном итоге хотите, чтобы иметь возможность построить C-программу проект с CMake и clang, в котором исходные файлы скомпилированы в биткод LLVM и исполняемый файл связан с файлами битового кода.

При использовании CMake просьба к clang to связать файлы битового кода означает запрос на ссылку в режим LTO, с опцией связи -flto.

И вы можете получить clang для биткода компилировать в LLVM с компиляцией -flto или с опцией -emit-llvm.

Для иллюстрации вот проект Hello World, состоящий из двух исходных файлов и одного заголовка:

$ ls -R
.:
CMakeLists.txt  hello.c  hello.h  main.c

Здесь:

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project (hello)
set(CMAKE_C_COMPILER clang)
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-flto")
add_executable(hello main.c hello.c)
target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -flto)
#target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -emit-llvm)

Он будет одинаково хорошо работать с:

#target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -flto)
target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -emit-llvm)

Создайте каталог сборки для CMake и перейдите туда:

$ mkdir build
$ cd build

Сгенерируйте систему сборки:

$ cmake ..

Строить:

$ make
Scanning dependencies of target hello
[ 33%] Building C object CMakeFiles/hello.dir/main.c.o
[ 66%] Building C object CMakeFiles/hello.dir/hello.c.o
[100%] Linking C executable hello
[100%] Built target hello

Вы не найдете ни *.bc целей в Makefiles, ни *.bc файлов. сгенерировано:

$ egrep -r '.*\.bc'; echo Done
Done
$ find -name '*.bc'; echo Done
Done

потому что вариант компиляции -flto или -emit-llvm приводит к выводу файл:

CMakeFiles/hello.dir/main.c.o
CMakeFiles/hello.dir/hello.c.o

который соответствует обычному соглашению об именах CMake, но на самом деле не является объектный файл но файл битового кода LLVM, как вы видите:

$ file $(find -name '*.o')
./CMakeFiles/hello.dir/hello.c.o: LLVM IR bitcode
./CMakeFiles/hello.dir/main.c.o:  LLVM IR bitcode

Программа делает обычное дело:

$ ./hello 
Hello World!

Позже

When I try " make hello.o " it should generate the object file right? the cmd executes successfully but, could not find the generated object file. Am I doing it right?

Вы делаете это одним правильным способом, хотя и не единственным правильным, но ваши ожидания ошибочны. Посмотрите еще раз:

$ file $(find -name '*.o')
./CMakeFiles/hello.dir/hello.c.o: LLVM IR bitcode
./CMakeFiles/hello.dir/main.c.o:  LLVM IR bitcode

Вы можете видеть, что файлы .o, созданные из hello.c и main.c make-файлом, сгенерированным CMake, вызываются не hello.o и main.o, а hello.c.o и main.c.o. CMake предпочитает скомпилированное имя файла, чтобы сохранить расширение исходный файл и добавьте .o. Это довольно распространенная практика. Итак, если вы хотели использовать make-файл для компиляции hello.c, наиболее очевидным правильным способом будет make hello.c.o.

Давайте посмотрим, что происходит на самом деле. В моем каталоге сборки CMake:

$ make VERBOSE=1 hello.c.o
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/hello.c.o
make[1]: Entering directory '/home/imk/develop/so/scrap/build'
make[1]: 'CMakeFiles/hello.dir/hello.c.o' is up to date.
make[1]: Leaving directory '/home/imk/develop/so/scrap/build'

Делать было нечего, потому что мой hello.c.o был в актуальном состоянии. Так что я удалите его и повторите:

$ rm CMakeFiles/hello.dir/hello.c.o
$ make VERBOSE=1 hello.c.o
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/hello.c.o
make[1]: Entering directory '/home/imk/develop/so/scrap/build'
Building C object CMakeFiles/hello.dir/hello.c.o
clang   -flto -o CMakeFiles/hello.dir/hello.c.o   -c /home/imk/develop/so/scrap/hello.c
make[1]: Leaving directory '/home/imk/develop/so/scrap/build'

Теперь он был перекомпилирован.

Однако, поскольку многие люди, такие как вы, ожидают, что hello.o будет скомпилирован из hello.c, CMake услужливо определяет hello.o как .PHONY цель это зависит от hello.c.o:

$ egrep  -A3 'hello.o.*:.*hello.c.o' Makefile 
hello.o: hello.c.o

.PHONY : hello.o

Так что на самом деле я могу сделать:

$ rm CMakeFiles/hello.dir/hello.c.o
$ make VERBOSE=1 hello.o
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/hello.c.o
make[1]: Entering directory '/home/imk/develop/so/scrap/build'
Building C object CMakeFiles/hello.dir/hello.c.o
clang   -flto -o CMakeFiles/hello.dir/hello.c.o   -c /home/imk/develop/so/scrap/hello.c
make[1]: Leaving directory '/home/imk/develop/so/scrap/build'

make hello.o это еще один способ сделать hello.c.o

Спасибо за подробное объяснение. Я попытался и получил ошибку, связанную с золотым линкером. " ошибка при загрузке плагина: /usr/bin/../lib/LLVMgold.so: невозможно открыть общий объектный файл: нет такого файла или каталога " Я работаю над этим, но когда я пытаюсь " сделать hello.o ", он должен генерировать объектный файл не так ли? cmd выполняется успешно, но не может найти сгенерированный объектный файл. Правильно ли я делаю?

manojh93 01.03.2019 11:27

Спасибо, сэр, я понял это. Я хочу попросить вас еще об одной помощи. Основная цель — сгенерировать единый файл битового кода LLVM для всей программы. И LLVMgold нужно исключить. Итак, теперь у нас есть файлы битового кода, что нужно добавить в CMakelists.txt, чтобы он использовал llvm-link для создания окончательного файла битового кода, связывающего эти предыдущие. Не могли бы вы помочь мне с этим? Спасибо

manojh93 04.03.2019 11:47

@ manojh93 manojh93 Извините, в Stackoverflow вы не можете продолжать сворачивать вопрос в новые вопросы. См. Что мне делать, когда кто-то отвечает на мой вопрос?. Если у вас есть проблема, выходящая за рамки исходного вопроса, которую вы не можете решить самостоятельно, вам следует задать новый вопрос

Mike Kinghan 04.03.2019 12:05

Проблема в том, что использование флага -emit-llvm не создает окончательный двоичный файл и останавливает тесты конфигурации, которые выполняет CMake, когда в них используется этот флаг.

Помимо того, что уже было написано об использовании инфраструктуры ДН, у вас есть 3 (или 2 с половиной) других альтернативы.

Один из них — использовать Полная программа LLVM и использовать предоставленные команды для извлечения соответствующих частей битового кода.

Другой способ — вручную настроить пользовательские цели (см. add_custom_target и add_custom_command) на ваших двоичных целях CMake, которые будут срабатывать при изменениях и будут воспроизводить желаемый результат, как если бы каждый раз выполнялись вручную в командной строке.

Теперь, в этом последнем пункте, у меня была аналогичная потребность, поэтому я создал проект CMake, который обеспечивает эту функциональность (llvm-ir-cmake-утилиты), но позволяет вам подключать эти пользовательские цели к существующим, как вам угодно и сочтете нужным, без необходимости переписывать все из каждый раз царапать.

В репозитории есть примеры, но, короче говоря, он позволяет вам прикреплять пользовательские цели к уже существующим целям CMake, например.

[...]
add_executable(qux ${SOURCES})

[...]
# this will create a bitcode generating target 
# and allow it to depend on the initial target in order to detect source code changes
llvmir_attach_bc_target(qux_bc qux)
add_dependencies(qux_bc qux)
[...]

После сделать,

$>file CMakeFiles/hello.dir/hello.c.o
CMakeFiles/hello.dir/hello.c.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

если установить (CMAKE_C_FLAGS "-emit-llvm")

написано раньше

project (hello)

Чтобы получить биткод IR, я написал:

###### CMakelists.txt ############
cmake_minimum_required(VERSION 2.8.9)
project (hello)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_C_FLAGS "-flto")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-flto")
add_executable(hello hello.c)
target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -flto)

Я работал несколько часов, чтобы Makefile работал для компиляции из IR код в родной с помощью lld, тогда с cmake это было намного быстрее. Затем, прочитав сгенерированный cmake Makefile, я смог исправить свой Makefile:

clang  -flto  -flto <hello.c.o> ..

это сработало, но я не знаю, почему -flto пишется дважды.

Большое спасибо за этот пост, показывающий clang как централизованный интерфейс для различных команд, предоставляемых llvm.

Другие вопросы по теме