• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Banana Make,只用一个make.h文件,取代那些令人生厌的gmake、nmake、cmake......构建系统

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
本文使用

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

许可。

项目地址:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



我不喜欢那些构建系统,我认为他们带头违反了他们自己制定的“机制优于策略”和“KISS”原则。为什么要学习那些丑陋死板的配置规则?图灵完备的脚本语言不更好吗?既然C编译器是必备的,那么把必要的功能封装进一个头文件里面,我总结最核心的就这几条:一、递归遍历文件目录;二、比较文件时间;三、串行、并行执行命令,不就能开心地用C语言写构建脚本了?客户也很高兴,因为他们完全不需要安装额外的构建系统,只需要键入gcc make.c && ./a.out或者cl make.c && make.exe就行了,多方便?

具体API定义,参见英文版文档,下面是一个范例:


#include "../banana-make/make.h"

#define prefix "js"
#define bin_dir "bin" pathsep
#define build_dir "build" pathsep
#define src_dir "src" pathsep
#define examples_dir "examples" pathsep
#define private_dir "private" pathsep
#define library_header_file src_dir prefix ".h"
#define dll_file_name prefix dllext
#define dll_file_path bin_dir dll_file_name
#define lib_file bin_dir prefix libext
char *cc_msvc = NULL;
char *cc_gcc = NULL;
char *link_msvc = NULL;
char *link_gcc = NULL;
double library_header_mtime = -DBL_MAX;
char *library_obj_files = NULL;
int library_link_required = false;

void compile_file(const char *c_file, const char *obj_file) {
char *cmd = compiler == msvc ? concat(cc_msvc, " /DDLL /DEXPORT /Fo", obj_file, " ", c_file) : concat(cc_gcc, " -D DLL -D EXPORT -o ", obj_file, " ", c_file);
async(cmd);
free(cmd);
}

void compile_library(const char *dir, const char *base, const char *ext) {
if (ext && equals(ext, ".c")) {
char *c_file = concat(dir, base, ext);
char *h_file = concat(dir, base, ".h");
char *obj_file = concat(build_dir, base, objext);
append(&library_obj_files, " ", obj_file);
if (max(library_header_mtime, mtime(c_file), mtime(h_file)) > mtime(obj_file)) {
compile_file(c_file, obj_file);
library_link_required = true;
}
free(obj_file);
free(h_file);
free(c_file);
}
}

void compile_executables(const char *dir, const char *base, const char *ext) {
if (ext && equals(ext, ".c")) {
char *c_file = concat(dir, base, ext);
char *obj_file = concat(build_dir, base, objext);
if (mtime(c_file) > mtime(obj_file) || library_link_required) {
compile_file(c_file, obj_file);
}
free(obj_file);
free(c_file);
}
}

void link_executables(const char *dir, const char *base, const char *ext) {
if (ext && equals(ext, ".c")) {
char *obj_file = concat(build_dir, base, objext);
char *exe_file = concat(bin_dir, base, exeext);
if (mtime(obj_file) > mtime(exe_file) || library_link_required) {
char *cmd;
cmd = compiler == msvc ? concat(link_msvc, " /out:", exe_file, " ", obj_file, " ", lib_file) : concat(link_gcc, " -o ", exe_file, " ", obj_file, " -L", bin_dir, " -l:", dll_file_name);
async(cmd);
free(cmd);
}
free(exe_file);
free(obj_file);
}
}

void build() {
library_header_mtime = mtime(library_header_file);
library_obj_files = (char *)calloc(1, 1);
listdir(src_dir, compile_library);
listdir(examples_dir, compile_executables);
listdir(private_dir, compile_executables);
await();
if (library_link_required || mtime(dll_file_path) == 0) {
char *cmd = compiler == msvc ? concat(link_msvc, " /dll /out:", dll_file_path, library_obj_files) : concat(link_gcc, " -shared -o ", dll_file_path, library_obj_files);
async(cmd);
free(cmd);
}
free(library_obj_files);
await();
listdir(examples_dir, link_executables);
listdir(private_dir, link_executables);
await();
}

void cleanup(const char *dir, const char *base, const char *ext) {
if (base) {
char *file_name = concat(dir, base, ext);
remove(file_name);
free(file_name);
} else {
listdir(dir, cleanup);
rmdir(dir);
}
}

int main(int argc, char **argv) {
enum {
debug,
ndebug,
release,
clean,
install,
help
} target;
if (argc == 1) {
target = debug;
} else if (argc == 2) {
if (equals(argv[1], "debug")) {
target = debug;
} else if (equals(argv[1], "ndebug")) {
target = ndebug;
} else if (equals(argv[1], "release")) {
target = release;
} else if (equals(argv[1], "clean")) {
target = clean;
} else if (equals(argv[1], "install")) {
target = install;
} else {
target = help;
}
} else {
target = help;
}
switch (target) {
case debug:
cc_msvc = "cl /nologo /c /W3 /MD";
cc_gcc = "gcc -c -Wall -std=gnu2x";
link_msvc = "link /nologo /debug";
link_gcc = "gcc -fvisibility=hidden -fvisibility-inlines-hidden -static -static-libgcc";
build();
return EXIT_SUCCESS;
case ndebug:
cc_msvc = "cl /nologo /c /W3 /MD /DNDEBUG";
cc_gcc = "gcc -c -Wall -std=gnu2x -DNDEBUG";
link_msvc = "link /nologo /debug";
link_gcc = "gcc -fvisibility=hidden -fvisibility-inlines-hidden -static -static-libgcc";
build();
return EXIT_SUCCESS;
case release:
cc_msvc = "cl /nologo /c /O2 /W3 /MD /DNDEBUG";
cc_gcc = "gcc -c -O3 -Wall -std=gnu2x -DNDEBUG";
link_msvc = "link /nologo";
link_gcc = "gcc -s -Wl,--exclude-all-symbols -fvisibility=hidden -fvisibility-inlines-hidden -static -static-libgcc";
build();
return EXIT_SUCCESS;
case clean:
listdir(bin_dir, cleanup);
listdir(build_dir, cleanup);
return EXIT_SUCCESS;
case install:
puts("Install");
return EXIT_SUCCESS;
default:
printf("Usage: %s [debug|ndebug|release|clean|install]\n", argv[0]);
return EXIT_FAILURE;
}
}


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу