]> git.tdb.fi Git - builder.git/commitdiff
Split Component into several subclasses
authorMikko Rasa <tdb@tdb.fi>
Mon, 6 Oct 2014 00:13:37 +0000 (03:13 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 6 Oct 2014 00:13:37 +0000 (03:13 +0300)
The create_targets function in particular was rather unwieldy and
contained four completely separate branches.  Having distinct component
types in different classes will also enhance modularity.

13 files changed:
source/binarycomponent.cpp [new file with mode: 0644]
source/binarycomponent.h [new file with mode: 0644]
source/component.cpp
source/component.h
source/datapackcomponent.cpp [new file with mode: 0644]
source/datapackcomponent.h [new file with mode: 0644]
source/installcomponent.cpp [new file with mode: 0644]
source/installcomponent.h [new file with mode: 0644]
source/sharedlibrary.cpp
source/sourcepackage.cpp
source/sourcepackage.h
source/tarballcomponent.cpp [new file with mode: 0644]
source/tarballcomponent.h [new file with mode: 0644]

diff --git a/source/binarycomponent.cpp b/source/binarycomponent.cpp
new file mode 100644 (file)
index 0000000..0d3e253
--- /dev/null
@@ -0,0 +1,137 @@
+#include <msp/fs/utils.h>
+#include "binarycomponent.h"
+#include "builder.h"
+#include "filetarget.h"
+#include "sourcepackage.h"
+#include "tool.h"
+
+using namespace std;
+using namespace Msp;
+
+BinaryComponent::BinaryComponent(SourcePackage &p, const string &n, Type t):
+       Component(p, n),
+       type(t)
+{ }
+
+void BinaryComponent::create_build_info()
+{
+       Component::create_build_info();
+
+       for(UseList::const_iterator i=uses.begin(); i!=uses.end(); ++i)
+       {
+               /* Select an include path that contains all the sources for this and the
+               used component.  This should produce a sensible result in most cases. */
+               FS::Path base;
+               for(SourceList::const_iterator j=sources.begin(); j!=sources.end(); ++j)
+                       base = base.empty() ? *j : FS::common_ancestor(base, *j);
+               const SourceList &use_sources = (*i)->get_sources();
+               for(SourceList::const_iterator j=use_sources.begin(); j!=use_sources.end(); ++j)
+                       base = FS::common_ancestor(base, *j);
+               build_info.incpath.push_back(base);
+               build_info.libs.push_back((*i)->get_name());
+               if(!(*i)->get_install())
+               {
+                       build_info.libmodes[(*i)->get_name()] = BuildInfo::STATIC;
+                       build_info.libpath.push_back((*i)->get_package().get_source_directory());
+               }
+       }
+
+       if(type==LIBRARY || type==MODULE)
+               if(build_info.libmode<BuildInfo::DYNAMIC)
+                       build_info.libmode = BuildInfo::DYNAMIC;
+}
+
+void BinaryComponent::update_exported_build_info(BuildInfo &binfo) const
+{
+       if(type==LIBRARY)
+               binfo.libs.push_back(name);
+}
+
+void BinaryComponent::create_targets() const
+{
+       Builder &builder = package.get_builder();
+       BuildGraph &build_graph = builder.get_build_graph();
+       const Toolchain &toolchain = builder.get_toolchain();
+       const Toolchain &pkg_tools = package.get_toolchain();
+
+       list<Target *> objs;
+       SourceList source_filenames = collect_source_files();
+       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)
+               {
+                       if(!src)
+                               src = tool->create_source(*this, *i);
+                       if(!src)
+                               continue;
+
+                       if(tool->accepts_suffix(ext))
+                       {
+                               Target *obj = tool->create_target(*src);
+                               objs.push_back(obj);
+                       }
+
+                       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);
+                       }
+               }
+       }
+
+       Tool &linker = toolchain.get_tool("LINK");
+
+       list<Target *> results;
+       if(type==LIBRARY)
+       {
+               Tool &archiver = toolchain.get_tool("AR");
+               results.push_back(linker.create_target(objs, "shared"));
+               results.push_back(archiver.create_target(objs));
+       }
+       else if(type==MODULE)
+               results.push_back(linker.create_target(objs, "shared"));
+       else
+               results.push_back(linker.create_target(objs));
+
+       for(list<Target *>::const_iterator i=results.begin(); i!=results.end(); ++i)
+       {
+               build_graph.add_primary_target(**i);
+               if(install)
+                       build_graph.add_installed_target(**i);
+       }
+}
+
+BinaryComponent::Loader::Loader(BinaryComponent &c):
+       DerivedObjectLoader<BinaryComponent, Component::Loader>(c)
+{
+       add("use", &Loader::use);
+}
+
+void BinaryComponent::Loader::use(const string &n)
+{
+       const BinaryComponent *comp = dynamic_cast<const BinaryComponent *>(&obj.package.get_component(n));
+       if(!comp || comp->type!=LIBRARY)
+               throw logic_error(n+" is not a library");
+
+       obj.uses.push_back(comp);
+}
diff --git a/source/binarycomponent.h b/source/binarycomponent.h
new file mode 100644 (file)
index 0000000..3a6affd
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef BINARYCOMPONENT_H_
+#define BINARYCOMPONENT_H_
+
+#include "component.h"
+
+class BinaryComponent: public Component
+{
+public:
+       class Loader: public Msp::DataFile::DerivedObjectLoader<BinaryComponent, Component::Loader>
+       {
+       public:
+               Loader(BinaryComponent &);
+       private:
+               void use(const std::string &);
+       };
+
+       enum Type
+       {
+               LIBRARY,
+               PROGRAM,
+               MODULE
+       };
+
+private:
+       typedef std::list<const Component *> UseList;
+
+       Type type;
+       UseList uses;
+
+public:
+       BinaryComponent(SourcePackage &, const std::string &, Type);
+
+       Type get_type() const { return type; }
+
+       virtual void create_build_info();
+       virtual void update_exported_build_info(BuildInfo &) const;
+       virtual void create_targets() const;
+};
+
+#endif
index 4e7f547f36f7d05b9212a09f957907e1c79c75a8..833a0ed20d507b665d59d9022dac7521bdce81d0 100644 (file)
@@ -7,25 +7,13 @@
 #include "booleanevaluator.h"
 #include "builder.h"
 #include "component.h"
-#include "csourcefile.h"
-#include "datapack.h"
-#include "executable.h"
-#include "file.h"
-#include "objectfile.h"
-#include "sharedlibrary.h"
 #include "sourcepackage.h"
-#include "staticlibrary.h"
-#include "tarball.h"
-#include "target.h"
-#include "tool.h"
-#include "toolchain.h"
 
 using namespace std;
 using namespace Msp;
 
-Component::Component(SourcePackage &p, Type t, const string &n):
+Component::Component(SourcePackage &p, const string &n):
        package(p),
-       type(t),
        name(n),
        install(false),
        deflt(true)
@@ -67,29 +55,6 @@ void Component::create_build_info()
                *i = (package.get_source_directory() / *i).str();
        for(BuildInfo::PathList::iterator i=build_info.libpath.begin(); i!=build_info.libpath.end(); ++i)
                *i = (package.get_source_directory() / *i).str();
-
-       for(UseList::const_iterator i=uses.begin(); i!=uses.end(); ++i)
-       {
-               /* Select an include path that contains all the sources for this and the
-               used component.  This should produce a sensible result in most cases. */
-               FS::Path base;
-               for(SourceList::const_iterator j=sources.begin(); j!=sources.end(); ++j)
-                       base = base.empty() ? *j : FS::common_ancestor(base, *j);
-               const SourceList &use_sources = (*i)->get_sources();
-               for(SourceList::const_iterator j=use_sources.begin(); j!=use_sources.end(); ++j)
-                       base = FS::common_ancestor(base, *j);
-               build_info.incpath.push_back(base);
-               build_info.libs.push_back((*i)->get_name());
-               if(!(*i)->get_install())
-               {
-                       build_info.libmodes[(*i)->get_name()] = BuildInfo::STATIC;
-                       build_info.libpath.push_back((*i)->get_package().get_source_directory());
-               }
-       }
-
-       if(type==LIBRARY || type==MODULE)
-               if(build_info.libmode<BuildInfo::DYNAMIC)
-                       build_info.libmode = BuildInfo::DYNAMIC;
 }
 
 BuildInfo Component::get_build_info_for_path(const FS::Path &path) const
@@ -118,157 +83,6 @@ BuildInfo Component::get_build_info_for_path(const FS::Path &path) const
        return binfo;
 }
 
-void Component::create_targets() const
-{
-       Builder &builder = package.get_builder();
-       BuildGraph &build_graph = builder.get_build_graph();
-       const Toolchain &toolchain = builder.get_toolchain();
-
-       SourceList source_filenames = collect_source_files();
-
-       string inst_loc;
-       if(type==TARBALL)
-       {
-               Tool &tar = toolchain.get_tool("TAR");
-
-               list<Target *> files;
-               for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
-               {
-                       FileTarget *file = builder.get_vfs().get_target(*i);
-                       if(!file)
-                               file = new File(builder, package, *i);
-                       files.push_back(file);
-               }
-
-               string tarname = name;
-               if(name=="@src")
-               {
-                       tarname = package.get_name()+"-"+package.get_version();
-                       files.insert(files.begin(), &package.get_build_file());
-
-                       const BuildGraph::TargetMap &targets = build_graph.get_targets();
-                       for(BuildGraph::TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
-                               if(i->second->get_package()==&package && !i->second->is_buildable())
-                                       if(find(files.begin(), files.end(), i->second)==files.end())
-                                               files.push_back(i->second);
-               }
-
-               Target *result = tar.create_target(files, tarname);
-
-               build_graph.get_target("tarballs")->add_dependency(*result);
-
-               return;
-       }
-       else if(type==INSTALL)
-       {
-               Target *inst = build_graph.get_target("install");
-               Tool &copy = toolchain.get_tool("CP");
-               for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
-               {
-                       FileTarget *ft;
-                       if(Target *tgt = builder.get_vfs().get_target(*i))
-                               ft = dynamic_cast<FileTarget *>(tgt);
-                       else
-                               ft = new File(builder, package, *i);
-                       inst->add_dependency(*copy.create_target(*ft, name));
-               }
-       }
-       else if(type==DATAPACK)
-       {
-               Tool &dcomp = toolchain.get_tool("DATA");
-
-               list<Target *> files;
-               for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
-               {
-                       string ext = FS::extpart(FS::basename(*i));
-                       if(ext==".mdt")
-                       {
-                               Target *src = dcomp.create_source(*this, *i);
-                               files.push_back(dcomp.create_target(*src, "collection"));
-                       }
-                       else if(Target *tgt = builder.get_vfs().get_target(*i))
-                               files.push_back(tgt);
-                       else
-                               files.push_back(new File(builder, package, *i));
-               }
-
-               Target *result = dcomp.create_target(files, "pack");
-
-               build_graph.add_primary_target(*result);
-               if(install)
-                       build_graph.add_installed_target(*result);
-       }
-
-       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)
-                       {
-                               if(!src)
-                                       src = tool->create_source(*this, *i);
-                               if(!src)
-                                       continue;
-
-                               if(tool->accepts_suffix(ext))
-                               {
-                                       Target *obj = tool->create_target(*src);
-                                       objs.push_back(obj);
-                               }
-
-                               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);
-                               }
-                       }
-               }
-
-               Tool &linker = toolchain.get_tool("LINK");
-
-               list<Target *> results;
-               if(type==LIBRARY)
-               {
-                       Tool &archiver = toolchain.get_tool("AR");
-                       results.push_back(linker.create_target(objs, "shared"));
-                       results.push_back(archiver.create_target(objs));
-               }
-               else if(type==MODULE)
-                       results.push_back(linker.create_target(objs, "shared"));
-               else
-                       results.push_back(linker.create_target(objs));
-
-               for(list<Target *>::const_iterator i=results.begin(); i!=results.end(); ++i)
-               {
-                       build_graph.add_primary_target(**i);
-                       if(install)
-                               build_graph.add_installed_target(**i);
-               }
-       }
-}
-
 Component::SourceList Component::collect_source_files() const
 {
        SourceList files;
@@ -321,7 +135,6 @@ Component::Loader::Loader(Component &c):
        add("build_info",      &Loader::build_info);
        add("require",         &Loader::require);
        add("default",         &Component::deflt);
-       add("use",             &Loader::use);
 }
 
 void Component::Loader::build_info()
@@ -372,15 +185,3 @@ void Component::Loader::source(const string &s)
 {
        obj.sources.push_back((obj.package.get_source_directory()/s).str());
 }
-
-void Component::Loader::use(const string &n)
-{
-       const SourcePackage::ComponentList &components = obj.package.get_components();
-       for(SourcePackage::ComponentList::const_iterator i=components.begin(); i!=components.end(); ++i)
-               if(i->get_name()==n && i->get_type()==LIBRARY)
-               {
-                       obj.uses.push_back(&*i);
-                       return;
-               }
-       throw invalid_argument("Component::Loader::use");
-}
index 7cbd1e13cbe1f0099522161e4e2eb74c708fcad3..d33ca25ae47900d9f156f6c24ec73fcf5ad1c578 100644 (file)
@@ -31,42 +31,28 @@ public:
                void overlay(const std::string &);
                void require(const std::string &);
                void source(const std::string &);
-               void use(const std::string &);
-       };
-
-       enum Type
-       {
-               LIBRARY,
-               PROGRAM,
-               MODULE,
-               DATAPACK,
-               INSTALL,
-               TARBALL
        };
 
        typedef std::list<Msp::FS::Path> SourceList;
        typedef std::list<std::string> OverlayList;
-       typedef std::list<const Component *> UseList;
 
 protected:
        SourcePackage &package;
-       Type type;
        std::string name;
        SourceList sources;
        OverlayList overlays;
        bool install;
        BuildInfo build_info;
        Package::Requirements requires;
-       UseList uses;
        bool deflt;
        InstallMap install_map;
        std::list<std::string> problems;
 
 public:
-       Component(SourcePackage &, Type, const std::string &);
+       Component(SourcePackage &, const std::string &);
+       virtual ~Component() { }
 
        const SourcePackage &get_package() const { return package; }
-       Type get_type() const { return type; }
        const std::string &get_name() const { return name; }
 
        /** Returns a list of sources for the component.  They may refer to
@@ -83,7 +69,6 @@ public:
        bool get_install() const { return install; }
        const InstallMap &get_install_map() const { return install_map; }
        const Package::Requirements &get_required_packages() const { return requires; }
-       const UseList &get_used_components() const { return uses; }
        bool is_default() const { return deflt; }
        const std::list<std::string> &get_problems() const { return problems; }
 
@@ -92,13 +77,15 @@ public:
 
        /** Prepares the build information for building.  Pulls build info from the
        parent and dependency packages, and adds any component-specific flags. */
-       void create_build_info();
+       virtual void create_build_info();
+
+       virtual void update_exported_build_info(BuildInfo &) const { }
 
        const BuildInfo &get_build_info() const { return build_info; }
 
        BuildInfo get_build_info_for_path(const Msp::FS::Path &) const;
 
-       void create_targets() const;
+       virtual void create_targets() const = 0;
 };
 
 #endif
diff --git a/source/datapackcomponent.cpp b/source/datapackcomponent.cpp
new file mode 100644 (file)
index 0000000..f936e91
--- /dev/null
@@ -0,0 +1,42 @@
+#include <msp/fs/utils.h>
+#include "builder.h"
+#include "datapackcomponent.h"
+#include "file.h"
+#include "sourcepackage.h"
+#include "tool.h"
+
+using namespace std;
+using namespace Msp;
+
+DataPackComponent::DataPackComponent(SourcePackage &p, const string &n):
+       Component(p, n)
+{ }
+
+void DataPackComponent::create_targets() const
+{
+       Builder &builder = package.get_builder();
+       Tool &dcomp = builder.get_toolchain().get_tool("DATA");
+
+       list<Target *> files;
+       SourceList source_filenames = collect_source_files();
+       for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
+       {
+               string ext = FS::extpart(FS::basename(*i));
+               if(ext==".mdt")
+               {
+                       Target *src = dcomp.create_source(*this, *i);
+                       files.push_back(dcomp.create_target(*src, "collection"));
+               }
+               else if(Target *tgt = builder.get_vfs().get_target(*i))
+                       files.push_back(tgt);
+               else
+                       files.push_back(new File(builder, package, *i));
+       }
+
+       Target *result = dcomp.create_target(files, "pack");
+
+       BuildGraph &build_graph = builder.get_build_graph();
+       build_graph.add_primary_target(*result);
+       if(install)
+               build_graph.add_installed_target(*result);
+}
diff --git a/source/datapackcomponent.h b/source/datapackcomponent.h
new file mode 100644 (file)
index 0000000..75b99a6
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef DATAPACKCOMPONENT_H_
+#define DATAPACKCOMPONENT_H_
+
+#include "component.h"
+
+class DataPackComponent: public Component
+{
+public:
+       DataPackComponent(SourcePackage &, const std::string &);
+
+       virtual void create_targets() const;
+};
+
+#endif
diff --git a/source/installcomponent.cpp b/source/installcomponent.cpp
new file mode 100644 (file)
index 0000000..9584a51
--- /dev/null
@@ -0,0 +1,29 @@
+#include "installcomponent.h"
+#include "builder.h"
+#include "file.h"
+#include "sourcepackage.h"
+#include "tool.h"
+
+using namespace std;
+
+InstallComponent::InstallComponent(SourcePackage &p, const string &n):
+       Component(p, n)
+{ }
+
+void InstallComponent::create_targets() const
+{
+       Builder &builder = package.get_builder();
+       Target *inst = builder.get_build_graph().get_target("install");
+       Tool &copy = builder.get_toolchain().get_tool("CP");
+
+       SourceList source_filenames = collect_source_files();
+       for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
+       {
+               FileTarget *ft;
+               if(Target *tgt = builder.get_vfs().get_target(*i))
+                       ft = dynamic_cast<FileTarget *>(tgt);
+               else
+                       ft = new File(builder, package, *i);
+               inst->add_dependency(*copy.create_target(*ft, name));
+       }
+}
diff --git a/source/installcomponent.h b/source/installcomponent.h
new file mode 100644 (file)
index 0000000..43dae71
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef INSTALLCOMPONENT_H_
+#define INSTALLCOMPONENT_H_
+
+#include "component.h"
+
+class InstallComponent: public Component
+{
+public:
+       InstallComponent(SourcePackage &, const std::string &);
+
+       virtual void create_targets() const;
+};
+
+#endif
index 6600b740332a23dff7a882a0a63e6c99afcbd8ec..6c816bd43bf3d5cf0cebdc425ada3d01d2e225fe 100644 (file)
@@ -1,7 +1,7 @@
 #include <msp/fs/utils.h>
 #include <msp/strings/format.h>
+#include "binarycomponent.h"
 #include "builder.h"
-#include "component.h"
 #include "objectfile.h"
 #include "sharedlibrary.h"
 #include "sourcepackage.h"
@@ -28,7 +28,8 @@ SharedLibrary::SharedLibrary(Builder &b, const Component &c, const list<ObjectFi
        else
                install_location = "lib";
 
-       if(component->get_type()==Component::MODULE)
+       const BinaryComponent &bcomp = dynamic_cast<const BinaryComponent &>(*component);
+       if(bcomp.get_type()==BinaryComponent::MODULE)
                install_location /= package->get_name();
        else
        {
@@ -59,7 +60,8 @@ SharedLibrary::SharedLibrary(Builder &b, const Component &c, const list<ObjectFi
 
 string SharedLibrary::generate_filename(const Component &comp)
 {
-       if(comp.get_type()==Component::MODULE)
+       const BinaryComponent &bcomp = dynamic_cast<const BinaryComponent &>(comp);
+       if(bcomp.get_type()==BinaryComponent::MODULE)
                return comp.get_name()+".m";
        else
        {
index ddfa00fb9bf3175eb59a7391b2e16cd38555370b..1dd7dbd1062263b91f71bc7fd0cd007cd28e8f97 100644 (file)
@@ -1,13 +1,19 @@
+#include <algorithm>
 #include <cstdlib>
+#include <msp/core/maputils.h>
 #include <msp/fs/utils.h>
 #include <msp/io/print.h>
 #include <msp/strings/lexicalcast.h>
 #include <msp/strings/utils.h>
+#include "binarycomponent.h"
 #include "binarypackage.h"
 #include "booleanevaluator.h"
 #include "builder.h"
+#include "datapackcomponent.h"
 #include "file.h"
+#include "installcomponent.h"
 #include "pkgconfigfile.h"
+#include "tarballcomponent.h"
 #include "tool.h"
 #include "sourcegenerator.h"
 #include "sourcepackage.h"
 using namespace std;
 using namespace Msp;
 
-namespace {
-
-bool component_sort(const Component &c1, const Component &c2)
-{ return c1.get_type()<c2.get_type(); }
-
-}
-
-
 SourcePackage::SourcePackage(Builder &b, const string &n, const FS::Path &f):
        Package(b, n),
        source_dir(FS::dirname(f)),
@@ -35,8 +33,14 @@ SourcePackage::SourcePackage(Builder &b, const string &n, const FS::Path &f):
        build_file = builder.get_vfs().get_target(f);
        if(!build_file)
                build_file = new File(builder, *this, f);
-       components.push_back(Component(*this, Component::TARBALL, "@src"));
-       source_tarball = &components.back();
+       source_tarball = new TarballComponent(*this, "@src");
+       components.push_back(source_tarball);
+}
+
+SourcePackage::~SourcePackage()
+{
+       for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
+               delete *i;
 }
 
 FS::Path SourcePackage::get_temp_directory() const
@@ -64,6 +68,14 @@ FS::Path SourcePackage::get_output_directory() const
                return source_dir/arch.get_name();
 }
 
+const Component &SourcePackage::get_component(const string &n) const
+{
+       for(ComponentList::const_iterator i=components.begin(); i!=components.end(); ++i)
+               if((*i)->get_name()==n)
+                       return **i;
+       throw key_error(n);
+}
+
 bool SourcePackage::match_feature(const string &feat, const string *comp) const
 {
        string value = config.get_option("with_"+feat).value;
@@ -101,37 +113,24 @@ void SourcePackage::do_prepare()
                        build_info.defines[ident] = "1";
        }
 
-       bool export_paths = false;
-       for(list<Component>::iterator i=components.begin(); i!=components.end(); ++i)
+       for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
        {
-               i->prepare();
-               i->create_build_info();
-
-               if(i->get_type()==Component::LIBRARY)
-               {
-                       export_binfo.libs.push_back(i->get_name());
-                       export_paths = true;
-               }
-       }
+               (*i)->prepare();
+               (*i)->create_build_info();
 
-       if(export_paths)
-       {
-               export_binfo.incpath.push_back((builder.get_prefix()/"include").str());
-               export_binfo.libpath.push_back((builder.get_prefix()/"lib").str());
+               (*i)->update_exported_build_info(export_binfo);
        }
 
        cache.load();
 
-       bool pc_needed = false;
-       for(ComponentList::const_iterator i=components.begin(); i!=components.end(); ++i)
-       {
-               i->create_targets();
-               if(i->get_type()==Component::LIBRARY)
-                       pc_needed = true;
-       }
+       for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
+               (*i)->create_targets();
 
-       if(pc_needed)
+       if(!export_binfo.libs.empty())
        {
+               export_binfo.incpath.push_back((builder.get_prefix()/"include").str());
+               export_binfo.libpath.push_back((builder.get_prefix()/"lib").str());
+
                PkgConfigFile *pc = new PkgConfigFile(builder, *this);
                builder.get_build_graph().get_target("install")->add_dependency(*builder.get_toolchain().get_tool("CP").create_target(*pc));
        }
@@ -164,12 +163,12 @@ void SourcePackage::Loader::init(const Config::InputOptions *o)
        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>);
-       add("module",      &Loader::component<Component::MODULE>);
-       add("install",     &Loader::component<Component::INSTALL>);
+       add("program",     &Loader::component_arg<BinaryComponent, BinaryComponent::Type, BinaryComponent::PROGRAM>);
+       add("library",     &Loader::component_arg<BinaryComponent, BinaryComponent::Type, BinaryComponent::LIBRARY>);
+       add("module",      &Loader::component_arg<BinaryComponent, BinaryComponent::Type, BinaryComponent::MODULE>);
+       add("install",     &Loader::component<InstallComponent>);
        add("interface_version", &Loader::interface_version);
-       add("datapack",    &Loader::component<Component::DATAPACK>);
+       add("datapack",    &Loader::component<DataPackComponent>);
        add("source_tarball", &Loader::source_tarball);
        add("tarball",     &Loader::tarball);
        add("version",     &Loader::version);
@@ -177,7 +176,11 @@ void SourcePackage::Loader::init(const Config::InputOptions *o)
 
 void SourcePackage::Loader::finish()
 {
-       obj.components.sort(component_sort);
+       /* Make sure the source tarball is last in the list so targets from all
+       other components wil be created first */
+       ComponentList::iterator i = find(obj.components.begin(), obj.components.end(), obj.source_tarball);
+       if(i!=obj.components.end())
+               obj.components.splice(obj.components.end(), obj.components, i);
 }
 
 void SourcePackage::Loader::feature(const string &n, const string &d)
@@ -196,11 +199,19 @@ void SourcePackage::Loader::feature(const string &n, const string &d)
        }
 }
 
-template<Component::Type t>
+template<typename C>
 void SourcePackage::Loader::component(const string &n)
 {
-       Component comp(obj, t, n);
-       load_sub(comp);
+       C *comp = new C(obj, n);
+       load_sub(*comp);
+       obj.components.push_back(comp);
+}
+
+template<typename C, typename A, A a>
+void SourcePackage::Loader::component_arg(const string &n)
+{
+       C *comp = new C(obj, n, a);
+       load_sub(*comp);
        obj.components.push_back(comp);
 }
 
@@ -239,7 +250,7 @@ void SourcePackage::Loader::source_tarball()
 
 void SourcePackage::Loader::tarball(const string &n)
 {
-       Component trbl(obj, Component::TARBALL, n);
+       TarballComponent trbl(obj, n);
        load_sub(trbl);
 }
 
index 3d868631871591d88e2f511007c3d15c06c60202..66296001e44229265753f3c52056cef6a2652b02 100644 (file)
@@ -14,6 +14,7 @@
 class Builder;
 class BuildType;
 class FileTarget;
+class TarballComponent;
 
 /**
 A package that can be built by Builder.
@@ -33,8 +34,10 @@ public:
                void init(const Config::InputOptions *);
                virtual void finish();
                void feature(const std::string &, const std::string &);
-               template<Component::Type>
+               template<typename C>
                void component(const std::string &);
+               template<typename C, typename A, A>
+               void component_arg(const std::string &);
                void build_info();
                void generate(const std::string &);
                void if_feature(const std::string &);
@@ -44,7 +47,7 @@ public:
                void version(const std::string &);
        };
 
-       typedef std::list<Component> ComponentList;
+       typedef std::list<Component *> ComponentList;
 
 private:
        typedef std::list<Feature> FeatureList;
@@ -60,12 +63,13 @@ private:
        FeatureList features;
        BuildInfo build_info;
        ComponentList components;
-       Component *source_tarball;
+       TarballComponent *source_tarball;
        Config config;
        mutable Cache cache;
 
 public:
        SourcePackage(Builder &, const std::string &, const Msp::FS::Path &);
+       ~SourcePackage();
 
        const std::string &get_version() const { return version; }
        const std::string &get_interface_version() const { return interface_version; }
@@ -77,7 +81,7 @@ public:
        Msp::FS::Path get_output_directory() const;
 
        const Toolchain &get_toolchain() const { return local_tools; }
-       const ComponentList &get_components() const { return components; }
+       const Component &get_component(const std::string &) const;
        const Config &get_config() const { return config; }
        bool match_feature(const std::string &, const std::string *) const;
        void set_build_type(const BuildType &);
diff --git a/source/tarballcomponent.cpp b/source/tarballcomponent.cpp
new file mode 100644 (file)
index 0000000..c94103c
--- /dev/null
@@ -0,0 +1,46 @@
+#include <algorithm>
+#include "builder.h"
+#include "file.h"
+#include "sourcepackage.h"
+#include "tarballcomponent.h"
+#include "tool.h"
+
+using namespace std;
+
+TarballComponent::TarballComponent(SourcePackage &p, const string &n):
+       Component(p, n)
+{ }
+
+void TarballComponent::create_targets() const
+{
+       Builder &builder = package.get_builder();
+
+       list<Target *> files;
+       SourceList source_filenames = collect_source_files();
+       for(SourceList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
+       {
+               FileTarget *file = builder.get_vfs().get_target(*i);
+               if(!file)
+                       file = new File(builder, package, *i);
+               files.push_back(file);
+       }
+
+       BuildGraph &build_graph = builder.get_build_graph();
+
+       string tarname = name;
+       if(name=="@src")
+       {
+               tarname = package.get_name()+"-"+package.get_version();
+               files.insert(files.begin(), &package.get_build_file());
+
+               const BuildGraph::TargetMap &targets = build_graph.get_targets();
+               for(BuildGraph::TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
+                       if(i->second->get_package()==&package && !i->second->is_buildable())
+                               if(find(files.begin(), files.end(), i->second)==files.end())
+                                       files.push_back(i->second);
+       }
+
+       const Toolchain &toolchain = builder.get_toolchain();
+       Target *result = toolchain.get_tool("TAR").create_target(files, tarname);
+       build_graph.get_target("tarballs")->add_dependency(*result);
+}
diff --git a/source/tarballcomponent.h b/source/tarballcomponent.h
new file mode 100644 (file)
index 0000000..d54f95e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef TARBALLCOMPONENT_H_
+#define TARBALLCOMPONENT_H_
+
+#include "component.h"
+
+class TarballComponent: public Component
+{
+public:
+       TarballComponent(SourcePackage &, const std::string &);
+
+       virtual void create_targets() const;
+};
+
+#endif