diff options
Diffstat (limited to 'src/task_ld.cc')
-rw-r--r-- | src/task_ld.cc | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/task_ld.cc b/src/task_ld.cc new file mode 100644 index 0000000..91f3316 --- /dev/null +++ b/src/task_ld.cc @@ -0,0 +1,227 @@ +#include "task_ld.h" + +#include <iostream> +#include <fstream> + +#include "libcppbuild.h" +#include "settings.h" +#include "execute.h" + +namespace +{ +std::string readFile(const std::string &fileName) +{ + std::ifstream ifs(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + + std::ifstream::pos_type fileSize = ifs.tellg(); + ifs.seekg(0, std::ios::beg); + + std::vector<char> bytes(fileSize); + ifs.read(bytes.data(), fileSize); + + return std::string(bytes.data(), fileSize); +} + +std::vector<std::string> addPrefix(const std::vector<std::string>& lst, + const Settings& settings) +{ + std::vector<std::string> out; + for(const auto& item : lst) + { + std::filesystem::path file = settings.builddir; + file /= item; + out.push_back(file.string()); + } + return out; +} +} // namespace :: + +TaskLD::TaskLD(const BuildConfiguration& config, + const Settings& settings, + const std::string& target, + const std::vector<std::string>& objects) + : Task(config, addPrefix(config.depends, settings)) + , config(config) + , settings(settings) +{ + target_type = TargetType::Executable; + + targetFile = settings.builddir; + targetFile /= target; + for(const auto& object : objects) + { + std::filesystem::path objectFile = object; + objectFiles.push_back(objectFile); + dependsStr.push_back(objectFile.string()); + } + + for(const auto& dep : config.depends) + { + std::filesystem::path depFile = settings.builddir; + depFile /= dep; + depFiles.push_back(depFile); + } + + flagsFile = settings.builddir / targetFile.stem(); + flagsFile += ".flags"; + + target_type = TargetType::Executable; + source_language = Language::C; + for(const auto& source : config.sources) + { + std::filesystem::path sourceFile(source); + if(sourceFile.extension().string() != ".c") + { + source_language = Language::Cpp; + } + } +} + +bool TaskLD::dirtyInner() +{ + if(!std::filesystem::exists(targetFile)) + { + return true; + } + + if(!std::filesystem::exists(flagsFile)) + { + return true; + } + + for(const auto& objectFile : objectFiles) + { + if(std::filesystem::last_write_time(targetFile) <= + std::filesystem::last_write_time(objectFile)) + { + return true; + } + } + + { + auto lastFlags = readFile(flagsFile.string()); + if(flagsString() != lastFlags) + { + //std::cout << "The compiler flags changed\n"; + return true; + } + } + + return false; +} + +int TaskLD::runInner() +{ + std::string objectlist; + for(const auto& objectFile : objectFiles) + { + if(!objectlist.empty()) + { + objectlist += " "; + } + objectlist += objectFile.string(); + } + + std::vector<std::string> args; + for(const auto& objectFile : objectFiles) + { + args.push_back(objectFile.string()); + } + + for(const auto& depFile : depFiles) + { + if(depFile.extension() == ".so") + { + args.push_back(std::string("-L") + settings.builddir); + auto lib = depFile.stem().string().substr(3); // strip 'lib' prefix + args.push_back(std::string("-l") + lib); + } + else if(depFile.extension() == ".a") + { + args.push_back(depFile.string()); + } + } + + for(const auto& flag : config.ldflags) + { + args.push_back(flag); + } + args.push_back("-o"); + args.push_back(targetFile.string()); + + { // Write flags to file. + std::ofstream flagsStream(flagsFile); + flagsStream << flagsString(); + } + + if(settings.verbose == 0) + { + std::cout << "LD => " << targetFile.string() << "\n"; + } + + auto tool = compiler(); + return execute(tool, args, settings.verbose > 0); +} + +int TaskLD::clean() +{ + if(std::filesystem::exists(targetFile)) + { + std::cout << "Removing " << targetFile.string() << "\n"; + std::filesystem::remove(targetFile); + } + + if(std::filesystem::exists(flagsFile)) + { + std::cout << "Removing " << flagsFile.string() << "\n"; + std::filesystem::remove(flagsFile); + } + + return 0; +} + +std::vector<std::string> TaskLD::depends() const +{ + std::vector<std::string> deps; + for(const auto& objectFile : objectFiles) + { + deps.push_back(objectFile.string()); + } + + for(const auto& depFile : depFiles) + { + deps.push_back(depFile.string()); + } + + return deps; +} + +std::string TaskLD::target() const +{ + return targetFile.string(); +} + +std::string TaskLD::flagsString() const +{ + std::string flagsStr; + for(const auto& flag : config.ldflags) + { + if(flag != config.ldflags[0]) + { + flagsStr += " "; + } + flagsStr += flag; + } + flagsStr += "\n"; + + for(const auto& dep : config.depends) + { + if(dep != config.depends[0]) + { + flagsStr += " "; + } + flagsStr += dep; + } + + return flagsStr; +} |