From 10fd7f926e9c7bf01862246e3cd866f4671758f7 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Sun, 13 Nov 2016 14:31:34 -0800 Subject: [PATCH] enormous speedup for compiling Wx resources Replace bin2c.cmake script with one written in C and compiled as an intermediate target. The C version is roughly 12000 times faster. On msys2, the cmake version takes 7.5 minutes on this system, while the C version takes 0.037 seconds. --- src/wx/CMakeLists.txt | 17 +++++++++------ src/wx/bin2c.c | 51 +++++++++++++++++++++++++++++++++++++++++++ src/wx/bin2c.cmake | 24 -------------------- 3 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 src/wx/bin2c.c delete mode 100644 src/wx/bin2c.cmake diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index ded3c76c..571a1f2f 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -89,20 +89,24 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # wxrc does not support xrs files in -c output (> 10x compression) -# so do it manually using slow but portable bin2c.cmake script +# we do it using the bin2.c utility + +ADD_EXECUTABLE(bin2c bin2c.c) +# don't want SDL_main here +SET_TARGET_PROPERTIES(bin2c PROPERTIES COMPILE_FLAGS "-Dmain=main") + ADD_CUSTOM_COMMAND(OUTPUT wxvbam.xrs WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND wxrc ${CMAKE_CURRENT_SOURCE_DIR}/xrc/*.xrc -o wxvbam.xrs DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/xrc/*.xrc) ADD_CUSTOM_COMMAND(OUTPUT builtin-xrc.h - COMMAND ${CMAKE_COMMAND} -DINFILE=wxvbam.xrs -DOUTFILE=builtin-xrc.h -DVARNAME=builtin_xrs -P ${CMAKE_CURRENT_SOURCE_DIR}/bin2c.cmake - DEPENDS wxvbam.xrs) + COMMAND bin2c wxvbam.xrs builtin-xrc.h builtin_xrs + DEPENDS bin2c wxvbam.xrs) # use a built-in vba-over.ini if no config file present ADD_CUSTOM_COMMAND(OUTPUT builtin-over.h - COMMAND ${CMAKE_COMMAND} -DINFILE=${CMAKE_CURRENT_SOURCE_DIR}/../vba-over.ini -DOUTFILE=builtin-over.h -DVARNAME=builtin_over -P ${CMAKE_CURRENT_SOURCE_DIR}/bin2c.cmake - DEPENDS ../vba-over.ini) - + COMMAND bin2c ${CMAKE_CURRENT_SOURCE_DIR}/../vba-over.ini builtin-over.h builtin_over + DEPENDS bin2c ../vba-over.ini) # I don't like duplicating/triplicating code, so I only declare # event handlers once, and copy them in other places they are needed @@ -179,7 +183,6 @@ SET( RES_WX ) SET( CM_STUFF - bin2c.cmake copy-events.cmake ) diff --git a/src/wx/bin2c.c b/src/wx/bin2c.c new file mode 100644 index 00000000..267efd24 --- /dev/null +++ b/src/wx/bin2c.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) { + char* in_file_name = argv[1]; + char* out_file_name = argv[2]; + char* var_name = argv[3]; + FILE* in_file = fopen(in_file_name, "rb"); + char* in_file_err = !in_file ? strerror(errno) : NULL; + FILE* out_file = fopen(out_file_name, "w"); + char* out_file_err = !out_file ? strerror(errno) : NULL; + unsigned char* buf = (unsigned char*)malloc(4096); + size_t bytes_read; + int file_pos = 0; + + if (!buf) return 1; + + if (!in_file) { + fprintf(stderr, "Can't open input file '%s': %s\n", in_file_name, in_file_err); + return 1; + } + + if (!out_file) { + fprintf(stderr, "Can't open '%s' for writing: %s\n", out_file_name, out_file_err); + return 1; + } + + fprintf(out_file, "/* generated from %s: do not edit */\n" + "const unsigned char %s[] = {\n", in_file_name, var_name); + + while ((bytes_read = fread(buf, 1, 4096, in_file))) { + int i = 0; + for (; i < bytes_read; i++) { + char* comma = feof(in_file) && i == bytes_read - 1 ? "" : ","; + + fprintf(out_file, "0x%02x%s", buf[i], comma); + + if (++file_pos % 16 == 0) fprintf(out_file, "\n"); + } + } + + fprintf(out_file, "};\n"); + + free(buf); + fclose(in_file); + fclose(out_file); + + return 0; +} diff --git a/src/wx/bin2c.cmake b/src/wx/bin2c.cmake deleted file mode 100644 index 6aaa17e2..00000000 --- a/src/wx/bin2c.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# portably convert binary file to header -FUNCTION(FILE2C INFILE VARNAME OUTFILE) - FILE(READ ${INFILE} HEXFILE HEX) - STRING(LENGTH ${HEXFILE} XRSLEN) - SET(HEXPOS 0) - FILE(WRITE ${OUTFILE} - "/* generated from ${INFILE}; do not edit */\n" - "const unsigned char ${VARNAME}[] = {") - WHILE(${HEXPOS} LESS ${XRSLEN}) - MATH(EXPR LPOS "${HEXPOS} % 32") - IF(NOT ${LPOS}) - FILE(APPEND ${OUTFILE} "\n") - ENDIF(NOT ${LPOS}) - STRING(SUBSTRING ${HEXFILE} ${HEXPOS} 2 HEXBYTE) - FILE(APPEND ${OUTFILE} "0x${HEXBYTE}") - MATH(EXPR HEXPOS "${HEXPOS} + 2") - IF(${HEXPOS} LESS ${XRSLEN}) - FILE(APPEND ${OUTFILE} ",") - ENDIF(${HEXPOS} LESS ${XRSLEN}) - ENDWHILE(${HEXPOS} LESS ${XRSLEN}) - FILE(APPEND ${OUTFILE} "};\n") -ENDFUNCTION(FILE2C) - -FILE2C(${INFILE} ${VARNAME} ${OUTFILE})