hash_t string_hash(const char *str_in) { return string_hash_add(5381, str_in); }
/* *** */ 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; }