From 8a3daba2ce4cfa292b92a25679fb5d8fa596521b Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Fri, 8 Sep 2017 20:54:16 +0200 Subject: [PATCH] all-in-one: basic support for building an all-in-one c file --- CMakeLists.txt | 28 ++++++++++++++++++- allinone/build.js | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 allinone/build.js diff --git a/CMakeLists.txt b/CMakeLists.txt index 313dcbe..c541847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ else() endif() file(GLOB_RECURSE SOURCES_SRC src/*.c src/*.h) +file(GLOB_RECURSE SOURCES_SRC_C src/*.c) file(GLOB_RECURSE SOURCES_INCLUDE include/*.h) file(GLOB SOURCES_TEST test/*.c) file(GLOB_RECURSE SOURCES_TEST_SHARED test/shared/*.c test/shared/*.h) @@ -33,7 +34,30 @@ foreach(HEADER_SOURCE ${SOURCES_INCLUDE}) get_filename_component(HEADER_NAME ${HEADER_SOURCE} NAME_WE) string(TOUPPER ${HEADER_NAME} HEADER_NAME_UC) - set(DLL_NAME "${HEADER_NAME}") + set(ALLINONE_NAME "${HEADER_NAME}-all-in-one.c.out") + set(ALLINONE_SRC_C "allinone/${HEADER_NAME}-all-in-one.c") + add_custom_command( + OUTPUT ${ALLINONE_SRC_C} + COMMAND node allinone/build.js ${HEADER_SOURCE} ${SOURCES_SRC_C} > ${ALLINONE_SRC_C} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + IMPLICIT_DEPENDS c ${SOURCES_INCLUDE} ${SOURCES_SRC} + ) + + add_custom_target(${ALLINONE_NAME} DEPENDS ${ALLINONE_SRC_C}) + + set(ALLINONE_DLL_NAME "${HEADER_NAME}-all-in-one.dll") + set(ALLINONE_DLL_OUTPUT "${HEADER_NAME}-all-in-one") + add_library(${ALLINONE_DLL_NAME} SHARED ${ALLINONE_SRC_C}) + if(MSVC) + target_compile_definitions(${ALLINONE_DLL_NAME} PUBLIC "-D${HEADER_NAME_UC}_EXTERN=__declspec(dllexport)" ) + else() + target_compile_definitions(${ALLINONE_DLL_NAME} PUBLIC "-D${HEADER_NAME_UC}_EXTERN=__attribute__((visibility(\"default\")))") + endif() + set_target_properties(${ALLINONE_DLL_NAME} PROPERTIES OUTPUT_NAME ${ALLINONE_DLL_OUTPUT}) + + + set(DLL_NAME "${HEADER_NAME}.dll") + set(DLL_OUTPUT "${HEADER_NAME}") add_library(${DLL_NAME} SHARED ${HEADER_SOURCE} ${SOURCES_SRC}) target_include_directories(${DLL_NAME} PUBLIC include) if(MSVC) @@ -43,4 +67,6 @@ foreach(HEADER_SOURCE ${SOURCES_INCLUDE}) target_compile_options(${DLL_NAME} PUBLIC -include ${HEADER_SOURCE} -fvisibility=hidden) target_compile_definitions(${DLL_NAME} PUBLIC "-D${HEADER_NAME_UC}_EXTERN=__attribute__((visibility(\"default\")))") endif() + set_target_properties(${DLL_NAME} PROPERTIES OUTPUT_NAME ${DLL_OUTPUT}) + endforeach(HEADER_SOURCE ${SOURCES_INCLUDE}) diff --git a/allinone/build.js b/allinone/build.js new file mode 100644 index 0000000..10a742f --- /dev/null +++ b/allinone/build.js @@ -0,0 +1,71 @@ +var path = require('path'); + +var fs = require('fs'); +var included = {}; + +function lines(filename) { + if (/[\/\\]/.test(filename)) + return fs.readFileSync(filename, 'utf8').split(/\r?\n/g); + + var PATH = [ '.', 'include', 'src' ]; + for (;;) { + var dir = PATH.shift(); + try { + return fs.readFileSync(dir + '/' + filename, 'utf8').split(/\r?\n/g); + } catch (e) { + if (PATH.length == 0) + throw e; + } + } +} + +function comment(s) { + return ''; //'/* ' + s + '*/' +} + +function include(line, filename) { + var key = path.basename(filename).toLowerCase(); + if (included[key]) + return comment(line); + console.error("Including: " + key); + included[key] = true; + return lines(filename); +} + +var sys_included = {}; +function include_sys(line, filename) { + var key = path.basename(filename).toLowerCase(); + if (sys_included[key]) + return comment(line); + + sys_included[key] = true; +} + +var source = []; +for (var i = 2; i < process.argv.length; i++) { + var filename = process.argv[i]; + source = source.concat(include(null, filename)); +} + +var patterns = [ + {re : /^\s*#include\s*"([^"]*)".*$/, fn : include}, + {re : /^\s*#include\s*<([^"]*)>.*$/, fn : include_sys} +] + +restart: for (var lno = 0; lno < source.length;) { + for (var i in patterns) { + var line = source[lno]; + var pattern = patterns[i]; + var match = pattern.re.exec(line); + if (match) { + var repl = pattern.fn.apply(null, match); + if (repl != null && repl !== line) { + source.splice.apply(source, [ lno, 1 ].concat(repl)); + continue restart; + } + } + } + lno++; +} + +console.log(source.join('\n'));