]> git.tdb.fi Git - builder.git/commitdiff
Add files.
authorMikko Rasa <tdb@tdb.fi>
Sun, 27 Aug 2006 12:45:01 +0000 (12:45 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 27 Aug 2006 12:45:01 +0000 (12:45 +0000)
Doesn't build anything yet.

20 files changed:
Build [new file with mode: 0644]
source/builder.cpp [new file with mode: 0644]
source/builder.h [new file with mode: 0644]
source/buildinfo.h [new file with mode: 0644]
source/component.cpp [new file with mode: 0644]
source/component.h [new file with mode: 0644]
source/executable.cpp [new file with mode: 0644]
source/executable.h [new file with mode: 0644]
source/header.h [new file with mode: 0644]
source/misc.cpp [new file with mode: 0644]
source/misc.h [new file with mode: 0644]
source/objectfile.cpp [new file with mode: 0644]
source/objectfile.h [new file with mode: 0644]
source/package.cpp [new file with mode: 0644]
source/package.h [new file with mode: 0644]
source/sourcefile.cpp [new file with mode: 0644]
source/sourcefile.h [new file with mode: 0644]
source/target.cpp [new file with mode: 0644]
source/target.h [new file with mode: 0644]
source/virtualtarget.h [new file with mode: 0644]

diff --git a/Build b/Build
new file mode 100644 (file)
index 0000000..4db65e6
--- /dev/null
+++ b/Build
@@ -0,0 +1,16 @@
+package "builder"
+{
+       version "0.1";
+       description "Mikkosoft Productions software builder";
+
+       require "mspframework";
+       require "mspparser";
+       require "msppath";
+       require "mspregex++";
+
+       program "builder"
+       {
+               source "source";
+               install true;
+       };
+};
diff --git a/source/builder.cpp b/source/builder.cpp
new file mode 100644 (file)
index 0000000..3f93a67
--- /dev/null
@@ -0,0 +1,222 @@
+#include <fstream>
+#include <msp/strutils.h>
+#include <msp/parser/parser.h>
+#include <msp/path/utils.h>
+#include "builder.h"
+#include "executable.h"
+#include "header.h"
+#include "misc.h"
+#include "objectfile.h"
+#include "package.h"
+#include "virtualtarget.h"
+
+using namespace std;
+using namespace Msp;
+
+Builder::Builder(int argc, char **argv):
+       verbose(1),
+       cwd(Path::getcwd())
+{
+       for(int i=1; i<argc; ++i)
+               cmdline_targets.push_back(argv[i]);
+       if(cmdline_targets.empty())
+               cmdline_targets.push_back("default");
+}
+
+Package *Builder::get_package(const string &n)
+{
+       PackageMap::iterator i=packages.find(n);
+       if(i!=packages.end())
+               return i->second;
+
+       list<string> argv;
+       argv.push_back("pkg-config");
+       argv.push_back("--variable=source");
+       argv.push_back(n);
+       Path::Path srcdir=run_command(argv);
+       if(srcdir.empty())
+       {
+               string dirname=n;
+               if(dirname.compare(0, 3, "msp"))
+                       dirname.erase(0, 3);
+               if(Path::exists(cwd/dirname))
+                       srcdir=cwd/dirname;
+               else if(Path::exists(cwd/".."/dirname))
+                       srcdir=cwd/".."/dirname;
+       }
+       else
+               srcdir=strip(srcdir.str());
+       
+       if(!srcdir.empty())
+               load_build_file(srcdir/"Build");
+
+       return 0;
+}
+
+Target *Builder::get_target(const string &n)
+{
+       TargetMap::iterator i=targets.find(n);
+       if(i!=targets.end())
+               return i->second;
+       return 0;
+}
+
+Target *Builder::get_header(const string &include, const string &from, const list<string> &path)
+{
+       string id=from+":"+include;
+       TargetMap::iterator i=includes.find(id);
+       if(i!=includes.end())
+               return i->second;
+
+       string fn=include.substr(1);
+       Target *tgt;
+       if(include[0]=='"' && (tgt=check_header(Path::Path(from)/fn)))
+               return tgt;
+       if((tgt=check_header(Path::Path("/usr/include")/fn)))
+               return tgt;
+       if((tgt=check_header(Path::Path("/usr/include/c++/4.1.2")/fn)))
+               return tgt;
+       for(list<string>::const_iterator j=path.begin(); j!=path.end(); ++j)
+               if((tgt=check_header(Path::Path(*j)/fn)))
+                       return tgt;
+       
+       return 0;
+}
+
+int Builder::main()
+{
+       if(load_build_file("Build"))
+       {
+               cerr<<"No build info here.\n";
+               return 1;
+       }
+
+       default_pkg=packages.begin()->second;
+
+       while(!new_pkgs.empty())
+       {
+               Package *pkg=new_pkgs.front();
+               new_pkgs.erase(new_pkgs.begin());
+               pkg->resolve_refs();
+       }
+
+       cout<<"Active packages:";
+       for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
+       {
+               cout<<' '<<i->second->get_name();
+               if(i->second->get_buildable())
+                       cout<<'*';
+       }
+       cout<<'\n';
+       
+       create_targets();
+
+       for(TargetMap::iterator i=targets.begin(); i!=targets.end(); ++i)
+               cout<<i->second->get_name()<<' '<<i->second->get_type()<<'\n';
+
+       cout<<"Active targets: "<<targets.size()<<'\n';
+
+       return 0;
+}
+
+int Builder::load_build_file(const Path::Path &fn)
+{
+       ifstream in(fn.str().c_str());
+       if(!in)
+               return -1;
+
+       Parser::Parser parser(in, fn.str());
+       Loader loader(*this, cwd/fn.subpath(0, fn.size()-1));
+       loader.load(parser);
+
+       return 0;
+}
+
+void Builder::create_targets()
+{
+       Target *world=new VirtualTarget(*this, "world");
+       add_target(world);
+       Target *def_tgt=new VirtualTarget(*this, "default");
+       add_target(def_tgt);
+
+       for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
+       {
+               cout<<i->second->get_source()<<'\n';
+               const ComponentList &components=i->second->get_components();
+               for(ComponentList::const_iterator j=components.begin(); j!=components.end(); ++j)
+               {
+                       Path::Path base=i->second->get_source()/j->get_source();
+                       cout<<base<<'\n';
+                       list<string> files=list_files(base);
+
+                       list<ObjectFile *> objs;
+                       for(list<string>::iterator k=files.begin(); k!=files.end(); ++k)
+                       {
+                               Path::Path fn=base/ *k;
+                               //cout<<*k<<'\n';
+                               string ext=Path::splitext(*k).ext;
+                               if(ext==".cpp" || ext==".c")
+                               {
+                                       SourceFile *src=new SourceFile(*this, &*j, fn.str());
+                                       add_target(src);
+                                       
+                                       ObjectFile *obj=new ObjectFile(*this, *j, *src);
+                                       add_target(obj);
+                                       objs.push_back(obj);
+                               }
+                               else if(ext==".h")
+                                       add_target(new Header(*this, &*j, fn.str()));
+                       }
+
+                       Executable *exe=new Executable(*this, *j, objs);
+                       add_target(exe);
+                       if(i->second==default_pkg)
+                               def_tgt->add_depend(exe);
+               }
+       }
+
+       while(!new_tgts.empty())
+       {
+               Target *tgt=new_tgts.front();
+               new_tgts.erase(new_tgts.begin());
+               tgt->find_depends();
+       }
+}
+
+Target *Builder::check_header(const Msp::Path::Path &fn)
+{
+       Target *tgt=get_target(fn.str());
+       if(tgt) return tgt;
+
+       if(Path::exists(fn))
+       {
+               add_target(tgt=new SystemHeader(*this, fn.str()));
+               return tgt;
+       }
+       return 0;
+}
+
+void Builder::add_target(Target *t)
+{
+       targets.insert(TargetMap::value_type(t->get_name(), t));
+       new_tgts.push_back(t);
+}
+
+Application::RegApp<Builder> Builder::reg;
+
+Builder::Loader::Loader(Builder &b, const Path::Path &s):
+       bld(b),
+       src(s)
+{
+       add("package", &Loader::package);
+}
+
+void Builder::Loader::package(const string &n)
+{
+       Package *pkg=new Package(bld, n, src);
+       load_sub(*pkg);
+       bld.packages.insert(PackageMap::value_type(n, pkg));
+       bld.new_pkgs.push_back(pkg);
+       //cout<<"loaded "<<pkg->get_name()<<'\n';
+}
+
diff --git a/source/builder.h b/source/builder.h
new file mode 100644 (file)
index 0000000..f66b310
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef BUILDER_H_
+#define BUILDER_H_
+
+#include <list>
+#include <map>
+#include <string>
+#include <msp/framework/application.h>
+#include <msp/parser/loader.h>
+#include <msp/path/path.h>
+
+class Package;
+class Target;
+
+class Builder: public Msp::Application
+{
+public:
+       Builder(int, char **);
+       unsigned get_verbose() const { return verbose; }
+       Package  *get_package(const std::string &);
+       Target   *get_target(const std::string &);
+       Target   *get_header(const std::string &, const std::string &, const std::list<std::string> &);
+       int      main();
+private:
+       class Loader: public Msp::Parser::Loader
+       {
+       public:
+               Loader(Builder &, const Msp::Path::Path &);
+       private:
+               Builder &bld;
+               Msp::Path::Path src;
+               
+               void package(const std::string &);
+       };
+
+       typedef std::map<std::string, Package *> PackageMap;
+       typedef std::map<std::string, Target *>  TargetMap;
+       
+       std::list<std::string> cmdline_targets;
+       TargetMap  targets;
+       PackageMap packages;
+       unsigned   verbose;
+       Package    *default_pkg;
+       Msp::Path::Path cwd;
+       std::list<Package *> new_pkgs;
+       TargetMap  includes;
+       std::list<Target *> new_tgts;
+
+       int load_build_file(const Msp::Path::Path &);
+       void create_targets();
+       Target *check_header(const Msp::Path::Path &);
+       void add_target(Target *);
+       
+       static Msp::Application::RegApp<Builder> reg;
+};
+
+#endif
diff --git a/source/buildinfo.h b/source/buildinfo.h
new file mode 100644 (file)
index 0000000..02549ea
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef BUILDINFO_H_
+#define BUILDINFO_H_
+
+#include <list>
+#include <string>
+
+class BuildInfo
+{
+public:
+       typedef std::list<std::string> InfoList;
+       
+       InfoList cflags;
+       InfoList defines;
+       InfoList incpath;
+       InfoList ldflags;
+       InfoList libpath;
+       InfoList libs;
+
+       void add(const BuildInfo &);
+       void unique();
+};
+
+#endif
diff --git a/source/component.cpp b/source/component.cpp
new file mode 100644 (file)
index 0000000..bab7ba1
--- /dev/null
@@ -0,0 +1,23 @@
+#include "component.h"
+#include "package.h"
+
+using namespace std;
+
+Component::Component(Package &p, Type t, const string &n):
+       pkg(p),
+       type(t),
+       name(n)
+{ }
+
+Component::Loader::Loader(Component &c):
+       comp(c)
+{
+       add("source",          &Loader::source);
+       add("install",         &Component::install);
+       add("install_headers", &Component::install_headers);
+}
+
+void Component::Loader::source(const string &s)
+{
+       comp.source=comp.pkg.get_source()/s;
+}
diff --git a/source/component.h b/source/component.h
new file mode 100644 (file)
index 0000000..c5e1d0c
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef COMPONENT_H_
+#define COMPONENT_H_
+
+#include <string>
+#include <msp/parser/loader.h>
+#include <msp/path/path.h>
+#include "buildinfo.h"
+
+class Package;
+
+class Component
+{
+public:
+       class Loader: public Msp::Parser::Loader
+       {
+       public:
+               Loader(Component &);
+               Component &get_object() { return comp; }
+       private:
+               Component &comp;
+
+               void source(const std::string &);
+       };
+       
+       enum Type
+       {
+               PROGRAM,
+               LIBRARY,
+               MODULE
+       };
+
+       Component(Package &, Type, const std::string &);
+       const Package &get_package() const { return pkg; }
+       Type get_type() const { return type; }
+       const std::string &get_name() const { return name; }
+       const Msp::Path::Path &get_source() const { return source; }
+       const BuildInfo &get_build_info() const { return build_info; }
+protected:
+       Package     &pkg;
+       Type        type;
+       std::string name;
+       Msp::Path::Path source;
+       bool        install;
+       std::string install_headers;
+       BuildInfo   build_info;
+};
+typedef std::list<Component> ComponentList;
+
+#endif
diff --git a/source/executable.cpp b/source/executable.cpp
new file mode 100644 (file)
index 0000000..2dfeee8
--- /dev/null
@@ -0,0 +1,28 @@
+#include "component.h"
+#include "executable.h"
+#include "objectfile.h"
+#include "package.h"
+
+using namespace std;
+
+Executable::Executable(Builder &b, const Component &c, const list<ObjectFile *> &objs):
+       Target(b, &c.get_package(), generate_target_name(c)),
+       comp(c)
+{
+       for(list<ObjectFile *>::const_iterator i=objs.begin(); i!=objs.end(); ++i)
+               add_depend(*i);
+}
+
+string Executable::generate_target_name(const Component &comp)
+{
+       string prefix;
+       string suffix;
+
+       if(comp.get_type()==Component::LIBRARY)
+       {
+               prefix="lib";
+               suffix=".so";
+       }
+
+       return (comp.get_package().get_source()/(prefix+comp.get_name()+suffix)).str();
+}
diff --git a/source/executable.h b/source/executable.h
new file mode 100644 (file)
index 0000000..3e34851
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef EXECUTABLE_H_
+#define EXECUTABLE_H_
+
+#include "target.h"
+
+class Component;
+class ObjectFile;
+
+class Executable: public Target
+{
+public:
+       Executable(Builder &, const Component &, const std::list<ObjectFile *> &);
+       const char *get_type() const { return "Executable"; }
+       void find_depends() { }
+private:
+       const Component &comp;
+
+       static std::string generate_target_name(const Component &);
+};
+
+#endif
diff --git a/source/header.h b/source/header.h
new file mode 100644 (file)
index 0000000..6541cd4
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef HEADER_H_
+#define HEADER_H_
+
+#include "sourcefile.h"
+
+class Header: public SourceFile
+{
+public:
+       Header(Builder &b, const Component *c, const std::string &f): SourceFile(b,c,f) { }
+       const char *get_type() const { return "Header"; }
+};
+
+class SystemHeader: public Header
+{
+public:
+       SystemHeader(Builder &b, const std::string &f): Header(b,0,f) { }
+       const char *get_type() const { return "SystemHeader"; }
+       void find_depends() { }
+};
+
+#endif
diff --git a/source/misc.cpp b/source/misc.cpp
new file mode 100644 (file)
index 0000000..37616a9
--- /dev/null
@@ -0,0 +1,51 @@
+#include <iostream>
+#include <sys/wait.h>
+#include <msp/iter.h>
+#include "misc.h"
+
+using namespace std;
+using namespace Msp;
+
+string run_command(const list<string> &argv)
+{
+       int pfd[2];
+       pipe(pfd);
+
+       string result;
+
+       pid_t pid=fork();
+       if(pid==0)
+       {
+               char *argv_[argv.size()+1];
+               for(CountingIterator<const string, list<string>::const_iterator> i=argv.begin(); i!=argv.end(); ++i)
+                       argv_[i.count()]=strdup(i->c_str());
+               argv_[argv.size()]=0;
+               close(pfd[0]);
+               dup2(pfd[1], 1);
+               dup2(pfd[1], 2);
+               execvp(argv_[0], argv_);
+               ::exit(1);
+       }
+       else if(pid==-1)
+               cerr<<"Failed to execute "<<argv.front()<<'\n';
+       else
+       {
+               close(pfd[1]);
+               while(1)
+               {
+                       char buf[1024];
+                       int len=read(pfd[0], buf, sizeof(buf));
+                       if(len<=0)
+                       {
+                               if(waitpid(pid, 0, WNOHANG))
+                                       break;
+                       }
+                       else
+                               result.append(buf, len);
+               }
+       }
+       
+       return result;
+}
+
+
diff --git a/source/misc.h b/source/misc.h
new file mode 100644 (file)
index 0000000..ae2ff69
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef MISC_H_
+#define MISC_H_
+
+#include <list>
+#include <string>
+
+std::string run_command(const std::list<std::string> &);
+
+#endif
diff --git a/source/objectfile.cpp b/source/objectfile.cpp
new file mode 100644 (file)
index 0000000..b308c2b
--- /dev/null
@@ -0,0 +1,21 @@
+#include <msp/path/utils.h>
+#include "builder.h"
+#include "component.h"
+#include "objectfile.h"
+#include "package.h"
+#include "sourcefile.h"
+
+using namespace std;
+using namespace Msp;
+
+ObjectFile::ObjectFile(Builder &b, const Component &c, SourceFile &src):
+       Target(b, &c.get_package(), generate_target_name(c, src.get_name())),
+       comp(c)
+{
+       add_depend(&src);
+}
+
+string ObjectFile::generate_target_name(const Component &comp, const string &src)
+{
+       return (comp.get_package().get_source()/"temp"/comp.get_name()/(Path::splitext(src.substr(src.rfind('/')+1)).base+".o")).str();
+}
diff --git a/source/objectfile.h b/source/objectfile.h
new file mode 100644 (file)
index 0000000..d270529
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef OBJECTFILE_H_
+#define OBJECTFILE_H_
+
+#include "target.h"
+
+class Component;
+class SourceFile;
+
+class ObjectFile: public Target
+{
+public:
+       ObjectFile(Builder &, const Component &, SourceFile &);
+       const char *get_type() const { return "ObjectFile"; }
+       void find_depends() { }
+private:
+       const Component &comp;
+       
+       static std::string generate_target_name(const Component &, const std::string &);
+};
+
+#endif
diff --git a/source/package.cpp b/source/package.cpp
new file mode 100644 (file)
index 0000000..5cf7e07
--- /dev/null
@@ -0,0 +1,66 @@
+#include "builder.h"
+#include "package.h"
+
+using namespace std;
+using namespace Msp;
+
+PackageRef::PackageRef(Builder &b, const string &n):
+       builder(b),
+       name(n),
+       package(0)
+{ }
+
+Package *PackageRef::get_package()
+{
+       if(!package)
+               package=builder.get_package(name);
+       return package;
+}
+
+Package::Package(Builder &b, const string &n, const Path::Path &s):
+       builder(b),
+       name(n),
+       source(s),
+       buildable(false)
+{
+}
+
+void Package::resolve_refs()
+{
+       for(list<PackageRef>::iterator i=requires.begin(); i!=requires.end(); ++i)
+               i->get_package();
+}
+
+Package::Loader::Loader(Package &p):
+       pkg(p)
+{
+       add("version",     &Package::version);
+       add("description", &Package::description);
+       add("require",     &Loader::require);
+       add("program",     &Loader::program);
+       add("library",     &Loader::library);
+}
+
+Package::Loader::~Loader()
+{
+       pkg.buildable=true;
+}
+
+void Package::Loader::require(const string &n)
+{
+       pkg.requires.push_back(PackageRef(pkg.builder, n));
+}
+
+void Package::Loader::program(const std::string &n)
+{
+       Component prog(pkg, Component::PROGRAM, n);
+       load_sub(prog);
+       pkg.components.push_back(prog);
+}
+
+void Package::Loader::library(const std::string &n)
+{
+       Component prog(pkg, Component::LIBRARY, n);
+       load_sub(prog);
+       pkg.components.push_back(prog);
+}
diff --git a/source/package.h b/source/package.h
new file mode 100644 (file)
index 0000000..42c453a
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef PACKAGE_H_
+#define PACKAGE_H_
+
+#include <list>
+#include <string>
+#include <msp/parser/loader.h>
+#include "buildinfo.h"
+#include "component.h"
+
+class Builder;
+class Package;
+
+class PackageRef
+{
+public:
+       PackageRef(Builder &, const std::string &);
+       Package *get_package();
+private:
+       Builder     &builder;
+       std::string name;
+       Package     *package;
+};
+
+class Package
+{
+public:
+       class Loader: public Msp::Parser::Loader
+       {
+       public:
+               Loader(Package &);
+               Package &get_object() { return pkg; }
+               ~Loader();
+       private:
+               Package &pkg;
+               
+               void require(const std::string &);
+               void program(const std::string &);
+               void library(const std::string &);
+       };
+
+       Package(Builder &, const std::string &, const Msp::Path::Path &);
+       Package(Builder &, const std::string &, const std::list<std::string> &);
+       const std::string   &get_name() const { return name; }
+       const Msp::Path::Path &get_source() const { return source; }
+       const ComponentList &get_components() const { return components; }
+       bool                get_buildable() const { return buildable; }
+       void resolve_refs();
+
+       static Package *create(Builder &, const std::string &);
+private:
+       Builder       &builder;
+       std::string   name;
+       std::string   version;
+       std::string   description;
+       std::list<PackageRef> requires;
+       BuildInfo     build_info;
+       BuildInfo     export_binfo;
+       Msp::Path::Path source;
+       bool          buildable;
+       ComponentList components;
+};
+
+#endif
diff --git a/source/sourcefile.cpp b/source/sourcefile.cpp
new file mode 100644 (file)
index 0000000..55910a6
--- /dev/null
@@ -0,0 +1,34 @@
+#include <fstream>
+#include <msp/regex++/regex++.h>
+#include "builder.h"
+#include "component.h"
+#include "sourcefile.h"
+
+using namespace std;
+using namespace Msp;
+
+SourceFile::SourceFile(Builder &b, const Component *c, const string &n):
+       Target(b, c?&c->get_package():0, n),
+       comp(c)
+{ }
+
+void SourceFile::find_depends()
+{
+       ifstream in(name.c_str());
+       if(!in) return;
+
+       Regex r_include("^[ \t]*#include[ \t]+([\"<].*)[\">]");
+
+       string line;
+       while(getline(in, line))
+               if(RegMatch match=r_include.match(line))
+                       includes.push_back(match[1].str());
+
+       string path=name.substr(0, name.rfind('/'));
+       for(list<string>::iterator i=includes.begin(); i!=includes.end(); ++i)
+       {
+               Target *hdr=builder.get_header(*i, path, comp->get_build_info().incpath);
+               if(hdr)
+                       add_depend(hdr);
+       }
+}
diff --git a/source/sourcefile.h b/source/sourcefile.h
new file mode 100644 (file)
index 0000000..962c575
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef SOURCEFILE_H_
+#define SOURCEFILE_H_
+
+#include "target.h"
+
+class Component;
+
+class SourceFile: public Target
+{
+public:
+       SourceFile(Builder &, const Component *, const std::string &);
+       void find_depends();
+       const char *get_type() const { return "SourceFile"; }
+private:
+       const Component *comp;
+       std::list<std::string> includes;
+};
+
+#endif
diff --git a/source/target.cpp b/source/target.cpp
new file mode 100644 (file)
index 0000000..481d2f4
--- /dev/null
@@ -0,0 +1,47 @@
+#include "builder.h"
+#include "target.h"
+
+using namespace std;
+
+Target *TargetRef::get_target()
+{
+       if(!target)
+               target=builder.get_target(name);
+       return target;
+}
+
+Target *Target::get_buildable_target()
+{
+       if(rebuild && ready_for_build && !building)
+               return this;
+
+       for(list<Target *>::iterator i=depends.begin(); i!=depends.end(); ++i)
+       {
+               Target *tgt=(*i)->get_buildable_target();
+               if(tgt)
+                       return tgt;
+       }
+
+       return 0;
+}
+
+void Target::add_depend(Target *dep)
+{
+       depends.push_back(dep);
+       dep->rdepends.push_back(this);
+}
+
+Target::Target(Builder &b, const Package *p, const string &n):
+       builder(b),
+       package(p),
+       name(n),
+       building(false),
+       rebuild(false),
+       ready_for_build(false)
+{ }
+
+void Target::mark_rebuild(const std::string &reason)
+{
+       rebuild=true;
+       rebuild_reason=reason;
+}
diff --git a/source/target.h b/source/target.h
new file mode 100644 (file)
index 0000000..21135b0
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef TARGET_H_
+#define TARGET_H_
+
+#include <list>
+#include <string>
+#include <msp/time/timestamp.h>
+
+class Builder;
+class Package;
+class Target;
+
+class TargetRef
+{
+public:
+       TargetRef(Builder &b, const std::string &n): builder(b), name(n) { }
+       Target *get_target();
+private:
+       Builder &builder;
+       std::string name;
+       Target *target;
+};
+
+class Target
+{
+public:
+       const std::string &get_name() const { return name; }
+       Target *get_buildable_target();
+       bool   get_rebuild() const { return rebuild; }
+       const std::string &get_rebuild_reason() const { return rebuild_reason; }
+       virtual void find_depends()=0;
+       void   add_depend(Target *);
+       virtual const char *get_type() const=0;
+       virtual ~Target() { }
+protected:
+       Builder     &builder;
+       const Package *package;
+       std::string name;
+       bool        building;
+       bool        rebuild;
+       std::string rebuild_reason;
+       Msp::Time::TimeStamp mtime;
+       std::list<Target *> depends;
+       std::list<Target *> rdepends;
+       bool        ready_for_build;
+
+       Target(Builder &, const Package *, const std::string &);
+       void mark_rebuild(const std::string &);
+};
+
+#endif
diff --git a/source/virtualtarget.h b/source/virtualtarget.h
new file mode 100644 (file)
index 0000000..e388061
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef VIRTUALTARGET_H_
+#define VIRTUALTARGET_H_
+
+#include "target.h"
+
+class VirtualTarget: public Target
+{
+public:
+       VirtualTarget(Builder &b, const std::string &n): Target(b,0,n) { }
+       const char *get_type() const { return "VirtualTarget"; }
+       void find_depends() { }
+};
+
+#endif