Скрипт написанный на питоне, генерирующий мейкфайл для вашего проекта по заданной схеме и настройкам компиляторов. Схема строится из целей, зависящий от друг друга. Проект создан и направлен на Школу Программирования 21 в Моксве и Казани.
- Одна папка - одна цель. За каждую папку отвечает своя цель в схеме
- Все артефакты сборки сохраняются в папку build, которая будет храниться в вашей основной директории от который вы будете строить мейкфайл.
- Поддерживаемые языки: C, C++, ASM (Nasm)
- root_dir/
- some_c_library/ # библиотека на C
- file1.c
- file2.c
- ...
- fileN.c
- h1.h
- h2.h
- ...
- hN.h
- some_cpp_library/ # библиотека на C++
- inc/
- header1.h
- header2.h
- file.cpp
- file1.cpp
- file2.cpp
- file3.c
- file4.cpp
- some_c_bundle/ # набор из библиотек
- include/
- lib_h1.h
- lib_h2.h
- lib_h3.h
- lib1/ # допустим что ее нельзя будет подключить без some_c_library
- src11.c
- src12.c
- src13.c
- lib2/
- src21.c
- sec22.c
- lib3/
- src3.c
- program_1/ # Использует библиотеку some_cpp_library и some_c_bundle и внешнюю библиотеку boost.System
- h1.h
- src1.cpp
- main.cpp
- program_2/ # Использует библиотеку some_c_library
- h1.h
- h2.h
- src1.c
- src2.c
- src3.c
- main.c
Допустим что у нас проект с такой структурой папок. Тогда что-бы сгенерировать мейкфайл, нужно заполнить launch.py таким образом:
from package import generate_makefile
SOME_C_LIB = {
"type": "lib",
"name": "some_c_lib",
"path": "some_c_library",
"sources": ["*.c", "fileN.c"], # Поддежка регулярных выражений для файлов в папке цели
}
SOME_CPP_LIB = {
"type": "lib",
"name": "some_cpp_lib",
"path": "some_cpp_library",
"sources": ["*.c", "*.cpp"],
"includes": ["some_cpp_library/inc"], # пути до папок с заголовоными файлами
}
BUNDLE_LIB1 = {
"type": "lib",
"name": "lib1",
"path": "some_c_bundle/lib1",
"sources": ["src11.c", "src12.c", "src13.c"],
"includes": ["some_c_bundle/include", "some_c_library"],
"peerdirs": [SOME_C_LIB] # указываем словарь с описание первой библиотеки
}
BUNDLE_LIB2 = {
"type": "lib",
"name": "lib2",
"path": "some_c_bundle/lib2",
"sources": ["src21.c", "src22.c"],
"includes": ["some_c_bundle/include"],
}
BUNDLE_LIB3 = {
"type": "lib",
"name": "lib3",
"path": "some_c_bundle/lib3",
"sources": ["src3.c"],
"includes": ["some_c_bundle/include"],
}
SOME_C_BUNDLE = {
"type": "bundle"
"peerdirs": [BUNDLE_LIB1, BUNDLE_LIB2, BUNDLE_LIB3],
}
PROGRAM_1 = {
"type": "prog",
"name": "program_1",
"path": "program_1",
"sources": ["*.cpp"],
"peerdirs": [SOME_CPP_LIB, SOME_C_BUNDLE],
"external_libs": {"boost_system", "path/to/boost_system_lib"}, # внешние библиотеку подрубаются через -l boost_system -L path/to/boost_system_lib
"out": ".", # результат сборки будет положен в папку ./
"compiler": "cpp", # сборка (линковка) идет через cpp-компилятор
"phtread": True
}
PROGRAM_2 = {
"type": "prog",
"name": "program_2",
"path": "program_2",
"sources": ["*.c"],
"peerdirs": [SOME_C_LIB],
"out": "."
}
# Теперь формируем гланый бандл, а то есть набор основных целей компиляции, куда входят наши программы
PROGRAMS_BUNDLE = {
"type": "bundle",
"peedirs": [PROGRAM_1, PROGRAM_2]
}
generate_makefile(BUNDLE, compiler_options={
"c": {
"flags": "-Wall -Werror -Wextra",
"binary": "clang"
},
"cpp": {
"flags": "-O2",
"binary": "clang++"
} # просто перечисляем, что бы генератор включил его в список файлов
})
Опция отвечающая за тип цели. Может быть "prog" если наша цель это исполняемый файл (по умолчанию), "lib" если наша цель это статическая библиотека, "bundle" если мы хотим объединить несколько целей в одну.
Для bundle - обязательно указать только "peerdirs" опцию, где мы перечислим объдиняемые цели.
Для prog и lib - обязательно указать "sources" и "name"
Имя цели, влияет на название финального объекта сборки. Для "prog" это имя исполняемого файла, а для "lib" имя статической библеотеки строится следующим образом: "lib{NAME}.a". Так-же имя выставляется в переменных мейкфайла и прочем. Имена не должны быть одинаковыми, поведение в такой ситуации не определенно.
Путь до папки где находятся исходники цели. Указывать желательно относительно корня проекта. Генерацию мейкфайла желательно производить в корневой папке проекта, иначе не будут работать шаблоны для имен исхоников ("*.c"). Две цели могут иметь одинаковый папки path, но это не желательно со стороны архитектуры проекта!
Путь до папки куда будет положен конечный результат работы правила makefile.
Пути до папок с заголовочными файлами (для С и С++) который подключаются через -I
Исходники которые находятся в "path". Для исходников работают шаблоны названий файлов ("*?[][!]"). Для их корректной работы вы должны генерировать свой мейкфайл из корня проекта!!! В зависимости от расширения имени файла, он будет скомпилирован каким то компилятором (".c", ".s", ".cpp"), расширение можно поменять в опциях комплиятора ("file_extenstion").
Зависимости цели, вы должны передать объекты других целей. Логично добавлять зависимости программы от библиотек или бандлов. Логично добавлять зависимости библиотеки от бандла или библиотеки. bundle принимает любые зависимости, потому что является набором целей, цели входящие в набор bundle указываются в поле "peerdirs"
Отвечает за подключение внешних бибилиотек. Вы должны указать словарь ключ/значение, где ключ это название библиотеки, а значение это папка где эта библиотека находится (если путь указать как пустую строку, то поиск будет вестить по стандратным путям)
Компилятор для линковки цели. Пока что возможны только компиляторы "c" и "cpp". "nasm" - используется только для компиляции конкретных объектников, линковка пока только через выше перечисленные компиляторы.
Если нужно подключить при линковке -pthread.
Настройки компилятора задаются словарем ключ/значения где ключ - название компилятора ("c","cpp","nasm"), а значения опции для каждого компилятора. Компиляторы используются для линковки всех объектников и для компиляции самих объектников. Линковка доступна только для "c" и "c++".
Опция для указания стандарта для "c" или "cpp", к примеру "-std=c99"
Флаги для компилятров. "flags" - флаги для компиляции и для линковки. "link_flags" - задаются только для линковки. "compile_flags" - флаги только для компиляции объектников. (При использовании "nasm" можно указывать только "flags".)
Программа для конкретного компилятора (для "c" к примеру clang)
Формат выходных файлов для nasm. Список доступных форматов можно увидеть в мануале nasm (nasm -hf
)
Расширение файлов исходника для выбора компилятора для компиляции объектных файлов. Для "c" это "c" :)