From 4e2a160d94ca808cfb511cc2d38e115d989809f2 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 18 Nov 2016 23:06:20 +0200 Subject: [PATCH] Support source generators that combine multiple files into one Some existing tools have processing unit annotations too, but for some of them it's not clear what the unit should be. --- source/binarycomponent.cpp | 26 ++++++++++++++++++++++---- source/gnuarchiver.cpp | 1 + source/gnulinker.cpp | 2 ++ source/sourcegenerator.cpp | 14 +++++++++++--- source/tar.cpp | 4 +++- source/tool.cpp | 16 ++++++++++++++++ source/tool.h | 14 ++++++++++++++ 7 files changed, 69 insertions(+), 8 deletions(-) diff --git a/source/binarycomponent.cpp b/source/binarycomponent.cpp index 565e8bc..74ac0ba 100644 --- a/source/binarycomponent.cpp +++ b/source/binarycomponent.cpp @@ -64,12 +64,30 @@ void BinaryComponent::create_targets() const Tool *gen = pkg_tools.get_tool_for_suffix(ext); if(gen) { - Target *tmpl = gen->create_source(*this, *i); - if(tmpl) + list templates; + templates.push_back(gen->create_source(*this, *i)); + + Tool::ProcessingUnit processing_unit = gen->get_processing_unit(); + if(processing_unit!=Tool::ONE_FILE) { - src = gen->create_target(*tmpl); - ext = FS::extpart(FS::basename(dynamic_cast(*src).get_path())); + FS::Path source_dir = FS::dirname(*i); + SourceList::const_iterator j = i; + for(++j; j!=source_filenames.end(); ) + { + if((processing_unit!=Tool::DIRECTORY || FS::dirname(*j)==source_dir) && + pkg_tools.get_tool_for_suffix(FS::extpart(FS::basename(*j)))==gen) + { + templates.push_back(gen->create_source(*this, *j)); + // Remove additional files so they won't get processed again + source_filenames.erase(j++); + } + else + ++j; + } } + + src = gen->create_target(templates); + ext = FS::extpart(FS::basename(dynamic_cast(*src).get_path())); } Tool *tool = toolchain.get_tool_for_suffix(ext, true); diff --git a/source/gnuarchiver.cpp b/source/gnuarchiver.cpp index 158a4d4..1700070 100644 --- a/source/gnuarchiver.cpp +++ b/source/gnuarchiver.cpp @@ -18,6 +18,7 @@ GnuArchiver::GnuArchiver(Builder &b, const Architecture &a): { set_command("ar", true); input_suffixes.push_back(".o"); + processing_unit = COMPONENT; } Target *GnuArchiver::create_target(const list &sources, const string &) diff --git a/source/gnulinker.cpp b/source/gnulinker.cpp index 1b969b4..cc0a50d 100644 --- a/source/gnulinker.cpp +++ b/source/gnulinker.cpp @@ -27,6 +27,8 @@ GnuLinker::GnuLinker(Builder &b, const Architecture &a, const FS::Path &sysroot) input_suffixes.push_back(".o"); input_suffixes.push_back(".a"); + processing_unit = COMPONENT; + if(!sysroot.empty()) { build_info.sysroot = sysroot; diff --git a/source/sourcegenerator.cpp b/source/sourcegenerator.cpp index f00b26b..192ae28 100644 --- a/source/sourcegenerator.cpp +++ b/source/sourcegenerator.cpp @@ -22,7 +22,7 @@ Target *SourceGenerator::create_source(const Component &comp, const FS::Path &pa Target *SourceGenerator::create_target(const list &sources, const string &) { - if(sources.size()!=1) + if(sources.empty()) throw invalid_argument("SourceGenerator::create_target"); if(out_suffixes.empty()) throw logic_error("No output suffixes"); @@ -30,7 +30,13 @@ Target *SourceGenerator::create_target(const list &sources, const stri TemplateFile &tmpl = dynamic_cast(*sources.front()); const Component *comp = tmpl.get_component(); const SourcePackage *pkg = tmpl.get_package(); - string base = FS::basepart(FS::basename(tmpl.get_path())); + string base; + if(processing_unit==ONE_FILE) + base = FS::basepart(FS::basename(tmpl.get_path())); + else if(processing_unit==DIRECTORY) + base = FS::basename(FS::dirname(tmpl.get_path())); + else + base = comp->get_name(); Target *primary = 0; for(list::const_iterator i=out_suffixes.begin(); i!=out_suffixes.end(); ++i) @@ -41,7 +47,8 @@ Target *SourceGenerator::create_target(const list &sources, const stri FS::Path fn = pkg->get_temp_directory()/comp->get_name()/(base+*i); Target *target = tool->create_source(*comp, fn); target->set_tool(*this); - target->add_dependency(tmpl); + for(list::const_iterator j=sources.begin(); j!=sources.end(); ++j) + target->add_dependency(**j); if(primary) primary->add_side_effect(*target); else @@ -82,6 +89,7 @@ SourceGenerator::Loader::Loader(SourceGenerator &sg): add("command", &Loader::command); add("in_suffix", &Loader::in_suffix); add("out_suffix", &Loader::out_suffix); + add("processing_unit", static_cast(&SourceGenerator::processing_unit)); } void SourceGenerator::Loader::argument(const string &a) diff --git a/source/tar.cpp b/source/tar.cpp index bcaa852..6dee843 100644 --- a/source/tar.cpp +++ b/source/tar.cpp @@ -13,7 +13,9 @@ using namespace Msp; Tar::Tar(Builder &b): Tool(b, "TAR") -{ } +{ + processing_unit = COMPONENT; +} Target *Tar::create_target(const list &sources, const string &arg) { diff --git a/source/tool.cpp b/source/tool.cpp index 3aa2db3..e2afe79 100644 --- a/source/tool.cpp +++ b/source/tool.cpp @@ -12,6 +12,7 @@ Tool::Tool(Builder &b, const string &t): architecture(0), tag(t), executable(0), + processing_unit(ONE_FILE), prepared(false) { } @@ -20,6 +21,7 @@ Tool::Tool(Builder &b, const Architecture &a, const string &t): architecture(&a), tag(t), executable(0), + processing_unit(ONE_FILE), prepared(false) { } @@ -71,3 +73,17 @@ SubTool::SubTool(Tool &p): Tool(p), parent(p) { } + + +void operator>>(const LexicalConverter &conv, Tool::ProcessingUnit &unit) +{ + const string &str = conv.get(); + if(str=="FILE") + unit = Tool::ONE_FILE; + else if(str=="DIRECTORY") + unit = Tool::DIRECTORY; + else if(str=="COMPONENT") + unit = Tool::COMPONENT; + else + throw lexical_error(format("conversion of '%s' to ProcessingUnit", str)); +} diff --git a/source/tool.h b/source/tool.h index ad89e47..2f8c25b 100644 --- a/source/tool.h +++ b/source/tool.h @@ -21,6 +21,13 @@ Examples include compilers and linkers. class Tool { public: + enum ProcessingUnit + { + ONE_FILE, + DIRECTORY, + COMPONENT + }; + typedef std::list SearchPath; typedef std::list SuffixList; @@ -32,6 +39,7 @@ protected: FileTarget *executable; SuffixList input_suffixes; SuffixList aux_suffixes; + ProcessingUnit processing_unit; SearchPath system_path; BuildInfo build_info; bool prepared; @@ -70,6 +78,9 @@ public: auxiliary suffixes are considered as well */ bool accepts_suffix(const std::string &, bool aux = false) const; + /** Returns the grouping unit this tool prefers to process. */ + ProcessingUnit get_processing_unit() const { return processing_unit; } + /// Returns the systemwide search path for source files. const SearchPath &get_system_path() const { return system_path; } @@ -125,4 +136,7 @@ protected: SubTool(Tool &); }; + +void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &); + #endif -- 2.43.0