From: Mikko Rasa Date: Sun, 8 Apr 2012 16:11:29 +0000 (+0300) Subject: Big rewrite for a more tool-centric approach X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=338eefb513953ae55e8e3614c009c242ba8ad74e;p=builder.git Big rewrite for a more tool-centric approach --- diff --git a/source/action.cpp b/source/action.cpp deleted file mode 100644 index 89cd46b..0000000 --- a/source/action.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#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 index afe4697..0000000 --- a/source/action.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef ACTION_H_ -#define ACTION_H_ - -#include -#include - -class Builder; - -/** -Actions are executed to rebuild targets. -*/ -class Action -{ -public: - /// Emitted when the action has finished - sigc::signal 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 diff --git a/source/analyzer.cpp b/source/analyzer.cpp index d59519c..dd8894c 100644 --- a/source/analyzer.cpp +++ b/source/analyzer.cpp @@ -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 index 6d1d502..0000000 --- a/source/archive.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#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(*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 index e95749e..0000000 --- a/source/archive.h +++ /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 diff --git a/source/binary.cpp b/source/binary.cpp index aa75b45..41db493 100644 --- a/source/binary.cpp +++ b/source/binary.cpp @@ -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(); diff --git a/source/binary.h b/source/binary.h index 7c1a701..5239dc3 100644 --- a/source/binary.h +++ b/source/binary.h @@ -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 &); diff --git a/source/builder.cpp b/source/builder.cpp index 7704a96..57764b7 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -13,19 +13,25 @@ #include #include #include -#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 actions; + vector tasks; unsigned count = 0; @@ -766,36 +771,38 @@ int Builder::do_build() while(!finish) { - if(actions.size()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; icheck(); - 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::iterator i=clean_tgts.begin(); i!=clean_tgts.end(); ++i) if(FileTarget *ft = dynamic_cast(*i)) - { - Action *action = new Unlink(*this, *ft); - while(action->check()<0) ; - delete action; - } + unlink(ft->get_path()); return 0; } diff --git a/source/builder.h b/source/builder.h index 44bf878..25f0645 100644 --- a/source/builder.h +++ b/source/builder.h @@ -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 index 4960d42..0000000 --- a/source/compile.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#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::const_iterator i=binfo.warnings.begin(); i!=binfo.warnings.end(); ++i) - argv.push_back("-W"+*i); - for(list::const_iterator i=binfo.cflags.begin(); i!=binfo.cflags.end(); ++i) - argv.push_back(*i); - for(list::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i) - argv.push_back("-I"+*i); - for(list::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 index 5b55c4e..0000000 --- a/source/compile.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef COMPILE_H_ -#define COMPILE_H_ - -#include -#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 diff --git a/source/component.cpp b/source/component.cpp index c12399f..24dce77 100644 --- a/source/component.cpp +++ b/source/component.cpp @@ -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 inst_list; + PathList source_filenames = collect_source_files(); + list 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 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(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(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 objs; - for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i) + list 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 results; + const Tool &linker = toolchain.get_tool("LINK"); + + list 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::const_iterator i=results.begin(); i!=results.end(); ++i) + for(list::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::const_iterator i=inst_list.begin(); i!=inst_list.end(); ++i) + const Tool © = toolchain.get_tool("CP"); + for(list::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); } } diff --git a/source/config.cpp b/source/config.cpp index afb86ea..a518b63 100644 --- a/source/config.cpp +++ b/source/config.cpp @@ -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 &) - { } } diff --git a/source/copy.cpp b/source/copy.cpp index 8ea7f35..b5ac403 100644 --- a/source/copy.cpp +++ b/source/copy.cpp @@ -7,55 +7,64 @@ #include #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 &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(*sources.front()); + const SourcePackage &pkg = dynamic_cast(*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(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; } diff --git a/source/copy.h b/source/copy.h index bc4c173..6150fad 100644 --- a/source/copy.h +++ b/source/copy.h @@ -3,35 +3,36 @@ #include #include -#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 &, 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 index bec3d4b..0000000 --- a/source/datacompile.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#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 index 7348338..0000000 --- a/source/datacompile.h +++ /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 index 0000000..2f806bf --- /dev/null +++ b/source/datacompiler.cpp @@ -0,0 +1,23 @@ +#include +#include "datacompiler.h" + +using namespace std; + +DataCompiler::DataCompiler(Builder &b): + Tool(b, "DATA") +{ +} + +Target *DataCompiler::create_target(const list &sources, const string &) const +{ + if(sources.size()!=1) + throw invalid_argument("DataCompiler::create_target"); + throw runtime_error("Not implemented"); + //File &source = dynamic_cast(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 index 0000000..e4c8ea2 --- /dev/null +++ b/source/datacompiler.h @@ -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 &, const std::string &) const; + virtual Task *run(const Target &) const; +}; + +#endif diff --git a/source/datafile.cpp b/source/datafile.cpp index afde084..3164d8e 100644 --- a/source/datafile.cpp +++ b/source/datafile.cpp @@ -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"); diff --git a/source/datafile.h b/source/datafile.h index eeaed1a..071a82b 100644 --- a/source/datafile.h +++ b/source/datafile.h @@ -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 index cad9ba8..0000000 --- a/source/externalaction.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include -#include -#include -#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 index 1f830c9..0000000 --- a/source/externalaction.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef EXTERNALACTION_H_ -#define EXTERNALACTION_H_ - -#include -#include -#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 index 0000000..2471666 --- /dev/null +++ b/source/externaltask.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "externaltask.h" + +using namespace std; +using namespace Msp; + +ExternalTask::ExternalTask(const vector &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 cargv(argv.size()+1); + for(unsigned i=0; i(&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 index 0000000..1701313 --- /dev/null +++ b/source/externaltask.h @@ -0,0 +1,21 @@ +#ifndef EXTERNALTASK_H_ +#define EXTERNALTASK_H_ + +#include +#include +#include +#include "task.h" + +class ExternalTask: public Task +{ +private: + int pid; + int exit_code; + +public: + ExternalTask(const std::vector &, const Msp::FS::Path &); + + virtual Status check(); +}; + +#endif diff --git a/source/file.h b/source/file.h index 76c0379..4f5618f 100644 --- a/source/file.h +++ b/source/file.h @@ -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 index 0000000..8eab751 --- /dev/null +++ b/source/gnuarchiver.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#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 &sources, const string &) const +{ + if(sources.empty()) + throw invalid_argument("GnuArchiver::create_target"); + + list objs; + for(list::const_iterator i=sources.begin(); i!=sources.end(); ++i) + { + if(ObjectFile *obj = dynamic_cast(*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(target); + const Component &comp = lib.get_component(); + + vector 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(*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 index 0000000..f1a4b63 --- /dev/null +++ b/source/gnuarchiver.h @@ -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 &, 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 index 0000000..4ff46e8 --- /dev/null +++ b/source/gnuccompiler.cpp @@ -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 index 0000000..918f9bd --- /dev/null +++ b/source/gnuccompiler.h @@ -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 index 0000000..62a7e32 --- /dev/null +++ b/source/gnucompiler.cpp @@ -0,0 +1,65 @@ +#include +#include +#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 &sources, const std::string &) const +{ + if(sources.size()!=1) + throw invalid_argument("GnuCCompiler::create_target"); + SourceFile &source = dynamic_cast(*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(target); + const Component &comp = object.get_component(); + + vector argv; + argv.push_back(name); + argv.push_back("-c"); + + const BuildInfo &binfo = comp.get_build_info(); + for(list::const_iterator i=binfo.warnings.begin(); i!=binfo.warnings.end(); ++i) + argv.push_back("-W"+*i); + for(list::const_iterator i=binfo.cflags.begin(); i!=binfo.cflags.end(); ++i) + argv.push_back(*i); + for(list::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i) + argv.push_back("-I"+*i); + for(list::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 index 0000000..9cdf670 --- /dev/null +++ b/source/gnucompiler.h @@ -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 &, 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 index 0000000..8084a03 --- /dev/null +++ b/source/gnucxxcompiler.cpp @@ -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 index 0000000..bebb7b7 --- /dev/null +++ b/source/gnucxxcompiler.h @@ -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 index 0000000..45cfd7f --- /dev/null +++ b/source/gnulinker.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#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 &sources, const std::string &arg) const +{ + if(sources.empty()) + throw invalid_argument("GnuLinker::create_target"); + list objs; + for(list::const_iterator i=sources.begin(); i!=sources.end(); ++i) + { + if(ObjectFile *obj = dynamic_cast(*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(target); + const SharedLibrary *shlib = dynamic_cast(&bin); + + string command = "gcc"; + + const list &depends = target.get_depends(); + for(list::const_iterator i=depends.begin(); i!=depends.end(); ++i) + if(ObjectFile *obj = dynamic_cast(*i)) + { + const Tool *tool = obj->get_tool(); + if(dynamic_cast(tool)) + command = "g++"; + } + + vector 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::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i) + argv.push_back(*i); + for(list::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(tgt)) + argv.push_back(relative(obj->get_path(), work_dir).str()); + else if(StaticLibrary *stlib = dynamic_cast(tgt)) + argv.push_back(stlib->get_path().str()); + else if(Library *lib = dynamic_cast(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 index 0000000..6268944 --- /dev/null +++ b/source/gnulinker.h @@ -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 &, const std::string &) const; + virtual Task *run(const Target &) const; +}; + +#endif diff --git a/source/install.cpp b/source/install.cpp index bfda555..4040d19 100644 --- a/source/install.cpp +++ b/source/install.cpp @@ -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()) diff --git a/source/install.h b/source/install.h index 0cc0fb8..2eb88d4 100644 --- a/source/install.h +++ b/source/install.h @@ -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 index 2b00afe..0000000 --- a/source/internalaction.cpp +++ /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 index 60942cd..0000000 --- a/source/internalaction.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef INTERNALACTION_H_ -#define INTERNALACTION_H_ - -#include -#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 index 0000000..68a5e25 --- /dev/null +++ b/source/internaltask.cpp @@ -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 index 0000000..ea25ba8 --- /dev/null +++ b/source/internaltask.h @@ -0,0 +1,31 @@ +#ifndef INTERNALTASK_H_ +#define INTERNALTASK_H_ + +#include +#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 index 5cee287..0000000 --- a/source/link.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#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(&bin)) - if(!lib->get_soname().empty()) - argv.push_back("-Wl,-soname,"+lib->get_soname()); - - const BuildInfo &binfo = comp.get_build_info(); - for(list::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i) - argv.push_back(*i); - for(list::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(tgt)) - argv.push_back(relative(obj->get_path(), work_dir).str()); - else if(StaticLibrary *stlib = dynamic_cast(tgt)) - argv.push_back(stlib->get_path().str()); - else if(Library *lib = dynamic_cast(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 index ccad294..0000000 --- a/source/link.h +++ /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 diff --git a/source/objectfile.cpp b/source/objectfile.cpp index cb42a8e..4fb2ee4 100644 --- a/source/objectfile.cpp +++ b/source/objectfile.cpp @@ -1,7 +1,6 @@ #include #include #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(); diff --git a/source/objectfile.h b/source/objectfile.h index 8b58e7a..2148314 100644 --- a/source/objectfile.h +++ b/source/objectfile.h @@ -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 &); }; diff --git a/source/pkgconfig.cpp b/source/pkgconfig.cpp index 1c7bed3..eb4fad0 100644 --- a/source/pkgconfig.cpp +++ b/source/pkgconfig.cpp @@ -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"); } diff --git a/source/pkgconfig.h b/source/pkgconfig.h index c196e4f..4b2505d 100644 --- a/source/pkgconfig.h +++ b/source/pkgconfig.h @@ -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 index 33687eb..0000000 --- a/source/pkgconfigaction.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#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(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 index dc96acd..0000000 --- a/source/pkgconfigaction.h +++ /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 index 0000000..708a913 --- /dev/null +++ b/source/pkgconfiggenerator.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#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 &, const string &) const +{ + throw logic_error("Not implemented"); +} + +Task *PkgConfigGenerator::run(const Target &target) const +{ + const PkgConfig &pkgc = dynamic_cast(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(*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 index 0000000..1f0d99a --- /dev/null +++ b/source/pkgconfiggenerator.h @@ -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 ⌖ + + public: + Worker(const PkgConfig &); + + private: + virtual void main(); + }; + +public: + PkgConfigGenerator(Builder &); + + virtual Target *create_target(const std::list &, const std::string &) const; + virtual Task *run(const Target &) const; +}; + +#endif diff --git a/source/sourcefile.h b/source/sourcefile.h index 7189623..18d8604 100644 --- a/source/sourcefile.h +++ b/source/sourcefile.h @@ -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 diff --git a/source/staticlibrary.cpp b/source/staticlibrary.cpp index b61f70a..f69f98f 100644 --- a/source/staticlibrary.cpp +++ b/source/staticlibrary.cpp @@ -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 &); + 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 &); }; diff --git a/source/systemlibrary.h b/source/systemlibrary.h index f95217f..ee647ff 100644 --- a/source/systemlibrary.h +++ b/source/systemlibrary.h @@ -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 &); }; diff --git a/source/tar.cpp b/source/tar.cpp index d3301a0..82330ca 100644 --- a/source/tar.cpp +++ b/source/tar.cpp @@ -11,33 +11,44 @@ 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 &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(*sources.front()->get_package()); + + TarBall *tarball = new TarBall(builder, src_pkg, arg); + for(list::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(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(*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) diff --git a/source/tar.h b/source/tar.h index 250b5ff..c11587e 100644 --- a/source/tar.h +++ b/source/tar.h @@ -2,30 +2,32 @@ #define TAR_H_ #include -#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 &, const std::string &) const; + virtual Task *run(const Target &) const; }; #endif diff --git a/source/tarball.cpp b/source/tarball.cpp index 47df5c1..71e1637 100644 --- a/source/tarball.cpp +++ b/source/tarball.cpp @@ -14,8 +14,3 @@ const SourcePackage *TarBall::get_package() const { return static_cast(package); } - -Action *TarBall::create_action() -{ - return new Tar(builder, *this); -} diff --git a/source/tarball.h b/source/tarball.h index ce8fc1b..18ff19d 100644 --- a/source/tarball.h +++ b/source/tarball.h @@ -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 diff --git a/source/target.cpp b/source/target.cpp index f2a1a13..6ba6471 100644 --- a/source/target.cpp +++ b/source/target.cpp @@ -1,10 +1,11 @@ #include #include -#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(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; diff --git a/source/target.h b/source/target.h index d971a55..48bd7e4 100644 --- a/source/target.h +++ b/source/target.h @@ -7,9 +7,10 @@ #include #include -class Action; class Builder; class Package; +class Task; +class Tool; class Target; typedef std::list 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 index 0000000..d2cf5a4 --- /dev/null +++ b/source/task.h @@ -0,0 +1,26 @@ +#ifndef TASK_H_ +#define TASK_H_ + +#include + +class Task +{ +public: + enum Status + { + RUNNING, + SUCCESS, + ERROR + }; + + sigc::signal 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 index 0000000..e185849 --- /dev/null +++ b/source/tool.cpp @@ -0,0 +1,21 @@ +#include +#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 sources; + sources.push_back(&source); + return create_target(sources, arg); +} diff --git a/source/tool.h b/source/tool.h new file mode 100644 index 0000000..1736e1c --- /dev/null +++ b/source/tool.h @@ -0,0 +1,33 @@ +#ifndef TOOL_H_ +#define TOOL_H_ + +#include +#include +#include + +class Builder; +class Component; +class Target; +class Task; + +class Tool +{ +protected: + Builder &builder; + std::string tag; + std::list input_suffixes; + + Tool(Builder &, const std::string &); + +public: + const std::string &get_tag() const { return tag; } + const std::list &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 &, 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 index 0000000..6c7dae1 --- /dev/null +++ b/source/toolchain.cpp @@ -0,0 +1,31 @@ +#include +#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 index 0000000..1060e09 --- /dev/null +++ b/source/toolchain.h @@ -0,0 +1,24 @@ +#ifndef TOOLCHAIN_H_ +#define TOOLCHAIN_H_ + +#include +#include + +class Tool; + +class Toolchain +{ +private: + typedef std::map 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 index 76445f6..0000000 --- a/source/unlink.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "filetarget.h" -#include "sourcepackage.h" -#include "unlink.h" - -Unlink::Unlink(Builder &b, const FileTarget &t): - Action(b) -{ - const SourcePackage &spkg = *static_cast(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 index 8a01156..0000000 --- a/source/unlink.h +++ /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 diff --git a/source/virtualtarget.h b/source/virtualtarget.h index 9822e65..a7fd8f6 100644 --- a/source/virtualtarget.h +++ b/source/virtualtarget.h @@ -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