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)
}
}
+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)
{