]> git.tdb.fi Git - builder.git/commitdiff
Big rewrite for a more tool-centric approach
authorMikko Rasa <tdb@tdb.fi>
Sun, 8 Apr 2012 16:11:29 +0000 (19:11 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 8 Jul 2012 21:08:48 +0000 (00:08 +0300)
70 files changed:
source/action.cpp [deleted file]
source/action.h [deleted file]
source/analyzer.cpp
source/archive.cpp [deleted file]
source/archive.h [deleted file]
source/binary.cpp
source/binary.h
source/builder.cpp
source/builder.h
source/compile.cpp [deleted file]
source/compile.h [deleted file]
source/component.cpp
source/config.cpp
source/copy.cpp
source/copy.h
source/datacompile.cpp [deleted file]
source/datacompile.h [deleted file]
source/datacompiler.cpp [new file with mode: 0644]
source/datacompiler.h [new file with mode: 0644]
source/datafile.cpp
source/datafile.h
source/externalaction.cpp [deleted file]
source/externalaction.h [deleted file]
source/externaltask.cpp [new file with mode: 0644]
source/externaltask.h [new file with mode: 0644]
source/file.h
source/gnuarchiver.cpp [new file with mode: 0644]
source/gnuarchiver.h [new file with mode: 0644]
source/gnuccompiler.cpp [new file with mode: 0644]
source/gnuccompiler.h [new file with mode: 0644]
source/gnucompiler.cpp [new file with mode: 0644]
source/gnucompiler.h [new file with mode: 0644]
source/gnucxxcompiler.cpp [new file with mode: 0644]
source/gnucxxcompiler.h [new file with mode: 0644]
source/gnulinker.cpp [new file with mode: 0644]
source/gnulinker.h [new file with mode: 0644]
source/install.cpp
source/install.h
source/internalaction.cpp [deleted file]
source/internalaction.h [deleted file]
source/internaltask.cpp [new file with mode: 0644]
source/internaltask.h [new file with mode: 0644]
source/link.cpp [deleted file]
source/link.h [deleted file]
source/objectfile.cpp
source/objectfile.h
source/pkgconfig.cpp
source/pkgconfig.h
source/pkgconfigaction.cpp [deleted file]
source/pkgconfigaction.h [deleted file]
source/pkgconfiggenerator.cpp [new file with mode: 0644]
source/pkgconfiggenerator.h [new file with mode: 0644]
source/sourcefile.h
source/staticlibrary.cpp
source/staticlibrary.h
source/systemlibrary.h
source/tar.cpp
source/tar.h
source/tarball.cpp
source/tarball.h
source/target.cpp
source/target.h
source/task.h [new file with mode: 0644]
source/tool.cpp [new file with mode: 0644]
source/tool.h [new file with mode: 0644]
source/toolchain.cpp [new file with mode: 0644]
source/toolchain.h [new file with mode: 0644]
source/unlink.cpp [deleted file]
source/unlink.h [deleted file]
source/virtualtarget.h

diff --git a/source/action.cpp b/source/action.cpp
deleted file mode 100644 (file)
index 89cd46b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <msp/io/print.h>
-#include "action.h"
-
-using namespace Msp;
-using namespace std;
-
-void Action::announce(const string &pkg, const string &tool, const string &tgt)
-{
-       IO::print("[%-10s] [%4s] %s\n", pkg.substr(0, 10), tool, tgt);
-}
diff --git a/source/action.h b/source/action.h
deleted file mode 100644 (file)
index afe4697..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef ACTION_H_
-#define ACTION_H_
-
-#include <string>
-#include <sigc++/sigc++.h>
-
-class Builder;
-
-/**
-Actions are executed to rebuild targets.
-*/
-class Action
-{
-public:
-       /// Emitted when the action has finished
-       sigc::signal<void> signal_done;
-       
-protected:
-       Builder &builder;
-       
-       Action(Builder &b): builder(b) { }
-public:
-       virtual ~Action() { }
-
-       /**
-       Checks whether the action is done and emits signal_done if it is.  Returns 0
-       if the action has completed successfully, 1 if an error was encountered and
-       -1 if it is still executing.
-       */
-       virtual int check() = 0;
-       
-protected:
-       /**
-       Annouces the action by printing out the package name, tool and target name.
-       */
-       void announce(const std::string &, const std::string &, const std::string &);
-};
-
-#endif
index d59519c13115c186d52fc230353690c08372bd62..dd8894c61b4d61a122c236c8c9116091658a0f2f 100644 (file)
@@ -7,6 +7,7 @@
 #include "package.h"
 #include "sourcefile.h"
 #include "target.h"
+#include "tool.h"
 
 using namespace std;
 using namespace Msp;
@@ -38,6 +39,7 @@ void Analyzer::analyze()
        row.push_back("Name");
        row.push_back("Package");
        row.push_back("Type");
+       row.push_back("Tool");
        row.push_back("Rebuild");
        table.push_back(row);
        
@@ -87,7 +89,12 @@ void Analyzer::build_depend_table(Target &tgt, unsigned depth)
                row.push_back("");
        
        row.push_back(tgt.get_type());
-       
+       const Tool *tool = tgt.get_tool();
+       if(tool)
+               row.push_back(tool->get_tag());
+       else
+               row.push_back("");
+
        if(tgt.get_rebuild())
        {
                if(tgt.get_rebuild_reason().empty())
diff --git a/source/archive.cpp b/source/archive.cpp
deleted file mode 100644 (file)
index 6d1d502..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <msp/fs/dir.h>
-#include <msp/fs/stat.h>
-#include <msp/fs/utils.h>
-#include "archive.h"
-#include "builder.h"
-#include "component.h"
-#include "objectfile.h"
-#include "sourcepackage.h"
-#include "staticlibrary.h"
-
-using namespace std;
-using namespace Msp;
-
-Archive::Archive(Builder &b, const StaticLibrary &lib):
-       ExternalAction(b)
-{
-       const Component &comp = lib.get_component();
-
-       work_dir = comp.get_package().get_source();
-
-       std::string tool = "AR";
-       argv.push_back(builder.get_current_arch().get_tool(tool));
-       argv.push_back("rc");
-
-       argv.push_back(relative(lib.get_path(), work_dir).str());
-       const TargetList &deps = lib.get_depends();
-       for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
-               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
-                       argv.push_back(relative(obj->get_path(), work_dir).str());
-
-       FS::Path lpath = lib.get_path();
-       if(!builder.get_dry_run())
-       {
-               FS::mkpath(FS::dirname(lpath), 0755);
-               if(FS::exists(lib.get_path()))
-                       FS::unlink(lib.get_path());
-       }
-
-       announce(comp.get_package().get_name(), tool, relative(lpath, work_dir).str().substr(2));
-
-       launch();
-}
diff --git a/source/archive.h b/source/archive.h
deleted file mode 100644 (file)
index e95749e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ARCHIVE_H_
-#define ARCHIVE_H_
-
-#include "externalaction.h"
-
-class StaticLibrary;
-
-/**
-Creates an archive of object files, a.k.a. static library.
-*/
-class Archive: public ExternalAction
-{
-public:
-       Archive(Builder &, const StaticLibrary &);
-};
-
-#endif
index aa75b4599a52486614cd7c8df74a6a3f40bab2ab..41db493fdb8feed0cd47f0009a7f228815f1c8b7 100644 (file)
@@ -69,11 +69,6 @@ void Binary::find_depends()
        deps_ready = true;
 }
 
-Action *Binary::create_action()
-{
-       return new Link(builder, *this);
-}
-
 FS::Path Binary::generate_target_path(const Component &c)
 {
        const SourcePackage &pkg = c.get_package();
index 7c1a701bcc973e43f675346819e0df4a10f80c01..5239dc3fc0e06411df34d1f033b5c9b30abe82c8 100644 (file)
@@ -20,8 +20,6 @@ public:
        const Component &get_component() const { return comp; }
        virtual void find_depends();
 protected:
-       virtual Action *create_action();
-
        /** Returns the path for the binary.  We can't do this in the constructor
        since we need to pass the value to the Target c'tor. */
        static Msp::FS::Path generate_target_path(const Component &);
index 7704a9634a0e7b086276086ddac50a236a3fc9d8..57764b781b26a3030a9b629567c241ed1a74937c 100644 (file)
 #include <msp/strings/utils.h>
 #include <msp/time/units.h>
 #include <msp/time/utils.h>
-#include "action.h"
 #include "analyzer.h"
 #include "binarypackage.h"
 #include "builder.h"
+#include "copy.h"
+#include "gnuarchiver.h"
+#include "gnuccompiler.h"
+#include "gnucxxcompiler.h"
+#include "gnulinker.h"
 #include "header.h"
 #include "install.h"
 #include "misc.h"
 #include "package.h"
 #include "pkgconfig.h"
+#include "pkgconfiggenerator.h"
 #include "sharedlibrary.h"
 #include "sourcepackage.h"
 #include "systemlibrary.h"
-#include "unlink.h"
+#include "tar.h"
+#include "task.h"
 #include "virtualtarget.h"
 
 using namespace std;
@@ -131,11 +137,13 @@ Builder::Builder(int argc, char **argv):
 
        cwd = FS::getcwd();
 
-       native_arch.set_tool("CC",  "gcc");
-       native_arch.set_tool("CXX", "g++");
-       native_arch.set_tool("LD",  "gcc");
-       native_arch.set_tool("LXX", "g++");
-       native_arch.set_tool("AR",  "ar");
+       toolchain.add_tool(new GnuCCompiler(*this));
+       toolchain.add_tool(new GnuCxxCompiler(*this));
+       toolchain.add_tool(new GnuLinker(*this));
+       toolchain.add_tool(new GnuArchiver(*this));
+       toolchain.add_tool(new Copy(*this));
+       toolchain.add_tool(new Tar(*this));
+       toolchain.add_tool(new PkgConfigGenerator(*this));
 
        load_build_file((FS::get_sys_data_dir(argv[0], "builder")/"builderrc").str());
        load_build_file((FS::get_user_data_dir("builder")/"rc").str());
@@ -400,7 +408,8 @@ Target *Builder::get_header(const string &include, const FS::Path &from, const l
        static string cxx_ver;
        if(cxx_ver.empty())
        {
-               StringList argv;
+               // XXX This needs to go elsewhere
+               /*StringList argv;
                argv.push_back(current_arch->get_tool("CXX"));
                argv.push_back("--version");
                if(RegMatch m = Regex("[0-9]\\.[0-9.]+").match(run_command(argv)))
@@ -416,7 +425,7 @@ Target *Builder::get_header(const string &include, const FS::Path &from, const l
                        if(verbose>=5)
                                IO::print("C++ version is %s\n", cxx_ver);
                }
-               else
+               else*/
                        cxx_ver = "-";
        }
 
@@ -577,21 +586,17 @@ FS::Path Builder::get_package_location(const string &name)
 
 int Builder::load_build_file(const FS::Path &fn)
 {
-       try
-       {
-               IO::BufferedFile in(fn.str());
+       if(!FS::exists(fn))
+               return -1;
 
-               if(verbose>=3)
-                       IO::print("Reading %s\n", fn);
+       IO::BufferedFile in(fn.str());
 
-               DataFile::Parser parser(in, fn.str());
-               Loader loader(*this, fn.subpath(0, fn.size()-1));
-               loader.load(parser);
-       }
-       catch(const IO::file_not_found &)
-       {
-               return -1;
-       }
+       if(verbose>=3)
+               IO::print("Reading %s\n", fn);
+
+       DataFile::Parser parser(in, fn.str());
+       Loader loader(*this, fn.subpath(0, fn.size()-1));
+       loader.load(parser);
 
        return 0;
 }
@@ -757,7 +762,7 @@ int Builder::do_build()
        if(verbose>=1)
                IO::print("Will build %d target%s\n", total, (total!=1 ? "s" : ""));
 
-       vector<Action *> actions;
+       vector<Task *> tasks;
 
        unsigned count = 0;
 
@@ -766,36 +771,38 @@ int Builder::do_build()
 
        while(!finish)
        {
-               if(actions.size()<jobs && !fail)
+               if(tasks.size()<jobs && !fail)
                {
                        Target *tgt = cmdline->get_buildable_target();
                        if(tgt)
                        {
-                               Action *action = tgt->build();
-                               if(action)
-                                       actions.push_back(action);
+                               if(tgt->get_tool())
+                                       IO::print("[%-10s] [%-4s] %s\n", tgt->get_package()->get_name(), tgt->get_tool()->get_tag(), tgt->get_name());
+                               Task *task = tgt->build();
+                               if(task)
+                                       tasks.push_back(task);
 
                                if(show_progress)
                                        IO::print("%d of %d target%s built\033[1G", count, total, (total!=1 ? "s" : ""));
                        }
-                       else if(actions.empty())
+                       else if(tasks.empty())
                                finish = true;
                }
                else
                        Time::sleep(10*Time::msec);
 
-               for(unsigned i=0; i<actions.size();)
+               for(unsigned i=0; i<tasks.size();)
                {
-                       int status = actions[i]->check();
-                       if(status>=0)
+                       Task::Status status = tasks[i]->check();
+                       if(status!=Task::RUNNING)
                        {
                                ++count;
 
-                               delete actions[i];
-                               actions.erase(actions.begin()+i);
-                               if(status>0)
+                               delete tasks[i];
+                               tasks.erase(tasks.begin()+i);
+                               if(status==Task::ERROR)
                                        fail = true;
-                               if(actions.empty() && fail)
+                               if(tasks.empty() && fail)
                                        finish = true;
                        }
                        else
@@ -837,11 +844,7 @@ int Builder::do_clean()
 
        for(set<Target *>::iterator i=clean_tgts.begin(); i!=clean_tgts.end(); ++i)
                if(FileTarget *ft = dynamic_cast<FileTarget *>(*i))
-               {
-                       Action *action = new Unlink(*this, *ft);
-                       while(action->check()<0) ;
-                       delete action;
-               }
+                       unlink(ft->get_path());
 
        return 0;
 }
index 44bf878b4efa1e1b24d4793b669a1b08e5b342dc..25f06457b624da63f1a011f0d570c6badba03a82 100644 (file)
@@ -12,6 +12,7 @@
 #include "misc.h"
 #include "problem.h"
 #include "target.h"
+#include "toolchain.h"
 
 class Analyzer;
 class Config;
@@ -80,6 +81,7 @@ private:
        Architecture *current_arch;
        StringMap cross_prefixes;
        ProfileTemplateMap profile_tmpl;
+       Toolchain toolchain;
 
        ProblemList problems;
        Analyzer *analyzer;
@@ -146,6 +148,8 @@ public:
        const StringList &get_warnings() const { return warnings; }
        void apply_profile_template(Config &, const std::string &) const;
 
+       const Toolchain &get_toolchain() const { return toolchain; }
+
        /** Adds a target to both the target map and the new target queue.  Called
        from Target constructor. */
        void add_target(Target *);
diff --git a/source/compile.cpp b/source/compile.cpp
deleted file mode 100644 (file)
index 4960d42..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <msp/fs/dir.h>
-#include <msp/fs/utils.h>
-#include "builder.h"
-#include "buildinfo.h"
-#include "compile.h"
-#include "component.h"
-#include "objectfile.h"
-#include "sourcefile.h"
-#include "sourcepackage.h"
-
-using namespace std;
-using namespace Msp;
-
-Compile::Compile(Builder &b, const ObjectFile &obj):
-       ExternalAction(b)
-{
-       const Component &comp = obj.get_component();
-
-       work_dir = comp.get_package().get_source();
-
-       FS::Path spath = obj.get_source().get_path();
-
-       string ext = FS::extpart(spath.str());
-       const char *tool = 0;
-       if(ext==".cpp" || ext==".cc")
-               tool = "CXX";
-       else
-               tool = "CC";
-
-       argv.push_back(builder.get_current_arch().get_tool(tool));
-       argv.push_back("-c");
-
-       const BuildInfo &binfo = comp.get_build_info();
-       for(list<string>::const_iterator i=binfo.warnings.begin(); i!=binfo.warnings.end(); ++i)
-               argv.push_back("-W"+*i);
-       for(list<string>::const_iterator i=binfo.cflags.begin(); i!=binfo.cflags.end(); ++i)
-               argv.push_back(*i);
-       for(list<string>::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i)
-               argv.push_back("-I"+*i);
-       for(list<string>::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i)
-               argv.push_back("-D"+*i);
-
-       FS::Path opath = obj.get_path();
-       argv.push_back("-o");
-       argv.push_back(relative(opath, work_dir).str());
-       argv.push_back(relative(spath, work_dir).str());
-
-       if(!builder.get_dry_run())
-               FS::mkpath(FS::dirname(opath), 0755);
-
-       announce(comp.get_package().get_name(), tool, basename(opath));
-
-       launch();
-}
diff --git a/source/compile.h b/source/compile.h
deleted file mode 100644 (file)
index 5b55c4e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef COMPILE_H_
-#define COMPILE_H_
-
-#include <msp/fs/path.h>
-#include "externalaction.h"
-
-class Component;
-class ObjectFile;
-
-/**
-Compiles a source file into an object file.
-*/
-class Compile: public ExternalAction
-{
-public:
-       Compile(Builder &, const ObjectFile &);
-};
-
-#endif
index c12399f670f944e2a22f953862f3763ba05ff795..24dce7739d47bb34c947312eaeacda44816fdab2 100644 (file)
@@ -17,6 +17,8 @@
 #include "staticlibrary.h"
 #include "tarball.h"
 #include "target.h"
+#include "tool.h"
+#include "toolchain.h"
 
 using namespace std;
 using namespace Msp;
@@ -96,48 +98,55 @@ void Component::create_build_info()
 void Component::create_targets() const
 {
        Builder &builder = pkg.get_builder();
+       const Toolchain &toolchain = builder.get_toolchain();
        Target *world = builder.get_target("world");
        Target *def_tgt = builder.get_target("default");
 
-       PathList files = collect_source_files();
-       list<FileTarget *> inst_list;
+       PathList source_filenames = collect_source_files();
+       list<Target *> inst_list;
 
        string inst_loc;
        if(type==TARBALL)
        {
+               //const Tool &tar = toolchain.get_tool("TAR");
+
                string tarname = name;
                if(name=="@src")
+               {
                        tarname = pkg.get_name()+"-"+pkg.get_version();
-               TarBall *result = new TarBall(builder, pkg, tarname);
+                       source_filenames.push_back(pkg.get_source()/"Build");
+               }
+
+               list<Target *> files;
+               for(PathList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
+               {
+                       FileTarget *file = builder.get_target_by_path(*i);
+                       if(!file)
+                               file = new File(builder, *i);
+                       files.push_back(file);
+               }
 
                if(name=="@src")
                {
                        const Builder::TargetMap &targets = builder.get_targets();
                        for(Builder::TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
                                if(i->second->get_package()==&pkg && !i->second->is_buildable())
-                                       result->add_depend(i->second);
-                       files.push_back(pkg.get_source()/"Build");
+                                       files.push_back(i->second);
                }
 
-               for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
-               {
-                       FileTarget *ft;
-                       if(Target *tgt = builder.get_target_by_path(*i))
-                               ft = dynamic_cast<FileTarget *>(tgt);
-                       else
-                               ft = new File(builder, *i);
-                       result->add_depend(ft);
-               }
+               /* XXX The source files don't have a package at the moment, so we can't
+               create the tarball target until things get fixed up a bit */
+               /*Target *result = tar.create_target(files, tarname);
 
-               Target *tarbls_tgt = builder.get_target("tarballs");
-               tarbls_tgt->add_depend(result);
+               Target *tarballs_tgt = builder.get_target("tarballs");
+               tarballs_tgt->add_depend(result);*/
 
                return;
        }
        else if(type==INSTALL)
        {
                inst_loc = name;
-               for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
+               for(PathList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
                {
                        FileTarget *ft;
                        if(Target *tgt = builder.get_target_by_path(*i))
@@ -149,12 +158,14 @@ void Component::create_targets() const
        }
        else if(type==DATAFILE)
        {
+               const Tool &dcomp = toolchain.get_tool("DATA");
+
                File *source;
-               if(Target *tgt = builder.get_target_by_path(files.front()))
+               if(Target *tgt = builder.get_target_by_path(source_filenames.front()))
                        source = dynamic_cast<File *>(tgt);
                else
-                       source = new File(builder, pkg, files.front());
-               ::DataFile *result = new ::DataFile(builder, *this, *source);
+                       source = new File(builder, pkg, source_filenames.front());
+               Target *result = dcomp.create_target(*source);
 
                if(&pkg==builder.get_main_package() && deflt)
                        def_tgt->add_depend(result);
@@ -165,7 +176,7 @@ void Component::create_targets() const
        }
        else
        {
-               for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
+               for(PathList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
                {
                        string ext = FS::extpart(FS::basename(*i));
                        if(ext==".h")
@@ -183,28 +194,34 @@ void Component::create_targets() const
 
        if(type==PROGRAM || type==LIBRARY || type==MODULE)
        {
-               list<ObjectFile *> objs;
-               for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
+               list<Target *> objs;
+               for(PathList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
                {
                        string ext = FS::extpart(FS::basename(*i));
-                       if((ext==".cpp" || ext==".cc" || ext==".c"))
+                       const Tool *tool = toolchain.get_tool_for_suffix(ext);
+                       if(tool)
                        {
-                               SourceFile *src = new SourceFile(builder, *this, i->str());
-                               ObjectFile *obj = new ObjectFile(builder, *this, *src);
+                               Target *src = tool->create_source(*this, *i);
+                               Target *obj = tool->create_target(*src);
                                objs.push_back(obj);
                        }
                }
 
-               list<FileTarget *> results;
+               const Tool &linker = toolchain.get_tool("LINK");
+
+               list<Target *> results;
                if(type==LIBRARY)
                {
-                       results.push_back(new SharedLibrary(builder, *this, objs));
-                       results.push_back(new StaticLibrary(builder, *this, objs));
+                       const 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(new Executable(builder, *this, objs));
+                       results.push_back(linker.create_target(objs));
 
-               for(list<FileTarget *>::const_iterator i=results.begin(); i!=results.end(); ++i)
+               for(list<Target *>::const_iterator i=results.begin(); i!=results.end(); ++i)
                {
                        if(&pkg==builder.get_main_package() && deflt)
                                def_tgt->add_depend(*i);
@@ -216,9 +233,10 @@ void Component::create_targets() const
        }
 
        Target *inst_tgt = builder.get_target("install");
-       for(list<FileTarget *>::const_iterator i=inst_list.begin(); i!=inst_list.end(); ++i)
+       const Tool &copy = toolchain.get_tool("CP");
+       for(list<Target *>::const_iterator i=inst_list.begin(); i!=inst_list.end(); ++i)
        {
-               Install *inst = new Install(builder, pkg, **i, inst_loc);
+               Target *inst = copy.create_target(**i, inst_loc);
                inst_tgt->add_depend(inst);
        }
 }
index afb86ea7b2b4ff15a676662ecde6eaf003db63b8..a518b6302f8fd6cdea0fb4fd4d5e06fd06f991bc 100644 (file)
@@ -33,15 +33,14 @@ bool Config::is_option(const string &name) const
 
 void Config::select_last_profile()
 {
-       try
+       FS::Path profile_cache_fn = package.get_source()/".profile";
+       if(FS::exists(profile_cache_fn))
        {
-               IO::BufferedFile in((package.get_source()/".profile").str());
+               IO::BufferedFile in(profile_cache_fn.str());
                string profile;
                in.getline(profile);
                set_option("profile", profile);
        }
-       catch(const IO::file_not_found &)
-       { }
 
        freeze_mtime = true;
        package.get_builder().apply_profile_template(*this, get_option("profile").value);
@@ -121,18 +120,17 @@ void Config::load()
 {
        FS::Path fn = package.get_source()/(".options."+get_option("profile").value);
 
-       try
+       FS::Stat stat = FS::stat(fn);
+       if(stat)
        {
                IO::BufferedFile in(fn.str());
 
-               mtime = FS::stat(fn).get_modify_time();
+               mtime = stat.get_modify_time();
 
                DataFile::Parser parser(in, fn.str());
                Loader loader(*this);
                loader.load(parser);
        }
-       catch(const IO::file_not_found &)
-       { }
 }
 
 
index 8ea7f3537ab32d8e84aa2a3dd2731cf32ed1df1f..b5ac403c4d4eb72e42567122bb656d576287bb5a 100644 (file)
@@ -7,55 +7,64 @@
 #include <msp/io/print.h>
 #include "builder.h"
 #include "copy.h"
-#include "package.h"
+#include "install.h"
 
 using namespace std;
 using namespace Msp;
 
-Copy::Copy(Builder &b, const Package &pkg, const FS::Path &s, const FS::Path &d, const FS::Path &l):
-       InternalAction(b),
-       src(s),
-       dest(d),
-       link(l)
+Copy::Copy(Builder &b):
+       Tool(b, "CP")
+{ }
+
+Target *Copy::create_target(const list<Target *> &sources, const string &arg) const
 {
-       announce(pkg.get_name(), "COPY", dest.str());
-       if(builder.get_verbose()>=2)
-               IO::print("%s -> %s\n", s, d);
+       FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
+       const SourcePackage &pkg = dynamic_cast<const SourcePackage &>(*file_tgt.get_package());
+       Install *inst = new Install(builder, pkg, file_tgt, arg);
+       inst->set_tool(*this);
+       return inst;
+}
 
-       if(!builder.get_dry_run())
-               worker = new Worker(*this);
+Task *Copy::run(const Target &target) const
+{
+       const Install &install = dynamic_cast<const Install &>(target);
+       Worker *worker = new Worker(install);
+       return new InternalTask(worker);
 }
 
 
-Copy::Worker::Worker(Copy &c):
-       copy(c)
+Copy::Worker::Worker(const Install &t):
+       target(t)
 {
        launch();
 }
 
 void Copy::Worker::main()
 {
-       FS::mkpath(FS::dirname(copy.dest), 0755);
+       const FileTarget &source = target.get_source();
+       const FS::Path &src_path = source.get_path();
+       const FS::Path &dst_path = target.get_path();
+       FS::mkpath(FS::dirname(dst_path), 0755);
 
        // Remove old file.  Not doing this would cause Bad Stuff when installing libraries.
-       if(FS::exists(copy.dest))
+       if(FS::exists(dst_path))
        {
                try
                {
-                       unlink(copy.dest);
+                       unlink(dst_path);
                }
                catch(const exception &e)
                {
                        IO::print(IO::cerr, "%s\n", e.what());
-                       done = error = true;
+                       status = Task::ERROR;
                        return;
                }
        }
 
        try
        {
-               IO::File in(copy.src.str());
-               IO::File out(copy.dest.str(), IO::M_WRITE);
+               IO::File in(src_path.str());
+               IO::File out(dst_path.str(), IO::M_WRITE);
 
                // Actual transfer loop
                char buf[16384];
@@ -68,20 +77,21 @@ void Copy::Worker::main()
        catch(const exception &e)
        {
                IO::print(IO::cerr, "%s\n", e.what());
-               done = error = true;
+               status = Task::ERROR;
                return;
        }
 
        // Preserve file permissions
        struct stat st;
-       if(stat(copy.src.str().c_str(), &st)==0)
-               chmod(copy.dest.str().c_str(), st.st_mode&0777);
+       if(stat(src_path.str().c_str(), &st)==0)
+               chmod(dst_path.str().c_str(), st.st_mode&0777);
 
-       if(!copy.link.empty())
+       const FS::Path &link = target.get_symlink();
+       if(!link.empty())
        {
-               FS::Path relpath = FS::relative(copy.dest, FS::dirname(copy.link));
-               symlink(relpath.str().c_str(), copy.link.str().c_str());
+               FS::Path relpath = FS::relative(dst_path, FS::dirname(link));
+               symlink(relpath.str().c_str(), link.str().c_str());
        }
 
-       done = true;
+       status = Task::SUCCESS;
 }
index bc4c173b140be542a47f35ff91282c7a91e3e9cd..6150fadfefa660c287d8f2a850da098489f51893 100644 (file)
@@ -3,35 +3,36 @@
 
 #include <msp/core/thread.h>
 #include <msp/fs/path.h>
-#include "internalaction.h"
+#include "internaltask.h"
+#include "tool.h"
 
-class Package;
+class Install;
 
 /**
 Copies a file to another place.  Used by the Install target.
 */
-class Copy: public InternalAction
+class Copy: public Tool
 {
 private:
        /**
        A worker thread that actually does the data transfer.
        */
-       class Worker: public InternalAction::Worker
+       class Worker: public InternalTask::Worker
        {
-       public:
-               Worker(Copy &);
        private:
-               Copy &copy;
+               const Install &target;
 
-               void main();
+       public:
+               Worker(const Install &);
+       private:
+               virtual void main();
        };
 
-       Msp::FS::Path src;
-       Msp::FS::Path dest;
-       Msp::FS::Path link;
-
 public:
-       Copy(Builder &, const Package &, const Msp::FS::Path &, const Msp::FS::Path &, const Msp::FS::Path & =Msp::FS::Path());
+       Copy(Builder &);
+
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
 };
 
 #endif
diff --git a/source/datacompile.cpp b/source/datacompile.cpp
deleted file mode 100644 (file)
index bec3d4b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <msp/fs/dir.h>
-#include <msp/fs/utils.h>
-#include "builder.h"
-#include "component.h"
-#include "datacompile.h"
-#include "datafile.h"
-#include "file.h"
-#include "sourcepackage.h"
-
-using namespace Msp;
-
-DataCompile::DataCompile(Builder &b, ::DataFile &dfile):
-       ExternalAction(b)
-{
-       const Component &comp = dfile.get_component();
-
-       work_dir = comp.get_package().get_source();
-
-       argv.push_back("mspdatatool");
-       argv.push_back("-c");
-       argv.push_back("-b");
-
-       FS::Path opath = dfile.get_path();
-       argv.push_back("-o");
-       argv.push_back(relative(opath, work_dir).str());
-
-       FS::Path spath = dfile.get_source().get_path();
-       argv.push_back(relative(spath, work_dir).str());
-
-       if(!builder.get_dry_run())
-               FS::mkpath(FS::dirname(opath), 0755);
-
-       announce(comp.get_package().get_name(), "DATA", relative(opath, work_dir).str());
-
-       launch();
-}
diff --git a/source/datacompile.h b/source/datacompile.h
deleted file mode 100644 (file)
index 7348338..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef DATACOMPILE_H_
-#define DATACOMPILE_H_
-
-#include "externalaction.h"
-
-class DataFile;
-
-class DataCompile: public ExternalAction
-{
-public:
-       DataCompile(Builder &, DataFile &);
-};
-
-#endif
diff --git a/source/datacompiler.cpp b/source/datacompiler.cpp
new file mode 100644 (file)
index 0000000..2f806bf
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdexcept>
+#include "datacompiler.h"
+
+using namespace std;
+
+DataCompiler::DataCompiler(Builder &b):
+       Tool(b, "DATA")
+{
+}
+
+Target *DataCompiler::create_target(const list<Target *> &sources, const string &) const
+{
+       if(sources.size()!=1)
+               throw invalid_argument("DataCompiler::create_target");
+       throw runtime_error("Not implemented");
+       //File &source = dynamic_cast<File &>(sources.front());
+       //return new ::DataFile(
+}
+
+Task *DataCompiler::run(const Target &) const
+{
+       throw runtime_error("Not implemented");
+}
diff --git a/source/datacompiler.h b/source/datacompiler.h
new file mode 100644 (file)
index 0000000..e4c8ea2
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef DATACOMPILER_H_
+#define DATACOMPILER_H_
+
+#include "tool.h"
+
+class DataCompiler: public Tool
+{
+public:
+       DataCompiler(Builder &);
+
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
+};
+
+#endif
index afde084d4b1504698de48d537c2c342a1292103f..3164d8e38caeec5a532df9d8e402defe3e01fbf5 100644 (file)
@@ -1,5 +1,4 @@
 #include "component.h"
-#include "datacompile.h"
 #include "datafile.h"
 #include "file.h"
 #include "sourcepackage.h"
@@ -13,11 +12,6 @@ DataFile::DataFile(Builder &b, const Component &c, File &s):
        add_depend(&source);
 }
 
-Action *DataFile::create_action()
-{
-       return new DataCompile(builder, *this);
-}
-
 Msp::FS::Path DataFile::generate_target_path(const Component &comp)
 {
        return comp.get_package().get_out_dir()/(comp.get_name()+".dat");
index eeaed1a2e940351601eefcf0c8419496c7ba55ab..071a82b887d60d23d0fa2ef2e290f1a7c942aa79 100644 (file)
@@ -20,7 +20,6 @@ public:
        File &get_source() const { return source; }
 
 private:
-       virtual Action *create_action();
        static Msp::FS::Path generate_target_path(const Component &);
 };
 
diff --git a/source/externalaction.cpp b/source/externalaction.cpp
deleted file mode 100644 (file)
index cad9ba8..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <cstring>
-#include <cstdlib>
-#include <sys/wait.h>
-#include <msp/fs/dir.h>
-#include <msp/io/print.h>
-#include <msp/strings/utils.h>
-#include "builder.h"
-#include "externalaction.h"
-
-using namespace std;
-using namespace Msp;
-
-void ExternalAction::launch()
-{
-       if(builder.get_verbose()>=2)
-               IO::print("%s\n", join(argv.begin(), argv.end()));
-
-       if(builder.get_dry_run())
-               pid = -1;
-       else
-       {
-               pid = fork();
-               if(pid==0)
-               {
-                       char *argv_[argv.size()+1];
-
-                       unsigned j = 0;
-                       for(StringList::iterator i=argv.begin(); i!=argv.end(); ++i)
-                               argv_[j++] = strdup(i->c_str());
-                       argv_[j] = 0;
-
-                       if(!work_dir.empty())
-                               FS::chdir(work_dir);
-                       execvp(argv_[0], argv_);
-                       IO::print("Couldn't execute %s\n", argv.front());
-                       exit(1);
-               }
-               else if(pid<0)
-                       pid = 0;
-       }
-}
-
-int ExternalAction::check()
-{
-       if(builder.get_dry_run())
-       {
-               signal_done.emit();
-               return 0;
-       }
-
-       if(!pid)
-               return exit_code;
-
-       int status;
-       if(waitpid(pid, &status, WNOHANG)==pid)
-       {
-               signal_done.emit();
-               if(WIFEXITED(status))
-                       exit_code = WEXITSTATUS(status);
-               else
-                       exit_code = 254;
-               pid = 0;
-               return exit_code;
-       }
-       else
-               return -1;
-}
diff --git a/source/externalaction.h b/source/externalaction.h
deleted file mode 100644 (file)
index 1f830c9..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef EXTERNALACTION_H_
-#define EXTERNALACTION_H_
-
-#include <list>
-#include <string>
-#include "action.h"
-#include "misc.h"
-
-/**
-Base class for Actions that want to execute an external program.
-*/
-class ExternalAction: public Action
-{
-protected:
-       StringList argv;
-       Msp::FS::Path work_dir;
-       int pid;
-       int exit_code;
-       
-       ExternalAction(Builder &b): Action(b), pid(0), exit_code(0) { }
-
-       /** Starts the external program.  Fill in argv before calling this. */
-       void launch();
-
-public:
-       virtual int check();
-};
-
-#endif
diff --git a/source/externaltask.cpp b/source/externaltask.cpp
new file mode 100644 (file)
index 0000000..2471666
--- /dev/null
@@ -0,0 +1,58 @@
+#include <cstdlib>
+#include <sys/wait.h>
+#include <msp/fs/dir.h>
+#include <msp/io/print.h>
+#include "externaltask.h"
+
+using namespace std;
+using namespace Msp;
+
+ExternalTask::ExternalTask(const vector<string> &argv, const FS::Path &work_dir):
+       pid(-1),
+       exit_code(-1)
+{
+       if((pid = fork()))
+       {
+               if(pid==-1)
+                       exit_code = 1;
+               else
+                       exit_code = 0;
+       }
+       else
+       {
+               vector<const char *> cargv(argv.size()+1);
+               for(unsigned i=0; i<argv.size(); ++i)
+                       cargv[i] = argv[i].c_str();
+               cargv.back() = 0;
+
+               if(!work_dir.empty())
+                       FS::chdir(work_dir);
+               execvp(cargv.front(), const_cast<char *const *>(&cargv.front()));
+               IO::print("Couldn't execute %s\n", argv.front());
+               exit(1);
+       }
+}
+
+Task::Status ExternalTask::check()
+{
+       if(pid>0)
+       {
+               int status;
+               if(waitpid(pid, &status, WNOHANG)==pid)
+               {
+                       if(WIFEXITED(status))
+                               exit_code = WEXITSTATUS(status);
+                       else if(WIFSIGNALED(status))
+                               exit_code = 256+WTERMSIG(status);
+                       else
+                               exit_code = 1025;
+                       pid = 0;
+
+                       signal_finished.emit(!exit_code);
+               }
+               else
+                       return RUNNING;
+       }
+
+       return exit_code ? ERROR : SUCCESS;
+}
diff --git a/source/externaltask.h b/source/externaltask.h
new file mode 100644 (file)
index 0000000..1701313
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef EXTERNALTASK_H_
+#define EXTERNALTASK_H_
+
+#include <string>
+#include <vector>
+#include <msp/fs/path.h>
+#include "task.h"
+
+class ExternalTask: public Task
+{
+private:
+       int pid;
+       int exit_code;
+
+public:
+       ExternalTask(const std::vector<std::string> &, const Msp::FS::Path &);
+
+       virtual Status check();
+};
+
+#endif
index 76c03790a6d689173d2ee9bd849fb7ea6ac935c1..4f5618f1565037723c1aa6609efe741f37f9f73c 100644 (file)
@@ -11,9 +11,8 @@ class File: public FileTarget
 public:
        File(Builder &b, const Msp::FS::Path &t): FileTarget(b, 0, t) { }
        File(Builder &b, Package &p, const Msp::FS::Path &t): FileTarget(b, &p, t) { }
+
        virtual const char *get_type() const { return "File"; }
-private:
-       virtual Action *create_action() { return 0; }
 };
 
 #endif
diff --git a/source/gnuarchiver.cpp b/source/gnuarchiver.cpp
new file mode 100644 (file)
index 0000000..8eab751
--- /dev/null
@@ -0,0 +1,68 @@
+#include <msp/fs/dir.h>
+#include <msp/fs/stat.h>
+#include <msp/fs/utils.h>
+#include <stdexcept>
+#include "builder.h"
+#include "component.h"
+#include "externaltask.h"
+#include "gnuarchiver.h"
+#include "objectfile.h"
+#include "sourcepackage.h"
+#include "staticlibrary.h"
+
+using namespace std;
+using namespace Msp;
+
+GnuArchiver::GnuArchiver(Builder &b):
+       Tool(b, "AR")
+{
+       input_suffixes.push_back(".o");
+}
+
+Target *GnuArchiver::create_target(const list<Target *> &sources, const string &) const
+{
+       if(sources.empty())
+               throw invalid_argument("GnuArchiver::create_target");
+
+       list<ObjectFile *> objs;
+       for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+       {
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+                       objs.push_back(obj);
+               else
+                       throw invalid_argument("GnuLinker::create_target");
+       }
+
+       const Component &comp = objs.front()->get_component();
+       StaticLibrary *lib = new StaticLibrary(builder, comp, objs);
+       lib->set_tool(*this);
+       return lib;
+}
+
+Task *GnuArchiver::run(const Target &target) const
+{
+       const StaticLibrary &lib = dynamic_cast<const StaticLibrary &>(target);
+       const Component &comp = lib.get_component();
+
+       vector<string> argv;
+       argv.push_back("ar");
+       argv.push_back("rc");
+
+       FS::Path work_dir = comp.get_package().get_source();
+
+       argv.push_back(relative(lib.get_path(), work_dir).str());
+
+       const TargetList &deps = lib.get_depends();
+       for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+                       argv.push_back(relative(obj->get_path(), work_dir).str());
+
+       if(!builder.get_dry_run())
+       {
+               FS::mkpath(FS::dirname(lib.get_path()), 0755);
+               if(FS::exists(lib.get_path()))
+                       FS::unlink(lib.get_path());
+       }
+
+       return new ExternalTask(argv, work_dir);
+}
diff --git a/source/gnuarchiver.h b/source/gnuarchiver.h
new file mode 100644 (file)
index 0000000..f1a4b63
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef GNUARCHIVER_H_
+#define GNUARCHIVER_H_
+
+#include "tool.h"
+
+class GnuArchiver: public Tool
+{
+public:
+       GnuArchiver(Builder &);
+
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
+};
+
+#endif
diff --git a/source/gnuccompiler.cpp b/source/gnuccompiler.cpp
new file mode 100644 (file)
index 0000000..4ff46e8
--- /dev/null
@@ -0,0 +1,10 @@
+#include "gnuccompiler.h"
+
+using namespace std;
+using namespace Msp;
+
+GnuCCompiler::GnuCCompiler(Builder &b):
+       GnuCompiler(b, "CC", "gcc")
+{
+       input_suffixes.push_back(".c");
+}
diff --git a/source/gnuccompiler.h b/source/gnuccompiler.h
new file mode 100644 (file)
index 0000000..918f9bd
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef GNUCCOMPILER_H_
+#define GNUCCOMPILER_H_
+
+#include "gnucompiler.h"
+
+class GnuCCompiler: public GnuCompiler
+{
+public:
+       GnuCCompiler(Builder &);
+
+};
+
+#endif
diff --git a/source/gnucompiler.cpp b/source/gnucompiler.cpp
new file mode 100644 (file)
index 0000000..62a7e32
--- /dev/null
@@ -0,0 +1,65 @@
+#include <msp/fs/dir.h>
+#include <msp/fs/utils.h>
+#include "builder.h"
+#include "component.h"
+#include "externaltask.h"
+#include "gnucompiler.h"
+#include "objectfile.h"
+#include "sourcefile.h"
+#include "sourcepackage.h"
+
+using namespace std;
+using namespace Msp;
+
+GnuCompiler::GnuCompiler(Builder &b, const string &t, const string &n):
+       Tool(b, t),
+       name(n)
+{ }
+
+Target *GnuCompiler::create_source(const Component &comp, const FS::Path &path) const
+{
+       return new SourceFile(builder, comp, path);
+}
+
+Target *GnuCompiler::create_target(const list<Target *> &sources, const std::string &) const
+{
+       if(sources.size()!=1)
+               throw invalid_argument("GnuCCompiler::create_target");
+       SourceFile &source = dynamic_cast<SourceFile &>(*sources.front());
+       ObjectFile *obj = new ObjectFile(builder, *source.get_component(), source);
+       obj->set_tool(*this);
+       return obj;
+}
+
+Task *GnuCompiler::run(const Target &target) const
+{
+       const ObjectFile &object = dynamic_cast<const ObjectFile &>(target);
+       const Component &comp = object.get_component();
+
+       vector<string> argv;
+       argv.push_back(name);
+       argv.push_back("-c");
+
+       const BuildInfo &binfo = comp.get_build_info();
+       for(list<string>::const_iterator i=binfo.warnings.begin(); i!=binfo.warnings.end(); ++i)
+               argv.push_back("-W"+*i);
+       for(list<string>::const_iterator i=binfo.cflags.begin(); i!=binfo.cflags.end(); ++i)
+               argv.push_back(*i);
+       for(list<string>::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i)
+               argv.push_back("-I"+*i);
+       for(list<string>::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i)
+               argv.push_back("-D"+*i);
+
+       FS::Path obj_path = object.get_path();
+       FS::Path src_path = object.get_source().get_path();
+       FS::Path work_dir = comp.get_package().get_source();
+
+       argv.push_back("-o");
+       argv.push_back(relative(obj_path, work_dir).str());
+       argv.push_back(relative(src_path, work_dir).str());
+
+       if(!builder.get_dry_run())
+               FS::mkpath(FS::dirname(obj_path), 0755);
+
+       return new ExternalTask(argv, work_dir);
+}
diff --git a/source/gnucompiler.h b/source/gnucompiler.h
new file mode 100644 (file)
index 0000000..9cdf670
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef GNUCOMPILER_H_
+#define GNUCOMPILER_H_
+
+#include "tool.h"
+
+class GnuCompiler: public Tool
+{
+protected:
+       std::string name;
+
+       GnuCompiler(Builder &, const std::string &, const std::string &);
+
+public:
+       virtual Target *create_source(const Component &, const Msp::FS::Path &) const;
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
+};
+
+#endif
diff --git a/source/gnucxxcompiler.cpp b/source/gnucxxcompiler.cpp
new file mode 100644 (file)
index 0000000..8084a03
--- /dev/null
@@ -0,0 +1,8 @@
+#include "gnucxxcompiler.h"
+
+GnuCxxCompiler::GnuCxxCompiler(Builder &b):
+       GnuCompiler(b, "CXX", "g++")
+{
+       input_suffixes.push_back(".cpp");
+       input_suffixes.push_back(".cc");
+}
diff --git a/source/gnucxxcompiler.h b/source/gnucxxcompiler.h
new file mode 100644 (file)
index 0000000..bebb7b7
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef GNUCXXCOMPILER_H_
+#define GNUCXXCOMPILER_H_
+
+#include "gnucompiler.h"
+
+class GnuCxxCompiler: public GnuCompiler
+{
+public:
+       GnuCxxCompiler(Builder &);
+};
+
+#endif
diff --git a/source/gnulinker.cpp b/source/gnulinker.cpp
new file mode 100644 (file)
index 0000000..45cfd7f
--- /dev/null
@@ -0,0 +1,105 @@
+#include <stdexcept>
+#include <vector>
+#include <msp/fs/dir.h>
+#include <msp/fs/utils.h>
+#include "builder.h"
+#include "component.h"
+#include "executable.h"
+#include "externaltask.h"
+#include "gnucxxcompiler.h"
+#include "gnulinker.h"
+#include "objectfile.h"
+#include "sharedlibrary.h"
+#include "sourcepackage.h"
+#include "staticlibrary.h"
+
+using namespace std;
+using namespace Msp;
+
+GnuLinker::GnuLinker(Builder &b):
+       Tool(b, "LINK")
+{
+       input_suffixes.push_back(".o");
+       input_suffixes.push_back(".a");
+}
+
+Target *GnuLinker::create_target(const list<Target *> &sources, const std::string &arg) const
+{
+       if(sources.empty())
+               throw invalid_argument("GnuLinker::create_target");
+       list<ObjectFile *> objs;
+       for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+       {
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+                       objs.push_back(obj);
+               else
+                       throw invalid_argument("GnuLinker::create_target");
+       }
+
+       const Component &comp = objs.front()->get_component();
+       Binary *bin = 0;
+       if(arg=="shared")
+               bin = new SharedLibrary(builder, comp, objs);
+       else
+               bin = new Executable(builder, comp, objs);
+       bin->set_tool(*this);
+       return bin;
+}
+
+Task *GnuLinker::run(const Target &target) const
+{
+       const Binary &bin = dynamic_cast<const Binary &>(target);
+       const SharedLibrary *shlib = dynamic_cast<const SharedLibrary *>(&bin);
+
+       string command = "gcc";
+
+       const list<Target *> &depends = target.get_depends();
+       for(list<Target *>::const_iterator i=depends.begin(); i!=depends.end(); ++i)
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+               {
+                       const Tool *tool = obj->get_tool();
+                       if(dynamic_cast<const GnuCxxCompiler *>(tool))
+                               command = "g++";
+               }
+
+       vector<string> argv;
+       argv.push_back(command);
+
+       const Component &comp = bin.get_component();
+
+       if(shlib)
+       {
+               argv.push_back("-shared");
+               if(!shlib->get_soname().empty())
+                       argv.push_back("-Wl,-soname,"+shlib->get_soname());
+       }
+       else if(comp.get_package().get_library_mode()==ALL_STATIC)
+               argv.push_back("-static");
+
+       const BuildInfo &binfo = comp.get_build_info();
+       for(list<string>::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i)
+               argv.push_back(*i);
+       for(list<string>::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
+               argv.push_back("-L"+*i);
+
+       FS::Path work_dir = comp.get_package().get_source();
+
+       argv.push_back("-o");
+       argv.push_back(relative(bin.get_path(), work_dir).str());
+       for(TargetList::const_iterator i=depends.begin(); i!=depends.end(); ++i)
+       {
+               Target *tgt = (*i)->get_real_target();
+
+               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(tgt))
+                       argv.push_back(relative(obj->get_path(), work_dir).str());
+               else if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(tgt))
+                       argv.push_back(stlib->get_path().str());
+               else if(Library *lib = dynamic_cast<Library *>(tgt))
+                       argv.push_back("-l"+lib->get_libname());
+       }
+
+       if(!builder.get_dry_run())
+               FS::mkpath(FS::dirname(bin.get_path()), 0755);
+
+       return new ExternalTask(argv, work_dir);
+}
diff --git a/source/gnulinker.h b/source/gnulinker.h
new file mode 100644 (file)
index 0000000..6268944
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef GNULINKER_H_
+#define GNULINKER_H_
+
+#include "tool.h"
+
+class GnuLinker: public Tool
+{
+public:
+       GnuLinker(Builder &);
+
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
+};
+
+#endif
index bfda555cda9269c962c2d683d1eae5518c7dc9bb..4040d19ed2f3325967331f118afda4ac36cef258 100644 (file)
@@ -43,11 +43,6 @@ void Install::check_rebuild()
                mark_rebuild(source.get_name()+" needs rebuilding");
 }
 
-Action *Install::create_action()
-{
-       return new Copy(builder, *package, source.get_path(), path, link);
-}
-
 FS::Path Install::generate_target_path(const FileTarget &tgt, const std::string &loc)
 {
        if(!tgt.get_package())
index 0cc0fb8a178bdcc874389ecbb74f072fa7565902..2eb88d4c8684100f6b3c29ed2571b4b84aadf7c1 100644 (file)
@@ -17,10 +17,10 @@ public:
        Install(Builder &, const SourcePackage &, FileTarget &, const std::string & =std::string());
        virtual const char *get_type() const { return "Install"; }
        FileTarget &get_source() const { return source; }
+       const Msp::FS::Path &get_symlink() const { return link; }
        virtual Target *get_real_target();
 private:
        virtual void check_rebuild();
-       virtual Action *create_action();
 
        static Msp::FS::Path generate_target_path(const FileTarget &i, const std::string &);
 };
diff --git a/source/internalaction.cpp b/source/internalaction.cpp
deleted file mode 100644 (file)
index 2b00afe..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "internalaction.h"
-
-InternalAction::InternalAction(Builder &b):
-       Action(b),
-       worker(0)
-{ }
-
-InternalAction::~InternalAction()
-{
-       delete worker;
-}
-
-int InternalAction::check()
-{
-       if(!worker)  // True for dry run
-       {
-               signal_done.emit();
-               return 0;
-       }
-
-       if(worker->get_done())
-       {
-               signal_done.emit();
-               worker->join();
-               return worker->get_error()?1:0;
-       }
-
-       return -1;
-}
-
-
-InternalAction::Worker::Worker():
-       done(false),
-       error(false)
-{ }
diff --git a/source/internalaction.h b/source/internalaction.h
deleted file mode 100644 (file)
index 60942cd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef INTERNALACTION_H_
-#define INTERNALACTION_H_
-
-#include <msp/core/thread.h>
-#include "action.h"
-
-class InternalAction: public Action
-{
-protected:
-       class Worker: public Msp::Thread
-       {
-       public:
-               bool get_done() const { return done; }
-               bool get_error() const { return error; }
-       protected:
-               bool done;
-               bool error;
-
-               Worker();
-       };
-
-       Worker *worker;
-
-       InternalAction(Builder &);
-public:
-       virtual ~InternalAction();
-
-       virtual int check();
-};
-
-#endif
diff --git a/source/internaltask.cpp b/source/internaltask.cpp
new file mode 100644 (file)
index 0000000..68a5e25
--- /dev/null
@@ -0,0 +1,20 @@
+#include "internaltask.h"
+
+InternalTask::InternalTask(Worker *w):
+       worker(w)
+{ }
+
+InternalTask::~InternalTask()
+{
+       delete worker;
+}
+
+Task::Status InternalTask::check()
+{
+       return worker->get_status();
+}
+
+
+InternalTask::Worker::Worker():
+       status(RUNNING)
+{ }
diff --git a/source/internaltask.h b/source/internaltask.h
new file mode 100644 (file)
index 0000000..ea25ba8
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef INTERNALTASK_H_
+#define INTERNALTASK_H_
+
+#include <msp/core/thread.h>
+#include "task.h"
+
+class InternalTask: public Task
+{
+public:
+       class Worker: public Msp::Thread
+       {
+       protected:
+               Status status;
+
+               Worker();
+
+       public:
+               Status get_status() const { return status; }
+       };
+
+private:
+       Worker *worker;
+
+public:
+       InternalTask(Worker *);
+       ~InternalTask();
+
+       virtual Status check();
+};
+
+#endif
diff --git a/source/link.cpp b/source/link.cpp
deleted file mode 100644 (file)
index 5cee287..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <msp/fs/dir.h>
-#include <msp/fs/utils.h>
-#include "builder.h"
-#include "component.h"
-#include "executable.h"
-#include "install.h"
-#include "link.h"
-#include "objectfile.h"
-#include "package.h"
-#include "sharedlibrary.h"
-#include "staticlibrary.h"
-#include "systemlibrary.h"
-
-using namespace std;
-using namespace Msp;
-
-Link::Link(Builder &b, const Binary &bin):
-       ExternalAction(b)
-{
-       const Component &comp = bin.get_component();
-
-       work_dir = comp.get_package().get_source();
-
-       //XXX Determine whether to use g++ or gcc
-       string tool = "LXX";
-       argv.push_back(builder.get_current_arch().get_tool(tool));
-
-       if(comp.get_type()==Component::LIBRARY || comp.get_type()==Component::MODULE)
-               argv.push_back("-shared");
-       else if(comp.get_package().get_library_mode()==ALL_STATIC)
-               argv.push_back("-static");
-
-       if(const SharedLibrary *lib = dynamic_cast<const SharedLibrary *>(&bin))
-               if(!lib->get_soname().empty())
-                       argv.push_back("-Wl,-soname,"+lib->get_soname());
-
-       const BuildInfo &binfo = comp.get_build_info();
-       for(list<string>::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i)
-               argv.push_back(*i);
-       for(list<string>::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
-               argv.push_back("-L"+*i);
-
-       argv.push_back("-o");
-       argv.push_back(relative(bin.get_path(), work_dir).str());
-       const TargetList &deps = bin.get_depends();
-       for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
-       {
-               Target *tgt = (*i)->get_real_target();
-
-               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(tgt))
-                       argv.push_back(relative(obj->get_path(), work_dir).str());
-               else if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(tgt))
-                       argv.push_back(stlib->get_path().str());
-               else if(Library *lib = dynamic_cast<Library *>(tgt))
-                       argv.push_back("-l"+lib->get_libname());
-       }
-
-       FS::Path binpath = bin.get_path();
-       if(!builder.get_dry_run())
-               FS::mkpath(FS::dirname(binpath), 0755);
-
-       announce(comp.get_package().get_name(), tool, relative(binpath, work_dir).str().substr(2));
-
-       launch();
-}
diff --git a/source/link.h b/source/link.h
deleted file mode 100644 (file)
index ccad294..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef LINK_H_
-#define LINK_H_
-
-#include "externalaction.h"
-
-class Executable;
-
-/**
-Links object files and libraries to produce an executable.
-*/
-class Link: public ExternalAction
-{
-public:
-       Link(Builder &, const Binary &);
-};
-
-#endif
index cb42a8e78edfa6f7fbfe873245f748896c3f9b58..4fb2ee4a87fba7c8c7b4b5d33f4da925a1732053 100644 (file)
@@ -1,7 +1,6 @@
 #include <algorithm>
 #include <msp/fs/utils.h>
 #include "builder.h"
-#include "compile.h"
 #include "component.h"
 #include "install.h"
 #include "objectfile.h"
@@ -63,11 +62,6 @@ void ObjectFile::add_depend(Target *tgt)
        new_deps.push_back(tgt);
 }
 
-Action *ObjectFile::create_action()
-{
-       return new Compile(builder, *this);
-}
-
 FS::Path ObjectFile::generate_target_path(const Component &comp, const string &src)
 {
        const SourcePackage &pkg = comp.get_package();
index 8b58e7a1ae93f14ecd6b4702c47c3b3af785ec19..21483147cfa20cb7dd22b115450baec00e8ed89e 100644 (file)
@@ -34,7 +34,6 @@ private:
        /** Adds a target to the dependency list as well as the new dependencies
        list. */
        void add_depend(Target *);
-       virtual Action *create_action();
 
        static Msp::FS::Path generate_target_path(const Component &, const std::string &);
 };
index 1c7bed3a1eb51e9d79295cd2c1da9bd09a12633e..eb4fad0c3ac9c24e412e2a89e561d9b18b341ebe 100644 (file)
@@ -1,14 +1,10 @@
+#include "builder.h"
 #include "package.h"
 #include "pkgconfig.h"
-#include "pkgconfigaction.h"
 
 PkgConfig::PkgConfig(Builder &b, const SourcePackage &p):
        FileTarget(b, &p, p.get_source()/(p.get_name()+".pc"))
 {
        buildable = true;
-}
-
-Action *PkgConfig::create_action()
-{
-       return new PkgConfigAction(builder, *this);
+       tool = &builder.get_toolchain().get_tool("PCG");
 }
index c196e4f4701ea75b7d52d83c7e6625ff0b465794..4b2505dcefa6213e9ccfef953c878f3771aaf6d4 100644 (file)
@@ -11,9 +11,8 @@ class PkgConfig: public FileTarget
 {
 public:
        PkgConfig(Builder &, const SourcePackage &);
+
        virtual const char *get_type() const { return "PkgConfig"; }
-private:
-       virtual Action *create_action();
 };
 
 #endif
diff --git a/source/pkgconfigaction.cpp b/source/pkgconfigaction.cpp
deleted file mode 100644 (file)
index 33687eb..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <msp/fs/utils.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include "builder.h"
-#include "package.h"
-#include "pkgconfig.h"
-#include "pkgconfigaction.h"
-
-using namespace std;
-using namespace Msp;
-
-PkgConfigAction::PkgConfigAction(Builder &b, const PkgConfig &p):
-       Action(b)
-{
-       const SourcePackage &spkg = *static_cast<const SourcePackage *>(p.get_package());
-
-       announce(spkg.get_name(), "PC", basename(p.get_path()));
-
-       IO::BufferedFile out(p.get_path().str(), IO::M_WRITE);
-       IO::print(out, "prefix=%s\n", builder.get_prefix().str());
-       IO::print(out, "source=%s\n\n", spkg.get_source());
-
-       IO::print(out, "Name: %s\n", spkg.get_name());
-       IO::print(out, "Description: %s\n", spkg.get_description());
-       IO::print(out, "Version: %s\n", spkg.get_version());
-
-       IO::print(out, "Requires:");
-       const PackageList &reqs = spkg.get_requires();
-       for(PackageList::const_iterator i=reqs.begin(); i!=reqs.end(); ++i)
-               if((*i)->get_use_pkgconfig())
-                       IO::print(out, " %s", (*i)->get_name());
-       out.put('\n');
-
-       const BuildInfo &binfo = spkg.get_exported_binfo();
-       IO::print(out, "Libs:");
-       for(StringList::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
-               IO::print(out, " -L%s", prefixify(*i));
-       for(StringList::const_iterator i=binfo.libs.begin(); i!=binfo.libs.end(); ++i)
-               IO::print(out, " -l%s", *i);
-       for(StringList::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i)
-               IO::print(out, " %s", *i);
-       out.put('\n');
-
-       IO::print(out, "Cflags:");
-       for(StringList::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i)
-               IO::print(out, " -I%s", prefixify(*i));
-       for(StringList::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i)
-               IO::print(out, " -D%s", *i);
-       for(StringList::const_iterator i=binfo.cflags.begin(); i!=binfo.cflags.end(); ++i)
-               IO::print(out, " %s", *i);
-       out.put('\n');
-}
-
-int PkgConfigAction::check()
-{
-       signal_done.emit();
-       return 0;
-}
-
-string PkgConfigAction::prefixify(const std::string &path)
-{
-       const string &prefix = builder.get_prefix().str();
-       if(!path.compare(0, prefix.size(), prefix))
-               return "${prefix}"+path.substr(prefix.size());
-       return path;
-}
diff --git a/source/pkgconfigaction.h b/source/pkgconfigaction.h
deleted file mode 100644 (file)
index dc96acd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef PKGCONFIGACTION_H_
-#define PKGCONFIGACTION_H_
-
-#include "action.h"
-
-class PkgConfig;
-
-/**
-Action for building a PkgConfig target.  I just couldn't come up with a less
-lame name...
-*/
-class PkgConfigAction: public Action
-{
-public:
-       PkgConfigAction(Builder &, const PkgConfig &);
-       virtual int check();
-private:
-       std::string prefixify(const std::string &);
-};
-
-#endif
diff --git a/source/pkgconfiggenerator.cpp b/source/pkgconfiggenerator.cpp
new file mode 100644 (file)
index 0000000..708a913
--- /dev/null
@@ -0,0 +1,73 @@
+#include <msp/fs/utils.h>
+#include <msp/io/file.h>
+#include <msp/io/print.h>
+#include "builder.h"
+#include "pkgconfig.h"
+#include "pkgconfiggenerator.h"
+
+using namespace std;
+using namespace Msp;
+
+PkgConfigGenerator::PkgConfigGenerator(Builder &b):
+       Tool(b, "PCG")
+{
+}
+
+Target *PkgConfigGenerator::create_target(const list<Target *> &, const string &) const
+{
+       throw logic_error("Not implemented");
+}
+
+Task *PkgConfigGenerator::run(const Target &target) const
+{
+       const PkgConfig &pkgc = dynamic_cast<const PkgConfig &>(target);
+       Worker *worker = new Worker(pkgc);
+       return new InternalTask(worker);
+}
+
+
+PkgConfigGenerator::Worker::Worker(const PkgConfig &t):
+       target(t)
+{
+       launch();
+}
+
+void PkgConfigGenerator::Worker::main()
+{
+       Builder &builder = target.get_package()->get_builder();
+       const SourcePackage &spkg = dynamic_cast<const SourcePackage &>(*target.get_package());
+
+       IO::BufferedFile out(target.get_path().str(), IO::M_WRITE);
+       IO::print(out, "prefix=%s\n", builder.get_prefix().str());
+       IO::print(out, "source=%s\n\n", spkg.get_source());
+
+       IO::print(out, "Name: %s\n", spkg.get_name());
+       IO::print(out, "Description: %s\n", spkg.get_description());
+       IO::print(out, "Version: %s\n", spkg.get_version());
+
+       IO::print(out, "Requires:");
+       const PackageList &reqs = spkg.get_requires();
+       for(PackageList::const_iterator i=reqs.begin(); i!=reqs.end(); ++i)
+               if((*i)->get_use_pkgconfig())
+                       IO::print(out, " %s", (*i)->get_name());
+       out.put('\n');
+
+       const BuildInfo &binfo = spkg.get_exported_binfo();
+       IO::print(out, "Libs:");
+       for(StringList::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
+               IO::print(out, " -L%s", FS::relative(*i, builder.get_prefix()).str());
+       for(StringList::const_iterator i=binfo.libs.begin(); i!=binfo.libs.end(); ++i)
+               IO::print(out, " -l%s", *i);
+       for(StringList::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i)
+               IO::print(out, " %s", *i);
+       out.put('\n');
+
+       IO::print(out, "Cflags:");
+       for(StringList::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i)
+               IO::print(out, " -I%s", FS::relative(*i, builder.get_prefix()).str());
+       for(StringList::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i)
+               IO::print(out, " -D%s", *i);
+       for(StringList::const_iterator i=binfo.cflags.begin(); i!=binfo.cflags.end(); ++i)
+               IO::print(out, " %s", *i);
+       out.put('\n');
+}
diff --git a/source/pkgconfiggenerator.h b/source/pkgconfiggenerator.h
new file mode 100644 (file)
index 0000000..1f0d99a
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef PKGCONFIGGENERATOR_H_
+#define PKGCONFIGGENERATOR_H_
+
+#include "internaltask.h"
+#include "tool.h"
+
+class PkgConfig;
+
+class PkgConfigGenerator: public Tool
+{
+private:
+       class Worker: public InternalTask::Worker
+       {
+       private:
+               const PkgConfig &target;
+
+       public:
+               Worker(const PkgConfig &);
+
+       private:
+               virtual void main();
+       };
+
+public:
+       PkgConfigGenerator(Builder &);
+
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
+};
+
+#endif
index 71896231e97395417e0b00b50ba9963f15bf27e1..18d86045cdee8092c83e834371603ca93490c5e3 100644 (file)
@@ -22,8 +22,6 @@ public:
        const StringList &get_includes() const { return includes; }
        const Component *get_component() const { return comp; }
        virtual void find_depends();
-private:
-       virtual Action *create_action() { return 0; }
 };
 
 #endif
index b61f70a03333a59256590559c7ad6495fceb94e4..f69f98f85fd141e7e0a386d7be01c6c3bf44780e 100644 (file)
@@ -1,4 +1,3 @@
-#include "archive.h"
 #include "component.h"
 #include "objectfile.h"
 #include "sourcepackage.h"
@@ -16,11 +15,6 @@ StaticLibrary::StaticLibrary(Builder &b, const Component &c, const list<ObjectFi
                add_depend(*i);
 }
 
-Action *StaticLibrary::create_action()
-{
-       return new Archive(builder, *this);
-}
-
 Msp::FS::Path StaticLibrary::generate_target_path(const Component &c)
 {
        return c.get_package().get_out_dir()/("lib"+c.get_name()+".a");
index ae3cbef993f3b5708a91fba7f146c34d31754106..9d0bbadb08dcd268f56b3e143b5b6f00b46884f0 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef STATICLIB_H_
-#define STATICLIB_H_
+#ifndef STATICLIBRARY_H_
+#define STATICLIBRARY_H_
 
 #include "library.h"
 
@@ -16,11 +16,10 @@ private:
 
 public:
        StaticLibrary(Builder &, const Component &, const std::list<ObjectFile *> &);
+
        virtual const char *get_type() const { return "StaticLibrary"; }
        const Component &get_component() const { return comp; }
 private:
-       virtual Action *create_action();
-
        static Msp::FS::Path generate_target_path(const Component &);
 };
 
index f95217f2673a2199383cee4a8d4ec948be49d478..ee647ffa6ce128dd797916ef471e43b7ceb15664 100644 (file)
@@ -10,10 +10,9 @@ class SystemLibrary: public Library
 {
 public:
        SystemLibrary(Builder &, const Msp::FS::Path &);
+
        virtual const char *get_type() const { return "SystemLibrary"; }
 private:
-       virtual Action *create_action() { return 0; }
-
        static std::string extract_libname(const Msp::FS::Path &);
 };
 
index d3301a0dbcb1ae1e3d0bae93689d9400c8c9c772..82330caa9762f34531be65b56fcffcdd2b2eb3f6 100644 (file)
 using namespace std;
 using namespace Msp;
 
-Tar::Tar(Builder &b, const TarBall &t):
-       InternalAction(b),
-       tarball(t)
+Tar::Tar(Builder &b):
+       Tool(b, "TAR")
+{ }
+
+Target *Tar::create_target(const list<Target *> &sources, const string &arg) const
 {
-       string basename = FS::basename(tarball.get_path());
-       announce(tarball.get_package()->get_name(), "TAR ", basename);
-       if(builder.get_verbose()>=2)
-               IO::print("Create %s\n", basename);
+       if(!sources.front()->get_package())
+               throw invalid_argument("Tar::create_target");
+       const SourcePackage &src_pkg = dynamic_cast<const SourcePackage &>(*sources.front()->get_package());
+
+       TarBall *tarball = new TarBall(builder, src_pkg, arg);
+       for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+               tarball->add_depend(*i);
 
-       if(!builder.get_dry_run())
-               worker = new Worker(*this);
+       return tarball;
+}
+
+Task *Tar::run(const Target &target) const
+{
+       const TarBall &tarball = dynamic_cast<const TarBall &>(target);
+       Worker *worker = new Worker(tarball);
+       return new InternalTask(worker);
 }
 
 
-Tar::Worker::Worker(Tar &t):
-       tar(t)
+Tar::Worker::Worker(const TarBall &tb):
+       tarball(tb)
 {
        launch();
 }
 
 void Tar::Worker::main()
 {
-       const FS::Path &pkg_src = tar.tarball.get_package()->get_source();
-       FS::Path basedir = FS::basepart(FS::basename(tar.tarball.get_path()));
+       const FS::Path &pkg_src = tarball.get_package()->get_source();
+       FS::Path basedir = FS::basepart(FS::basename(tarball.get_path()));
 
-       IO::File out(tar.tarball.get_path().str(), IO::M_WRITE);
-       const TargetList &deps = tar.tarball.get_depends();
+       IO::File out(tarball.get_path().str(), IO::M_WRITE);
+       const TargetList &deps = tarball.get_depends();
        for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
        {
                FileTarget *ft = dynamic_cast<FileTarget *>(*i);
@@ -51,8 +62,8 @@ void Tar::Worker::main()
                if(rel_path.size()>99)
                {
                        IO::print("Can't store %s in tar archive - too long name\n", rel_path);
-                       error = true;
-                       break;
+                       status = Task::ERROR;
+                       return;
                }
 
                memcpy(buf, rel_path.data(), rel_path.size());
@@ -82,7 +93,7 @@ void Tar::Worker::main()
                }
        }
 
-       done = true;
+       status = Task::SUCCESS;
 }
 
 void Tar::Worker::store_number(char *buf, unsigned value, unsigned length)
index 250b5ffae1b60392f1848c8924baf43b64c70787..c11587ecbf1ba17cfe35e5928dc47720c01c21fd 100644 (file)
@@ -2,30 +2,32 @@
 #define TAR_H_
 
 #include <msp/core/thread.h>
-#include "internalaction.h"
-#include "misc.h"
+#include "internaltask.h"
+#include "tool.h"
 
 class TarBall;
 
-class Tar: public InternalAction
+class Tar: public Tool
 {
 private:
-       class Worker: public InternalAction::Worker
+       class Worker: public InternalTask::Worker
        {
-       public:
-               Worker(Tar &);
        private:
-               Tar &tar;
+               const TarBall &tarball;
+
+       public:
+               Worker(const TarBall &);
 
-               void main();
+       private:
+               virtual void main();
                void store_number(char *, unsigned, unsigned);
        };
 
-       const TarBall &tarball;
-       StringList files;
-
 public:
-       Tar(Builder &, const TarBall &);
+       Tar(Builder &);
+
+       virtual Target *create_target(const std::list<Target *> &, const std::string &) const;
+       virtual Task *run(const Target &) const;
 };
 
 #endif
index 47df5c170560d9d0b197b6852cd3007dc231d049..71e16377ee613cc24be87fce3d9364cf8b18b2a3 100644 (file)
@@ -14,8 +14,3 @@ const SourcePackage *TarBall::get_package() const
 {
        return static_cast<const SourcePackage *>(package);
 }
-
-Action *TarBall::create_action()
-{
-       return new Tar(builder, *this);
-}
index ce8fc1bf13795fe82033a4f59cdff3dda6ffec58..18ff19dcfcd9a8b72cad6f448a42cf7122c53b6b 100644 (file)
@@ -7,10 +7,9 @@ class TarBall: public FileTarget
 {
 public:
        TarBall(Builder &, const SourcePackage &, const std::string &);
+
        virtual const char *get_type() const { return "TarBall"; }
        const SourcePackage *get_package() const;
-private:
-       virtual Action *create_action();
 };
 
 #endif
index f2a1a1372e482489a24a1ce5bbf9de38dae011b6..6ba64717e4272405fb79b8a008df471dd9f57b4c 100644 (file)
@@ -1,10 +1,11 @@
 #include <msp/fs/stat.h>
 #include <msp/fs/utils.h>
-#include "action.h"
 #include "builder.h"
 #include "filetarget.h"
 #include "package.h"
 #include "target.h"
+#include "task.h"
+#include "tool.h"
 
 using namespace std;
 using namespace Msp;
@@ -13,6 +14,7 @@ Target::Target(Builder &b, const Package *p, const string &n):
        builder(b),
        package(p),
        name(n),
+       tool(0),
        buildable(false),
        building(false),
        rebuild(false),
@@ -44,6 +46,11 @@ Target *Target::get_buildable_target()
        return 0;
 }
 
+void Target::set_tool(const Tool &t)
+{
+       tool = &t;
+}
+
 void Target::add_depend(Target *dep)
 {
        if(dep==this)
@@ -70,28 +77,26 @@ void Target::prepare()
        prepared = true;
 }
 
-Action *Target::build()
+Task *Target::build()
 {
        if(!buildable)
        {
                rebuild = false;
                return 0;
        }
+       if(!tool)
+               throw logic_error("buildable && !tool");
 
        // XXX Minor breach of OO here
        if(FileTarget *ft = dynamic_cast<FileTarget *>(this))
                if(!builder.get_dry_run() && FS::exists(ft->get_path()))
                        FS::unlink(ft->get_path());
 
-       Action *action = create_action();
-       if(action)
-       {
-               action->signal_done.connect(sigc::mem_fun(this, &Target::build_done));
-
-               building = true;
-       }
+       Task *task = tool->run(*this);
+       task->signal_finished.connect(sigc::mem_fun(this, &Target::build_finished));
+       building = true;
 
-       return action;
+       return task;
 }
 
 void Target::mark_rebuild(const std::string &reason)
@@ -100,7 +105,7 @@ void Target::mark_rebuild(const std::string &reason)
        rebuild_reason = reason;
 }
 
-void Target::build_done()
+void Target::build_finished(bool /*success*/)
 {
        building = false;
        rebuild = false;
index d971a55bbd46f7dd8a444903a3477c69c02a8a2b..48bd7e4438502e466d2c34770b408e7bb55765ea 100644 (file)
@@ -7,9 +7,10 @@
 #include <string>
 #include <msp/time/timestamp.h>
 
-class Action;
 class Builder;
 class Package;
+class Task;
+class Tool;
 
 class Target;
 typedef std::list<Target *> TargetList;
@@ -25,6 +26,7 @@ protected:
        const Package *package;
        std::string name;
 
+       const Tool *tool;
        bool buildable;
        bool building;
        bool rebuild;
@@ -59,6 +61,9 @@ public:
        */
        virtual Target *get_real_target() { return this; }
 
+       void set_tool(const Tool &);
+       const Tool *get_tool() const { return tool; }
+
        bool is_buildable() const { return buildable; }
        bool get_rebuild() const { return rebuild; }
        const std::string &get_rebuild_reason() const { return rebuild_reason; }
@@ -82,7 +87,7 @@ public:
        /**
        Starts building the target.  Returns the Action used for building.
        */
-       Action *build();
+       Task *build();
 protected:
        void mark_rebuild(const std::string &);
 
@@ -92,14 +97,9 @@ protected:
        virtual void check_rebuild() = 0;
 
        /**
-       Creates and returns an Action suitable for building this target.
-       */
-       virtual Action *create_action() =0;
-
-       /**
-       Handler for the build_done signal of Action.
+       Handler for the build_finished signal of Task.
        */
-       virtual void build_done();
+       virtual void build_finished(bool);
 };
 
 #endif
diff --git a/source/task.h b/source/task.h
new file mode 100644 (file)
index 0000000..d2cf5a4
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef TASK_H_
+#define TASK_H_
+
+#include <sigc++/signal.h>
+
+class Task
+{
+public:
+       enum Status
+       {
+               RUNNING,
+               SUCCESS,
+               ERROR
+       };
+
+       sigc::signal<void, bool> signal_finished;
+
+protected:
+       Task() { }
+public:
+       virtual ~Task() { }
+
+       virtual Status check() = 0;
+};
+
+#endif
diff --git a/source/tool.cpp b/source/tool.cpp
new file mode 100644 (file)
index 0000000..e185849
--- /dev/null
@@ -0,0 +1,21 @@
+#include <algorithm>
+#include "tool.h"
+
+using namespace std;
+
+Tool::Tool(Builder &b, const string &t):
+       builder(b),
+       tag(t)
+{ }
+
+bool Tool::accepts_suffix(const string &suffix) const
+{
+       return find(input_suffixes.begin(), input_suffixes.end(), suffix)!=input_suffixes.end();
+}
+
+Target *Tool::create_target(Target &source, const string &arg) const
+{
+       list<Target *> sources;
+       sources.push_back(&source);
+       return create_target(sources, arg);
+}
diff --git a/source/tool.h b/source/tool.h
new file mode 100644 (file)
index 0000000..1736e1c
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef TOOL_H_
+#define TOOL_H_
+
+#include <list>
+#include <string>
+#include <msp/fs/path.h>
+
+class Builder;
+class Component;
+class Target;
+class Task;
+
+class Tool
+{
+protected:
+       Builder &builder;
+       std::string tag;
+       std::list<std::string> input_suffixes;
+
+       Tool(Builder &, const std::string &);
+
+public:
+       const std::string &get_tag() const { return tag; }
+       const std::list<std::string> &get_input_suffixes() const { return input_suffixes; }
+       bool accepts_suffix(const std::string &) const;
+
+       virtual Target *create_source(const Component &, const Msp::FS::Path &) const { return 0; }
+       Target *create_target(Target &, const std::string & = std::string()) const;
+       virtual Target *create_target(const std::list<Target *> &, const std::string & = std::string()) const = 0;
+       virtual Task *run(const Target &) const = 0;
+};
+
+#endif
diff --git a/source/toolchain.cpp b/source/toolchain.cpp
new file mode 100644 (file)
index 0000000..6c7dae1
--- /dev/null
@@ -0,0 +1,31 @@
+#include <msp/core/maputils.h>
+#include "tool.h"
+#include "toolchain.h"
+
+using namespace std;
+using namespace Msp;
+
+Toolchain::~Toolchain()
+{
+       for(ToolMap::iterator i=tools.begin(); i!=tools.end(); ++i)
+               delete i->second;
+}
+
+void Toolchain::add_tool(Tool *tool)
+{
+       insert_unique(tools, tool->get_tag(), tool);
+}
+
+const Tool &Toolchain::get_tool(const string &tag) const
+{
+       return *get_item(tools, tag);
+}
+
+const Tool *Toolchain::get_tool_for_suffix(const string &suffix) const
+{
+       for(ToolMap::const_iterator i=tools.begin(); i!=tools.end(); ++i)
+               if(i->second->accepts_suffix(suffix))
+                       return i->second;
+
+       return 0;
+}
diff --git a/source/toolchain.h b/source/toolchain.h
new file mode 100644 (file)
index 0000000..1060e09
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef TOOLCHAIN_H_
+#define TOOLCHAIN_H_
+
+#include <map>
+#include <string>
+
+class Tool;
+
+class Toolchain
+{
+private:
+       typedef std::map<std::string, Tool *> ToolMap;
+
+       ToolMap tools;
+
+public:
+       ~Toolchain();
+
+       void add_tool(Tool *);
+       const Tool &get_tool(const std::string &) const;
+       const Tool *get_tool_for_suffix(const std::string &) const;
+};
+
+#endif
diff --git a/source/unlink.cpp b/source/unlink.cpp
deleted file mode 100644 (file)
index 76445f6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <msp/core/systemerror.h>
-#include <msp/fs/utils.h>
-#include "filetarget.h"
-#include "sourcepackage.h"
-#include "unlink.h"
-
-Unlink::Unlink(Builder &b, const FileTarget &t):
-       Action(b)
-{
-       const SourcePackage &spkg = *static_cast<const SourcePackage *>(t.get_package());
-
-       announce(spkg.get_name(), "RM", relative(t.get_path(), spkg.get_source()).str());
-
-       try
-       {
-               unlink(t.get_path());
-       }
-       catch(const Msp::system_error &)
-       { }
-}
-
-int Unlink::check()
-{
-       signal_done.emit();
-       return 0;
-}
diff --git a/source/unlink.h b/source/unlink.h
deleted file mode 100644 (file)
index 8a01156..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef UNLINK_H_
-#define UNLINK_H_
-
-#include "action.h"
-
-class FileTarget;
-
-class Unlink: public Action
-{
-public:
-       Unlink(Builder &, const FileTarget &);
-       virtual int check();
-};
-
-#endif
index 9822e65e89eb0b26301dce5eb87a6c3ea1cd9af2..a7fd8f6cf94d2a7b5718bdc8c20b1e117b03335a 100644 (file)
@@ -13,7 +13,6 @@ public:
        virtual const char *get_type() const { return "VirtualTarget"; }
 private:
        virtual void check_rebuild();
-       virtual Action *create_action() { return 0; }
 };
 
 #endif