if(type==PROGRAM || type==LIBRARY || type==MODULE)
{
list<Target *> objs;
+ const Toolchain &pkg_tools = package.get_toolchain();
for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
{
string ext = FS::extpart(FS::basename(*i));
+ Target *src = 0;
+
+ Tool *gen = pkg_tools.get_tool_for_suffix(ext);
+ if(gen)
+ {
+ Target *tmpl = gen->create_source(*this, *i);
+ if(tmpl)
+ {
+ src = gen->create_target(*tmpl);
+ ext = FS::extpart(FS::basename(dynamic_cast<FileTarget &>(*src).get_path()));
+ }
+ }
+
Tool *tool = toolchain.get_tool_for_suffix(ext, true);
if(tool)
{
- Target *src = tool->create_source(*this, *i);
+ if(!src)
+ src = tool->create_source(*this, *i);
if(!src)
continue;
objs.push_back(obj);
}
- if(type==LIBRARY && install && dynamic_cast<FileTarget *>(src)->is_installable())
- build_graph.add_installed_target(*src);
+ if(type==LIBRARY && install)
+ {
+ if(dynamic_cast<FileTarget *>(src)->is_installable())
+ build_graph.add_installed_target(*src);
+
+ const Target::Dependencies &side_effects = src->get_side_effects();
+ for(Target::Dependencies::const_iterator j=side_effects.begin(); j!=side_effects.end(); ++j)
+ if(dynamic_cast<FileTarget *>(*j)->is_installable())
+ build_graph.add_installed_target(**j);
+ }
}
}
#include "component.h"
#include "filetarget.h"
#include "installmap.h"
+#include "sourcepackage.h"
+#include "templatefile.h"
using namespace std;
using namespace Msp;
unsigned overlay_depth = 0;
if(comp && !comp->get_overlays().empty())
{
+ // Check if the target resides in an overlay directory
const Component::OverlayList &overlays = comp->get_overlays();
string last_dir = FS::basename(FS::dirname(target.get_path()));
for(Component::OverlayList::const_iterator i=overlays.begin(); i!=overlays.end(); ++i)
overlay_depth = 1;
}
- const FS::Path &source = target.get_path();
+ FS::Path source = target.get_path();
+ if(comp)
+ {
+ /* Check if the target is a generated source file, residing in the
+ temporary directory */
+ const SourcePackage &pkg = comp->get_package();
+ int temp_depth = FS::descendant_depth(source, pkg.get_temp_directory());
+ if(temp_depth>0)
+ {
+ // If it is, use the generating template's directory instead
+ const Target::Dependencies &deps = target.get_dependencies();
+ for(Target::Dependencies::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+ if(const TemplateFile *tmpl = dynamic_cast<const TemplateFile *>(*i))
+ {
+ source = FS::dirname(tmpl->get_path())/FS::basename(source);
+ break;
+ }
+ }
+ }
+
+ /* Look for a mapping entry matching both the target's original location
+ and default install location */
FS::Path install = target.get_install_location();
for(list<Entry>::const_iterator i=entries.begin(); i!=entries.end(); ++i)
{
--- /dev/null
+#include <msp/fs/utils.h>
+#include "builder.h"
+#include "executable.h"
+#include "externaltask.h"
+#include "sourcegenerator.h"
+#include "sourcepackage.h"
+#include "templatefile.h"
+
+using namespace std;
+using namespace Msp;
+
+SourceGenerator::SourceGenerator(Builder &b, const SourcePackage &p, const string &t):
+ Tool(b, t),
+ package(p)
+{ }
+
+Target *SourceGenerator::create_source(const Component &comp, const FS::Path &path) const
+{
+ return new TemplateFile(builder, comp, path);
+}
+
+Target *SourceGenerator::create_target(const list<Target *> &sources, const string &)
+{
+ if(sources.size()!=1)
+ throw invalid_argument("SourceGenerator::create_target");
+
+ 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()));
+
+ Target *primary = 0;
+ for(list<string>::const_iterator i=out_suffixes.begin(); i!=out_suffixes.end(); ++i)
+ {
+ Tool *tool = builder.get_toolchain().get_tool_for_suffix(*i, true);
+ if(tool)
+ {
+ 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);
+ if(primary)
+ primary->add_side_effect(*target);
+ else
+ primary = target;
+ }
+ }
+
+ return primary;
+}
+
+void SourceGenerator::do_prepare()
+{
+ FS::Path exe_fn = package.get_source_directory()/command;
+ executable = builder.get_vfs().get_target(exe_fn);
+ if(!executable)
+ executable = new Executable(builder, exe_fn);
+}
+
+Task *SourceGenerator::run(const Target &target) const
+{
+ const SourceFile &out_src = dynamic_cast<const SourceFile &>(target);
+ const FS::Path &work_dir = out_src.get_package()->get_source_directory();
+
+ vector<string> args;
+ args.push_back(executable->get_path().str());
+
+ const Target::Dependencies &deps = target.get_dependencies();
+ for(Target::Dependencies::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+ if(const TemplateFile *tmpl = dynamic_cast<const TemplateFile *>(*i))
+ args.push_back(FS::relative(tmpl->get_path(), work_dir).str());
+
+ args.push_back(FS::relative(out_src.get_path(), work_dir).str());
+
+ return new ExternalTask(args, work_dir);
+}
+
+
+SourceGenerator::Loader::Loader(SourceGenerator &sg):
+ DataFile::ObjectLoader<SourceGenerator>(sg)
+{
+ add("command", &Loader::command);
+ add("in_suffix", &Loader::in_suffix);
+ add("out_suffix", &Loader::out_suffix);
+}
+
+void SourceGenerator::Loader::command(const string &c)
+{
+ obj.set_command(c);
+}
+
+void SourceGenerator::Loader::in_suffix(const string &s)
+{
+ obj.input_suffixes.push_back(s);
+}
+
+void SourceGenerator::Loader::out_suffix(const string &s)
+{
+ obj.out_suffixes.push_back(s);
+}
--- /dev/null
+#ifndef SOURCEGENERATOR_H_
+#define SOURCEGENERATOR_H_
+
+#include <msp/datafile/objectloader.h>
+#include "sourcepackage.h"
+#include "tool.h"
+
+class SourceGenerator: public Tool
+{
+public:
+ class Loader: public Msp::DataFile::ObjectLoader<SourceGenerator>
+ {
+ public:
+ Loader(SourceGenerator &);
+
+ private:
+ void command(const std::string &);
+ void in_suffix(const std::string &);
+ void out_suffix(const std::string &);
+ };
+
+private:
+ const SourcePackage &package;
+ std::list<std::string> out_suffixes;
+
+public:
+ SourceGenerator(Builder &, const SourcePackage &, const std::string &);
+
+ virtual Target *create_source(const Component &, const Msp::FS::Path &) const;
+ virtual Target *create_target(const std::list<Target *> &, const std::string &);
+
+private:
+ virtual void do_prepare();
+
+public:
+ virtual Task *run(const Target &) const;
+};
+
+#endif
#include "file.h"
#include "pkgconfigfile.h"
#include "tool.h"
+#include "sourcegenerator.h"
#include "sourcepackage.h"
using namespace std;
add("description", &SourcePackage::description);
add("build_info", &Loader::build_info);
add("feature", &Loader::feature);
+ add("generate", &Loader::generate);
add("if_feature", &Loader::if_feature);
add("program", &Loader::component<Component::PROGRAM>);
add("library", &Loader::component<Component::LIBRARY>);
load_sub(obj.build_info);
}
+void SourcePackage::Loader::generate(const string &tag)
+{
+ SourceGenerator *gen = new SourceGenerator(obj.builder, obj, tag);
+ load_sub(*gen);
+ obj.local_tools.add_tool(gen);
+}
+
void SourcePackage::Loader::if_feature(const string &cond)
{
bool match = obj.match_feature(cond);
#include "config.h"
#include "feature.h"
#include "package.h"
+#include "toolchain.h"
class Builder;
class BuildType;
template<Component::Type>
void component(const std::string &);
void build_info();
+ void generate(const std::string &);
void if_feature(const std::string &);
void interface_version(const std::string &);
void source_tarball();
FileTarget *build_file;
Msp::FS::Path source_dir;
const BuildType *build_type;
+ Toolchain local_tools;
FeatureList features;
BuildInfo build_info;
ComponentList components;
Msp::FS::Path get_temp_directory() const;
Msp::FS::Path get_output_directory() const;
+ const Toolchain &get_toolchain() const { return local_tools; }
const ComponentList &get_components() const { return components; }
const Config &get_config() const { return config; }
bool match_feature(const std::string &) const;
--- /dev/null
+#include "templatefile.h"
+
+using namespace Msp;
+
+TemplateFile::TemplateFile(Builder &b, const Component &c, const FS::Path &p):
+ SourceFile(b, c, p)
+{ }
--- /dev/null
+#ifndef TEMPLATEFILE_H_
+#define TEMPLATEFILE_H_
+
+#include "sourcefile.h"
+
+/**
+Input file for SourceGenerator.
+*/
+class TemplateFile: public SourceFile
+{
+public:
+ TemplateFile(Builder &, const Component &, const Msp::FS::Path &);
+
+ virtual const char *get_type() const { return "TemplateFile"; }
+};
+
+#endif