]> git.tdb.fi Git - builder.git/commitdiff
Move class PackageRef to its own files
authorMikko Rasa <tdb@tdb.fi>
Mon, 25 Sep 2006 10:58:41 +0000 (10:58 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 25 Sep 2006 10:58:41 +0000 (10:58 +0000)
Implement --dry-run
Add support for alternate build files (--file)
Implement --what-if for a single target
Change default behavior to be no build when analyzing and implement --build to override this
Hash the search paths for get_header and get_library
Add conf_all option
Make bootstrap.sh canonicalize library path

13 files changed:
bootstrap.sh
source/builder.cpp
source/builder.h
source/compile.cpp
source/copy.cpp
source/copy.h
source/externalaction.cpp
source/externalaction.h
source/link.cpp
source/package.cpp
source/package.h
source/packageref.cpp [new file with mode: 0644]
source/packageref.h [new file with mode: 0644]

index cd94382884dd6614cd9daa374acf982092d91ef8..f878935d86726dc797e33cbbf2fca28656844d65 100755 (executable)
@@ -7,6 +7,8 @@ if [ -z "$LIBPATH" ]; then
        LIBPATH=`pwd`/..
 fi
 
+LIBPATH=`readlink -f $LIBPATH`
+
 mkdir -p include/msp
 
 sources=source/*.cpp
index 7ba6be89a55fd03ccc5d570f4a325ff2c0b29300..1917cd42288223796c123ae23797a04734b5e6e4 100644 (file)
@@ -26,6 +26,8 @@ using namespace Msp;
 Builder::Builder(int argc, char **argv):
        verbose(1),
        cwd(Path::getcwd()),
+       build_file("Build"),
+       do_build(true),
        analyzer(0),
        jobs(1),
        chrome(false)
@@ -39,9 +41,10 @@ Builder::Builder(int argc, char **argv):
        getopt.add_option(GetOpt::Option('W', "what-if", GetOpt::REQUIRED));
        getopt.add_option(GetOpt::Option('B', "build-all", GetOpt::NONE));
        getopt.add_option(GetOpt::Option('C', "chdir", GetOpt::REQUIRED));
-       getopt.add_option(GetOpt::Option('j', "jobs", GetOpt::REQUIRED));
+       getopt.add_option(GetOpt::Option('j', "jobs", GetOpt::REQUIRED, "1"));
        getopt.add_option(GetOpt::Option('h', "help", GetOpt::NONE));
        getopt.add_option(GetOpt::Option('c', "clean", GetOpt::NONE));
+       getopt.add_option(GetOpt::Option('f', "file", GetOpt::REQUIRED, "Build"));
        getopt.add_option(GetOpt::Option("chrome", GetOpt::NONE));
        getopt.add_option(GetOpt::Option("full-paths", GetOpt::NONE));
        int index=getopt(argc, argv);
@@ -67,17 +70,22 @@ Builder::Builder(int argc, char **argv):
                if(getopt["max-depth"])
                        analyzer->set_max_depth(strtol(getopt["max-depth"].arg()));
                analyzer->set_full_paths(getopt["full-paths"]);
+
+               if(!getopt['b'])
+                       do_build=false;
        }
 
-       if(getopt['j'])
-               jobs=max(strtol(getopt['j'].arg()), 1L);
+       dry_run=getopt['n'];
+
+       jobs=max(strtol(getopt['j'].arg()), 1L);
 
-       if(getopt["chrome"])
-               chrome=true;
+       chrome=getopt["chrome"];
 
        if(getopt['C'])
                chdir(getopt['C'].arg().c_str());
 
+       build_file=getopt['f'].arg();
+
        for(int i=index; i<argc; ++i)
        {
                string v(argv[i]);
@@ -90,6 +98,9 @@ Builder::Builder(int argc, char **argv):
 
        if(cmdline_targets.empty())
                cmdline_targets.push_back("default");
+
+       if(getopt['W'])
+               what_if.push_back(getopt['W'].arg());
 }
 
 /**
@@ -105,6 +116,7 @@ Package *Builder::get_package(const string &n)
        if(i!=packages.end())
                return i->second;
 
+       // Try to get source directory with pkgconfig
        list<string> argv;
        argv.push_back("pkg-config");
        argv.push_back("--variable=source");
@@ -115,12 +127,14 @@ Package *Builder::get_package(const string &n)
        if(!srcdir.empty())
                dirs.push_back(srcdir);
 
+       // Make some other guesses about the source directory
        string dirname=n;
        if(!dirname.compare(0, 3, "msp"))
                dirname.erase(0, 3);
        dirs.push_back(cwd/dirname);
        dirs.push_back(cwd/".."/dirname);
 
+       // Go through the candidate directories and look for a Build file
        for(PathList::iterator j=dirs.begin(); j!=dirs.end(); ++j)
                if(!load_build_file(*j/"Build"))
                {
@@ -129,7 +143,8 @@ Package *Builder::get_package(const string &n)
                                return i->second;
                        break;
                }
-       
+
+       // Package source not found - create a binary package
        Package *pkg=Package::create(*this, n);
        packages.insert(PackageMap::value_type(n, pkg));
        if(pkg)
@@ -149,10 +164,18 @@ Target *Builder::get_target(const string &n)
        return 0;
 }
 
+/**
+Tries to locate a header included from a given location and with a given include
+path.  Considers known targets as well as existing files.
+*/
 Target *Builder::get_header(const string &include, const string &from, const list<string> &path)
 {
-       //XXX Should really hash the include path here
-       string id=from+":"+include;
+       string hash(8, 0);
+       update_hash(hash, from);
+       for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
+               update_hash(hash, *i);
+
+       string id=hash+include;
        TargetMap::iterator i=includes.find(id);
        if(i!=includes.end())
                return i->second;
@@ -163,6 +186,7 @@ Target *Builder::get_header(const string &include, const string &from, const lis
                return tgt;
        if((tgt=check_header(Path::Path("/usr/include")/fn)))
                return tgt;
+       //XXX Determine the C++ header location dynamically
        if((tgt=check_header(Path::Path("/usr/include/c++/4.1.2")/fn)))
                return tgt;
        for(list<string>::const_iterator j=path.begin(); j!=path.end(); ++j)
@@ -176,13 +200,17 @@ Target *Builder::get_library(const string &lib, const list<string> &path)
 {
        string hash(8, 0);
        for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
-               for(unsigned j=0; j<i->size(); ++j)
-                       hash[j%8]^=(*i)[j];
+               update_hash(hash, *i);
+
+       string id=hash+lib;
+       TargetMap::iterator i=libraries.find(id);
+       if(i!=libraries.end())
+               return i->second;
 
        string basename="lib"+lib+".so";
-       for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
+       for(list<string>::const_iterator j=path.begin(); j!=path.end(); ++j)
        {
-               string full=(Path::Path(*i)/basename).str();
+               string full=(Path::Path(*j)/basename).str();
                Target *tgt=get_target(full);
                if(tgt) return tgt;
                
@@ -198,7 +226,7 @@ Target *Builder::get_library(const string &lib, const list<string> &path)
 
 int Builder::main()
 {
-       if(load_build_file(cwd/"Build"))
+       if(load_build_file(cwd/build_file))
        {
                cerr<<"No build info here.\n";
                return 1;
@@ -206,10 +234,11 @@ int Builder::main()
 
        default_pkg=packages.begin()->second;
 
+       bool conf_all=cmdline_options.count("conf_all");
        while(!new_pkgs.empty())
        {
                Package *pkg=new_pkgs.front();
-               if(pkg==default_pkg)
+               if(pkg==default_pkg || conf_all)
                        pkg->process_options(cmdline_options);
                new_pkgs.erase(new_pkgs.begin());
                pkg->resolve_refs();
@@ -254,7 +283,8 @@ int Builder::main()
        if(analyzer)
                analyzer->analyze();
 
-       build();
+       if(do_build)
+               build();
 
        return exit_code;
 }
@@ -397,6 +427,17 @@ int Builder::create_targets()
                        new_tgts.push_back(tgt);
        }
 
+       for(list<string>::iterator i=what_if.begin(); i!=what_if.end(); ++i)
+       {
+               Target *tgt=get_target((cwd/ *i).str());
+               if(!tgt)
+               {
+                       cerr<<"Unknown what-if target "<<*i<<'\n';
+                       return -1;
+               }
+               tgt->touch();
+       }
+
        Target *cmdline=new VirtualTarget(*this, "cmdline");
        add_target(cmdline);
        world->add_depend(cmdline);
@@ -437,6 +478,16 @@ void Builder::add_target(Target *t)
        new_tgts.push_back(t);
 }
 
+void Builder::update_hash(string &hash, const string &value)
+{
+       for(unsigned i=0; i<value.size(); ++i)
+               hash[i%hash.size()]^=value[i];
+}
+
+/**
+This function supervises the build process, starting new actions when slots
+become available.
+*/
 int Builder::build()
 {
        Target *cmdline=get_target("cmdline");
index 34afb92e91aafccdaef1896042404d251b9da8e9..cff7c4e20aeb25439746f9bea8eed94fc9d96fc0 100644 (file)
@@ -18,6 +18,7 @@ class Builder: public Msp::Application
 public:
        Builder(int, char **);
        unsigned get_verbose() const { return verbose; }
+       bool     get_dry_run() const { return dry_run; }
        Package  *get_package(const std::string &);
        Target   *get_target(const std::string &);
        Target   *get_header(const std::string &, const std::string &, const std::list<std::string> &);
@@ -55,6 +56,9 @@ private:
        ToolMap     tools;
        unsigned    verbose;
        Msp::Path::Path cwd;
+       Msp::Path::Path build_file;
+       bool        do_build;
+       bool        dry_run;
        Analyzer    *analyzer;
        unsigned    jobs;
        std::list<std::string> what_if;
@@ -64,6 +68,7 @@ private:
        int create_targets();
        Target *check_header(const Msp::Path::Path &);
        void add_target(Target *);
+       void update_hash(std::string &, const std::string &);
        int build();
        
        static Msp::Application::RegApp<Builder> reg;
index 15aaee9e800477f30ebf475ca96ff4ce64928ff9..d823c30a5ace4d90aab67ec050e9fa8cc1e2379f 100644 (file)
@@ -1,4 +1,5 @@
 #include <msp/path/utils.h>
+#include "builder.h"
 #include "buildinfo.h"
 #include "compile.h"
 #include "component.h"
@@ -39,7 +40,8 @@ Compile::Compile(Builder &b, const Path::Path &s, const Path::Path &o, const Com
        argv.push_back(object.str());
        argv.push_back(source.str());
 
-       Path::mkpath(object.subpath(0, object.size()-1), 0755);
+       if(!builder.get_dry_run())
+               Path::mkpath(object.subpath(0, object.size()-1), 0755);
 
        announce(comp.get_package().get_name(), tool, relative(object.str(), comp.get_package().get_source()).str());
 
index cdbbd48f1eead0b7c399a4b7ec7ad534252be2c4..1f764dc038045575bb526c44939fcad4ac72add5 100644 (file)
@@ -12,24 +12,36 @@ Copy::Copy(Builder &b, const Package &pkg, const Path::Path &s, const Path::Path
        Action(b),
        src(s),
        dest(d),
-       worker(*this)
+       worker(0)
 {
-       announce(pkg.get_name(), "INST", dest[-1]);
+       announce(pkg.get_name(), "COPY", dest[-1]);
        if(builder.get_verbose()>=2)
                cout<<s<<" -> "<<d<<'\n';
+       
+       if(!builder.get_dry_run())
+               worker=new Worker(*this);
 }
 
 int Copy::check()
 {
-       if(worker.get_done())
+       if(!worker)
+               return 0;
+       
+       if(worker->get_done())
        {
                signal_done.emit();
-               worker.join();
-               return worker.get_error()?1:0;
+               worker->join();
+               return worker->get_error()?1:0;
        }
+       
        return -1;
 }
 
+Copy::~Copy()
+{
+       delete worker;
+}
+
 void Copy::Worker::main()
 {
        Path::mkpath(copy.dest.subpath(0, copy.dest.size()-1), 0755);
index ade21dd2b446e9c06d5afd13f7a72cf8bb518154..018b3de8e6cac0b0df823403353a13568a40284b 100644 (file)
@@ -12,6 +12,7 @@ class Copy: public Action
 public:
        Copy(Builder &, const Package &, const Msp::Path::Path &, const Msp::Path::Path &);
        int check();
+       ~Copy();
 private:
        class Worker: public Msp::Thread
        {
@@ -29,7 +30,7 @@ private:
 
        Msp::Path::Path src;
        Msp::Path::Path dest;
-       Worker worker;
+       Worker *worker;
 };
 
 #endif
index 81d28b37a6a7398fd0b186256c328a912ae87168..7f9e974ebd64ba398424545aeaddb844a5a7ab04 100644 (file)
@@ -8,6 +8,12 @@ using namespace Msp;
 
 int ExternalAction::check()
 {
+       if(builder.get_dry_run())
+       {
+               signal_done.emit();
+               return 0;
+       }
+       
        if(!pid)
                return 255;
 
@@ -16,9 +22,10 @@ int ExternalAction::check()
        {
                signal_done.emit();
                if(WIFEXITED(status))
-                       return WEXITSTATUS(status);
+                       exit_code=WEXITSTATUS(status);
                else
-                       return 254;
+                       exit_code=254;
+               return exit_code;
        }
        else
                return -1;
@@ -37,16 +44,21 @@ void ExternalAction::launch()
                cout<<'\n';
        }
        
-       pid=fork();
-       if(pid==0)
+       if(builder.get_dry_run())
+               pid=-1;
+       else
        {
-               char *argv_[argv.size()+1];
-               for(CountingIterator<string, list<string>::iterator> i=argv.begin(); i!=argv.end(); ++i)
-                       argv_[i.count()]=strdup(i->c_str());
-               argv_[argv.size()]=0;
-               execvp(argv_[0], argv_);
-               exit(1);
+               pid=fork();
+               if(pid==0)
+               {
+                       char *argv_[argv.size()+1];
+                       for(CountingIterator<string, list<string>::iterator> i=argv.begin(); i!=argv.end(); ++i)
+                               argv_[i.count()]=strdup(i->c_str());
+                       argv_[argv.size()]=0;
+                       execvp(argv_[0], argv_);
+                       exit(1);
+               }
+               else if(pid<0)
+                       pid=0;
        }
-       else if(pid<0)
-               pid=0;
 }
index 52eed37e5da12857725d19b128b2f2869dc5cb27..0d0924a966e049777f0afe02bd700d80e9d6e025 100644 (file)
@@ -12,8 +12,9 @@ public:
 protected:
        std::list<std::string> argv;
        int pid;
+       int exit_code;
        
-       ExternalAction(Builder &b): Action(b) { }
+       ExternalAction(Builder &b): Action(b), pid(0), exit_code(0) { }
        void launch();
 };
 
index e2c0f1222a83cb9d7baea296f8fcda4da17c0130..96089da8b58116ee24d95b9d57171bca04d0cd8c 100644 (file)
@@ -1,7 +1,9 @@
 #include <msp/path/utils.h>
+#include "builder.h"
 #include "component.h"
 #include "executable.h"
 #include "link.h"
+#include "objectfile.h"
 #include "package.h"
 
 using namespace std;
@@ -27,10 +29,12 @@ Link::Link(Builder &b, const Executable &exe, const Component &comp):
        argv.push_back(exe.get_name());
        const list<Target *> &deps=exe.get_depends();
        for(list<Target *>::const_iterator i=deps.begin(); i!=deps.end(); ++i)
-               argv.push_back((*i)->get_name());
+               if(dynamic_cast<ObjectFile *>(*i))
+                       argv.push_back((*i)->get_name());
 
        Path::Path epath=exe.get_name();
-       Path::mkpath(epath.subpath(0, epath.size()-1), 0755);
+       if(!builder.get_dry_run())
+               Path::mkpath(epath.subpath(0, epath.size()-1), 0755);
 
        announce(comp.get_package().get_name(), "LINK", relative(epath, comp.get_package().get_source()).str());
 
index 58611800db87bc510db83997daddc0d352499cc0..d937daf7d920a7a5bd760ced3a0ad281184e42a4 100644 (file)
@@ -7,19 +7,6 @@
 using namespace std;
 using namespace Msp;
 
-PackageRef::PackageRef(Builder &b, const string &n):
-       builder(b),
-       name(n),
-       package(0)
-{ }
-
-Package *PackageRef::resolve()
-{
-       if(!package)
-               package=builder.get_package(name);
-       return package;
-}
-
 Package::Package(Builder &b, const string &n, const Path::Path &s):
        builder(b),
        name(n),
index eee157234f6df23b6ec4acbc912bd4bc22e53dee..d5402ef9a168c6563ec01c6e0e573cf1c68cbdfc 100644 (file)
@@ -7,22 +7,9 @@
 #include "buildinfo.h"
 #include "component.h"
 #include "config.h"
+#include "packageref.h"
 
 class Builder;
-class Package;
-
-class PackageRef
-{
-public:
-       PackageRef(Builder &, const std::string &);
-       const std::string &get_name() const { return name; }
-       Package *get_package() const { return package; }
-       Package *resolve();
-private:
-       Builder     &builder;
-       std::string name;
-       Package     *package;
-};
 
 class Package
 {
diff --git a/source/packageref.cpp b/source/packageref.cpp
new file mode 100644 (file)
index 0000000..0f7dc26
--- /dev/null
@@ -0,0 +1,18 @@
+#include "builder.h"
+#include "package.h"
+#include "packageref.h"
+
+using namespace std;
+
+PackageRef::PackageRef(Builder &b, const string &n):
+       builder(b),
+       name(n),
+       package(0)
+{ }
+
+Package *PackageRef::resolve()
+{
+       if(!package)
+               package=builder.get_package(name);
+       return package;
+}
diff --git a/source/packageref.h b/source/packageref.h
new file mode 100644 (file)
index 0000000..bc44da3
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef PACKAGEREF_H_
+#define PACKAGEREF_H_
+
+#include <string>
+
+class Builder;
+class Package;
+
+class PackageRef
+{
+public:
+       PackageRef(Builder &, const std::string &);
+       const std::string &get_name() const { return name; }
+       Package *get_package() const { return package; }
+       Package *resolve();
+private:
+       Builder     &builder;
+       std::string name;
+       Package     *package;
+};
+
+#endif