From: Mikko Rasa Date: Sat, 24 Dec 2022 21:25:29 +0000 (+0200) Subject: Rework Tool::prepare to be able to work on other objects than self X-Git-Url: http://git.tdb.fi/?p=builder.git;a=commitdiff_plain;h=68ef01e3f94ba5d0297e7979551e7d9404906db7 Rework Tool::prepare to be able to work on other objects than self This is another piece required for inheritance-less tool customization. --- diff --git a/source/androidcompiler.cpp b/source/androidcompiler.cpp index 63fd527..db089b2 100644 --- a/source/androidcompiler.cpp +++ b/source/androidcompiler.cpp @@ -39,11 +39,14 @@ AndroidCompiler::AndroidCompiler(Builder &b, const Architecture &a, const string build_info.libs.push_back("gnustl_static"); } -void AndroidCompiler::do_prepare() +void AndroidCompiler::do_prepare(ToolData &tool) const { - GnuCompiler::do_prepare(); + const Architecture &arch = *static_cast(tool).get_architecture(); + + GnuCompiler::do_prepare(tool); if(tag=="CXX") { + unsigned version = tool.extra_data; string version_str = format("%d.%d.%d", version>>16, (version>>8)&0xFF, version&0xFF); FS::Path libstdcxx_dir = ndk.get_root_dir()/"sources"/"cxx-stl"/"gnu-libstdc++"; FS::Path libstdcxx_path; @@ -56,7 +59,7 @@ void AndroidCompiler::do_prepare() string::size_type dot = version_str.rfind('.'); if(dot==string::npos) { - problems.push_back("C++ standard library not found"); + tool.problems.push_back("C++ standard library not found"); return; } @@ -64,16 +67,16 @@ void AndroidCompiler::do_prepare() } FS::Path public_dir = libstdcxx_path/"include"; - system_path.push_back(public_dir); - build_info.incpath.push_back(public_dir); + tool.system_path.push_back(public_dir); + tool.build_info.incpath.push_back(public_dir); FS::Path arch_path = libstdcxx_path/"libs"; builder.get_logger().log("files", "Traversing %s", arch_path.str()); - string arch_dir = architecture->best_match(list_files(arch_path)); + string arch_dir = arch.best_match(list_files(arch_path)); if(!arch_dir.empty()) { - build_info.incpath.push_back(libstdcxx_path/"libs"/arch_dir/"include"); - build_info.libpath.push_back(libstdcxx_path/"libs"/arch_dir); + tool.build_info.incpath.push_back(libstdcxx_path/"libs"/arch_dir/"include"); + tool.build_info.libpath.push_back(libstdcxx_path/"libs"/arch_dir); } } } diff --git a/source/androidcompiler.h b/source/androidcompiler.h index d03c4fd..9f42099 100644 --- a/source/androidcompiler.h +++ b/source/androidcompiler.h @@ -14,7 +14,7 @@ public: AndroidCompiler(Builder &, const Architecture &, const std::string &, const AndroidNdk &); protected: - void do_prepare() override; + void do_prepare(ToolData &) const override; }; #endif diff --git a/source/apkbuilder.cpp b/source/apkbuilder.cpp index e487784..e426c89 100644 --- a/source/apkbuilder.cpp +++ b/source/apkbuilder.cpp @@ -38,10 +38,11 @@ Target *ApkBuilder::create_target(const vector &sources, const string return apk; } -void ApkBuilder::do_prepare() +void ApkBuilder::do_prepare(ToolData &tool) const { - jarsigner = &builder.get_toolchain().get_tool("JSGN"); + Tool *jarsigner = &builder.get_toolchain().get_tool("JSGN"); jarsigner->prepare(); + tool.extra_data = jarsigner; } Task *ApkBuilder::_run(const AndroidPackageFile &apk) @@ -75,6 +76,6 @@ Task *ApkBuilder::_run(const AndroidPackageFile &apk) 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(tool.jarsigner->run(apk)); + chain->add_task(tool.extra_data.value()->run(apk)); return chain; } diff --git a/source/apkbuilder.h b/source/apkbuilder.h index 09d849c..96525e0 100644 --- a/source/apkbuilder.h +++ b/source/apkbuilder.h @@ -7,15 +7,12 @@ class AndroidPackageFile; class ApkBuilder: public Tool { -private: - Tool *jarsigner = 0; - public: ApkBuilder(Builder &); Target *create_target(const std::vector &, const std::string &) override; protected: - void do_prepare() override; + void do_prepare(ToolData &) const override; private: static Task *_run(const AndroidPackageFile &); diff --git a/source/gnucompiler.cpp b/source/gnucompiler.cpp index 424a5b4..a96f5a3 100644 --- a/source/gnucompiler.cpp +++ b/source/gnucompiler.cpp @@ -28,8 +28,7 @@ const char *cpus[] = } GnuCompiler::GnuCompiler(Builder &b, const Architecture &a, const string &t): - Tool(b, &a, t), - version(0) + Tool(b, &a, t) { if(tag=="CC") { @@ -103,21 +102,23 @@ string GnuCompiler::create_build_signature(const BuildInfo &binfo) const return result; } -void GnuCompiler::do_prepare() +void GnuCompiler::do_prepare(ToolData &tool) const { - prepare_syspath(); - prepare_version(); + prepare_syspath(tool); + prepare_version(tool); } -void GnuCompiler::prepare_syspath() +void GnuCompiler::prepare_syspath(ToolData &tool) const { bool path_found = false; - const FS::Path &sysroot = build_info.sysroot; + const FS::Path &sysroot = tool.build_info.sysroot; + const std::string &tool_tag = static_cast(tool).get_tag(); - if(executable) + const FileTarget *exe = static_cast(tool).get_executable(); + if(exe) { ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(exe->get_path().str()); argv.push_back("-Wp,-v"); argv.push_back("-E"); if(tag=="CXX") @@ -145,8 +146,8 @@ void GnuCompiler::prepare_syspath() else if(record_path) { FS::Path path = strip(output.substr(start, newline-start)); - builder.get_logger().log("tools", "Got %s system path: %s", tag, path); - system_path.push_back(path); + builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, path); + tool.system_path.push_back(path); } start = newline+1; } @@ -157,32 +158,35 @@ void GnuCompiler::prepare_syspath() if(!path_found) { - builder.get_logger().log("tools", "No %s system path found, using defaults", tag); + builder.get_logger().log("tools", "No %s system path found, using defaults", tool_tag); + const Architecture &arch = *static_cast(tool).get_architecture(); if(!sysroot.empty()) - system_path.push_back(sysroot/"usr/include"); - else if(architecture->is_native()) - system_path.push_back("/usr/include"); + tool.system_path.push_back(sysroot/"usr/include"); + else if(arch.is_native()) + tool.system_path.push_back("/usr/include"); else - system_path.push_back(format("/usr/%s/include", architecture->get_cross_prefix())); + tool.system_path.push_back(format("/usr/%s/include", arch.get_cross_prefix())); } } -void GnuCompiler::prepare_version() +void GnuCompiler::prepare_version(ToolData &tool) const { - if(!executable) + const FileTarget *exe = static_cast(tool).get_executable(); + if(!exe) return; - string exe_path = executable->get_path().str(); - version = query_version("-dumpversion"); + string exe_path = exe->get_path().str(); + unsigned version = query_version(exe_path, "-dumpversion"); if(version>=0x70000) - version = query_version("-dumpfullversion"); - builder.get_logger().log("tools", "%s version is %d.%d.%d", FS::basename(executable->get_path()), version>>16, (version>>8)&0xFF, version&0xFF); + version = query_version(exe_path, "-dumpfullversion"); + tool.extra_data = version; + builder.get_logger().log("tools", "%s version is %d.%d.%d", FS::basename(exe->get_path()), version>>16, (version>>8)&0xFF, version&0xFF); } -unsigned GnuCompiler::query_version(const string &arg) const +unsigned GnuCompiler::query_version(const string &exe_path, const string &arg) const { ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(exe_path); argv.push_back(arg); builder.get_logger().log("auxcommands", "Running %s", join(argv.begin(), argv.end())); @@ -204,7 +208,7 @@ unsigned GnuCompiler::query_version(const string &arg) const Task *GnuCompiler::_run(const ObjectFile &object) { - const GnuCompiler &tool = dynamic_cast(*object.get_tool()); + const Tool &tool = *object.get_tool(); const Architecture &arch = *tool.get_architecture(); ExternalTask::Arguments argv; @@ -228,7 +232,8 @@ Task *GnuCompiler::_run(const ObjectFile &object) { argv.push_back("-Wextra"); argv.push_back("-Wundef"); - if(tool.version>=0x80000) + unsigned version = tool.get_extra_data(); + if(version>=0x80000) argv.push_back("-Wno-cast-function-type"); } if(binfo.warning_level>=3) diff --git a/source/gnucompiler.h b/source/gnucompiler.h index 8521a1f..54e1d76 100644 --- a/source/gnucompiler.h +++ b/source/gnucompiler.h @@ -14,9 +14,6 @@ appropriate type. */ class GnuCompiler: public Tool { -protected: - unsigned version; - public: GnuCompiler(Builder &, const Architecture &, const std::string &); @@ -25,10 +22,10 @@ public: Target *create_target(const std::vector &, const std::string &) override; std::string create_build_signature(const BuildInfo &) const override; protected: - void do_prepare() override; - void prepare_syspath(); - void prepare_version(); - unsigned query_version(const std::string &) const; + void do_prepare(ToolData &) const override; + void prepare_syspath(ToolData &) const; + void prepare_version(ToolData &) const; + unsigned query_version(const std::string &, const std::string &) const; private: static Task *_run(const ObjectFile &); diff --git a/source/gnulinker.cpp b/source/gnulinker.cpp index 2416449..f37cf99 100644 --- a/source/gnulinker.cpp +++ b/source/gnulinker.cpp @@ -98,15 +98,17 @@ string GnuLinker::create_build_signature(const BuildInfo &binfo) const return result; } -void GnuLinker::do_prepare() +void GnuLinker::do_prepare(ToolData &tool) const { bool path_found = false; - const FS::Path &sysroot = build_info.sysroot; + const FS::Path &sysroot = tool.build_info.sysroot; + const std::string &tool_tag = static_cast(tool).get_tag(); - if(executable) + const FileTarget *exe = static_cast(tool).get_executable(); + if(exe) { ExternalTask::Arguments argv; - argv.push_back(executable->get_path().str()); + argv.push_back(exe->get_path().str()); argv.push_back("-Wl,--verbose"); argv.push_back("-nostdlib"); if(!sysroot.empty()) @@ -139,8 +141,8 @@ void GnuLinker::do_prepare() } path /= output.substr(search_dir, end-search_dir); - builder.get_logger().log("tools", "Got %s system path: %s", tag, path); - system_path.push_back(path); + builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, path); + tool.system_path.push_back(path); path_found = true; start = end+3; @@ -152,26 +154,26 @@ void GnuLinker::do_prepare() if(!path_found) { - builder.get_logger().log("tools", "No %s system path found, using defaults", tag); + builder.get_logger().log("tools", "No %s system path found, using defaults", tool_tag); if(!sysroot.empty()) - system_path.push_back(sysroot/"usr/lib"); + tool.system_path.push_back(sysroot/"usr/lib"); else if(architecture->is_native()) { - system_path.push_back("/lib"); - system_path.push_back("/usr/lib"); + tool.system_path.push_back("/lib"); + tool.system_path.push_back("/usr/lib"); if(architecture->match_name("pc-32-linux")) { - system_path.push_back("/lib/i386-linux-gnu"); - system_path.push_back("/usr/lib/i386-linux-gnu"); + tool.system_path.push_back("/lib/i386-linux-gnu"); + tool.system_path.push_back("/usr/lib/i386-linux-gnu"); } else if(architecture->match_name("pc-64-linux")) { - system_path.push_back("/lib/x86_64-linux-gnu"); - system_path.push_back("/usr/lib/x86_64-linux-gnu"); + tool.system_path.push_back("/lib/x86_64-linux-gnu"); + tool.system_path.push_back("/usr/lib/x86_64-linux-gnu"); } } else - system_path.push_back(format("/usr/%s/lib", architecture->get_cross_prefix())); + tool.system_path.push_back(format("/usr/%s/lib", architecture->get_cross_prefix())); } } diff --git a/source/gnulinker.h b/source/gnulinker.h index c04afd1..9964ffa 100644 --- a/source/gnulinker.h +++ b/source/gnulinker.h @@ -21,7 +21,7 @@ public: Target *create_install(Target &) const override; std::string create_build_signature(const BuildInfo &) const override; protected: - void do_prepare() override; + void do_prepare(ToolData &) const override; private: static Task *_run(const Binary &); }; diff --git a/source/msvccompiler.cpp b/source/msvccompiler.cpp index c3361ee..7d751de 100644 --- a/source/msvccompiler.cpp +++ b/source/msvccompiler.cpp @@ -73,22 +73,24 @@ string MsvcCompiler::create_build_signature(const BuildInfo &binfo) const return result; } -void MsvcCompiler::do_prepare() +void MsvcCompiler::do_prepare(ToolData &tool) const { + const std::string &tool_tag = static_cast(tool).get_tag(); + const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir(); - system_path.push_back(vc_base_dir/"include"); + tool.system_path.push_back(vc_base_dir/"include"); const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir(); const string &win_sdk_ver = ms_tools.get_windows_sdk_version(); - system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt"); - system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared"); - system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um"); + tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt"); + tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared"); + tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um"); string path; - for(const FS::Path &p: system_path) + for(const FS::Path &p: tool.system_path) { append(path, ";", p.str()); - builder.get_logger().log("tools", "Got %s system path: %s", tag, p); + builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, p); } setenv("INCLUDE", path); diff --git a/source/msvccompiler.h b/source/msvccompiler.h index 484fe46..f3b9a31 100644 --- a/source/msvccompiler.h +++ b/source/msvccompiler.h @@ -20,7 +20,7 @@ public: std::string create_build_signature(const BuildInfo &) const override; protected: - void do_prepare() override; + void do_prepare(ToolData &) const override; public: static Task *_run(const ObjectFile &); diff --git a/source/msvclinker.cpp b/source/msvclinker.cpp index f802ef6..968bd5d 100644 --- a/source/msvclinker.cpp +++ b/source/msvclinker.cpp @@ -63,23 +63,25 @@ string MsvcLinker::create_build_signature(const BuildInfo &binfo) const return result; } -void MsvcLinker::do_prepare() +void MsvcLinker::do_prepare(ToolData &tool) const { - string arch_dir = (architecture->get_bits()==64 ? "x64" : "x86"); + const std::string &tool_tag = static_cast(tool).get_tag(); + const Architecture &arch = *static_cast(tool).get_architecture(); + string arch_dir = (arch.get_bits()==64 ? "x64" : "x86"); const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir(); - system_path.push_back(vc_base_dir/"lib"/arch_dir); + tool.system_path.push_back(vc_base_dir/"lib"/arch_dir); const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir(); const string &win_sdk_ver = ms_tools.get_windows_sdk_version(); - system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"ucrt"/arch_dir); - system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"um"/arch_dir); + tool.system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"ucrt"/arch_dir); + tool.system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"um"/arch_dir); string path; - for(const FS::Path &p: system_path) + for(const FS::Path &p: tool.system_path) { append(path, ";", p.str()); - builder.get_logger().log("tools", "Got %s system path: %s", tag, p); + builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, p); } setenv("LIB", path); diff --git a/source/msvclinker.h b/source/msvclinker.h index 95ff2a9..44cb986 100644 --- a/source/msvclinker.h +++ b/source/msvclinker.h @@ -18,7 +18,7 @@ public: std::string create_build_signature(const BuildInfo &) const override; protected: - void do_prepare() override; + void do_prepare(ToolData &data) const override; public: static Task *_run(const Binary &); diff --git a/source/tool.cpp b/source/tool.cpp index cd00237..d7b27ff 100644 --- a/source/tool.cpp +++ b/source/tool.cpp @@ -37,19 +37,24 @@ Target *Tool::create_target(Target &source, const string &arg) return create_target(sources, arg); } -void Tool::prepare() +void Tool::prepare(Tool *tool) { - if(prepared) + if(!tool) + tool = this; + else if(tool->get_base_tool()!=this) + throw invalid_argument("Tool::prepare"); + + if(tool->prepared) return; - prepared = true; - if(!command.empty()) - executable = builder.get_vfs().find_binary(command); - do_prepare(); + tool->prepared = true; + if(!tool->command.empty()) + tool->executable = builder.get_vfs().find_binary(tool->command); + do_prepare(*tool); if(!command.empty() && !executable) { - builder.get_logger().log("problems", "Can't find executable %s for %s", command, tag); - problems.push_back(format("Can't find executable %s", command)); + builder.get_logger().log("problems", "Can't find executable %s for %s", tool->command, tool->tag); + tool->problems.push_back(format("Can't find executable %s", tool->command)); } } diff --git a/source/tool.h b/source/tool.h index 5ea6335..85bae55 100644 --- a/source/tool.h +++ b/source/tool.h @@ -16,11 +16,20 @@ class Component; class FileTarget; class Target; +class ToolData +{ +public: + VirtualFileSystem::SearchPath system_path; + BuildInfo build_info; + Msp::Variant extra_data; + std::vector problems; +}; + /** Base class for tools. Tools are used to turn targets into other targets. Examples include compilers and linkers. */ -class Tool +class Tool: protected ToolData { public: enum ProcessingUnit @@ -39,14 +48,12 @@ protected: std::vector input_suffixes; std::vector aux_suffixes; ProcessingUnit processing_unit = ONE_FILE; - VirtualFileSystem::SearchPath system_path; - BuildInfo build_info; std::function run_func; bool prepared = false; - std::vector problems; Tool(Builder &b, const std::string &t): Tool(b, 0, t) { } Tool(Builder &b, const Architecture *a, const std::string &t): builder(b), architecture(a), tag(t) { } + public: virtual ~Tool() { } @@ -58,6 +65,8 @@ public: tool is architecture-agnostic. */ const Architecture *get_architecture() const { return architecture; } + virtual const Tool *get_base_tool() const { return this; } + protected: void set_run(std::function); @@ -100,6 +109,8 @@ public: the chain. */ const BuildInfo &get_build_info() const { return build_info; } + const Msp::Variant &get_extra_data() const { return extra_data; } + /// Creates a source file appropriate for this tool. virtual Target *create_source(const Component &, const Msp::FS::Path &) const { return 0; } @@ -122,10 +133,10 @@ public: virtual std::string create_build_signature(const BuildInfo &) const; - void prepare(); + void prepare(Tool * = 0); protected: - virtual void do_prepare() { } + virtual void do_prepare(ToolData &) const { } public: const std::vector &get_problems() const { return problems; }