From: Mikko Rasa Date: Fri, 30 Dec 2022 17:00:15 +0000 (+0200) Subject: Rewrite BinaryComponent::create_targets in a more general way X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=1ab0b29388ce71004b95bc6bec6d9ef3b4371e12;p=builder.git Rewrite BinaryComponent::create_targets in a more general way Instead of assuming a generator-compiler-linker chain, with generators only coming from the package, it now applies tools until it arrives at object files, which are then fed to the linker. This allows global generator tools and also allows multiple generators to be chained, with the caveat that if the chain contains more than one step operating on a directory or a component, the results may be unpredictable. --- diff --git a/source/lib/binarycomponent.cpp b/source/lib/binarycomponent.cpp index 3209ccc..d29673a 100644 --- a/source/lib/binarycomponent.cpp +++ b/source/lib/binarycomponent.cpp @@ -48,70 +48,69 @@ void BinaryComponent::create_targets() const const Toolchain &toolchain = builder.get_toolchain(); const Toolchain &pkg_tools = package.get_toolchain(); + Tool &linker = toolchain.get_tool("LINK"); + + vector pending = create_sources(); + vector objs; - vector source_filenames = collect_source_files(); - objs.reserve(source_filenames.size()); - for(auto i=source_filenames.begin(); i!=source_filenames.end(); ++i) + while(!pending.empty()) { - string ext = FS::extpart(FS::basename(*i)); - Target *src = 0; - - Tool *gen = pkg_tools.get_tool_for_suffix(ext); - if(gen) + Tool *tool = 0; + for(auto i=pending.begin(); i!=pending.end(); ) { - vector templates; - templates.push_back(gen->create_source(*this, *i)); + string ext = FS::extpart(FS::basename((*i)->get_path())); + if(linker.accepts_suffix(ext)) + { + /* Targets accepted by the linker should not be processed further + before feeding them to the linker */ + objs.push_back(*i); + i = pending.erase(i); + continue; + } - Tool::ProcessingUnit processing_unit = gen->get_processing_unit(); - if(processing_unit!=Tool::ONE_FILE) + // Pick the tool with the smallest processing unit + Tool *tgt_tool = pkg_tools.get_tool_for_suffix(ext); + if(!tgt_tool) + tgt_tool = toolchain.get_tool_for_suffix(ext); + if(tgt_tool && (!tool || tgt_tool->get_processing_unit()get_processing_unit())) { - FS::Path source_dir = FS::dirname(*i); - for(auto j=next(i); 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 - j = source_filenames.erase(j); - } - else - ++j; - } + tool = tgt_tool; + if(tool->get_processing_unit()==Tool::ONE_FILE) + break; } - src = gen->create_target(templates); - ext = FS::extpart(FS::basename(dynamic_cast(*src).get_path())); + ++i; } - Tool *tool = toolchain.get_tool_for_suffix(ext, true); - if(tool) - { - if(!src) - src = tool->create_source(*this, *i); - if(!src) - continue; + if(!tool) + break; - if(tool->accepts_suffix(ext)) + Tool::ProcessingUnit processing_unit = tool->get_processing_unit(); + if(processing_unit==Tool::ONE_FILE) + { + // Process all pending accepted by the tool + for(FileTarget *&t: pending) { - Target *obj = tool->create_target(*src); - objs.push_back(obj); + string ext = FS::extpart(FS::basename(t->get_path())); + if(tool->accepts_suffix(ext)) + { + t = &dynamic_cast(*tool->create_target(*t)); + if(type==LIBRARY && install) + create_install(*t); + } } - + } + else + { + // Process one group of pending accepted by the tool + vector group = extract_group(pending, *tool); + FileTarget &tgt = dynamic_cast(*tool->create_target(group)); + pending.push_back(&tgt); if(type==LIBRARY && install) - { - if(dynamic_cast(src)->is_installable()) - build_graph.add_installed_target(*src); - - for(Target *s: src->get_side_effects()) - if(dynamic_cast(s)->is_installable()) - build_graph.add_installed_target(*s); - } + create_install(tgt); } } - Tool &linker = toolchain.get_tool("LINK"); - vector results; results.reserve(2); if(type==LIBRARY) @@ -133,6 +132,74 @@ void BinaryComponent::create_targets() const } } +vector BinaryComponent::create_sources() const +{ + const Toolchain &toolchain = package.get_builder().get_toolchain(); + const Toolchain &pkg_tools = package.get_toolchain(); + + vector targets; + for(const FS::Path &s: collect_source_files()) + { + string ext = FS::extpart(FS::basename(s)); + Target *src = 0; + + Tool *tool = pkg_tools.get_tool_for_suffix(ext, true); + if(tool) + src = tool->create_source(*this, s); + if(!src) + { + tool = toolchain.get_tool_for_suffix(ext, true); + if(tool) + src = tool->create_source(*this, s); + } + + if(FileTarget *file = dynamic_cast(src)) + { + targets.push_back(file); + if(type==LIBRARY && install) + create_install(*file); + } + } + + return targets; +} + +vector BinaryComponent::extract_group(vector &targets, const Tool &tool) +{ + Tool::ProcessingUnit processing_unit = tool.get_processing_unit(); + vector group; + FS::Path group_dir; + for(auto i=targets.begin(); i!=targets.end(); ) + { + const FS::Path &path = (*i)->get_path(); + string ext = FS::extpart(FS::basename(path)); + FS::Path dir = FS::dirname(path); + if(tool.accepts_suffix(ext) && (processing_unit!=Tool::DIRECTORY || group.empty() || dir==group_dir)) + { + group.push_back(*i); + group_dir = dir; + i = targets.erase(i); + } + else + ++i; + } + + return group; +} + +void BinaryComponent::create_install(FileTarget &target) const +{ + BuildGraph &build_graph = package.get_builder().get_build_graph(); + + if(target.is_installable()) + build_graph.add_installed_target(target); + + for(Target *s: target.get_side_effects()) + if(dynamic_cast(*s).is_installable()) + build_graph.add_installed_target(*s); +} + + BinaryComponent::Loader::Loader(BinaryComponent &c): DataFile::DerivedObjectLoader(c) { diff --git a/source/lib/binarycomponent.h b/source/lib/binarycomponent.h index ef145da..eaa123c 100644 --- a/source/lib/binarycomponent.h +++ b/source/lib/binarycomponent.h @@ -3,6 +3,10 @@ #include "component.h" +class FileTarget; +class Target; +class Tool; + class BinaryComponent: public Component { public: @@ -33,6 +37,10 @@ public: void create_build_info() override; void update_exported_build_info(BuildInfo &) const override; void create_targets() const override; +private: + std::vector create_sources() const; + static std::vector extract_group(std::vector &, const Tool &); + void create_install(FileTarget &) const; }; #endif