//#bb ldlibs := -lpthread #include #include #include #include #include #include "BBParser.h" #include "parallel.h" #include "toolchain.h" #include "globals.h" #include "logger.h" #include "sys.h" #include "build.h" #include "compdb.h" int main(int argc, char **argv) { std::string outDir = "bbbuild"; int jobs = parallel::coreCount() * 1.2 + 2; std::string workDir = ""; std::string target = ""; const char *shortopts = "hvo:j:C:cp"; const struct option opts[] = { { "help", no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, { "output", required_argument, NULL, 'o' }, { "jobs", required_argument, NULL, 'j' }, { "directory", required_argument, NULL, 'C' }, { "target", required_argument, NULL, 't' }, {}, }; const char usage[] = "Usage: bbbuild [options...] [sources]\n" "\n" " -h, --help " "Show this help text.\n" " -v, --verbose " "Show every command as it's executing.\n" " -o, --output " "Set output directory. Default: bbbuild\n" " -j, --jobs " "Set the number of jobs run simultaneously. " "Default: the number of cores in the machine.\n" " -C, --directory " "Change directory before doing anything else.\n"; // Parse options from argv while (1) { int optidx; int c = getopt_long(argc, argv, shortopts, opts, &optidx); if (c < 0) { break; } switch (c) { case 'h': puts(usage); return 0; case 'v': global::verbose += 1; break; case 'o': outDir = optarg; break; case 'j': jobs = atoi(optarg); if (jobs <= 0) { fprintf(stderr, "Can't run %i jobs.\n", jobs); return 1; } break; case 'C': workDir = optarg; break; default: printf("Unknown option: '%c'.\n%s", (char)c, usage); return 1; } } logger::LogContext logCtx = logger::init(); parallel::ParallelContext par = parallel::init(jobs); // Change directory? if (workDir.size() > 0) { fprintf(stderr, "Entering directory '%s'\n", workDir.c_str()); sys::chdir(workDir); } // Read in variables from conf if it exists BBVariables variables; if (sys::fileExists(outDir + "/.config.bb")) { std::ifstream f = sys::ifstream(outDir + "/.config.bb"); BBParser parser(f, BBParser::FLAG_NONE); parser.parse(variables); } // Read non-option arguments (variable definitions and args) bool varsChanged = false; std::vector args; while (optind < argc) { char *arg = argv[optind++]; char *eq = strchr(arg, '='); if (eq == nullptr) { args.push_back(arg); } else { varsChanged = true; std::stringstream val(eq + 1); BBParser parser(val, BBParser::FLAG_NONE); std::string key(arg, eq - arg); std::vector &list = variables[key]; list.clear(); parser.parseList(variables, list); } } // If our variables changed, write out the new ones if (varsChanged) { std::ofstream f = sys::ofstream(outDir + "/.config.bb"); BBWriter w(f); w.write(variables); } // Build dependency graph std::unique_ptr root = buildDepTree(outDir, variables); if (root == nullptr) { logger::log("No source files."); return 0; } sys::mkdirp(outDir); // Build compile commands { std::ofstream f = sys::ofstream(outDir + "/compile_commands.json"); compdb::Writer writer(f); root->writeCompDB(outDir, writer); sys::symlink(outDir + "/compile_commands.json", "compile_commands.json"); } // Build the project if (root->hasChanged(outDir)) { root->startBuild(outDir); root->joinBuild(); } else { logger::log("Nothing to do."); } }