/* like file_createdir, but automatically creates all top-level directories needed If you feed it "output/somefiles/output.o" it will create "output/somefiles" */ int file_createpath(const char *output_name) { char buffer[MAX_PATH_LENGTH]; int i; char t; /* fish out the directory */ if(path_directory(output_name, buffer, sizeof(buffer)) != 0) { fprintf(stderr, "path error: %s\n", buffer); return -1; } /* no directory in path */ if(buffer[0] == 0) return 0; /* check if we need to do a deep walk */ if(file_createdir(buffer) == 0) return 0; /* create dir by doing a deep walk */ i = 0; while(1) { if((buffer[i] == '/') || (buffer[i] == 0)) { /* insert null terminator */ t = buffer[i]; buffer[i] = 0; if(file_createdir(buffer) != 0) { fprintf(stderr, "path error2: %s\n", buffer); return -1; } /* restore the path */ buffer[i] = t; } if(buffer[i] == 0) break; i++; } /* return success */ return 0; }
int lf_mkdir(struct lua_State *L) { if(lua_gettop(L) < 1) luaL_error(L, "mkdir: too few arguments"); if(!lua_isstring(L,1)) luaL_error(L, "mkdir: expected string"); if(file_createdir(lua_tostring(L,1)) == 0) lua_pushnumber(L, 1); else lua_pushnil(L); return 1; }
/* *** */ static int bam(const char *scriptfile, const char **targets, int num_targets) { struct CONTEXT context; int build_error = 0; int setup_error = 0; int report_done = 0; /* build time */ time_t starttime = time(0x0); /* create the cache and tmp directory */ file_createdir(".bam"); /* zero out and create memory heap, graph */ memset(&context, 0, sizeof(struct CONTEXT)); context.graphheap = mem_create(); context.deferredheap = mem_create(); context.graph = node_graph_create(context.graphheap); context.exit_on_error = option_abort_on_error; context.buildtime = timestamp(); /* create lua context */ /* HACK: Store the context pointer as the userdata pointer to the allocator to make sure that we have fast access to it. This makes the context_get_pointer call very fast */ context.lua = lua_newstate(lua_alloctor_malloc, &context); /* install panic function */ lua_atpanic(context.lua, lf_panicfunc); /* load cache (thread?) */ if(option_no_cache == 0) { /* create a hash of all the external variables that can cause the script to generate different results */ hash_t cache_hash = 0; char hashstr[64]; int i; for(i = 0; i < option_num_scriptargs; i++) cache_hash = string_hash_add(cache_hash, option_scriptargs[i]); string_hash_tostr(cache_hash, hashstr); sprintf(cache_filename, ".bam/%s", hashstr); event_begin(0, "cache load", cache_filename); context.cache = cache_load(cache_filename); event_end(0, "cache load", NULL); } /* do the setup */ setup_error = bam_setup(&context, scriptfile, targets, num_targets); /* done with the loopup heap */ mem_destroy(context.deferredheap); /* close the lua state */ lua_close(context.lua); /* do actions if we don't have any errors */ if(!setup_error) { event_begin(0, "prepare", NULL); build_error = context_build_prepare(&context); event_end(0, "prepare", NULL); if(!build_error) { event_begin(0, "prioritize", NULL); build_error = context_build_prioritize(&context); event_end(0, "prioritize", NULL); } if(!build_error) { if(option_debug_nodes) /* debug dump all nodes */ node_debug_dump(context.graph); else if(option_debug_nodes_detailed) /* debug dump all nodes detailed */ node_debug_dump_detailed(context.graph); else if(option_debug_jobs) /* debug dump all jobs */ node_debug_dump_jobs(context.graph); else if(option_debug_joblist) /* debug dumps the joblist */ context_dump_joblist(&context); else if(option_debug_dot) /* debug dump all nodes as dot */ node_debug_dump_dot(context.graph, context.target); else if(option_debug_jobs_dot) /* debug dump all jobs as dot */ node_debug_dump_jobs_dot(context.graph, context.target); else if(option_dry) { } else { /* run build or clean */ if(option_clean) { event_begin(0, "clean", NULL); build_error = context_build_clean(&context); event_end(0, "end", NULL); } else { event_begin(0, "build", NULL); build_error = context_build_make(&context); event_end(0, "build", NULL); report_done = 1; } } } } /* save cache (thread?) */ if(option_no_cache == 0 && setup_error == 0) { event_begin(0, "cache save", cache_filename); cache_save(cache_filename, context.graph); event_end(0, "cache save", NULL); } /* clean up */ mem_destroy(context.graphheap); free(context.joblist); cache_free(context.cache); /* print final report and return */ if(setup_error) { /* no error message on setup error, it reports fine itself */ return setup_error; } else if(build_error) printf("%s: error: a build step failed\n", session.name); else if(report_done) { if(context.num_jobs == 0) printf("%s: targets are up to date already\n", session.name); else { time_t s = time(0x0) - starttime; if(s <= 1) printf("%s: done\n", session.name); else printf("%s: done (%d:%.2d)\n", session.name, (int)(s/60), (int)(s%60)); } } return build_error; }