+++ /dev/null
-#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);
-}
+++ /dev/null
-#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
#include "package.h"
#include "sourcefile.h"
#include "target.h"
+#include "tool.h"
using namespace std;
using namespace Msp;
row.push_back("Name");
row.push_back("Package");
row.push_back("Type");
+ row.push_back("Tool");
row.push_back("Rebuild");
table.push_back(row);
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())
+++ /dev/null
-#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();
-}
+++ /dev/null
-#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
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();
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 &);
#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;
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());
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)))
if(verbose>=5)
IO::print("C++ version is %s\n", cxx_ver);
}
- else
+ else*/
cxx_ver = "-";
}
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;
}
if(verbose>=1)
IO::print("Will build %d target%s\n", total, (total!=1 ? "s" : ""));
- vector<Action *> actions;
+ vector<Task *> tasks;
unsigned count = 0;
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
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;
}
#include "misc.h"
#include "problem.h"
#include "target.h"
+#include "toolchain.h"
class Analyzer;
class Config;
Architecture *current_arch;
StringMap cross_prefixes;
ProfileTemplateMap profile_tmpl;
+ Toolchain toolchain;
ProblemList problems;
Analyzer *analyzer;
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 *);
+++ /dev/null
-#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();
-}
+++ /dev/null
-#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
#include "staticlibrary.h"
#include "tarball.h"
#include "target.h"
+#include "tool.h"
+#include "toolchain.h"
using namespace std;
using namespace Msp;
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))
}
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);
}
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")
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);
}
Target *inst_tgt = builder.get_target("install");
- for(list<FileTarget *>::const_iterator i=inst_list.begin(); i!=inst_list.end(); ++i)
+ const Tool © = 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);
}
}
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);
{
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 &)
- { }
}
#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];
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;
}
#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 ©
+ const Install ⌖
- 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
+++ /dev/null
-#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();
-}
+++ /dev/null
-#ifndef DATACOMPILE_H_
-#define DATACOMPILE_H_
-
-#include "externalaction.h"
-
-class DataFile;
-
-class DataCompile: public ExternalAction
-{
-public:
- DataCompile(Builder &, DataFile &);
-};
-
-#endif
--- /dev/null
+#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");
+}
--- /dev/null
+#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
#include "component.h"
-#include "datacompile.h"
#include "datafile.h"
#include "file.h"
#include "sourcepackage.h"
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");
File &get_source() const { return source; }
private:
- virtual Action *create_action();
static Msp::FS::Path generate_target_path(const Component &);
};
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#include "gnuccompiler.h"
+
+using namespace std;
+using namespace Msp;
+
+GnuCCompiler::GnuCCompiler(Builder &b):
+ GnuCompiler(b, "CC", "gcc")
+{
+ input_suffixes.push_back(".c");
+}
--- /dev/null
+#ifndef GNUCCOMPILER_H_
+#define GNUCCOMPILER_H_
+
+#include "gnucompiler.h"
+
+class GnuCCompiler: public GnuCompiler
+{
+public:
+ GnuCCompiler(Builder &);
+
+};
+
+#endif
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#include "gnucxxcompiler.h"
+
+GnuCxxCompiler::GnuCxxCompiler(Builder &b):
+ GnuCompiler(b, "CXX", "g++")
+{
+ input_suffixes.push_back(".cpp");
+ input_suffixes.push_back(".cc");
+}
--- /dev/null
+#ifndef GNUCXXCOMPILER_H_
+#define GNUCXXCOMPILER_H_
+
+#include "gnucompiler.h"
+
+class GnuCxxCompiler: public GnuCompiler
+{
+public:
+ GnuCxxCompiler(Builder &);
+};
+
+#endif
--- /dev/null
+#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);
+}
--- /dev/null
+#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
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())
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 &);
};
+++ /dev/null
-#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)
-{ }
+++ /dev/null
-#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
--- /dev/null
+#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)
+{ }
--- /dev/null
+#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
+++ /dev/null
-#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();
-}
+++ /dev/null
-#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
#include <algorithm>
#include <msp/fs/utils.h>
#include "builder.h"
-#include "compile.h"
#include "component.h"
#include "install.h"
#include "objectfile.h"
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();
/** 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 &);
};
+#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");
}
{
public:
PkgConfig(Builder &, const SourcePackage &);
+
virtual const char *get_type() const { return "PkgConfig"; }
-private:
- virtual Action *create_action();
};
#endif
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
--- /dev/null
+#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');
+}
--- /dev/null
+#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 ⌖
+
+ 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
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
-#include "archive.h"
#include "component.h"
#include "objectfile.h"
#include "sourcepackage.h"
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");
-#ifndef STATICLIB_H_
-#define STATICLIB_H_
+#ifndef STATICLIBRARY_H_
+#define STATICLIBRARY_H_
#include "library.h"
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 &);
};
{
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 &);
};
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);
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());
}
}
- done = true;
+ status = Task::SUCCESS;
}
void Tar::Worker::store_number(char *buf, unsigned value, unsigned length)
#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
{
return static_cast<const SourcePackage *>(package);
}
-
-Action *TarBall::create_action()
-{
- return new Tar(builder, *this);
-}
{
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
#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;
builder(b),
package(p),
name(n),
+ tool(0),
buildable(false),
building(false),
rebuild(false),
return 0;
}
+void Target::set_tool(const Tool &t)
+{
+ tool = &t;
+}
+
void Target::add_depend(Target *dep)
{
if(dep==this)
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)
rebuild_reason = reason;
}
-void Target::build_done()
+void Target::build_finished(bool /*success*/)
{
building = false;
rebuild = false;
#include <string>
#include <msp/time/timestamp.h>
-class Action;
class Builder;
class Package;
+class Task;
+class Tool;
class Target;
typedef std::list<Target *> TargetList;
const Package *package;
std::string name;
+ const Tool *tool;
bool buildable;
bool building;
bool rebuild;
*/
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; }
/**
Starts building the target. Returns the Action used for building.
*/
- Action *build();
+ Task *build();
protected:
void mark_rebuild(const std::string &);
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
--- /dev/null
+#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
+++ /dev/null
-#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;
-}
+++ /dev/null
-#ifndef UNLINK_H_
-#define UNLINK_H_
-
-#include "action.h"
-
-class FileTarget;
-
-class Unlink: public Action
-{
-public:
- Unlink(Builder &, const FileTarget &);
- virtual int check();
-};
-
-#endif
virtual const char *get_type() const { return "VirtualTarget"; }
private:
virtual void check_rebuild();
- virtual Action *create_action() { return 0; }
};
#endif