#include "LinkStep.h" #include #include #include "sys.h" #include "logger.h" #include "globals.h" #include "BXParser.h" bool LinkStep::checkHasChanged(const std::string &outDir) { std::string targetPath = toolchain::targetFilePath(type_, path_, outDir); if (!sys::fileExists(targetPath)) { return true; } std::string confPath = this->confPath(outDir); if (!sys::fileExists(confPath)) { return true; } BXVariables cachedVariables; try { bufio::IFStream f(confPath); BXParser parser(f); parser.parse(cachedVariables); } catch (BXParseError &err) { logger::log(confPath + ": " + err.what()); return true; } auto commandIt = cachedVariables.find("command"); if (commandIt == cachedVariables.end()) { logger::log(confPath + ": Missing 'command' field"); return true; } if (linkCommand(outDir) != commandIt->second) { return true; } return false; } void LinkStep::doBuild(const std::string &outDir) { std::vector command = linkCommand(outDir); std::string dirPath = sys::dirname(outDir + '/' + path_); BXVariables newCachedVars = { { "command", command}, }; bufio::OFStream f(confPath(outDir)); BXWriter writer(f); writer.write(newCachedVars); sys::mkdirp(dirPath); sys::ProcConf conf; conf.print = true; conf.prefix = "(LD)"; sys::execute(command, conf); } toolchain::FileType LinkStep::doGetLinkType() { for (auto &child: children()) { if (child->linkType() == toolchain::FileType::CXX) { return toolchain::FileType::CXX; } } return toolchain::FileType::C; } std::vector &LinkStep::linkCommand(const std::string &outDir) { if (hasLinkCommand_) { return linkCommand_; } std::vector objs; for (auto &dep: deps_) { for (auto &obj: dep->publicObjects(outDir)) { objs.push_back(obj); } } // TODO: Don't use FileType::CXX hard-coded here linkCommand_ = toolchain::getLinkCommand( publicLDFlags(outDir), publicLDLibs(outDir), linkType(), type_, objs, path_, outDir); hasLinkCommand_ = true; return linkCommand_; }