#include "build.h" #include #include #include #include #include "sys.h" #include "BXParser.h" #include "CompileStep.h" #include "LinkStep.h" #include "logger.h" static std::string extension(const std::string &path) { size_t idx = path.find_last_of('.'); if (idx >= std::string::npos) { return ""; } char ext[16] = { 0 }; strncpy(ext, path.c_str() + idx, sizeof(ext) - 1); return ext; } static void addFile( std::string path, BXVariables variables, std::vector> &deps) { toolchain::FileType type; std::string ext = extension(path); if (ext == ".c") { type = toolchain::FileType::C; } else if (ext == ".C" || ext == ".cc" || ext == ".cxx" || ext == ".cpp") { type = toolchain::FileType::CXX; } else { return; } deps.push_back(std::make_unique(std::move(path), type, std::move(variables))); } static void findDeps( const std::string &dir, const std::string &name, const BXVariables &variables, std::vector> &deps) { std::string path = dir + "/" + name; sys::FileInfo info; try { info = sys::fileInfo(path); } catch (std::exception &ex) { logger::log(ex.what()); return; } if (info.isDir) { // May or may not need to copy variables BXVariables subvars; const BXVariables *varsptr = &variables; std::vector subpaths; // There might be a $path/build.bx. If there is, files in that dir // needs a new copy of variables, and that $path/build.bx might contain // a files property. if (sys::fileExists(path + "/build.bx")) { subvars = variables; varsptr = &subvars; std::ifstream stream = sys::ifstream("build.bx"); BXParser parser(stream, BXParser::FLAG_NONE); parser.parse(subvars); auto it = subvars.find("files"); if (it == subvars.end()) { sys::readDir(path, subpaths); } else { subpaths = it->second; subvars.erase(it); } } else { sys::readDir(path, subpaths); } std::sort(subpaths.begin(), subpaths.end()); for (auto &subpath: subpaths) { findDeps(path, subpath, *varsptr, deps); } } else { addFile(std::move(path), variables, deps); } } static std::string findTargetName(const BXVariables &variables) { auto it = variables.find("target"); if (it != variables.end() && it->second.size() != 0) { return it->second[0]; } // TODO: Find from deps return "target"; } std::unique_ptr buildDepTree(const std::string &outDir, BXVariables variables) { // Read config from file if (sys::fileExists("build.bx")) { std::ifstream stream = sys::ifstream("build.bx"); BXParser parser(stream, BXParser::FLAG_NONE); parser.parse(variables); } // Find source files/dirs std::vector sourcePaths; { auto it = variables.find("files"); if (it == variables.end()) { sys::readDir(".", sourcePaths); } else { sourcePaths = it->second; variables.erase(it); } } // Find dependencies std::vector> deps; for (std::string &path: sourcePaths) { findDeps(".", path, variables, deps); } std::unique_ptr link = std::make_unique( findTargetName(variables), toolchain::TargetType::BINARY); for (auto &dep: deps) { link->addChild(std::move(dep)); } return link; }