// HyperRogue: alternative build system // This reads the file 'hyper.cpp' and compiles the cpp files it includes into separate object files, and then links them. // Tested in Linux, should work in other systems with some changes. // Options: // -O2 -- optimize // -O3 -- optimize // -D... -- change compilation flags // [file.cpp] -- add a module to the build (e.g. ./mymake rogueviz) #include #include #include #include #include #include #include #include #include #include using namespace std; string opts; string default_standard = " -std=c++11"; string standard = default_standard; string preprocessor; string compiler; string linker; string libs; string default_exec_name; bool verbose = false; bool quiet = false; int batch_size = thread::hardware_concurrency() + 1; bool mingw64 = false; int sdlver = 1; int mysystem(string cmdline) { if(verbose) { printf("%s\n", cmdline.c_str()); } if (mingw64) cmdline = "sh -c '" + cmdline + "'"; // because system(arg) passes arg to cmd.exe on MinGW return system(cmdline.c_str()); } bool file_exists(string fname) { return access(fname.c_str(), F_OK) != -1; } #if defined(MAC) string os = "mac"; #elif defined(WINDOWS) string os = "mingw64"; #else string os = "linux"; #endif string exec_name = ""; void set_linux() { preprocessor = "g++ -E"; compiler = "g++ -Wall -Wextra -Wno-maybe-uninitialized -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-invalid-offsetof -rdynamic -fdiagnostics-color=always -c"; linker = "g++ -rdynamic"; default_exec_name = "hyper"; if(sdlver == 2) { opts = "-DFHS -DLINUX -I/usr/include/SDL2"; libs = " -lSDL2 -lSDL2_ttf -lSDL2_mixer -lSDL2_gfx -lGLEW -lGL -lpng -rdynamic -lpthread -lz"; } else if(sdlver == 1) { opts = "-DFHS -DLINUX -I/usr/include/SDL"; libs = " -lSDL -lSDL_ttf -lSDL_mixer -lSDL_gfx -lGLEW -lGL -lpng -rdynamic -lpthread -lz"; } else { opts = "-DFHS -DLINUX"; libs = " -rdynamic -lpthread -lz"; } } void set_mac() { preprocessor = "g++ -E"; compiler = "g++ -W -Wall -Wextra -Wsuggest-override -pedantic -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-invalid-offsetof -c"; linker = "g++"; default_exec_name = "hyper"; opts = "-DMAC -I/usr/local/include"; libs = " -L/usr/local/lib -framework AppKit -framework OpenGL -lSDL -lSDLMain -lSDL_gfx -lSDL_mixer -lSDL_ttf -lpng -lpthread -lz"; } void set_mingw64() { mingw64 = true; preprocessor = "g++ -E"; compiler = "g++ -mwindows -W -Wall -Wextra -Wno-unused-parameter -Wno-invalid-offsetof -Wno-implicit-fallthrough -Wno-maybe-uninitialized -c"; linker = "g++"; default_exec_name = "hyper"; opts = "-DWINDOWS -DCAP_GLEW=1 -DCAP_PNG=1"; libs = " hyper.res -lopengl32 -lSDL -lSDL_gfx -lSDL_mixer -lSDL_ttf -lpthread -lz -lglew32 -lpng"; setvbuf(stdout, NULL, _IONBF, 0); // MinGW is quirky with output buffering } /* cross-compile Linux to Windows (tested on Archlinux) */ void set_mingw64_cross() { preprocessor = "x86_64-w64-mingw32-g++ -E"; compiler = "x86_64-w64-mingw32-g++ -mwindows -W -Wall -Wextra -Wno-unused-parameter -Wno-invalid-offsetof -Wno-implicit-fallthrough -Wno-maybe-uninitialized -c"; linker = "x86_64-w64-mingw32-g++"; default_exec_name = "hyper.exe"; opts = "-DWINDOWS -DGLEW_STATIC -DUSE_STDFUNCTION=1 -DCAP_PNG=1"; if(sdlver == 1) opts += " -I /usr/x86_64-w64-mingw32/include/SDL/"; if(sdlver == 2) opts += " -I /usr/x86_64-w64-mingw32/include/SDL2/"; libs = " hyper64.res -static-libgcc -lopengl32"; if(sdlver == 1) libs += " -lSDL -lSDL_gfx -lSDL_mixer -lSDL_ttf"; if(sdlver == 2) libs += " -lSDL2 -lSDL2_gfx -lSDL2_mixer -lSDL2_ttf"; libs += " -lpthread -lz -lglew32 -lpng"; setvbuf(stdout, NULL, _IONBF, 0); // MinGW is quirky with output buffering if(!file_exists("hyper64.res")) mysystem("x86_64-w64-mingw32-windres hyper.rc -O coff -o hyper64.res"); } void set_web() { preprocessor = "/usr/lib/emscripten/em++ -E"; compiler = "/usr/lib/emscripten/em++ -c -Wno-invalid-offsetof"; default_standard = standard = " -std=c++17"; opts = "-DISWEB=1"; linker = "/usr/lib/emscripten/em++ -O2 -s USE_ZLIB=1 -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 -s TOTAL_MEMORY=512MB " "-s STACK_SIZE=1048576 " "-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"FS\",\"ccall\"]' " "-s EXPORTED_FUNCTIONS=\"['_main', '_use_file']\" " "-s DISABLE_EXCEPTION_CATCHING=0"; default_exec_name = "mhyper.html"; libs = ""; } void set_os(string o) { os = o; if(os == "linux") set_linux(); else if(os == "mac") set_mac(); else if(os == "mingw64") set_mingw64(); else if(os == "mingw64-cross") set_mingw64_cross(); else if(os == "web") set_web(); else { fprintf(stderr, "unknown OS"); exit(1); } } vector modules; vector hidden_dependencies; time_t get_file_time(const string s) { struct stat attr; if(stat(s.c_str(), &attr)) return 0; time_t res = attr.st_mtime; for(auto& hd: hidden_dependencies) if(s.substr(0, hd.size()) == hd) { int pos = 0; vector slashes = {0}; int numslash = 0; for(char c: s) { pos++; if(c == '/') slashes.push_back(pos), numslash++; } ifstream ifs(s); string s1; while(getline(ifs, s1)) { if(s1.substr(0, 10) == "#include \"") { string t = s1.substr(10); t = t.substr(0, t.find("\"")); int qdot = 0; while(t.substr(0, 3) == "../" && qdot < numslash) qdot++, t = t.substr(3); string u = s.substr(0, slashes[numslash - qdot]) + t; res = max(res, get_file_time(u)); } } } return res; } int optimized = 0; string obj_dir = "mymake_files"; string setdir = "../"; int main(int argc, char **argv) { set_os(os); int retval = 0; // for storing return values of some function calls for(string fname: {"Makefile.loc", "Makefile"}) if(file_exists(fname)) { retval = mysystem("make -f " + fname + " language-data.cpp autohdr.h"); if (retval) { printf("error during preparation!\n"); exit(retval); } break; } for(int i=1; i