{
add("source", &Loader::source);
add("install", &Component::install);
+ add("install_map", &Loader::install_map);
add("build_info", &Loader::build_info);
add("require", &Loader::require);
add("default", &Component::deflt);
{
load_sub(comp.build_info);
}
+
+void Component::Loader::install_map()
+{
+ load_sub(comp.install_map, comp.pkg.get_source());
+}
#include <msp/datafile/loader.h>
#include <msp/fs/path.h>
#include "buildinfo.h"
+#include "installmap.h"
#include "misc.h"
#include "package.h"
void source(const std::string &);
void require(const std::string &);
void build_info();
+ void install_map();
};
enum Type
BuildInfo build_info;
PackageList requires;
bool deflt;
+ InstallMap install_map;
public:
Component(SourcePackage &, Type, const std::string &);
bool get_install() const { return install; }
const PackageList &get_requires() const { return requires; }
bool is_default() const { return deflt; }
+ const InstallMap &get_install_map() const { return install_map; }
void configure(const StringMap &, unsigned);
FS::Path mid;
if(!loc.empty())
mid = loc;
+ else if(const Component *comp = tgt.get_component())
+ mid = comp->get_install_map().get_install_location(tgt);
else
mid = tgt.get_install_location();
--- /dev/null
+#include <msp/fs/utils.h>
+#include "filetarget.h"
+#include "installmap.h"
+
+using namespace std;
+using namespace Msp;
+
+void InstallMap::add_mapping(const FS::Path &src, const FS::Path &inst)
+{
+ Entry e;
+ e.source = src;
+ e.install = inst;
+ entries.push_back(e);
+}
+
+FS::Path InstallMap::get_install_location(const FileTarget &target) const
+{
+ const FS::Path &source = target.get_path();
+ FS::Path install = target.get_install_location();
+ for(list<Entry>::const_iterator i=entries.begin(); i!=entries.end(); ++i)
+ {
+ int source_depth = FS::descendant_depth(source, i->source);
+ if(source_depth>=0)
+ {
+ FS::Path install_base = FS::common_ancestor(install, i->install);
+ if(install_base.size()>1)
+ {
+ install = i->install/FS::dirname(source).subpath(i->source.size());
+ break;
+ }
+ }
+ }
+
+ return install;
+}
+
+
+InstallMap::Loader::Loader(InstallMap &m, const FS::Path &s):
+ DataFile::ObjectLoader<InstallMap>(m),
+ source_base(s)
+{
+ add("map", &Loader::map);
+}
+
+void InstallMap::Loader::map(const string &src, const string &inst)
+{
+ obj.add_mapping(source_base/src, inst);
+}
--- /dev/null
+#ifndef INSTALLMAP_H_
+#define INSTALLMAP_H_
+
+#include <list>
+#include <msp/datafile/objectloader.h>
+#include <msp/fs/path.h>
+
+class FileTarget;
+
+/**
+Maps install locations based on location in the source tree. Mappings are
+defined as pairs of source and install locations. Targets within a source
+location are mapped if their default install location shares a common prefix
+with the mapped install location. The remainder of the source location is
+appended to the mapped install location to form the final install location.
+*/
+class InstallMap
+{
+public:
+ class Loader: public Msp::DataFile::ObjectLoader<InstallMap>
+ {
+ private:
+ Msp::FS::Path source_base;
+
+ public:
+ Loader(InstallMap &, const Msp::FS::Path &);
+
+ private:
+ void map(const std::string &, const std::string &);
+ };
+
+private:
+ struct Entry
+ {
+ Msp::FS::Path source;
+ Msp::FS::Path install;
+ };
+
+ std::list<Entry> entries;
+
+public:
+ /** Adds an install mapping. Multiple mappings can be specified for the
+ same source location, but the first one that matches both that and the
+ target's default install location will be used. */
+ void add_mapping(const Msp::FS::Path &, const Msp::FS::Path &);
+
+ /** Returns the install location for a target. If no defined mappings match
+ the target, its default install location is returned. */
+ Msp::FS::Path get_install_location(const FileTarget &) const;
+};
+
+#endif