From: Mikko Rasa Date: Sat, 24 Dec 2022 12:30:54 +0000 (+0200) Subject: Redesign GnuLinker to work without subtools X-Git-Url: http://git.tdb.fi/?p=builder.git;a=commitdiff_plain;h=f0c0d720edc01f5faa72bb4ff4bf655445842678 Redesign GnuLinker to work without subtools --- diff --git a/source/gnulinker.cpp b/source/gnulinker.cpp index 3144097..619c9e7 100644 --- a/source/gnulinker.cpp +++ b/source/gnulinker.cpp @@ -29,14 +29,8 @@ GnuLinker::GnuLinker(Builder &b, const Architecture &a): processing_unit = COMPONENT; - default_linker = new Linker(*this, "CC"); - cxx_linker = new Linker(*this, "CXX"); -} - -GnuLinker::~GnuLinker() -{ - delete default_linker; - delete cxx_linker; + set_command("gcc"); + set_run(_run); } Target *GnuLinker::create_target(const vector &sources, const string &arg) @@ -45,14 +39,8 @@ Target *GnuLinker::create_target(const vector &sources, const string & throw invalid_argument("GnuLinker::create_target"); vector objs; objs.reserve(sources.size()); - Linker *linker = default_linker; for(Target *s: sources) - { - ObjectFile &obj = dynamic_cast(*s); - objs.push_back(&obj); - if(obj.get_tool()->get_tag()=="CXX") - linker = cxx_linker; - } + objs.push_back(&dynamic_cast(*s)); const Component &comp = *objs.front()->get_component(); Binary *bin = 0; @@ -68,7 +56,7 @@ Target *GnuLinker::create_target(const vector &sources, const string & } else bin = new Executable(builder, comp, objs); - bin->set_tool(*linker); + bin->set_tool(*this); return bin; } @@ -92,62 +80,74 @@ Target *GnuLinker::create_install(Target &target) const return 0; } +string GnuLinker::create_build_signature(const BuildInfo &binfo) const +{ + string result = Tool::create_build_signature(binfo); + result += ','; + if(binfo.libmode<=BuildInfo::STATIC) + result += 't'; + else + result += 'd'; + if(binfo.strip) + result += 's'; + if(!binfo.libs.empty()) + { + result += ",l"; + result += join(binfo.libs.begin(), binfo.libs.end(), ",l"); + } + return result; +} + void GnuLinker::do_prepare() { bool path_found = false; const FS::Path &sysroot = build_info.sysroot; - Tool &compiler = builder.get_toolchain().get_tool("CC"); - if(dynamic_cast(&compiler)) + if(executable) { - compiler.prepare(); - FileTarget *compiler_exe = compiler.get_executable(); - if(compiler_exe) + ExternalTask::Arguments argv; + argv.push_back(executable->get_path().str()); + argv.push_back("-Wl,--verbose"); + argv.push_back("-nostdlib"); + if(!sysroot.empty()) + argv.push_back("--sysroot="+sysroot.str()); + + builder.get_logger().log("auxcommands", "Running %s", join(argv.begin(), argv.end())); + try { - ExternalTask::Arguments argv; - argv.push_back(compiler_exe->get_path().str()); - argv.push_back("-Wl,--verbose"); - argv.push_back("-nostdlib"); - if(!sysroot.empty()) - argv.push_back("--sysroot="+sysroot.str()); - - builder.get_logger().log("auxcommands", "Running %s", join(argv.begin(), argv.end())); - try + string output = ExternalTask::run_and_capture_output(argv, FS::Path(), true); + string::size_type start = 0; + while(start(&compiler)) - { - compiler.prepare(); - executable = compiler.get_executable(); - } -} - -Task *GnuLinker::Linker::_run(const Binary &bin) -{ - const Linker &tool = dynamic_cast(*bin.get_tool()); + const Tool &tool = *bin.get_tool(); const Builder &builder = tool.get_builder(); const Architecture &arch = *tool.get_architecture(); @@ -295,13 +248,18 @@ Task *GnuLinker::Linker::_run(const Binary &bin) bool static_link_ok = (binfo.libmode<=BuildInfo::STATIC); + bool has_cplusplus = false; for(Target *d: bin.get_dependencies()) { FileTarget *file = dynamic_cast(d); Target *tgt = d->get_real_target(); if(ObjectFile *obj = dynamic_cast(tgt)) + { argv.push_back(relative(obj->get_path(), work_dir).str()); + if(obj->get_tool()->get_tag()=="CXX") + has_cplusplus = true; + } else if(StaticLibrary *stlib = dynamic_cast(tgt)) argv.push_back((file?file:stlib)->get_path().str()); else if(SharedLibrary *shlib = dynamic_cast(tgt)) @@ -327,11 +285,14 @@ Task *GnuLinker::Linker::_run(const Binary &bin) argv.push_back(l.substr(0, l.size()-10)); } + if(has_cplusplus) + argv.push_back("-lstdc++"); + if(static_link_ok) argv.push_back("-static"); else { - if(tool.compiler_tag=="CXX") + if(has_cplusplus) { auto i = binfo.libmodes.find("stdc++"); if(i!=binfo.libmodes.end() && i->second<=BuildInfo::STATIC) diff --git a/source/gnulinker.h b/source/gnulinker.h index 713b978..c04afd1 100644 --- a/source/gnulinker.h +++ b/source/gnulinker.h @@ -14,34 +14,16 @@ Uses either gcc or g++ depending on what was used to compile the object files. */ class GnuLinker: public Tool { -private: - class Linker: public SubTool - { - private: - std::string compiler_tag; - - public: - Linker(GnuLinker &, const std::string &); - - std::string create_build_signature(const BuildInfo &) const override; - private: - void do_prepare() override; - - public: - static Task *_run(const Binary &); - }; - - Linker *default_linker = 0; - Linker *cxx_linker = 0; - public: GnuLinker(Builder &, const Architecture &); - ~GnuLinker(); Target *create_target(const std::vector &, const std::string &) override; Target *create_install(Target &) const override; + std::string create_build_signature(const BuildInfo &) const override; protected: void do_prepare() override; +private: + static Task *_run(const Binary &); }; #endif