From 1ed833343bc83b83c5f61cbfd74423bbba677a04 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 22 Dec 2022 18:05:25 +0200 Subject: [PATCH] Redesign how tools are run It also uses functors now. The run functions access properties of the tool through the target. This will allow tool customization without having to derive from the class, which will be useful for modularization. --- source/androidassetpackagingtool.cpp | 10 +++--- source/androidassetpackagingtool.h | 5 ++- source/androidmanifestgenerator.cpp | 10 +++--- source/androidmanifestgenerator.h | 3 +- source/apkbuilder.cpp | 9 ++--- source/apkbuilder.h | 7 ++-- source/compilecommandsgenerator.cpp | 10 +++--- source/compilecommandsgenerator.h | 3 +- source/copy.cpp | 12 +++---- source/copy.h | 3 +- source/datatool.cpp | 6 ++-- source/datatool.h | 4 ++- source/gnuarchiver.cpp | 7 ++-- source/gnuarchiver.h | 6 +++- source/gnucompiler.cpp | 49 +++++++++++++++------------- source/gnucompiler.h | 7 ++-- source/gnulinker.cpp | 33 +++++++++---------- source/gnulinker.h | 7 ++-- source/jarsigner.cpp | 7 ++-- source/jarsigner.h | 6 +++- source/mingwdlltool.cpp | 7 ++-- source/mingwdlltool.h | 4 ++- source/msvcarchiver.cpp | 7 ++-- source/msvcarchiver.h | 4 ++- source/msvccompiler.cpp | 15 +++++---- source/msvccompiler.h | 3 +- source/msvclinker.cpp | 11 ++++--- source/msvclinker.h | 3 +- source/pkgconfiggenerator.cpp | 10 +++--- source/pkgconfiggenerator.h | 3 +- source/sourcegenerator.cpp | 18 +++++----- source/sourcegenerator.h | 5 ++- source/tar.cpp | 7 +--- source/tar.h | 1 - source/tool.cpp | 5 +++ source/tool.h | 34 +++++++++++++++++-- source/vcxprojectgenerator.cpp | 10 +++--- source/vcxprojectgenerator.h | 3 +- source/vssolutiongenerator.cpp | 10 +++--- source/vssolutiongenerator.h | 3 +- 40 files changed, 218 insertions(+), 149 deletions(-) diff --git a/source/androidassetpackagingtool.cpp b/source/androidassetpackagingtool.cpp index af8bc95..a511da0 100644 --- a/source/androidassetpackagingtool.cpp +++ b/source/androidassetpackagingtool.cpp @@ -24,6 +24,8 @@ AndroidAssetPackagingTool::AndroidAssetPackagingTool(Builder &b, const AndroidSd if(sdk.get_platform_jar().empty()) problems.push_back("Android platform not found"); + + set_run(_run); } Target *AndroidAssetPackagingTool::create_target(const vector &sources, const string &) @@ -47,18 +49,18 @@ Target *AndroidAssetPackagingTool::create_target(const vector &sources return res; } -Task *AndroidAssetPackagingTool::run(const Target &tgt) const +Task *AndroidAssetPackagingTool::_run(const AndroidResourceBundle &res) { - const AndroidResourceBundle &res = dynamic_cast(tgt); + const AndroidAssetPackagingTool &tool = dynamic_cast(*res.get_tool()); ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("package"); FS::Path work_dir = res.get_component()->get_package().get_source_directory(); argv.push_back("-I"); - argv.push_back(sdk.get_platform_jar().str()); + argv.push_back(tool.sdk.get_platform_jar().str()); argv.push_back("-F"); argv.push_back(FS::relative(res.get_path(), work_dir).str()); diff --git a/source/androidassetpackagingtool.h b/source/androidassetpackagingtool.h index 8f01e6d..e4f0f77 100644 --- a/source/androidassetpackagingtool.h +++ b/source/androidassetpackagingtool.h @@ -3,6 +3,7 @@ #include "tool.h" +class AndroidResourceBundle; class AndroidSdk; class AndroidAssetPackagingTool: public Tool @@ -14,7 +15,9 @@ public: AndroidAssetPackagingTool(Builder &, const AndroidSdk &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; + +private: + static Task *_run(const AndroidResourceBundle &); }; #endif diff --git a/source/androidmanifestgenerator.cpp b/source/androidmanifestgenerator.cpp index 70b1e20..0c48982 100644 --- a/source/androidmanifestgenerator.cpp +++ b/source/androidmanifestgenerator.cpp @@ -10,15 +10,15 @@ using namespace std; using namespace Msp; -Target *AndroidManifestGenerator::create_target(const vector &, const string &) +AndroidManifestGenerator::AndroidManifestGenerator(Builder &b): + Tool(b, "AMG") { - throw logic_error("not implemented"); + set_run_internal(_run); } -Task *AndroidManifestGenerator::run(const Target &target) const +Target *AndroidManifestGenerator::create_target(const vector &, const string &) { - const AndroidManifestFile &manifest = dynamic_cast(target); - return new InternalTask([&manifest]{ return _run(manifest); }); + throw logic_error("not implemented"); } bool AndroidManifestGenerator::_run(const AndroidManifestFile &manifest) diff --git a/source/androidmanifestgenerator.h b/source/androidmanifestgenerator.h index 6013c5f..58fc0b2 100644 --- a/source/androidmanifestgenerator.h +++ b/source/androidmanifestgenerator.h @@ -8,10 +8,9 @@ class AndroidManifestFile; class AndroidManifestGenerator: public Tool { public: - AndroidManifestGenerator(Builder &b): Tool(b, "AMG") { } + AndroidManifestGenerator(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const AndroidManifestFile &); diff --git a/source/apkbuilder.cpp b/source/apkbuilder.cpp index d232a6f..e487784 100644 --- a/source/apkbuilder.cpp +++ b/source/apkbuilder.cpp @@ -18,6 +18,7 @@ ApkBuilder::ApkBuilder(Builder &b): Tool(b, "APK") { set_command("jar"); + set_run(_run); } Target *ApkBuilder::create_target(const vector &sources, const string &) @@ -43,12 +44,12 @@ void ApkBuilder::do_prepare() jarsigner->prepare(); } -Task *ApkBuilder::run(const Target &tgt) const +Task *ApkBuilder::_run(const AndroidPackageFile &apk) { - const AndroidPackageFile &apk = dynamic_cast(tgt); + const ApkBuilder &tool = dynamic_cast(*apk.get_tool()); ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("u"); FS::Path input_path; @@ -74,6 +75,6 @@ Task *ApkBuilder::run(const Target &tgt) const task->set_stdin(FS::basename(input_path)); task->set_stdout(FS::relative(apk.get_path(), work_dir)); ChainedTask *chain = new ChainedTask(task); - chain->add_task(jarsigner->run(tgt)); + chain->add_task(tool.jarsigner->run(apk)); return chain; } diff --git a/source/apkbuilder.h b/source/apkbuilder.h index 4a8c16b..09d849c 100644 --- a/source/apkbuilder.h +++ b/source/apkbuilder.h @@ -3,6 +3,8 @@ #include "tool.h" +class AndroidPackageFile; + class ApkBuilder: public Tool { private: @@ -14,8 +16,9 @@ public: Target *create_target(const std::vector &, const std::string &) override; protected: void do_prepare() override; -public: - Task *run(const Target &) const override; + +private: + static Task *_run(const AndroidPackageFile &); }; #endif diff --git a/source/compilecommandsgenerator.cpp b/source/compilecommandsgenerator.cpp index 855a80a..bbd4e98 100644 --- a/source/compilecommandsgenerator.cpp +++ b/source/compilecommandsgenerator.cpp @@ -11,15 +11,15 @@ using namespace std; using namespace Msp; -Target *CompileCommandsGenerator::create_target(const vector &, const string &) +CompileCommandsGenerator::CompileCommandsGenerator(Builder &b): + Tool(b, "CCJG") { - throw logic_error("Not implemented"); + set_run_internal(_run); } -Task *CompileCommandsGenerator::run(const Target &target) const +Target *CompileCommandsGenerator::create_target(const vector &, const string &) { - const CompileCommandsJson &cmds = dynamic_cast(target); - return new InternalTask([&cmds]{ return _run(cmds); }); + throw logic_error("Not implemented"); } bool CompileCommandsGenerator::_run(const CompileCommandsJson &cmds) diff --git a/source/compilecommandsgenerator.h b/source/compilecommandsgenerator.h index e3116f9..a6fa6f9 100644 --- a/source/compilecommandsgenerator.h +++ b/source/compilecommandsgenerator.h @@ -8,10 +8,9 @@ class CompileCommandsJson; class CompileCommandsGenerator: public Tool { public: - CompileCommandsGenerator(Builder &b): Tool(b, "CCJG") { } + CompileCommandsGenerator(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const CompileCommandsJson &); diff --git a/source/copy.cpp b/source/copy.cpp index 9bca33f..8f6b81d 100644 --- a/source/copy.cpp +++ b/source/copy.cpp @@ -15,6 +15,12 @@ using namespace std; using namespace Msp; +Copy::Copy(Builder &b): + Tool(b, "CP") +{ + set_run_internal(_run); +} + Target *Copy::create_target(const vector &sources, const string &arg) { FileTarget &file_tgt = dynamic_cast(*sources.front()); @@ -23,12 +29,6 @@ Target *Copy::create_target(const vector &sources, const string &arg) return inst; } -Task *Copy::run(const Target &target) const -{ - const InstalledFile &install = dynamic_cast(target); - return new InternalTask([&install]{ return _run(install); }); -} - bool Copy::_run(const InstalledFile &install) { const FileTarget &source = install.get_source(); diff --git a/source/copy.h b/source/copy.h index c0a4339..d65bb05 100644 --- a/source/copy.h +++ b/source/copy.h @@ -11,10 +11,9 @@ Copies a file to another place. Used by the InstalledFile target. class Copy: public Tool { public: - Copy(Builder &b): Tool(b, "CP") { } + Copy(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const InstalledFile &); diff --git a/source/datatool.cpp b/source/datatool.cpp index b24de13..1bc629e 100644 --- a/source/datatool.cpp +++ b/source/datatool.cpp @@ -16,6 +16,7 @@ DataTool::DataTool(Builder &b): Tool(b, "DATA") { set_command("mspdatatool"); + set_run(_run); input_suffixes.push_back(".mdt"); } @@ -67,13 +68,14 @@ string DataTool::create_build_signature(const BuildInfo &binfo) const return result; } -Task *DataTool::run(const Target &tgt) const +Task *DataTool::_run(const Target &tgt) { + const Tool &tool = *tgt.get_tool(); const Component &comp = *tgt.get_component(); FS::Path work_dir = comp.get_package().get_source_directory(); vector argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("-o"); argv.push_back(FS::relative(dynamic_cast(tgt).get_path(), work_dir).str()); diff --git a/source/datatool.h b/source/datatool.h index 128f833..1cddebb 100644 --- a/source/datatool.h +++ b/source/datatool.h @@ -11,7 +11,9 @@ public: Target *create_source(const Component &, const Msp::FS::Path &) const override; Target *create_target(const std::vector &, const std::string &) override; std::string create_build_signature(const BuildInfo &) const override; - Task *run(const Target &) const override; + +private: + static Task *_run(const Target &); }; #endif diff --git a/source/gnuarchiver.cpp b/source/gnuarchiver.cpp index 24a022f..2f5ba24 100644 --- a/source/gnuarchiver.cpp +++ b/source/gnuarchiver.cpp @@ -19,6 +19,7 @@ GnuArchiver::GnuArchiver(Builder &b, const Architecture &a): set_command("ar", true); input_suffixes.push_back(".o"); processing_unit = COMPONENT; + set_run(_run); } Target *GnuArchiver::create_target(const vector &sources, const string &) @@ -37,13 +38,13 @@ Target *GnuArchiver::create_target(const vector &sources, const string return lib; } -Task *GnuArchiver::run(const Target &target) const +Task *GnuArchiver::_run(const StaticLibrary &lib) { - const StaticLibrary &lib = dynamic_cast(target); + const Tool &tool = *lib.get_tool(); const Component &comp = *lib.get_component(); vector argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("rc"); FS::Path work_dir = comp.get_package().get_source_directory(); diff --git a/source/gnuarchiver.h b/source/gnuarchiver.h index 0e4172b..4d21abe 100644 --- a/source/gnuarchiver.h +++ b/source/gnuarchiver.h @@ -3,13 +3,17 @@ #include "tool.h" +class StaticLibrary; + class GnuArchiver: public Tool { public: GnuArchiver(Builder &, const Architecture &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; + +private: + static Task *_run(const StaticLibrary &); }; #endif diff --git a/source/gnucompiler.cpp b/source/gnucompiler.cpp index b8b2515..0ec9222 100644 --- a/source/gnucompiler.cpp +++ b/source/gnucompiler.cpp @@ -51,6 +51,7 @@ GnuCompiler::GnuCompiler(Builder &b, const Architecture &a, const string &t): throw invalid_argument("GnuCompiler::GnuCompiler"); set_command((tag=="CXX" ? "g++" : "gcc"), true); + set_run(_run); } Target *GnuCompiler::create_source(const Component &comp, const FS::Path &path) const @@ -198,22 +199,24 @@ void GnuCompiler::prepare_version(const string &arg) { } } -Task *GnuCompiler::run(const Target &target) const +Task *GnuCompiler::_run(const ObjectFile &object) { - const ObjectFile &object = dynamic_cast(target); + const GnuCompiler &tool = dynamic_cast(*object.get_tool()); + const Architecture &arch = *tool.get_architecture(); ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("-c"); BuildInfo binfo; - target.collect_build_info(binfo); + object.collect_build_info(binfo); - string tag_for_std = (tag=="OBJC" ? "CC" : tag); + const std::string &tool_tag = tool.get_tag(); + string tag_for_std = (tool_tag=="OBJC" ? "CC" : tool_tag); if(binfo.standards.count(tag_for_std)) argv.push_back("-std="+get_item(binfo.standards, tag_for_std).str()); - if(tag=="OBJC" && binfo.standards.count(tag)) - argv.push_back("-fobjc-std="+get_item(binfo.standards, tag).str()); + if(tool_tag=="OBJC" && binfo.standards.count(tool_tag)) + argv.push_back("-fobjc-std="+get_item(binfo.standards, tool_tag).str()); if(binfo.warning_level>=1) { @@ -222,7 +225,7 @@ Task *GnuCompiler::run(const Target &target) const { argv.push_back("-Wextra"); argv.push_back("-Wundef"); - if(version>=0x80000) + if(tool.version>=0x80000) argv.push_back("-Wno-cast-function-type"); } if(binfo.warning_level>=3) @@ -230,7 +233,7 @@ Task *GnuCompiler::run(const Target &target) const argv.push_back("-pedantic"); argv.push_back("-Wno-long-long"); argv.push_back("-Wshadow"); - if(tag=="CC") + if(tool_tag=="CC") { argv.push_back("-Wc++-compat"); argv.push_back("-Wstrict-prototypes"); @@ -282,15 +285,15 @@ Task *GnuCompiler::run(const Target &target) const if(binfo.debug) argv.push_back("-fno-omit-frame-pointer"); } - if(binfo.threads && architecture->get_system()!="windows" && architecture->get_system()!="darwin") + if(binfo.threads && arch.get_system()!="windows" && arch.get_system()!="darwin") argv.push_back("-pthread"); - if(object.is_used_in_shared_library() && architecture->get_system()!="windows") + if(object.is_used_in_shared_library() && arch.get_system()!="windows") argv.push_back("-fPIC"); - if((architecture->get_type()=="x86" || architecture->get_type()=="ppc") && !architecture->is_native()) - argv.push_back(format("-m%d", architecture->get_bits())); + if((arch.get_type()=="x86" || arch.get_type()=="ppc") && !arch.is_native()) + argv.push_back(format("-m%d", arch.get_bits())); - string cpu = architecture->get_cpu(); + string cpu = arch.get_cpu(); if(!cpu.empty()) { for(unsigned i=0; cpus[i]; i+=2) @@ -302,25 +305,25 @@ Task *GnuCompiler::run(const Target &target) const argv.push_back("-march="+cpu); } - if(!architecture->get_fpu().empty()) + if(!arch.get_fpu().empty()) { - if(architecture->get_type()=="x86") + if(arch.get_type()=="x86") { - if(architecture->get_fpu()=="387") + if(arch.get_fpu()=="387") argv.push_back("-mfpmath=387"); - else if(!architecture->get_fpu().compare(0, 3, "sse")) + else if(!arch.get_fpu().compare(0, 3, "sse")) argv.push_back("-mfpmath=sse"); - if(architecture->get_fpu()=="sse") + if(arch.get_fpu()=="sse") argv.push_back("-msse2"); - else if(architecture->get_fpu()=="sse3") + else if(arch.get_fpu()=="sse3") argv.push_back("-msse3"); - else if(architecture->get_fpu()=="sse4.1") + else if(arch.get_fpu()=="sse4.1") argv.push_back("-msse4.1"); } - else if(architecture->get_type()=="arm") + else if(arch.get_type()=="arm") { - argv.push_back("-mfpu="+architecture->get_fpu()); + argv.push_back("-mfpu="+arch.get_fpu()); argv.push_back("-mfloat-abi=softfp"); } } diff --git a/source/gnucompiler.h b/source/gnucompiler.h index 1983f79..8257dd8 100644 --- a/source/gnucompiler.h +++ b/source/gnucompiler.h @@ -3,6 +3,8 @@ #include "tool.h" +class ObjectFile; + /** Common base class for GNU compilers. Turns SourceFiles into ObjectFiles. @@ -27,8 +29,9 @@ protected: void prepare_syspath(); void prepare_version(); void prepare_version(const std::string &); -public: - Task *run(const Target &) const override; + +private: + static Task *_run(const ObjectFile &); }; #endif diff --git a/source/gnulinker.cpp b/source/gnulinker.cpp index 56becc2..3144097 100644 --- a/source/gnulinker.cpp +++ b/source/gnulinker.cpp @@ -175,11 +175,6 @@ void GnuLinker::do_prepare() } } -Task *GnuLinker::run(const Target &) const -{ - throw logic_error("GnuLinker should not be run directly"); -} - GnuLinker::Linker::Linker(GnuLinker &p, const string &ct): SubTool(p), @@ -191,6 +186,8 @@ GnuLinker::Linker::Linker(GnuLinker &p, const string &ct): set_command("g++", true); else throw invalid_argument("GnuLinker::Linker::Linker"); + + set_run(_run); } string GnuLinker::Linker::create_build_signature(const BuildInfo &binfo) const @@ -225,12 +222,14 @@ void GnuLinker::Linker::do_prepare() } } -Task *GnuLinker::Linker::run(const Target &target) const +Task *GnuLinker::Linker::_run(const Binary &bin) { - const Binary &bin = dynamic_cast(target); + const Linker &tool = dynamic_cast(*bin.get_tool()); + const Builder &builder = tool.get_builder(); + const Architecture &arch = *tool.get_architecture(); ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); FS::Path work_dir = bin.get_component()->get_package().get_source_directory(); @@ -238,9 +237,9 @@ Task *GnuLinker::Linker::run(const Target &target) const { argv.push_back("-shared"); argv.push_back("-fPIC"); - if(architecture->get_system()!="windows" && !shlib->get_soname().empty()) + if(arch.get_system()!="windows" && !shlib->get_soname().empty()) { - if(architecture->get_system()=="darwin") + if(arch.get_system()=="darwin") { argv.push_back("-install_name"); argv.push_back(shlib->get_soname()); @@ -261,7 +260,7 @@ Task *GnuLinker::Linker::run(const Target &target) const } BuildInfo binfo; - target.collect_build_info(binfo); + bin.collect_build_info(binfo); const FS::Path &sysroot = binfo.sysroot; if(!sysroot.empty()) @@ -281,12 +280,12 @@ Task *GnuLinker::Linker::run(const Target &target) const argv.push_back("-L"+p.str()); if(binfo.strip) argv.push_back("-s"); - if(binfo.threads && architecture->get_system()!="windows" && architecture->get_system()!="darwin") + if(binfo.threads && arch.get_system()!="windows" && arch.get_system()!="darwin") argv.push_back("-pthread"); const Architecture &native_arch = builder.get_native_arch(); - if(architecture->is_native() && architecture->get_bits()!=native_arch.get_bits()) - argv.push_back(format("-m%d", architecture->get_bits())); + if(arch.is_native() && arch.get_bits()!=native_arch.get_bits()) + argv.push_back(format("-m%d", arch.get_bits())); argv.push_back("-o"); argv.push_back(relative(bin.get_path(), work_dir).str()); @@ -296,7 +295,7 @@ Task *GnuLinker::Linker::run(const Target &target) const bool static_link_ok = (binfo.libmode<=BuildInfo::STATIC); - for(Target *d: target.get_dependencies()) + for(Target *d: bin.get_dependencies()) { FileTarget *file = dynamic_cast(d); Target *tgt = d->get_real_target(); @@ -332,14 +331,14 @@ Task *GnuLinker::Linker::run(const Target &target) const argv.push_back("-static"); else { - if(compiler_tag=="CXX") + if(tool.compiler_tag=="CXX") { auto i = binfo.libmodes.find("stdc++"); if(i!=binfo.libmodes.end() && i->second<=BuildInfo::STATIC) argv.push_back("-static-libstdc++"); } - if(architecture->get_system()=="windows") + if(arch.get_system()=="windows") argv.push_back("-Wl,--enable-auto-import"); } diff --git a/source/gnulinker.h b/source/gnulinker.h index 821f746..713b978 100644 --- a/source/gnulinker.h +++ b/source/gnulinker.h @@ -3,6 +3,8 @@ #include "tool.h" +class Binary; + /** The GNU linker. Turns ObjectFiles into Executables and SharedLibraries. To create a shared library, specify "shared" as the second argument to @@ -24,8 +26,9 @@ private: std::string create_build_signature(const BuildInfo &) const override; private: void do_prepare() override; + public: - Task *run(const Target &) const override; + static Task *_run(const Binary &); }; Linker *default_linker = 0; @@ -39,8 +42,6 @@ public: Target *create_install(Target &) const override; protected: void do_prepare() override; -public: - Task *run(const Target &) const override; }; #endif diff --git a/source/jarsigner.cpp b/source/jarsigner.cpp index c8448d2..ac7c779 100644 --- a/source/jarsigner.cpp +++ b/source/jarsigner.cpp @@ -13,6 +13,7 @@ JarSigner::JarSigner(Builder &b): Tool(b, "JSGN") { set_command("jarsigner"); + set_run(_run); } Target *JarSigner::create_target(const vector &, const string &) @@ -20,12 +21,12 @@ Target *JarSigner::create_target(const vector &, const string &) throw logic_error("not implemented"); } -Task *JarSigner::run(const Target &tgt) const +Task *JarSigner::_run(const FileTarget &file) { - const FileTarget &file = dynamic_cast(tgt); + const Tool &tool = *file.get_tool(); ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); // TODO Make this generic FS::Path home_dir = Msp::getenv("HOME"); diff --git a/source/jarsigner.h b/source/jarsigner.h index 6f51244..f1b1c4f 100644 --- a/source/jarsigner.h +++ b/source/jarsigner.h @@ -3,13 +3,17 @@ #include "tool.h" +class FileTarget; + class JarSigner: public Tool { public: JarSigner(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; + +private: + static Task *_run(const FileTarget &); }; #endif diff --git a/source/mingwdlltool.cpp b/source/mingwdlltool.cpp index 922fe51..62ef705 100644 --- a/source/mingwdlltool.cpp +++ b/source/mingwdlltool.cpp @@ -19,6 +19,7 @@ MingwDllTool::MingwDllTool(Builder &b, const Architecture &a): Tool(b, a, "DLL") { set_command("dlltool", true); + set_run(_run); } Target *MingwDllTool::create_target(const vector &sources, const string &) @@ -57,8 +58,10 @@ Target *MingwDllTool::create_install(Target &target) const return 0; } -Task *MingwDllTool::run(const Target &target) const +Task *MingwDllTool::_run(const Target &target) { + const Tool &tool = *target.get_tool(); + const ImportLibrary *imp = dynamic_cast(&target); const ExportDefinitions *exp = 0; if(imp) @@ -69,7 +72,7 @@ Task *MingwDllTool::run(const Target &target) const throw invalid_argument("MingwDllTool::run"); vector argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); /* dlltool is stupid and puts temporary files in the working directory by default */ diff --git a/source/mingwdlltool.h b/source/mingwdlltool.h index 039ee7c..d9fb1cb 100644 --- a/source/mingwdlltool.h +++ b/source/mingwdlltool.h @@ -10,7 +10,9 @@ public: Target *create_target(const std::vector &, const std::string &) override; Target *create_install(Target &) const override; - Task *run(const Target &) const override; + +private: + static Task *_run(const Target &); }; #endif diff --git a/source/msvcarchiver.cpp b/source/msvcarchiver.cpp index 5544b27..2d5d842 100644 --- a/source/msvcarchiver.cpp +++ b/source/msvcarchiver.cpp @@ -17,6 +17,7 @@ MsvcArchiver::MsvcArchiver(Builder &b, const Architecture &a, const MicrosoftToo input_suffixes.push_back(".o"); processing_unit = COMPONENT; set_command((ms_tools.get_vc_bin_dir()/"lib.exe").str(), false); + set_run(_run); } Target *MsvcArchiver::create_target(const vector &sources, const string &) @@ -35,13 +36,13 @@ Target *MsvcArchiver::create_target(const vector &sources, const strin return lib; } -Task *MsvcArchiver::run(const Target &target) const +Task *MsvcArchiver::_run(const StaticLibrary &lib) { - const StaticLibrary &lib = dynamic_cast(target); const Component &comp = *lib.get_component(); + const Tool &tool = *lib.get_tool(); vector argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("/NOLOGO"); FS::Path work_dir = comp.get_package().get_source_directory(); diff --git a/source/msvcarchiver.h b/source/msvcarchiver.h index 03544a9..8b31bd9 100644 --- a/source/msvcarchiver.h +++ b/source/msvcarchiver.h @@ -4,6 +4,7 @@ #include "tool.h" class MicrosoftTools; +class StaticLibrary; class MsvcArchiver: public Tool { @@ -15,7 +16,8 @@ public: Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; +private: + static Task *_run(const StaticLibrary &); }; #endif diff --git a/source/msvccompiler.cpp b/source/msvccompiler.cpp index dbbc64d..099c123 100644 --- a/source/msvccompiler.cpp +++ b/source/msvccompiler.cpp @@ -34,6 +34,7 @@ MsvcCompiler::MsvcCompiler(Builder &b, const Architecture &a, const string &t, c throw invalid_argument("MsvcCompiler::MsvcCompiler"); set_command((ms_tools.get_vc_bin_dir()/"cl.exe").str(), false); + set_run(_run); } Target *MsvcCompiler::create_source(const Component &comp, const FS::Path &path) const @@ -93,22 +94,22 @@ void MsvcCompiler::do_prepare() setenv("INCLUDE", path); } -Task *MsvcCompiler::run(const Target &target) const +Task *MsvcCompiler::_run(const ObjectFile &object) { - const ObjectFile &object = dynamic_cast(target); + const Tool &tool = *object.get_tool(); ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("/nologo"); argv.push_back("/c"); BuildInfo binfo; - target.collect_build_info(binfo); + object.collect_build_info(binfo); - if(binfo.standards.count(tag)) + if(binfo.standards.count(tool.get_tag())) { - const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tag); - if((tag=="CXX" && std.year>2011) || (tag=="CC" && std.year>1999)) + const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tool.get_tag()); + if((tool.get_tag()=="CXX" && std.year>2011) || (tool.get_tag()=="CC" && std.year>1999)) argv.push_back("/std:"+std.str()); } diff --git a/source/msvccompiler.h b/source/msvccompiler.h index ef1da34..484fe46 100644 --- a/source/msvccompiler.h +++ b/source/msvccompiler.h @@ -4,6 +4,7 @@ #include "tool.h" class MicrosoftTools; +class ObjectFile; class MsvcCompiler: public Tool { @@ -22,7 +23,7 @@ protected: void do_prepare() override; public: - Task *run(const Target &) const override; + static Task *_run(const ObjectFile &); }; #endif diff --git a/source/msvclinker.cpp b/source/msvclinker.cpp index 78cf0b2..62e9d2a 100644 --- a/source/msvclinker.cpp +++ b/source/msvclinker.cpp @@ -26,6 +26,7 @@ MsvcLinker::MsvcLinker(Builder &b, const Architecture &a, const MicrosoftTools & processing_unit = COMPONENT; set_command((ms_tools.get_vc_bin_dir()/"link.exe").str(), false); + set_run(_run); } Target *MsvcLinker::create_target(const vector &sources, const string &arg) @@ -84,12 +85,12 @@ void MsvcLinker::do_prepare() setenv("LIB", path); } -Task *MsvcLinker::run(const Target &target) const +Task *MsvcLinker::_run(const Binary &bin) { - const Binary &bin = dynamic_cast(target); + const Tool &tool = *bin.get_tool(); vector argv; - argv.push_back(executable->get_path().str()); + argv.push_back(tool.get_executable()->get_path().str()); argv.push_back("/NOLOGO"); FS::Path work_dir = bin.get_component()->get_package().get_source_directory(); @@ -98,7 +99,7 @@ Task *MsvcLinker::run(const Target &target) const argv.push_back("/DLL"); BuildInfo binfo; - target.collect_build_info(binfo); + bin.collect_build_info(binfo); /*for(const FS::Path &p: binfo.libpath) argv.push_back("/LIBPATH:"+p.str());*/ @@ -109,7 +110,7 @@ Task *MsvcLinker::run(const Target &target) const argv.push_back("/OUT:"+relative(bin.get_path(), work_dir).str()); - for(Target *d: target.get_dependencies()) + for(Target *d: bin.get_dependencies()) { FileTarget *file = dynamic_cast(d); Target *tgt = d->get_real_target(); diff --git a/source/msvclinker.h b/source/msvclinker.h index 26b2aba..95ff2a9 100644 --- a/source/msvclinker.h +++ b/source/msvclinker.h @@ -3,6 +3,7 @@ #include "tool.h" +class Binary; class MicrosoftTools; class MsvcLinker: public Tool @@ -20,7 +21,7 @@ protected: void do_prepare() override; public: - Task *run(const Target &) const override; + static Task *_run(const Binary &); }; #endif diff --git a/source/pkgconfiggenerator.cpp b/source/pkgconfiggenerator.cpp index a6178a7..46387d3 100644 --- a/source/pkgconfiggenerator.cpp +++ b/source/pkgconfiggenerator.cpp @@ -9,15 +9,15 @@ using namespace std; using namespace Msp; -Target *PkgConfigGenerator::create_target(const vector &, const string &) +PkgConfigGenerator::PkgConfigGenerator(Builder &b): + Tool(b, "PCG") { - throw logic_error("Not implemented"); + set_run_internal(_run); } -Task *PkgConfigGenerator::run(const Target &target) const +Target *PkgConfigGenerator::create_target(const vector &, const string &) { - const PkgConfigFile &pkgc = dynamic_cast(target); - return new InternalTask([&pkgc]{ return _run(pkgc); }); + throw logic_error("Not implemented"); } bool PkgConfigGenerator::_run(const PkgConfigFile &pkgc) diff --git a/source/pkgconfiggenerator.h b/source/pkgconfiggenerator.h index 0f0886b..761a2c0 100644 --- a/source/pkgconfiggenerator.h +++ b/source/pkgconfiggenerator.h @@ -8,10 +8,9 @@ class PkgConfigFile; class PkgConfigGenerator: public Tool { public: - PkgConfigGenerator(Builder &b): Tool(b, "PCG") { } + PkgConfigGenerator(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const PkgConfigFile &); diff --git a/source/sourcegenerator.cpp b/source/sourcegenerator.cpp index cfb01af..72297fd 100644 --- a/source/sourcegenerator.cpp +++ b/source/sourcegenerator.cpp @@ -13,7 +13,9 @@ using namespace Msp; SourceGenerator::SourceGenerator(Builder &b, const SourcePackage &p, const string &t): Tool(b, t), package(p) -{ } +{ + set_run(&_run); +} Target *SourceGenerator::create_source(const Component &comp, const FS::Path &path) const { @@ -69,21 +71,21 @@ Target *SourceGenerator::create_target(const vector &sources, const st return primary; } -Task *SourceGenerator::run(const Target &target) const +Task *SourceGenerator::_run(const SourceFile &out_src) { - const SourceFile &out_src = dynamic_cast(target); const FS::Path &work_dir = out_src.get_package()->get_source_directory(); + const SourceGenerator &tool = dynamic_cast(*out_src.get_tool()); vector args; - args.push_back(executable->get_path().str()); - args.insert(args.end(), arguments.begin(), arguments.end()); + args.push_back(tool.get_executable()->get_path().str()); + args.insert(args.end(), tool.arguments.begin(), tool.arguments.end()); - for(const Target *d: target.get_dependencies()) + for(const Target *d: out_src.get_dependencies()) if(const TemplateFile *tmpl = dynamic_cast(d)) args.push_back(FS::relative(tmpl->get_path(), work_dir).str()); - if(!out_argument.empty()) - args.push_back(out_argument); + if(!tool.out_argument.empty()) + args.push_back(tool.out_argument); args.push_back(FS::relative(out_src.get_path(), work_dir).str()); return new ExternalTask(args, work_dir); diff --git a/source/sourcegenerator.h b/source/sourcegenerator.h index 3b96799..e9fe308 100644 --- a/source/sourcegenerator.h +++ b/source/sourcegenerator.h @@ -6,6 +6,8 @@ #include "sourcepackage.h" #include "tool.h" +class SourceFile; + class SourceGenerator: public Tool { public: @@ -35,7 +37,8 @@ public: Target *create_source(const Component &, const Msp::FS::Path &) const override; Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; +private: + static Task *_run(const SourceFile &); }; #endif diff --git a/source/tar.cpp b/source/tar.cpp index 446aa92..07c14ce 100644 --- a/source/tar.cpp +++ b/source/tar.cpp @@ -16,6 +16,7 @@ Tar::Tar(Builder &b): Tool(b, "TAR") { processing_unit = COMPONENT; + set_run_internal(&_run); } Target *Tar::create_target(const vector &sources, const string &arg) @@ -32,12 +33,6 @@ Target *Tar::create_target(const vector &sources, const string &arg) return tarball; } -Task *Tar::run(const Target &target) const -{ - const TarBall &tarball = dynamic_cast(target); - return new InternalTask([&tarball]{ return _run(tarball); }); -} - bool Tar::_run(const TarBall &tarball) { const FS::Path &pkg_src = tarball.get_package()->get_source_directory(); diff --git a/source/tar.h b/source/tar.h index fa4a4d6..befebb8 100644 --- a/source/tar.h +++ b/source/tar.h @@ -11,7 +11,6 @@ public: Tar(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const TarBall &); diff --git a/source/tool.cpp b/source/tool.cpp index 852fa2d..402d20d 100644 --- a/source/tool.cpp +++ b/source/tool.cpp @@ -20,6 +20,11 @@ void Tool::set_command(const string &cmd, bool cross) command = cmd; } +void Tool::set_run(function f) +{ + run_func = move(f); +} + bool Tool::accepts_suffix(const string &suffix, bool aux) const { return (any_equals(input_suffixes, suffix) || (aux && any_equals(aux_suffixes, suffix))); diff --git a/source/tool.h b/source/tool.h index 6fa4fb5..ec5bf02 100644 --- a/source/tool.h +++ b/source/tool.h @@ -1,10 +1,12 @@ #ifndef TOOL_H_ #define TOOL_H_ +#include #include #include #include #include "buildinfo.h" +#include "internaltask.h" #include "virtualfilesystem.h" class Architecture; @@ -13,7 +15,6 @@ class BuildInfo; class Component; class FileTarget; class Target; -class Task; /** Base class for tools. Tools are used to turn targets into other targets. @@ -40,6 +41,7 @@ protected: ProcessingUnit processing_unit = ONE_FILE; VirtualFileSystem::SearchPath system_path; BuildInfo build_info; + std::function run_func; bool prepared = false; std::vector problems; @@ -50,12 +52,24 @@ private: public: virtual ~Tool() { } + Builder &get_builder() const { return builder; } + const std::string &get_tag() const { return tag; } /** Returns the architecture this tool builds for. May return null if the tool is architecture-agnostic. */ const Architecture *get_architecture() const { return architecture; } +protected: + void set_run(std::function); + + template + void set_run(Task *(*)(const T &)); + + template + void set_run_internal(bool (*)(const T &)); + +public: /** Overrides the command used by the tool. The new command should accept the same command line arguments. Only works on tools that use an external command. If cross is true and the architecture is not native, a cross @@ -120,7 +134,7 @@ public: /** Invokes the tool to build a target. This should not be called directly; use Target::build() instead. */ - virtual Task *run(const Target &) const = 0; + Task *run(const Target &t) const { return run_func(t); } }; /** @@ -144,6 +158,22 @@ public: }; +template +void Tool::set_run(Task *(*f)(const T &)) +{ + set_run([f](const Target &t){ return f(dynamic_cast(t)); }); +} + +template +void Tool::set_run_internal(bool (*f)(const T &)) +{ + set_run([f](const Target &t){ + const T &ct = dynamic_cast(t); + return new InternalTask([f, &ct]{ return f(ct); }); + }); +} + + void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &); #endif diff --git a/source/vcxprojectgenerator.cpp b/source/vcxprojectgenerator.cpp index bafa8d9..8cfc12a 100644 --- a/source/vcxprojectgenerator.cpp +++ b/source/vcxprojectgenerator.cpp @@ -13,15 +13,15 @@ using namespace std; using namespace Msp; -Target *VcxProjectGenerator::create_target(const vector &, const string &) +VcxProjectGenerator::VcxProjectGenerator(Builder &b): + Tool(b, "VCXG") { - throw logic_error("Not implemented"); + set_run_internal(_run); } -Task *VcxProjectGenerator::run(const Target &target) const +Target *VcxProjectGenerator::create_target(const vector &, const string &) { - const VcxProjectFile &project = dynamic_cast(target); - return new InternalTask([&project]{ return _run(project); }); + throw logic_error("Not implemented"); } bool VcxProjectGenerator::_run(const VcxProjectFile &project) diff --git a/source/vcxprojectgenerator.h b/source/vcxprojectgenerator.h index 05f7401..f8283ff 100644 --- a/source/vcxprojectgenerator.h +++ b/source/vcxprojectgenerator.h @@ -8,10 +8,9 @@ class VcxProjectFile; class VcxProjectGenerator: public Tool { public: - VcxProjectGenerator(Builder &b): Tool(b, "VCXG") { } + VcxProjectGenerator(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const VcxProjectFile &); diff --git a/source/vssolutiongenerator.cpp b/source/vssolutiongenerator.cpp index 5fd8e4d..7dce076 100644 --- a/source/vssolutiongenerator.cpp +++ b/source/vssolutiongenerator.cpp @@ -11,15 +11,15 @@ using namespace std; using namespace Msp; -Target *VsSolutionGenerator::create_target(const vector &, const string &) +VsSolutionGenerator::VsSolutionGenerator(Builder &b): + Tool(b, "VSSG") { - throw logic_error("Not implemented"); + set_run_internal(_run); } -Task *VsSolutionGenerator::run(const Target &target) const +Target *VsSolutionGenerator::create_target(const vector &, const string &) { - const VsSolutionFile &solution = dynamic_cast(target); - return new InternalTask([&solution]{ return _run(solution); }); + throw logic_error("Not implemented"); } bool VsSolutionGenerator::_run(const VsSolutionFile &solution) diff --git a/source/vssolutiongenerator.h b/source/vssolutiongenerator.h index b7eaf31..ca33237 100644 --- a/source/vssolutiongenerator.h +++ b/source/vssolutiongenerator.h @@ -8,10 +8,9 @@ class VsSolutionFile; class VsSolutionGenerator: public Tool { public: - VsSolutionGenerator(Builder &b): Tool(b, "VSSG") { } + VsSolutionGenerator(Builder &); Target *create_target(const std::vector &, const std::string &) override; - Task *run(const Target &) const override; private: static bool _run(const VsSolutionFile &); -- 2.43.0