From: Mikko Rasa Date: Fri, 18 Nov 2016 21:06:20 +0000 (+0200) Subject: Support source generators that combine multiple files into one X-Git-Url: http://git.tdb.fi/?p=builder.git;a=commitdiff_plain;h=4e2a160d94ca808cfb511cc2d38e115d989809f2 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. --- 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