]> git.tdb.fi Git - builder.git/commitdiff
Rewrite BinaryComponent::create_targets in a more general way
authorMikko Rasa <tdb@tdb.fi>
Fri, 30 Dec 2022 17:00:15 +0000 (19:00 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 30 Dec 2022 17:00:15 +0000 (19:00 +0200)
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.

source/lib/binarycomponent.cpp
source/lib/binarycomponent.h

index 3209ccc185438f721d0892053564724c17fb87fa..d29673a73761e72420dc398cae16044c435fd942 100644 (file)
@@ -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<FileTarget *> pending = create_sources();
+
        vector<Target *> objs;
-       vector<FS::Path> 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<Target *> 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()<tool->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<FileTarget &>(*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<FileTarget &>(*tool->create_target(*t));
+                                       if(type==LIBRARY && install)
+                                               create_install(*t);
+                               }
                        }
-
+               }
+               else
+               {
+                       // Process one group of pending accepted by the tool
+                       vector<Target *> group = extract_group(pending, *tool);
+                       FileTarget &tgt = dynamic_cast<FileTarget &>(*tool->create_target(group));
+                       pending.push_back(&tgt);
                        if(type==LIBRARY && install)
-                       {
-                               if(dynamic_cast<FileTarget *>(src)->is_installable())
-                                       build_graph.add_installed_target(*src);
-
-                               for(Target *s: src->get_side_effects())
-                                       if(dynamic_cast<FileTarget *>(s)->is_installable())
-                                               build_graph.add_installed_target(*s);
-                       }
+                               create_install(tgt);
                }
        }
 
-       Tool &linker = toolchain.get_tool("LINK");
-
        vector<Target *> results;
        results.reserve(2);
        if(type==LIBRARY)
@@ -133,6 +132,74 @@ void BinaryComponent::create_targets() const
        }
 }
 
+vector<FileTarget *> BinaryComponent::create_sources() const
+{
+       const Toolchain &toolchain = package.get_builder().get_toolchain();
+       const Toolchain &pkg_tools = package.get_toolchain();
+
+       vector<FileTarget *> 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<FileTarget *>(src))
+               {
+                       targets.push_back(file);
+                       if(type==LIBRARY && install)
+                               create_install(*file);
+               }
+       }
+
+       return targets;
+}
+
+vector<Target *> BinaryComponent::extract_group(vector<FileTarget *> &targets, const Tool &tool)
+{
+       Tool::ProcessingUnit processing_unit = tool.get_processing_unit();
+       vector<Target *> 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<FileTarget &>(*s).is_installable())
+                       build_graph.add_installed_target(*s);
+}
+
+
 BinaryComponent::Loader::Loader(BinaryComponent &c):
        DataFile::DerivedObjectLoader<BinaryComponent, Component::Loader>(c)
 {
index ef145da49da7b6bdea0649412b6782318641d182..eaa123c0a4ae7fcf6d5c02fe481b0389eaee296d 100644 (file)
@@ -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<FileTarget *> create_sources() const;
+       static std::vector<Target *> extract_group(std::vector<FileTarget *> &, const Tool &);
+       void create_install(FileTarget &) const;
 };
 
 #endif