]> git.tdb.fi Git - builder.git/commitdiff
Adjust requires to library changes
authorMikko Rasa <tdb@tdb.fi>
Tue, 12 Jun 2007 18:35:12 +0000 (18:35 +0000)
committerMikko Rasa <tdb@tdb.fi>
Tue, 12 Jun 2007 18:35:12 +0000 (18:35 +0000)
Get rid of msp/algo.h
Add support for features and conditionals
Fix static library ordering
Implement cleaning
Use arch in finding system headers and libraries
Only put cflags, incpath and defines in export_binfo

20 files changed:
Build
bootstrap.sh
source/builder.cpp
source/builder.h
source/buildinfo.cpp
source/component.cpp
source/condition.cpp [new file with mode: 0644]
source/condition.h [new file with mode: 0644]
source/config.cpp
source/executable.cpp
source/externalaction.cpp
source/feature.h [new file with mode: 0644]
source/misc.cpp
source/objectfile.cpp
source/package.cpp
source/package.h
source/sourcefile.cpp
source/target.h
source/unlink.cpp [new file with mode: 0644]
source/unlink.h [new file with mode: 0644]

diff --git a/Build b/Build
index 8c59e73272cf69ef1dcf2556fde836d9d2eac352..cf9f0547b3f2e019595867c8bb115740d79245b5 100644 (file)
--- a/Build
+++ b/Build
@@ -4,10 +4,9 @@ package "builder"
        description "Mikkosoft Productions software builder";
 
        require "mspcore";
+       require "mspstrings";
        require "mspparser";
        require "msppath";
-       require "mspregex++";
-       require "mspgetopt++";
        require "sigc++-2.0";
 
        program "builder"
index f878935d86726dc797e33cbbf2fca28656844d65..f5ccced293f8ad18e3f623fc3947c02559b40e24 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-REQUIRED="misc core parser path regex++ getopt++"
+REQUIRED="core parser path strings"
 CFLAGS="-Iinclude `pkg-config --cflags sigc++-2.0`"
 LIBS="`pkg-config --libs sigc++-2.0` -lpthread"
 if [ -z "$LIBPATH" ]; then
index 723930a315b3c6e16c9d30192e4847762c5b5a26..5e2588334ca52a735e0b81b314c97674063b6253 100644 (file)
@@ -1,6 +1,6 @@
 #include <fstream>
 #include <iostream>
-#include <msp/progress.h>
+#include <set>
 #include <msp/core/error.h>
 #include <msp/getopt++/getopt++.h>
 #include <msp/parser/parser.h>
@@ -21,6 +21,7 @@
 #include "sharedlibrary.h"
 #include "staticlibrary.h"
 #include "systemlibrary.h"
+#include "unlink.h"
 #include "virtualtarget.h"
 
 using namespace std;
@@ -28,7 +29,8 @@ using namespace Msp;
 
 Builder::Builder(int argc, char **argv):
        analyzer(0),
-       do_build(false),
+       build(false),
+       clean(0),
        dry_run(false),
        help(false),
        verbose(1),
@@ -37,17 +39,18 @@ Builder::Builder(int argc, char **argv):
        jobs(1),
        conf_all(false),
        conf_only(false),
-       build_all(false)
+       build_all(false),
+       create_makefile(false)
 {
        string   analyze_mode;
        string   work_dir;
        bool     full_paths=false;
        unsigned max_depth=5;
-       
+
        GetOpt getopt;
        getopt.add_option('a', "analyze",    analyze_mode, GetOpt::REQUIRED_ARG);
-       getopt.add_option('b', "build",      do_build,     GetOpt::NO_ARG);
-//     getopt.add_option('c', "clean",      clean,        GetOpt::NO_ARG);
+       getopt.add_option('b', "build",      build,        GetOpt::NO_ARG);
+       getopt.add_option('c', "clean",      clean,        GetOpt::NO_ARG);
        getopt.add_option('f', "file",       build_file,   GetOpt::REQUIRED_ARG);
        getopt.add_option('h', "help",       help,         GetOpt::NO_ARG);
        getopt.add_option('j', "jobs",       jobs,         GetOpt::REQUIRED_ARG);
@@ -60,6 +63,7 @@ Builder::Builder(int argc, char **argv):
        getopt.add_option(     "chrome",     chrome,       GetOpt::NO_ARG);
        getopt.add_option(     "conf-only",  conf_only,    GetOpt::NO_ARG);
        getopt.add_option(     "full-paths", full_paths,   GetOpt::NO_ARG);
+       //getopt.add_option(     "makefile",   create_makefile, GetOpt::NO_ARG);
        getopt.add_option(     "max-depth",  max_depth,    GetOpt::REQUIRED_ARG);
        getopt(argc, argv);
 
@@ -81,8 +85,8 @@ Builder::Builder(int argc, char **argv):
                analyzer->set_max_depth(max_depth);
                analyzer->set_full_paths(full_paths);
        }
-       else
-               do_build=true;
+       else if(!clean && !create_makefile)
+               build=true;
 
        const list<string> &args=getopt.get_args();
        for(list<string>::const_iterator i=args.begin(); i!=args.end(); ++i)
@@ -103,8 +107,8 @@ Builder::Builder(int argc, char **argv):
        cwd=Path::getcwd();
 
        archs.insert(StringMap::value_type("native", ""));
-       archs.insert(StringMap::value_type("arm", "arm-linux-gnu-"));
-       archs.insert(StringMap::value_type("win32", "i586-mingw32msvc-"));
+       archs.insert(StringMap::value_type("arm", "arm-linux-gnu"));
+       archs.insert(StringMap::value_type("win32", "i586-mingw32msvc"));
 
        StringMap &native_tools=tools.insert(ToolMap::value_type("native", StringMap())).first->second;
        native_tools.insert(StringMap::value_type("CC",   "gcc"));
@@ -125,10 +129,11 @@ Builder::Builder(int argc, char **argv):
        {
                if(i->first=="native")
                        continue;
-               
+
                StringMap &arch_profile=profile_tmpl.insert(ProfileTemplateMap::value_type(i->first, StringMap())).first->second;
                arch_profile.insert(StringMap::value_type("arch",   i->first));
                arch_profile.insert(StringMap::value_type("prefix", "$HOME/local/$arch"));
+               arch_profile.insert(StringMap::value_type("outdir", "$profile"));
        }
 }
 
@@ -151,7 +156,7 @@ Package *Builder::get_package(const string &n)
        argv.push_back("--variable=source");
        argv.push_back(n);
        string srcdir=strip(run_command(argv));
-       
+
        PathList dirs;
        if(!srcdir.empty())
                dirs.push_back(srcdir);
@@ -199,7 +204,7 @@ path.  Considers known targets as well as existing files.  If a matching target
 is not found but a file exists, a new SystemHeader target will be created and
 returned.
 */
-Target *Builder::get_header(const string &include, const string &from, const list<string> &path)
+Target *Builder::get_header(const string &include, const string &, const string &from, const list<string> &path)
 {
        string hash(8, 0);
        update_hash(hash, from);
@@ -227,7 +232,7 @@ Target *Builder::get_header(const string &include, const string &from, const lis
        }
 
        includes.insert(TargetMap::value_type(id, tgt));
-       
+
        return tgt;
 }
 
@@ -242,7 +247,7 @@ a new SystemLibrary target will be created and returned.
 
 @return  Some kind of library target, if a match was found
 */
-Target *Builder::get_library(const string &lib, const list<string> &path, LibMode mode)
+Target *Builder::get_library(const string &lib, const string &arch, const list<string> &path, LibMode mode)
 {
        string hash(8, 0);
        for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
@@ -254,16 +259,20 @@ Target *Builder::get_library(const string &lib, const list<string> &path, LibMod
        if(i!=libraries.end())
                return i->second;
 
-       Target *tgt=0;
-       if((tgt=get_library(lib, "/lib", mode)))
-               ;
-       else if((tgt=get_library(lib, "/usr/lib", mode)))
-               ;
-       else
+       StringList syspath;
+       if(arch=="native")
        {
-               for(list<string>::const_iterator j=path.begin(); (j!=path.end() && !tgt); ++j)
-                       tgt=get_library(lib, cwd/ *j, mode);
+               syspath.push_back("/lib");
+               syspath.push_back("/usr/lib");
        }
+       else
+               syspath.push_back("/usr/"+get_arch_prefix(arch)+"/lib");
+
+       Target *tgt=0;
+       for(StringList::iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
+               tgt=get_library(lib, arch, *j, mode);
+       for(StringList::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
+               tgt=get_library(lib, arch, cwd/ *j, mode);
 
        libraries.insert(TargetMap::value_type(id, tgt));
 
@@ -295,7 +304,7 @@ string Builder::get_tool(const std::string &tool, const std::string &arch)
        if(j==i->second.end())
                throw InvalidParameterValue("Unknown tool");
 
-       return get_arch_prefix(arch)+j->second;
+       return get_arch_prefix(arch)+"-"+j->second;
 }
 
 void Builder::apply_profile_template(Config &config, const string &pt) const
@@ -397,8 +406,12 @@ int Builder::main()
        if(analyzer)
                analyzer->analyze();
 
-       if(do_build)
-               build();
+       //if(create_makefile
+
+       if(clean)
+               exit_code=do_clean();
+       else if(build)
+               exit_code=do_build();
 
        return exit_code;
 }
@@ -416,7 +429,7 @@ void Builder::usage(const char *reason, const char *argv0, bool brief)
 {
        if(reason)
                cerr<<reason<<'\n';
-       
+
        if(brief)
                cerr<<"Usage: "<<argv0<<" [-a|--analyze MODE] [-b|--build] [-c|--clean] [-f|--file FILE] [-h|--help] [-j|--jobs NUM] [-n||--dry-run] [-v|--verbose] [-A|--conf-all] [-B|--build-all] [-C|--chdir DIRECTORY] [-W|--what-if FILE] [--chrome] [--conf-only] [--full-paths] [--max-depth NUM] [<target> ...]";
        else
@@ -440,6 +453,7 @@ void Builder::usage(const char *reason, const char *argv0, bool brief)
                        "  --chrome            Use extra chrome to print status.\n"
                        "  --conf-only         Stop after configuring packages.\n"
                        "  --full-paths        Output full paths in analysis.\n"
+                       //"  --makefile          Create a makefile for this package.\n"
                        "  --max-depth NUM     Maximum depth to show in analysis.\n";
        }
 }
@@ -515,7 +529,7 @@ int Builder::create_targets()
                        }
 
                        bool build_exe=j->get_type()!=Component::HEADERS;
-                       
+
                        list<ObjectFile *> objs;
                        for(PathList::iterator k=files.begin(); k!=files.end(); ++k)
                        {
@@ -563,7 +577,7 @@ int Builder::create_targets()
                                }
                                else
                                        exe=new Executable(*this, *j, objs);
-                               
+
                                add_target(exe);
                                if(i->second==default_pkg)
                                {
@@ -671,28 +685,49 @@ Target *Builder::get_header(const Msp::Path::Path &fn)
        return 0;
 }
 
-Target *Builder::get_library(const string &lib, const Path::Path &path, LibMode mode)
+Target *Builder::get_library(const string &lib, const string &arch, const Path::Path &path, LibMode mode)
 {
-       string full;
-       if(mode!=DYNAMIC)
-       {
-               full=(path/("lib"+lib+".a")).str();
-               Target *tgt=get_target(full);
-               // Targets can only be associated with buildable packages (or no package at all)
-               if(tgt && (tgt->get_package() || mode==ALL_STATIC)) return tgt;
-       }
+       // Populate a list of candidate filenames
+       StringList candidates;
+
        if(mode!=ALL_STATIC)
        {
-               full=(path/("lib"+lib+".so")).str();
-               Target *tgt=get_target(full);
-               if(tgt) return tgt;
+               if(arch=="win32")
+                       candidates.push_back("lib"+lib+".dll");
+               else
+                       candidates.push_back("lib"+lib+".so");
        }
 
-       if(Path::exists(full))
+       /* Static libraries are always considered, since sometimes shared versions
+       may not be available */
+       candidates.push_back("lib"+lib+".a");
+       if(arch=="win32")
+               candidates.push_back("lib"+lib+".dll.a");
+
+       for(StringList::iterator i=candidates.begin(); i!=candidates.end(); ++i)
        {
-               Target *tgt=new SystemLibrary(*this, full);
-               add_target(tgt);
-               return tgt;
+               string full=(path/ *i).str();
+               Target *tgt=get_target(full);
+
+               if(tgt)
+               {
+                       Target *real_tgt=tgt;
+                       if(dynamic_cast<Install *>(tgt))
+                               real_tgt=real_tgt->get_depends().front();
+
+                       /* Ignore dynamic libraries from local packages unless library mode is
+                       DYNAMIC */
+                       if(dynamic_cast<SharedLibrary *>(real_tgt) && mode!=DYNAMIC)
+                               continue;
+                       else if(tgt)
+                               return tgt;
+               }
+               else if(Path::exists(full))
+               {
+                       tgt=new SystemLibrary(*this, full);
+                       add_target(tgt);
+                       return tgt;
+               }
        }
 
        return 0;
@@ -720,7 +755,7 @@ void Builder::update_hash(string &hash, const string &value)
 This function supervises the build process, starting new actions when slots
 become available.
 */
-int Builder::build()
+int Builder::do_build()
 {
        Target *cmdline=get_target("cmdline");
 
@@ -790,7 +825,43 @@ int Builder::build()
        if(fail)
                cout<<"Build failed\n";
 
-       return fail?-1:0;
+       return fail?1:0;
+}
+
+/**
+Cleans buildable targets.  If clean is 1, cleans only this package.  If
+clean is 2 or greater, cleans all buildable packages.
+*/
+int Builder::do_clean()
+{
+       // Cleaning doesn't care about ordering, so a simpler method can be used
+
+       set<Target *> clean_tgts;
+       TargetList queue;
+       queue.push_back(get_target("cmdline"));
+
+       while(!queue.empty())
+       {
+               Target *tgt=queue.front();
+               queue.erase(queue.begin());
+
+               if(tgt->get_buildable() && (tgt->get_package()==default_pkg || clean>=2))
+                       clean_tgts.insert(tgt);
+
+               const TargetList &deps=tgt->get_depends();
+               for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+                       if(!clean_tgts.count(*i))
+                               queue.push_back(*i);
+       }
+
+       for(set<Target *>::iterator i=clean_tgts.begin(); i!=clean_tgts.end(); ++i)
+       {
+               Action *action=new Unlink(*this, **i);
+               while(action->check()<0);
+               delete action;
+       }
+
+       return 0;
 }
 
 /**
index 385468210fc2590b433d6d426075dadc73a98224..6985db8cef39697864a60e74801f82e13f64c00f 100644 (file)
@@ -27,8 +27,8 @@ public:
        bool     get_build_all() const { return build_all; }
        Package  *get_package(const std::string &);
        Target   *get_target(const std::string &);
-       Target   *get_header(const std::string &, const std::string &, const StringList &);
-       Target   *get_library(const std::string &, const StringList &, LibMode);
+       Target   *get_header(const std::string &, const std::string &, const std::string &, const StringList &);
+       Target   *get_library(const std::string &, const std::string &, const StringList &, LibMode);
        const Msp::Path::Path &get_cwd() const { return cwd; }
        const std::string &get_arch_prefix(const std::string &) const;
        std::string get_tool(const std::string &, const std::string &);
@@ -45,7 +45,7 @@ private:
        private:
                Builder         &bld;
                Msp::Path::Path src;
-               
+
                void package(const std::string &);
        };
 
@@ -54,11 +54,11 @@ private:
        typedef std::map<std::string, Target *>    TargetMap;
        typedef std::map<std::string, StringMap>   ToolMap;
        typedef std::map<std::string, StringMap>   ProfileTemplateMap;
-       
+
        StringList   cmdline_targets;
        StringMap    cmdline_options;
        Msp::Path::Path cwd;
-       
+
        PackageMap   packages;
        PackageList  new_pkgs;
        Package      *default_pkg;
@@ -71,9 +71,10 @@ private:
        ToolMap      tools;    //< arch, tool name -> program name
        StringMap    archs;    //< arch -> prefix
        ProfileTemplateMap profile_tmpl;
-       
+
        Analyzer        *analyzer;
-       bool            do_build;
+       bool            build;
+       unsigned        clean;
        bool            dry_run;
        bool            help;
        unsigned        verbose;
@@ -84,16 +85,19 @@ private:
        bool            conf_all;
        bool            conf_only;
        bool            build_all;
+       bool            create_makefile;
 
        int    load_build_file(const Msp::Path::Path &);
        int    create_targets();
        Target *get_header(const Msp::Path::Path &);
-       Target *get_library(const std::string &, const Msp::Path::Path &, LibMode);
+       Target *get_library(const std::string &, const std::string &, const Msp::Path::Path &, LibMode);
        void   add_target(Target *);
        void   update_hash(std::string &, const std::string &);
-       int    build();
+       int    do_build();
+       int    do_clean();
+       int    do_create_makefile();
        void   package_help();
-       
+
        static Msp::Application::RegApp<Builder> reg;
 };
 
index de111e935303bfc2c055fd3617dface673cbd4d3..2b4876fbda871c38d6281a49497539f2b7d54236 100644 (file)
@@ -1,4 +1,3 @@
-#include <msp/algo.h>
 #include "buildinfo.h"
 
 using namespace Msp;
@@ -37,7 +36,7 @@ void BuildInfo::unique(StringList &l)
 {
        StringList l2;
        for(StringList::iterator i=l.begin(); i!=l.end(); ++i)
-               if(!contains(l2, *i))
+               if(find(l2.begin(), l2.end(), *i)==l2.end())
                        l2.push_back(*i);
        swap(l, l2);
 }
index 27a4c53c08805db4e23e2bdbbb186ba9c6ca018d..fdc0a6d02d572d945dbeb376e6f4a2d63dd217fc 100644 (file)
@@ -1,11 +1,9 @@
-#include <msp/error.h>
+#include <msp/core/error.h>
 #include "component.h"
 #include "package.h"
 
 using namespace std;
 
-#include <iostream>
-
 Component::Component(Package &p, Type t, const string &n):
        pkg(p),
        type(t),
diff --git a/source/condition.cpp b/source/condition.cpp
new file mode 100644 (file)
index 0000000..97e93f1
--- /dev/null
@@ -0,0 +1,71 @@
+#include <msp/strings/utils.h>
+#include "condition.h"
+#include "package.h"
+
+using namespace std;
+using namespace Msp;
+
+#include <iostream>
+
+Condition::Condition(Package &p, const string &expr):
+       pkg(p)
+{
+       vector<string> parts=split(expr);
+
+       for(vector<string>::iterator i=parts.begin(); i!=parts.end(); ++i)
+       {
+               if(*i=="and")
+                       continue;
+               
+               unsigned token=i->find_first_of("=!");
+               if(token==string::npos)
+                       expression.insert(StringMap::value_type(*i, "!0"));
+               else if(token==0 && (*i)[0]=='!')
+                       expression.insert(StringMap::value_type(*i, "=0"));
+               else
+                       expression.insert(StringMap::value_type(i->substr(0, token), i->substr(token)));
+       }
+}
+
+void Condition::resolve_refs()
+{
+       for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
+               i->resolve();
+}
+
+bool Condition::eval()
+{
+       const Config &conf=pkg.get_config();
+
+       bool result=true;
+       for(StringMap::iterator i=expression.begin(); i!=expression.end(); ++i)
+       {
+               bool neg=(i->second[0]=='!');
+               unsigned start=1;
+               if(i->second[1]=='=')
+                       ++start;
+
+               if((conf.get_option(i->first).value==i->second.substr(start))==neg)
+                       result=false;
+       }
+
+       return result;
+}
+
+
+Condition::Loader::Loader(Condition &c):
+       cond(c)
+{
+       add("require",    &Loader::require);
+       add("build_info", &Loader::build_info);
+}
+
+void Condition::Loader::require(const string &pkg)
+{
+       cond.requires.push_back(PackageRef(cond.pkg.get_builder(), pkg));
+}
+
+void Condition::Loader::build_info()
+{
+       load_sub(cond.build_info);
+}
diff --git a/source/condition.h b/source/condition.h
new file mode 100644 (file)
index 0000000..f518aea
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef CONDITION_H_
+#define CONDITION_H_
+
+#include <msp/parser/loader.h>
+#include "buildinfo.h"
+#include "misc.h"
+#include "packageref.h"
+
+class Config;
+
+class Condition
+{
+public:
+       class Loader: public Msp::Parser::Loader
+       {
+       public:
+               Loader(Condition &);
+       private:
+               Condition &cond;
+
+               void require(const std::string &);
+               void build_info();
+       };
+
+       Condition(Package &, const std::string &);
+       const PkgRefList &get_requires() const { return requires; }
+       const BuildInfo  &get_build_info() const { return build_info; }
+       void             resolve_refs();
+       bool             eval();
+private:
+       Package    &pkg;
+       StringMap  expression;
+       PkgRefList requires;
+       BuildInfo  build_info;
+};
+typedef std::list<Condition> ConditionList;
+
+#endif
index afa60e87e45f10fe3a0e0c9780e2c52c9a607741..e7207ce8a249151a112afe6b6a4f393a7de82b9b 100644 (file)
@@ -1,5 +1,5 @@
 #include <fstream>
-#include <msp/error.h>
+#include <msp/core/error.h>
 #include <msp/path/utils.h>
 #include <msp/time/utils.h>
 #include "builder.h"
@@ -172,7 +172,7 @@ void Config::save() const
 
        ofstream out(fn.str().c_str());
        if(!out) return;
-       
+
        for(i=options.begin(); i!=options.end(); ++i)
                out<<"option \""<<i->second.name<<"\" \""<<i->second.value<<"\";\n";
 }
index db8bd11db0b3c832790d3cbdbef4d2f717ad80fd..e632937775abc1b73f3c2a798b21c2eda8a20443 100644 (file)
@@ -1,5 +1,4 @@
 #include <iostream>
-#include <msp/algo.h>
 #include "builder.h"
 #include "component.h"
 #include "executable.h"
@@ -27,7 +26,7 @@ Finds and adds any required libraries to the dependencies.
 void Executable::find_depends()
 {
        LibMode libmode=package->get_library_mode();
-       
+
        list<const Component *> queue;
        list<Target *> dep_libs;
        queue.push_back(&comp);
@@ -35,17 +34,17 @@ void Executable::find_depends()
        {
                const Component *c=queue.front();
                queue.erase(queue.begin());
-               
+
+               const StringList &libpath=c->get_build_info().libpath;
+               const string &arch=c->get_package().get_arch();
+
                const list<string> &libs=c->get_build_info().libs;
                for(StringList::const_iterator i=libs.begin(); i!=libs.end(); ++i)
                {
-                       Target *lib=builder.get_library(*i, c->get_build_info().libpath, libmode);
+                       Target *lib=builder.get_library(*i, arch, libpath, libmode);
                        if(lib)
                        {
-                               if(contains(depends, lib))
-                                       continue;
-
-                               dep_libs.push_front(lib);
+                               dep_libs.push_back(lib);
 
                                if(dynamic_cast<Install *>(lib))
                                        lib=lib->get_depends().front();
@@ -58,8 +57,16 @@ void Executable::find_depends()
                }
        }
 
+       /* Add only the last occurrence of each library to the actual dependencies.
+       This ensures that static library ordering is correct. */
        for(list<Target *>::iterator i=dep_libs.begin(); i!=dep_libs.end(); ++i)
-               add_depend(*i);
+       {
+               bool last=true;
+               for(list<Target *>::iterator j=i; (last && j!=dep_libs.end()); ++j)
+                       last=(j==i || *j!=*i);
+               if(last)
+                       add_depend(*i);
+       }
 
        deps_ready=true;
 }
index 97f6c619f426cb16e50cef20aa170e2008b86ea7..de799e4c550877e91927d8b85bcd5596d2b9b3f0 100644 (file)
@@ -1,6 +1,5 @@
 #include <sys/wait.h>
 #include <iostream>
-#include <msp/iter.h>
 #include "builder.h"
 #include "externalaction.h"
 
@@ -14,7 +13,7 @@ int ExternalAction::check()
                signal_done.emit();
                return 0;
        }
-       
+
        if(!pid)
                return exit_code;
 
@@ -48,7 +47,7 @@ void ExternalAction::launch()
                }
                cout<<'\n';
        }
-       
+
        if(builder.get_dry_run())
                pid=-1;
        else
@@ -57,9 +56,12 @@ void ExternalAction::launch()
                if(pid==0)
                {
                        char *argv_[argv.size()+1];
-                       for(CountingIterator<string, StringList::iterator> i=argv.begin(); i!=argv.end(); ++i)
-                               argv_[i.count()]=strdup(i->c_str());
-                       argv_[argv.size()]=0;
+
+                       unsigned j=0;
+                       for(StringList::iterator i=argv.begin(); i!=argv.end(); ++i)
+                               argv_[j++]=strdup(i->c_str());
+                       argv_[j]=0;
+
                        execvp(argv_[0], argv_);
                        cout<<"Couldn't execute "<<argv.front()<<'\n';
                        exit(1);
diff --git a/source/feature.h b/source/feature.h
new file mode 100644 (file)
index 0000000..a42e825
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef FEATURE_H_
+#define FEATURE_H_
+
+struct Feature
+{
+       std::string name;
+       std::string descr;
+
+       Feature(const std::string &n, const std::string &d): name(n), descr(d) { }
+};
+typedef std::list<Feature> FeatureList;
+
+#endif
index 35953a74efb00b4a1ad1e1979469eecd74427c72..0d7a13de81931dcfb2e5b7e82229d32c9711d5a7 100644 (file)
@@ -1,6 +1,5 @@
 #include <iostream>
 #include <sys/wait.h>
-#include <msp/iter.h>
 #include "misc.h"
 
 using namespace std;
@@ -21,12 +20,16 @@ string run_command(const StringList &argv)
        if(pid==0)
        {
                char *argv_[argv.size()+1];
-               for(CountingIterator<const string, StringList::const_iterator> i=argv.begin(); i!=argv.end(); ++i)
-                       argv_[i.count()]=strdup(i->c_str());
-               argv_[argv.size()]=0;
+
+               unsigned j=0;
+               for(StringList::const_iterator i=argv.begin(); i!=argv.end(); ++i)
+                       argv_[j++]=strdup(i->c_str());
+               argv_[j]=0;
+
                close(pfd[0]);
                dup2(pfd[1], 1);
                dup2(pfd[1], 2);
+
                execvp(argv_[0], argv_);
                ::exit(1);
        }
@@ -48,7 +51,7 @@ string run_command(const StringList &argv)
                                result.append(buf, len);
                }
        }
-       
+
        return result;
 }
 
index 3f4ba2019f32a835449d72ce336f0f08076573d7..02f1ba5cb653aa558cbbb304e9d88d92df5ccfdc 100644 (file)
@@ -1,4 +1,3 @@
-#include <msp/algo.h>
 #include <msp/path/utils.h>
 #include "builder.h"
 #include "compile.h"
@@ -65,11 +64,14 @@ void ObjectFile::find_depends(Target *tgt)
        if(!src)
                return;
 
+       const string &arch=comp.get_package().get_arch();
+       const StringList &incpath=comp.get_build_info().incpath;
+
        const list<string> &includes=src->get_includes();
        for(list<string>::const_iterator i=includes.begin(); i!=includes.end(); ++i)
        {
-               Target *hdr2=builder.get_header(*i, path, comp.get_build_info().incpath);
-               if(hdr2 && !contains(depends, hdr2))
+               Target *hdr2=builder.get_header(*i, arch, path, incpath);
+               if(hdr2 && find(depends.begin(), depends.end(), hdr2)==depends.end())
                        add_depend(hdr2);
        }
 }
index 74dcbaa693a09e0e32969659b193bced835a95f2..49866a71d2442f8aff3fd902c12d52c31aa98554 100644 (file)
@@ -21,7 +21,10 @@ Package::Package(Builder &b, const string &n, const Path::Path &s):
        conf_done(false),
        use_pkgconfig(true),
        need_path(false)
-{ }
+{
+       if(builder.get_verbose()>=4)
+               cout<<"Created buildable package "<<n<<" at "<<s<<'\n';
+}
 
 /**
 Sets the path where the package files were installed.  This is only useful for
@@ -89,6 +92,7 @@ void Package::resolve_refs()
                Package *pkg=i->resolve();
                if(pkg) all_reqs.push_back(pkg);
        }
+
        for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
        {
                i->resolve_refs();
@@ -97,6 +101,15 @@ void Package::resolve_refs()
                        if(j->get_package())
                                all_reqs.push_back(j->get_package());
        }
+
+       for(ConditionList::iterator i=conditions.begin(); i!=conditions.end(); ++i)
+       {
+               i->resolve_refs();
+               const PkgRefList &creqs=i->get_requires();
+               for(PkgRefList::const_iterator j=creqs.begin(); j!=creqs.end(); ++j)
+                       if(j->get_package())
+                               all_reqs.push_back(j->get_package());
+       }
 }
 
 /**
@@ -120,7 +133,7 @@ void Package::configure(const StringMap &opts, unsigned flag)
                        config.select_profile(prof->second);
                else
                        config.select_last_profile();
-                       
+
                if(flag && config.update(opts))
                {
                        if(builder.get_verbose()>=2)
@@ -131,6 +144,14 @@ void Package::configure(const StringMap &opts, unsigned flag)
 
                config.finish();
 
+               for(ConditionList::iterator i=conditions.begin(); i!=conditions.end(); ++i)
+                       if(i->eval())
+                       {
+                               const PkgRefList &reqs=i->get_requires();
+                               requires.insert(requires.end(), reqs.begin(), reqs.end());
+                               build_info.add(i->get_build_info());
+                       }
+
                for(PackageList::iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
                {
                        if((*i)->get_need_path())
@@ -158,13 +179,13 @@ Package *Package::create(Builder &b, const string &name)
        argv.push_back("--libs");
        argv.push_back(name);
        vector<string> info=split(run_command(argv));
-       
+
        bool need_path=false;
        bool use_pkgconfig=true;
        if(info.empty())
        {
                use_pkgconfig=false;
-               
+
                //XXX Put these in an external file
                if(name=="opengl")
                        info.push_back("-lGL");
@@ -176,10 +197,12 @@ Package *Package::create(Builder &b, const string &name)
                        need_path=true;
                else if(name=="devil")
                        info.push_back("-lIL");
+               else if(name=="Xlib")
+                       info.push_back("-lX11");
                else
                        return 0;
        }
-       
+
        Package *pkg=new Package(b, name, info);
        pkg->need_path=need_path;
        pkg->use_pkgconfig=use_pkgconfig;
@@ -206,6 +229,14 @@ Package::Package(Builder &b, const string &n, const vector<string> &info):
                else if(!i->compare(0, 2, "-l"))
                        export_binfo.libs.push_back(i->substr(2));
        }
+
+       if(builder.get_verbose()>=4)
+       {
+               cout<<"Created non-buildable package "<<name<<" with";
+               for(vector<string>::const_iterator i=info.begin(); i!=info.end(); ++i)
+                       cout<<' '<<*i;
+               cout<<'\n';
+       }
 }
 
 /**
@@ -234,9 +265,12 @@ void Package::init_config()
        if(flags&DATA)
                config.add_option("includedir", "$prefix/share",   "Data installation directory");*/
 
-       for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
-               if(i->get_package() && i->get_package()->get_need_path())
-                       config.add_option(i->get_name()+"_path", "", "Path for "+i->get_name());
+       for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i)
+               config.add_option("with_"+i->name, "0", i->descr);
+
+       for(PackageList::const_iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
+               if((*i)->get_need_path())
+                       config.add_option((*i)->get_name()+"_path", "", "Path for "+(*i)->get_name());
 }
 
 /**
@@ -252,11 +286,14 @@ void Package::create_build_info()
                        Package *pkg=i->get_package();
                        if(!pkg)
                                continue;
-                       build_info.add(pkg->get_exported_binfo());
-                       //XXX We probably really only want to pass cflags and defines through
-                       export_binfo.add(pkg->get_exported_binfo());
+                       const BuildInfo &ebi=pkg->get_exported_binfo();
+                       build_info.add(ebi);
+
+                       export_binfo.cflags.insert(export_binfo.cflags.end(), ebi.cflags.begin(), ebi.cflags.end());
+                       export_binfo.incpath.insert(export_binfo.incpath.end(), ebi.incpath.begin(), ebi.incpath.end());
+                       export_binfo.defines.insert(export_binfo.defines.end(), ebi.defines.begin(), ebi.defines.end());
                }
-       
+
                build_info.cflags.push_back("-Wall");
                build_info.cflags.push_back("-Wshadow");
                build_info.cflags.push_back("-Wextra");
@@ -287,6 +324,10 @@ void Package::create_build_info()
                        build_info.defines.push_back("DEBUG");
                }
 
+               for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i)
+                       if(lexical_cast<bool>(config.get_option("with_"+i->name).value))
+                               build_info.cflags.push_back("-DWITH_"+toupper(i->name));
+
                build_info.unique();
 
                for(list<Component>::iterator i=components.begin(); i!=components.end(); ++i)
@@ -314,6 +355,8 @@ Package::Loader::Loader(Package &p):
        add("version",     &Package::version);
        add("description", &Package::description);
        add("require",     &Loader::require);
+       add("feature",     &Loader::feature);
+       add("if",          &Loader::condition);
        add("program",     &Loader::program);
        add("library",     &Loader::library);
        add("module",      &Loader::module);
@@ -326,6 +369,18 @@ void Package::Loader::require(const string &n)
        pkg.requires.push_back(PackageRef(pkg.builder, n));
 }
 
+void Package::Loader::feature(const string &n, const string &d)
+{
+       pkg.features.push_back(Feature(n, d));
+}
+
+void Package::Loader::condition(const string &c)
+{
+       Condition cond(pkg, c);
+       load_sub(cond);
+       pkg.conditions.push_back(cond);
+}
+
 void Package::Loader::program(const string &n)
 {
        Component prog(pkg, Component::PROGRAM, n);
index fdc5aa2f0bc27dd264edc464815507e51c8771a2..75ef358f2c2d675150a10fa04cc546e590f6be5c 100644 (file)
@@ -6,7 +6,9 @@
 #include <msp/parser/loader.h>
 #include "buildinfo.h"
 #include "component.h"
+#include "condition.h"
 #include "config.h"
+#include "feature.h"
 #include "packageref.h"
 
 class Builder;
@@ -41,6 +43,8 @@ public:
                Package &pkg;
                
                void require(const std::string &);
+               void feature(const std::string &, const std::string &);
+               void condition(const std::string &);
                void program(const std::string &);
                void library(const std::string &);
                void module(const std::string &);
@@ -84,8 +88,10 @@ private:
        Msp::Path::Path source;
        PkgRefList    requires;
        PackageList   all_reqs;
+       FeatureList   features;
        BuildInfo     build_info;
        BuildInfo     export_binfo;
+       ConditionList conditions;
        ComponentList components;
        Config        config;
        bool          conf_done;
index c4eea79eee84fa2b4c76d18c5f8e3619746513d9..7be7889974c4733faf923b8be4b9563a4f970d50 100644 (file)
@@ -1,14 +1,13 @@
 #include <fstream>
-#include <msp/regex++/regex++.h>
+#include <msp/strings/regex.h>
 #include "builder.h"
 #include "component.h"
+#include "package.h"
 #include "sourcefile.h"
 
 using namespace std;
 using namespace Msp;
 
-#include <iostream>
-
 SourceFile::SourceFile(Builder &b, const Component *c, const string &n):
        Target(b, c?&c->get_package():0, n),
        comp(c)
@@ -28,12 +27,15 @@ void SourceFile::find_depends()
        string line;
        while(getline(in, line))
                if(RegMatch match=r_include.match(line))
-                       includes.push_back(match[1].str());
+                       includes.push_back(match[1].str);
+
+       const StringList &incpath=comp->get_build_info().incpath;
+       const string &arch=comp->get_package().get_arch();
 
        string path=name.substr(0, name.rfind('/'));
        for(list<string>::iterator i=includes.begin(); i!=includes.end(); ++i)
        {
-               Target *hdr=builder.get_header(*i, path, comp->get_build_info().incpath);
+               Target *hdr=builder.get_header(*i, arch, path, incpath);
                if(hdr)
                        add_depend(hdr);
        }
index fa744ac75f341fef278d9fe953a6654e0e317387..e4fb1f7f6f85ab1c11ab96fa954c983c7b98d9aa 100644 (file)
@@ -21,6 +21,7 @@ class Target
 public:
        const std::string  &get_name() const           { return name; }
        Target             *get_buildable_target();
+       bool               get_buildable() const       { return buildable; }
        bool               get_rebuild() const         { return rebuild; }
        const std::string  &get_rebuild_reason() const { return rebuild_reason; }
        const Msp::Time::TimeStamp &get_mtime() const  { return mtime; }
@@ -31,12 +32,12 @@ public:
        void               add_depend(Target *);
        virtual void       find_depends()              { deps_ready=true; }
        virtual void       prepare();
-       
+
        /**
        Creates and returns an Action suitable for building this target.
        */
        virtual Action     *build()=0;
-       
+
        void               reset_count()               { counted=false; }
        virtual unsigned   count_rebuild();
        void               touch();
diff --git a/source/unlink.cpp b/source/unlink.cpp
new file mode 100644 (file)
index 0000000..4bb9f66
--- /dev/null
@@ -0,0 +1,20 @@
+#include <msp/path/utils.h>
+#include "package.h"
+#include "target.h"
+#include "unlink.h"
+
+Unlink::Unlink(Builder &b, const Target &t):
+       Action(b)
+{
+       const Package &pkg=*t.get_package();
+
+       announce(pkg.get_name(), "RM", relative(t.get_name(), pkg.get_source()).str());
+
+       unlink(t.get_name().c_str());
+}
+
+int Unlink::check()
+{
+       signal_done.emit();
+       return 0;
+}
diff --git a/source/unlink.h b/source/unlink.h
new file mode 100644 (file)
index 0000000..106d11c
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef UNLINK_H_
+#define UNLINK_H_
+
+#include "action.h"
+
+class Target;
+
+class Unlink: public Action
+{
+public:
+       Unlink(Builder &, const Target &);
+       int check();
+};
+
+#endif