| #define STB_DEFINE |
| #include "stb.h" |
| |
| // true if no error |
| int run_command(char *batch_file, char *command) |
| { |
| char buffer[4096]; |
| if (batch_file[0]) { |
| sprintf(buffer, "%s && %s", batch_file, command); |
| return system(buffer) == 0; |
| } else { |
| return system(command) == 0; |
| } |
| } |
| |
| typedef struct |
| { |
| char *compiler_name; |
| char *batchfile; |
| char *objdir; |
| char *compiler; |
| char *args; |
| char *link; |
| } compiler_info; |
| |
| compiler_info *compilers; |
| char *shared_args; |
| char *shared_link; |
| |
| typedef struct |
| { |
| char *filelist; |
| } project_info; |
| |
| project_info *projects; |
| |
| enum { NONE, IN_COMPILERS, IN_ARGS, IN_PROJECTS, IN_LINK }; |
| |
| int main(int argc, char **argv) |
| { |
| int state = NONE; |
| int i,j,n; |
| char **line; |
| if (argc != 2) stb_fatal("Usage: stb_build_matrix {build-file}\n"); |
| line = stb_stringfile(argv[1], &n); |
| if (line == 0) stb_fatal("Couldn't open file '%s'\n", argv[1]); |
| |
| for (i=0; i < n; ++i) { |
| char *p = stb_trimwhite(line[i]); |
| if (p[0] == 0) continue; |
| else if (p[0] == '#') continue; |
| else if (0 == stricmp(p, "[compilers]")) { state = IN_COMPILERS; } |
| else if (0 == stricmp(p, "[args]" )) { state = IN_ARGS ; shared_args = NULL; } |
| else if (0 == stricmp(p, "[projects]" )) { state = IN_PROJECTS ; } |
| else if (0 == stricmp(p, "[link]" )) { state = IN_LINK ; shared_link = NULL; } |
| else { |
| switch (state) { |
| case NONE: stb_fatal("Invalid text outside section at line %d.", i+1); |
| case IN_COMPILERS: { |
| char buffer[4096]; |
| int count; |
| compiler_info ci; |
| char **tokens = stb_tokens_stripwhite(p, ",", &count), *batch; |
| if (count > 3) stb_fatal("Expecting name and batch file name at line %d.", i+1); |
| batch = (count==1 ? tokens[0] : tokens[1]); |
| if (strlen(batch)) |
| sprintf(buffer, "c:\\%s.bat", batch); |
| else |
| strcpy(buffer, ""); |
| ci.compiler_name = strdup(tokens[0]); |
| ci.batchfile = strdup(buffer); |
| ci.compiler = count==3 ? strdup(tokens[2]) : "cl"; |
| if (0==strnicmp(batch, "vcvars_", 7)) |
| ci.objdir = strdup(stb_sprintf("vs_%s_%d", batch+7, i)); |
| else |
| ci.objdir = strdup(stb_sprintf("%s_%d", batch, i)); |
| ci.args = shared_args; |
| ci.link = shared_link; |
| stb_arr_push(compilers, ci); |
| break; |
| } |
| case IN_ARGS: { |
| stb_arr_push(shared_args, ' '); |
| for (j=0; p[j] != 0; ++j) |
| stb_arr_push(shared_args, p[j]); |
| break; |
| } |
| case IN_LINK: { |
| stb_arr_push(shared_link, ' '); |
| for (j=0; p[j] != 0; ++j) |
| stb_arr_push(shared_link, p[j]); |
| break; |
| } |
| case IN_PROJECTS: { |
| project_info pi; |
| pi.filelist = strdup(p); |
| stb_arr_push(projects, pi); |
| break; |
| } |
| } |
| } |
| } |
| |
| _mkdir("obj"); |
| for (j=0; j < stb_arr_len(compilers); ++j) { |
| char command[4096]; |
| for (i=0; i < stb_arr_len(projects); ++i) { |
| int r; |
| _mkdir(stb_sprintf("obj/%s", compilers[j].objdir)); |
| if (stb_suffix(compilers[j].compiler, "cl")) |
| sprintf(command, "%s %.*s %s /link %.*s", |
| compilers[j].compiler, |
| stb_arr_len(compilers[j].args), compilers[j].args, |
| projects[i].filelist, |
| stb_arr_len(compilers[j].link), compilers[j].link); |
| else |
| sprintf(command, "%s %.*s %s %.*s", |
| compilers[j].compiler, |
| stb_arr_len(compilers[j].args), compilers[j].args, |
| projects[i].filelist, |
| stb_arr_len(compilers[j].link), compilers[j].link); |
| r = run_command(compilers[j].batchfile, command); |
| stbprint("{%c== Compiler %s == Building %s}\n", r ? '$' : '!', compilers[j].compiler_name, projects[i].filelist); |
| stb_copyfile("a.exe", stb_sprintf("obj/%s/a.exe", compilers[j].objdir)); |
| //printf("Copy: %s to %s\n", "a.exe", stb_sprintf("obj/%s/a.exe", compilers[j].objdir)); |
| stb_copyfile("temp.exe", stb_sprintf("obj/%s/temp.exe", compilers[j].objdir)); |
| system("if EXIST a.exe del /q a.exe"); |
| system("if EXIST temp.exe del /q temp.exe"); |
| system("if EXIST *.obj del /q *.obj"); |
| system("if EXIST *.o del /q *.o"); |
| if (!r) |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |