Tool *gen = pkg_tools.get_tool_for_suffix(ext);
if(gen)
{
- Target *tmpl = gen->create_source(*this, *i);
- if(tmpl)
+ list<Target *> 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<FileTarget &>(*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<FileTarget &>(*src).get_path()));
}
Tool *tool = toolchain.get_tool_for_suffix(ext, true);
{
set_command("ar", true);
input_suffixes.push_back(".o");
+ processing_unit = COMPONENT;
}
Target *GnuArchiver::create_target(const list<Target *> &sources, const string &)
input_suffixes.push_back(".o");
input_suffixes.push_back(".a");
+ processing_unit = COMPONENT;
+
if(!sysroot.empty())
{
build_info.sysroot = sysroot;
Target *SourceGenerator::create_target(const list<Target *> &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");
TemplateFile &tmpl = dynamic_cast<TemplateFile &>(*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<string>::const_iterator i=out_suffixes.begin(); i!=out_suffixes.end(); ++i)
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<Target *>::const_iterator j=sources.begin(); j!=sources.end(); ++j)
+ target->add_dependency(**j);
if(primary)
primary->add_side_effect(*target);
else
add("command", &Loader::command);
add("in_suffix", &Loader::in_suffix);
add("out_suffix", &Loader::out_suffix);
+ add("processing_unit", static_cast<ProcessingUnit SourceGenerator::*>(&SourceGenerator::processing_unit));
}
void SourceGenerator::Loader::argument(const string &a)
Tar::Tar(Builder &b):
Tool(b, "TAR")
-{ }
+{
+ processing_unit = COMPONENT;
+}
Target *Tar::create_target(const list<Target *> &sources, const string &arg)
{
architecture(0),
tag(t),
executable(0),
+ processing_unit(ONE_FILE),
prepared(false)
{ }
architecture(&a),
tag(t),
executable(0),
+ processing_unit(ONE_FILE),
prepared(false)
{ }
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));
+}
class Tool
{
public:
+ enum ProcessingUnit
+ {
+ ONE_FILE,
+ DIRECTORY,
+ COMPONENT
+ };
+
typedef std::list<Msp::FS::Path> SearchPath;
typedef std::list<std::string> SuffixList;
FileTarget *executable;
SuffixList input_suffixes;
SuffixList aux_suffixes;
+ ProcessingUnit processing_unit;
SearchPath system_path;
BuildInfo build_info;
bool prepared;
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; }
SubTool(Tool &);
};
+
+void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &);
+
#endif