]> git.tdb.fi Git - builder.git/commitdiff
Split class Package into SourcePackage and BinaryPackage
authorMikko Rasa <tdb@tdb.fi>
Sun, 9 Sep 2007 10:10:29 +0000 (10:10 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 9 Sep 2007 10:10:29 +0000 (10:10 +0000)
Load vertain data from a builderrc file

34 files changed:
builderrc [new file with mode: 0644]
source/archive.cpp
source/binarypackage.cpp [new file with mode: 0644]
source/binarypackage.h [new file with mode: 0644]
source/builder.cpp
source/builder.h
source/compile.cpp
source/component.cpp
source/component.h
source/condition.cpp
source/condition.h
source/config.cpp
source/config.h
source/dependencycache.cpp
source/dependencycache.h
source/executable.cpp
source/install.cpp
source/install.h
source/link.cpp
source/objectfile.cpp
source/package.cpp
source/package.h
source/pkgconfig.cpp
source/pkgconfig.h
source/pkgconfigaction.cpp
source/sourcefile.cpp
source/sourcepackage.cpp [new file with mode: 0644]
source/sourcepackage.h [new file with mode: 0644]
source/staticlibrary.cpp
source/tar.cpp
source/tarball.cpp
source/tarball.h
source/target.cpp
source/unlink.cpp

diff --git a/builderrc b/builderrc
new file mode 100644 (file)
index 0000000..6170aec
--- /dev/null
+++ b/builderrc
@@ -0,0 +1,72 @@
+binary_package "opengl"
+{
+       build_info
+       {
+               library "GL";
+       };
+};
+
+binary_package "pthread"
+{
+       build_info
+       {
+               library "pthread";
+       };
+};
+
+binary_package "gmpxx"
+{
+       build_info
+       {
+               library "gmpxx";
+       };
+};
+
+binary_package "fmod4"
+{
+       build_info
+       {
+               incpath "@/api/inc";
+               libpath "@/api/lib";
+               library "fmodex";
+       };
+       need_path true;
+};
+
+binary_package "xlib"
+{
+       build_info
+       {
+               library "X11";
+       };
+};
+
+architecture "arm" "arm-linux-gnu";
+architecture "win32" "i586-mingw32msvc";
+
+profile "debug"
+{
+       option "debug" "1";
+       option "outdir" "$profile";
+};
+
+profile "release"
+{
+       option "optimize" "3";
+       option "strip" "1";
+       option "outdir" "$profile";
+};
+
+profile "win32"
+{
+       option "arch" "win32";
+       option "prefix" "$HOME/local/$arch";
+       option "outdir" "$profile";
+};
+
+profile "arm"
+{
+       option "arch" "arm";
+       option "prefix" "$HOME/local/$arch";
+       option "outdir" "$profile";
+};
index b6c9582b5e62502b0e735c24b058c9a474528953..4dee50899f123ad580b5f3f66997527446442fec 100644 (file)
@@ -10,7 +10,7 @@ Distributed under the LGPL
 #include "builder.h"
 #include "component.h"
 #include "objectfile.h"
-#include "package.h"
+#include "sourcepackage.h"
 #include "staticlibrary.h"
 
 using namespace std;
@@ -21,7 +21,7 @@ Archive::Archive(Builder &b, const StaticLibrary &lib):
 {
        const Component &comp=lib.get_component();
 
-       argv.push_back(builder.get_tool("AR", lib.get_package()->get_arch()));
+       argv.push_back(builder.get_tool("AR", comp.get_package().get_arch()));
        argv.push_back("rc");
 
        argv.push_back(lib.get_name());
diff --git a/source/binarypackage.cpp b/source/binarypackage.cpp
new file mode 100644 (file)
index 0000000..c2c1886
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/strings/utils.h>
+#include "binarypackage.h"
+#include "builder.h"
+
+using namespace std;
+using namespace Msp;
+
+BinaryPackage::BinaryPackage(Builder &b, const string &n):
+       Package(b, n),
+       need_path(false)
+{
+       use_pkgconfig=false;
+}
+
+/**
+Sets the path where the package files were installed.  This is only useful if
+the package doesn't use pkg-config.
+*/
+void BinaryPackage::set_path(const Msp::Path::Path &p)
+{
+       path=builder.get_cwd()/p;
+}
+
+void BinaryPackage::create_build_info()
+{
+       for(StringList::iterator i=export_binfo.incpath.begin(); i!=export_binfo.incpath.end(); ++i)
+               if((*i)[0]=='@')
+                       *i=(path/i->substr(1)).str();
+
+       for(StringList::iterator i=export_binfo.libpath.begin(); i!=export_binfo.libpath.end(); ++i)
+               if((*i)[0]=='@')
+                       *i=(path/i->substr(1)).str();
+}
+
+BinaryPackage *BinaryPackage::from_pkgconfig(Builder &builder, const string &name)
+{
+       list<string> argv;
+       argv.push_back("pkg-config");
+       argv.push_back("--silence-errors");
+       argv.push_back("--cflags");
+       argv.push_back("--libs");
+       argv.push_back(name);
+       string info=run_command(argv);
+
+       if(info.empty())
+               return 0;
+
+
+       BinaryPackage *pkg=new BinaryPackage(builder, name);
+       pkg->use_pkgconfig=true;
+       BuildInfo &binfo=pkg->export_binfo;
+
+       vector<string> flags=split(info);
+       for(vector<string>::const_iterator i=flags.begin(); i!=flags.end(); ++i)
+       {
+               if(!i->compare(0, 2, "-I"))
+                       binfo.incpath.push_back(i->substr(2));
+               else if(!i->compare(0, 2, "-D"))
+                       binfo.defines.push_back(i->substr(2));
+               else if(!i->compare(0, 2, "-L"))
+                       binfo.libpath.push_back(i->substr(2));
+               else if(!i->compare(0, 2, "-l"))
+                       binfo.libs.push_back(i->substr(2));
+       }
+
+       return pkg;
+}
+
+
+BinaryPackage::Loader::Loader(BinaryPackage &p):
+       Package::Loader(p)
+{
+       add("need_path", &BinaryPackage::need_path);
+       add("build_info", &Loader::build_info);
+}
+
+void BinaryPackage::Loader::build_info()
+{
+       load_sub(static_cast<BinaryPackage &>(pkg).export_binfo);
+}
diff --git a/source/binarypackage.h b/source/binarypackage.h
new file mode 100644 (file)
index 0000000..b10331b
--- /dev/null
@@ -0,0 +1,41 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef BINARYPACKAGE_H_
+#define BINARYPACKAGE_H_
+
+#include "package.h"
+
+/**
+Represents a package that is installed on the system, but can't be built by
+Builder.
+*/
+class BinaryPackage: public Package
+{
+public:
+       class Loader: public Package::Loader
+       {
+       public:
+               Loader(BinaryPackage &);
+               BinaryPackage &get_object() { return static_cast<BinaryPackage &>(pkg); }
+       private:
+               void build_info();
+       };
+
+       BinaryPackage(Builder &, const std::string &);
+       void set_path(const Msp::Path::Path &);
+       bool get_need_path() const { return need_path; }
+
+       static BinaryPackage *from_pkgconfig(Builder &, const std::string &);
+private:
+       bool need_path;
+       Msp::Path::Path path;
+
+       virtual void create_build_info();
+};
+
+#endif
index 353bc29a74588945142b29b536bfa17e201ec1e7..f10f0eb9cb331eb41f32b2b053786366fdb19b2f 100644 (file)
@@ -17,6 +17,7 @@ Distributed under the LGPL
 #include <msp/time/utils.h>
 #include "action.h"
 #include "analyzer.h"
+#include "binarypackage.h"
 #include "builder.h"
 #include "header.h"
 #include "install.h"
@@ -24,6 +25,7 @@ Distributed under the LGPL
 #include "package.h"
 #include "pkgconfig.h"
 #include "sharedlibrary.h"
+#include "sourcepackage.h"
 #include "systemlibrary.h"
 #include "tarball.h"
 #include "unlink.h"
@@ -33,6 +35,7 @@ using namespace std;
 using namespace Msp;
 
 Builder::Builder(int argc, char **argv):
+       default_pkg(0),
        analyzer(0),
        build(false),
        clean(0),
@@ -112,8 +115,6 @@ 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"));
 
        StringMap &native_tools=tools.insert(ToolMap::value_type("native", StringMap())).first->second;
        native_tools.insert(StringMap::value_type("CC",   "gcc"));
@@ -122,24 +123,9 @@ Builder::Builder(int argc, char **argv):
        native_tools.insert(StringMap::value_type("LDXX", "g++"));
        native_tools.insert(StringMap::value_type("AR",   "ar"));
 
-       StringMap &release_profile=profile_tmpl.insert(ProfileTemplateMap::value_type("release", StringMap())).first->second;
-       release_profile.insert(StringMap::value_type("optimize", "3"));
-       release_profile.insert(StringMap::value_type("outdir",   "$profile"));
-
-       StringMap &debug_profile=profile_tmpl.insert(ProfileTemplateMap::value_type("debug", StringMap())).first->second;
-       debug_profile.insert(StringMap::value_type("debug",  "1"));
-       debug_profile.insert(StringMap::value_type("outdir", "$profile"));
-
-       for(StringMap::iterator i=archs.begin(); i!=archs.end(); ++i)
-       {
-               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"));
-       }
+       const char *home=getenv("HOME");
+       if(home)
+               load_build_file((Path::Path(home)/".builderrc").str());
 }
 
 /**
@@ -184,7 +170,8 @@ Package *Builder::get_package(const string &n)
                }
 
        // Package source not found - create a binary package
-       Package *pkg=Package::create(*this, n);
+       Package *pkg=BinaryPackage::from_pkgconfig(*this, n);
+
        packages.insert(PackageMap::value_type(n, pkg));
        if(pkg)
                new_pkgs.push_back(pkg);
@@ -344,8 +331,6 @@ int Builder::main()
                return 1;
        }
 
-       default_pkg=packages.begin()->second;
-
        while(!new_pkgs.empty())
        {
                Package *pkg=new_pkgs.front();
@@ -366,11 +351,12 @@ int Builder::main()
        StringMap problems;
        for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
        {
+               SourcePackage *spkg=dynamic_cast<SourcePackage *>(i->second);
                string prob;
                if(!i->second)
                        prob="missing";
-               else if(i->second->get_buildable() && i->second->get_arch()!=default_pkg->get_arch())
-                       prob="wrong architecture ("+i->second->get_arch()+")";
+               else if(spkg && spkg->get_arch()!=default_pkg->get_arch())
+                       prob="wrong architecture ("+spkg->get_arch()+")";
                if(!prob.empty())
                        problems.insert(StringMap::value_type(i->first, prob));
        }
@@ -396,7 +382,7 @@ int Builder::main()
                for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
                {
                        cout<<' '<<i->second->get_name();
-                       if(i->second->get_buildable())
+                       if(dynamic_cast<SourcePackage *>(i->second))
                                cout<<'*';
                        unsigned count=0;
                        unsigned ood_count=0;
@@ -486,6 +472,9 @@ int Builder::load_build_file(const Path::Path &fn)
        if(!in)
                return -1;
 
+       if(verbose>=3)
+               cout<<"Reading "<<fn<<'\n';
+
        DataFile::Parser parser(in, fn.str());
        Loader loader(*this, fn.subpath(0, fn.size()-1));
        loader.load(parser);
@@ -514,22 +503,21 @@ int Builder::create_targets()
 
        for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
        {
-               if(!i->second)
-                       continue;
-               if(!i->second->get_buildable())
+               SourcePackage *spkg=dynamic_cast<SourcePackage *>(i->second);
+               if(!spkg)
                        continue;
 
-               const ComponentList &components=i->second->get_components();
+               const ComponentList &components=spkg->get_components();
                for(ComponentList::const_iterator j=components.begin(); j!=components.end(); ++j)
                        j->create_targets();
 
-               if(i->second->get_install_flags()&(Package::LIB|Package::INCLUDE))
+               if(spkg->get_install_flags()&(SourcePackage::LIB|SourcePackage::INCLUDE))
                {
-                       PkgConfig *pc=new PkgConfig(*this, *i->second);
-                       install->add_depend(new Install(*this, *i->second, *pc));
+                       PkgConfig *pc=new PkgConfig(*this, *spkg);
+                       install->add_depend(new Install(*this, *spkg, *pc));
                }
 
-               tarballs->add_depend(new TarBall(*this, *i->second));
+               tarballs->add_depend(new TarBall(*this, *spkg));
        }
 
        // Find dependencies until no new targets are created
@@ -584,7 +572,8 @@ int Builder::create_targets()
        }
 
        for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
-               i->second->get_deps_cache().save();
+               if(SourcePackage *spkg=dynamic_cast<SourcePackage *>(i->second))
+                       spkg->get_deps_cache().save();
 
        return 0;
 }
@@ -802,18 +791,55 @@ void Builder::package_help()
 
 Application::RegApp<Builder> Builder::reg;
 
+
 Builder::Loader::Loader(Builder &b, const Path::Path &s):
        bld(b),
        src(s)
 {
+       add("architecture", &Loader::architecture);
+       add("binary_package", &Loader::binpkg);
+       add("profile", &Loader::profile);
        add("package", &Loader::package);
 }
 
+void Builder::Loader::architecture(const string &a, const string &p)
+{
+       bld.archs.insert(StringMap::value_type(a, p));
+}
+
+void Builder::Loader::binpkg(const string &n)
+{
+       BinaryPackage *pkg=new BinaryPackage(bld, n);
+       load_sub(*pkg);
+       bld.packages.insert(PackageMap::value_type(n, pkg));
+       bld.new_pkgs.push_back(pkg);
+}
+
+void Builder::Loader::profile(const string &n)
+{
+       StringMap prf;
+       load_sub<ProfileLoader>(prf);
+       bld.profile_tmpl.insert(ProfileTemplateMap::value_type(n, prf));
+}
+
 void Builder::Loader::package(const string &n)
 {
-       Package *pkg=new Package(bld, n, src);
+       SourcePackage *pkg=new SourcePackage(bld, n, src);
        load_sub(*pkg);
        bld.packages.insert(PackageMap::value_type(n, pkg));
        bld.new_pkgs.push_back(pkg);
+       if(!bld.default_pkg)
+               bld.default_pkg=pkg;
 }
 
+
+Builder::ProfileLoader::ProfileLoader(StringMap &p):
+       profile(p)
+{
+       add("option", &ProfileLoader::option);
+}
+
+void Builder::ProfileLoader::option(const string &o, const string &v)
+{
+       profile.insert(StringMap::value_type(o, v));
+}
index d2d7598eda39445aa14596d421c67f1e64e27d2a..879781df1cb7d989fa2f248b168c4a54f3644a80 100644 (file)
@@ -21,6 +21,7 @@ Distributed under the LGPL
 class Analyzer;
 class Config;
 class Package;
+class SourcePackage;
 
 /**
 The main application class.  Controls and owns everything.  Rules the world.
@@ -33,7 +34,7 @@ public:
        bool     get_dry_run() const   { return dry_run; }
        bool     get_build_all() const { return build_all; }
        Package  *get_package(const std::string &);
-       Package  *get_default_package() const { return default_pkg; }
+       SourcePackage *get_default_package() const { return default_pkg; }
        Target   *get_target(const std::string &) const;
        const TargetMap &get_targets() const { return targets; }
        Target   *get_header(const std::string &, const std::string &, const std::string &, const StringList &);
@@ -56,9 +57,22 @@ private:
                Builder         &bld;
                Msp::Path::Path src;
 
+               void architecture(const std::string &, const std::string &);
+               void binpkg(const std::string &);
+               void profile(const std::string &);
                void package(const std::string &);
        };
 
+       class ProfileLoader: public Msp::DataFile::Loader
+       {
+       public:
+               ProfileLoader(StringMap &);
+       private:
+               StringMap &profile;
+
+               void option(const std::string &, const std::string &);
+       };
+
        typedef std::list<Package *>               PackageList;
        typedef std::map<std::string, Package *>   PackageMap;
        typedef std::map<std::string, StringMap>   ToolMap;
@@ -70,7 +84,7 @@ private:
 
        PackageMap   packages;
        PackageList  new_pkgs;
-       Package      *default_pkg;
+       SourcePackage *default_pkg;
 
        TargetMap    targets;
        TargetList   new_tgts;
index 67278d16bdb2457efa8694962f909891c58a1baa..d07f3ef4ee3255cbef1d1299a72c13dffad8db00 100644 (file)
@@ -11,7 +11,7 @@ Distributed under the LGPL
 #include "compile.h"
 #include "component.h"
 #include "objectfile.h"
-#include "package.h"
+#include "sourcepackage.h"
 
 using namespace std;
 using namespace Msp;
@@ -31,7 +31,7 @@ Compile::Compile(Builder &b, const ObjectFile &obj):
        else
                tool="CC";
 
-       argv.push_back(builder.get_tool(tool, obj.get_package()->get_arch()));
+       argv.push_back(builder.get_tool(tool, comp.get_package().get_arch()));
        argv.push_back("-c");
        
        const BuildInfo &binfo=comp.get_build_info();
index 6a3796d197abb29f3090cbf9d7d8a89972b3cc60..6272321b56b702b3b730c9ccca53618efab08078 100644 (file)
@@ -7,20 +7,21 @@ Distributed under the LGPL
 
 #include <msp/core/error.h>
 #include <msp/path/utils.h>
+#include <msp/strings/lexicalcast.h>
 #include "builder.h"
 #include "component.h"
 #include "header.h"
 #include "install.h"
 #include "objectfile.h"
-#include "package.h"
 #include "sharedlibrary.h"
+#include "sourcepackage.h"
 #include "staticlibrary.h"
 #include "target.h"
 
 using namespace std;
 using namespace Msp;
 
-Component::Component(Package &p, Type t, const string &n):
+Component::Component(SourcePackage &p, Type t, const string &n):
        pkg(p),
        type(t),
        name(n),
@@ -54,6 +55,13 @@ void Component::create_build_info()
                build_info.add(i->get_package()->get_exported_binfo());
        }
 
+       if(type==PROGRAM)
+       {
+               string strip=pkg.get_config().get_option("strip").value;
+               if(lexical_cast<bool>(strip))
+                       build_info.ldflags.push_back("-s");
+       }
+
        if(modular)
        {
                build_info.ldflags.push_back("-rdynamic");
@@ -80,7 +88,7 @@ void Component::create_targets() const
 
        PathList files=collect_source_files();
 
-       bool build_exe=(type!=Component::HEADERS);
+       bool build_exe=(type!=HEADERS);
 
        list<ObjectFile *> objs;
        list<Target *> inst_tgts;
@@ -112,7 +120,7 @@ void Component::create_targets() const
        {
                Executable    *exe=0;
                StaticLibrary *slib=0;
-               if(type==Component::LIBRARY)
+               if(type==LIBRARY)
                {
                        exe=new SharedLibrary(builder, *this, objs);
                        slib=new StaticLibrary(builder, *this, objs);
index 36cd83e8a800795569c5d3a05d26c330677d37ec..387de4c5814e7bcd907ba5f9ee6b228a9131f0d9 100644 (file)
@@ -15,7 +15,7 @@ Distributed under the LGPL
 #include "misc.h"
 #include "packageref.h"
 
-class Package;
+class SourcePackage;
 
 /**
 Components specify things to be built.  Each component may build one binary (it
@@ -50,8 +50,8 @@ public:
                HEADERS
        };
 
-       Component(Package &, Type, const std::string &);
-       const Package     &get_package() const         { return pkg; }
+       Component(SourcePackage &, Type, const std::string &);
+       const SourcePackage &get_package() const         { return pkg; }
        Type              get_type() const             { return type; }
        const std::string &get_name() const            { return name; }
        const PathList    &get_sources() const         { return sources; }
@@ -65,7 +65,7 @@ public:
        void              create_build_info();
        void              create_targets() const;
 protected:
-       Package     &pkg;
+       SourcePackage &pkg;
        Type        type;
        std::string name;
        PathList    sources;
index b5833e9ea39295fb3539ecb9aa42f506e8ed3b92..c4c01b21fbdf692fc92cb4fe147a4ad58b969a86 100644 (file)
@@ -7,14 +7,12 @@ Distributed under the LGPL
 
 #include <msp/strings/utils.h>
 #include "condition.h"
-#include "package.h"
+#include "sourcepackage.h"
 
 using namespace std;
 using namespace Msp;
 
-#include <iostream>
-
-Condition::Condition(Package &p, const string &expr):
+Condition::Condition(SourcePackage &p, const string &expr):
        pkg(p)
 {
        vector<string> parts=split(expr);
@@ -23,7 +21,7 @@ Condition::Condition(Package &p, const string &expr):
        {
                if(*i=="and")
                        continue;
-               
+
                unsigned token=i->find_first_of("=!");
                if(token==string::npos)
                        expression.insert(StringMap::value_type(*i, "!0"));
index baf718cc43d5755265345235ad7a1bc63d250f30..433c0c8ee431dd8f4d81e8d25d4233a1f6bd2b48 100644 (file)
@@ -14,6 +14,7 @@ Distributed under the LGPL
 #include "packageref.h"
 
 class Config;
+class SourcePackage;
 
 class Condition
 {
@@ -29,13 +30,13 @@ public:
                void build_info();
        };
 
-       Condition(Package &, const std::string &);
+       Condition(SourcePackage &, 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;
+       SourcePackage &pkg;
        StringMap  expression;
        PkgRefList requires;
        BuildInfo  build_info;
index 74c3741466ae33131aa58d76551467c174f25dd6..0e8e6c2c742c29ea52ee887aed7b04f5472b0427 100644 (file)
@@ -11,12 +11,12 @@ Distributed under the LGPL
 #include <msp/time/utils.h>
 #include "builder.h"
 #include "config.h"
-#include "package.h"
+#include "sourcepackage.h"
 
 using namespace std;
 using namespace Msp;
 
-Config::Config(Package &p):
+Config::Config(SourcePackage &p):
        package(p),
        freeze_mtime(false)
 { }
index 1b7f853b21d11312ec3cecaeea0a8e7b21ac7bc6..ba23462c00e53a63196fcb0cb08fdae72fa40d2a 100644 (file)
@@ -15,7 +15,7 @@ Distributed under the LGPL
 #include <msp/time/timestamp.h>
 #include "misc.h"
 
-class Package;
+class SourcePackage;
 
 /**
 Manages configuration for a package.  A configuration may have an arbitary
@@ -38,7 +38,7 @@ public:
        };
        typedef std::map<std::string, Option> OptionMap;
 
-       Config(Package &);
+       Config(SourcePackage &);
        void add_option(const std::string &, const std::string &, const std::string &);
        const Option &get_option(const std::string &) const;
        const OptionMap &get_options() const          { return options; }
@@ -56,11 +56,11 @@ private:
                Loader(Config &);
        private:
                Config &conf;
-               
+
                void option(const std::string &, const std::string &);
        };
 
-       Package         &package;
+       SourcePackage   &package;
        OptionMap       options;
        Msp::Time::TimeStamp mtime;
        bool freeze_mtime;
index cc11383583601e935be062309266c6afe4d2fbb4..0d82d7027baffc66aba49611cfd026c554a7544c 100644 (file)
@@ -10,12 +10,12 @@ Distributed under the LGPL
 #include <msp/strings/utils.h>
 #include "builder.h"
 #include "dependencycache.h"
-#include "package.h"
+#include "sourcepackage.h"
 
 using namespace std;
 using namespace Msp;
 
-DependencyCache::DependencyCache(Package &p):
+DependencyCache::DependencyCache(SourcePackage &p):
        package(p),
        changed(false)
 { }
index 5cde40d919ce0d759a2ab1c862ad0818ce8d912f..f182f31c1a017e6e1f6fe58fcd6ba6929cc0eff1 100644 (file)
@@ -21,7 +21,7 @@ strings as value.  The targets are free to store whatever they want here.
 class DependencyCache
 {
 public:
-       DependencyCache(Package &p);
+       DependencyCache(SourcePackage &p);
        void             set_deps(const std::string &tgt, const StringList &d);
        const StringList &get_deps(const std::string &tgt) const;
        const Msp::Time::TimeStamp &get_mtime() const { return mtime; }
@@ -30,7 +30,7 @@ public:
 private:
        typedef std::map<std::string, StringList> DepsMap;
 
-       Package &package;
+       SourcePackage &package;
        DepsMap deps;
        Msp::Time::TimeStamp mtime;
        bool changed;
index ff1312205af0adf870a8ae040f271900eff5e02c..d1cc59aa174c278dac0c533e12254cbbbf71c5b7 100644 (file)
@@ -32,7 +32,7 @@ Finds and adds any required libraries to the dependencies.
 */
 void Executable::find_depends()
 {
-       LibMode libmode=package->get_library_mode();
+       LibMode libmode=comp.get_package().get_library_mode();
 
        list<const Component *> queue;
        list<Target *> dep_libs;
index e9be68298ee1dddda2ad6c5fd6577e730ddeb144..2cdd1aa1a4a959c6f34f754a273a8b9ffbf5497b 100644 (file)
@@ -18,7 +18,7 @@ Distributed under the LGPL
 using namespace std;
 using namespace Msp;
 
-Install::Install(Builder &b, const Package &p, Target &tgt):
+Install::Install(Builder &b, const SourcePackage &p, Target &tgt):
        Target(b, &p, generate_target_name(tgt))
 {
        buildable=true;
@@ -46,7 +46,9 @@ Action *Install::build()
 
 string Install::generate_target_name(const Target &tgt)
 {
-       Path::Path base=tgt.get_package()->get_prefix();
+       const SourcePackage *spkg=dynamic_cast<const SourcePackage *>(tgt.get_package());
+
+       Path::Path base=spkg->get_prefix();
        string tgtname=tgt.get_name().substr(tgt.get_name().rfind('/')+1);
 
        string mid;
index bdabc6e7c3853afd87d5425ba42f10bf14db25a4..672161580c8ee3b2bc67b5ac5d7d8396c3d62f2b 100644 (file)
@@ -8,6 +8,7 @@ Distributed under the LGPL
 #ifndef INSTALL_H_
 #define INSTALL_H_
 
+#include "sourcepackage.h"
 #include "target.h"
 
 /**
@@ -16,7 +17,7 @@ Represents the installation of a file.
 class Install: public Target
 {
 public:
-       Install(Builder &, const Package &, Target &);
+       Install(Builder &, const SourcePackage &, Target &);
        const char *get_type() const { return "Install"; }
        void       check_rebuild();
        Action     *build();
index 30fecfba29e49eac2fad7037bfd075a9deb618eb..a7ea2c55df4374fc1149fedc0b4eaf4dc922785b 100644 (file)
@@ -26,7 +26,7 @@ Link::Link(Builder &b, const Executable &exe):
        const Component &comp=exe.get_component();
 
        //XXX Determine whether to use g++ or gcc
-       argv.push_back(builder.get_tool("LDXX", exe.get_package()->get_arch()));
+       argv.push_back(builder.get_tool("LDXX", comp.get_package().get_arch()));
        
        if(comp.get_type()==Component::LIBRARY || comp.get_type()==Component::MODULE)
                argv.push_back("-shared");
index 5022bdd0a636774e7ac648c727ea06e2c3b28d34..809e70d40ba769b5ec4e64b00c5ad75557d78dbb 100644 (file)
@@ -11,8 +11,8 @@ Distributed under the LGPL
 #include "component.h"
 #include "install.h"
 #include "objectfile.h"
-#include "package.h"
 #include "sourcefile.h"
+#include "sourcepackage.h"
 
 using namespace std;
 using namespace Msp;
index 8fb2b4dde4ffe8dda0e0b2507aca1174ca7ee968..23a8d9c8e6c73a0b592d0d0de5849419d1df0b0b 100644 (file)
@@ -19,78 +19,12 @@ using namespace Msp;
 /**
 Creates a buildable package.
 */
-Package::Package(Builder &b, const string &n, const Path::Path &s):
+Package::Package(Builder &b, const string &n):
        builder(b),
        name(n),
-       buildable(true),
-       source(s),
-       config(*this),
        conf_done(false),
-       deps_cache(*this),
-       use_pkgconfig(true),
-       need_path(false)
-{
-       tar_files.push_back(source/"Build");
-
-       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
-non-buildable packages that don't use pkg-config.
-*/
-void Package::set_path(const Msp::Path::Path &p)
-{
-       path=builder.get_cwd()/p;
-}
-
-Msp::Path::Path Package::get_temp_dir() const
-{
-       return source/config.get_option("tempdir").value/config.get_option("profile").value;
-}
-
-Msp::Path::Path Package::get_out_dir() const
-{
-       return source/config.get_option("outdir").value;
-}
-
-/**
-Checks which kinds of things the components of this package install.
-
-@return  A bitmask of installed things
-*/
-unsigned Package::get_install_flags()
-{
-       unsigned flags=0;
-       for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
-       {
-               if(i->get_install())
-               {
-                       if(i->get_type()==Component::PROGRAM)
-                               flags|=BIN;
-                       else if(i->get_type()==Component::LIBRARY || i->get_type()==Component::MODULE)
-                               flags|=LIB;
-               }
-               if(!i->get_install_headers().empty())
-                       flags|=INCLUDE;
-       }
-
-       return flags;
-}
-
-LibMode Package::get_library_mode() const
-{
-       const string &mode=config.get_option("staticlibs").value;
-       if(mode=="all")
-               return ALL_STATIC;
-       else if(mode=="local")
-               return LOCAL_STATIC;
-       else if(mode=="none")
-               return DYNAMIC;
-       else
-               throw Exception("Unknown library mode");
-}
+       use_pkgconfig(true)
+{ }
 
 /**
 Tries to resolve all references to dependency packages.
@@ -98,28 +32,7 @@ Tries to resolve all references to dependency packages.
 void Package::resolve_refs()
 {
        for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
-       {
-               Package *pkg=i->resolve();
-               if(pkg) all_reqs.push_back(pkg);
-       }
-
-       for(ComponentList::iterator i=components.begin(); i!=components.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());
-       }
-
-       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());
-       }
+               i->resolve();
 }
 
 /**
@@ -134,302 +47,25 @@ void Package::configure(const StringMap &opts, unsigned flag)
        if(builder.get_verbose()>=3)
                cout<<"Configuring "<<name<<'\n';
 
-       if(buildable)
-       {
-               init_config();
-
-               StringMap::const_iterator prof=opts.find("profile");
-               if(prof!=opts.end() && flag)
-                       config.select_profile(prof->second);
-               else
-                       config.select_last_profile();
-
-               if(flag && config.update(opts))
-               {
-                       if(builder.get_verbose()>=2)
-                               cout<<"Configuration of "<<name<<" changed\n";
-                       if(!builder.get_dry_run())
-                               config.save();
-               }
-
-               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());
-                       }
+       do_configure(opts, flag);
 
-               for(PackageList::iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
-               {
-                       if((*i)->get_need_path())
-                               (*i)->set_path(config.get_option((*i)->get_name()+"_path").value);
-                       (*i)->configure(opts, flag&2);
-               }
-
-               deps_cache.load();
-       }
+       for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
+               i->get_package()->configure(opts, flag&2);
 
        create_build_info();
 
        conf_done=true;
 }
 
-/**
-Creates a non-buildable package with the given name.  Pkg-config is tried first
-to get build information.  If it fails, a built-in list of known packages is
-consulted.
-*/
-Package *Package::create(Builder &b, const string &name)
-{
-       list<string> argv;
-       argv.push_back("pkg-config");
-       argv.push_back("--silence-errors");
-       argv.push_back("--cflags");
-       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");
-               else if(name=="pthread")
-                       info.push_back("-lpthread");
-               else if(name=="gmpxx")
-                       info.push_back("-lgmpxx");
-               else if(name=="fmod4")
-                       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;
-       return pkg;
-}
-
 /*** private ***/
 
-Package::Package(Builder &b, const string &n, const vector<string> &info):
-       builder(b),
-       name(n),
-       buildable(false),
-       config(*this),
-       conf_done(false),
-       deps_cache(*this)
-{
-       for(vector<string>::const_iterator i=info.begin(); i!=info.end(); ++i)
-       {
-               if(!i->compare(0, 2, "-I"))
-                       export_binfo.incpath.push_back(i->substr(2));
-               else if(!i->compare(0, 2, "-D"))
-                       export_binfo.defines.push_back(i->substr(2));
-               else if(!i->compare(0, 2, "-L"))
-                       export_binfo.libpath.push_back(i->substr(2));
-               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';
-       }
-}
-
-/**
-Initializes configuration options and loads cached values.
-*/
-void Package::init_config()
-{
-       config.add_option("profile",    "default", "Configuration profile");
-       config.add_option("tempdir",    "temp",    "Directory for storing temporary files");
-       config.add_option("outdir",     ".",       "Directory to put build results in");
-       config.add_option("optimize",   "0",       "Apply compiler optimizations");
-       config.add_option("debug",      "0",       "Produce debugging symbols");
-       config.add_option("cpu",        "auto",    "CPU type to optimize for");
-       config.add_option("arch",       "native",  "Architecture for cross-compiling");
-       config.add_option("staticlibs", "local",   "Use static libraries");
-
-       unsigned flags=get_install_flags();
-       if(flags)
-               config.add_option("prefix",     "$HOME/local",     "Installation prefix");
-       /*if(flags&INCLUDE)
-               config.add_option("includedir", "$prefix/include", "Header installation directory");
-       if(flags&BIN)
-               config.add_option("includedir", "$prefix/bin",     "Binary installation directory");
-       if(flags&LIB)
-               config.add_option("includedir", "$prefix/lib",     "Library installation directory");
-       if(flags&DATA)
-               config.add_option("includedir", "$prefix/share",   "Data installation directory");*/
-
-       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());
-}
-
-/**
-Fills in build info based on configuration.  All required packages must be
-configured when this is called.
-*/
-void Package::create_build_info()
-{
-       if(buildable)
-       {
-               for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
-               {
-                       Package *pkg=i->get_package();
-                       if(!pkg)
-                               continue;
-                       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");
-               build_info.cflags.push_back("-Wpointer-arith");
-               build_info.cflags.push_back("-Wconversion");
-               build_info.cflags.push_back("-Werror");
-
-               unsigned flags=get_install_flags();
-
-               if(flags&INCLUDE)
-                       export_binfo.incpath.push_back((Path::Path(config.get_option("prefix").value)/"include").str());
-               if(flags&LIB)
-                       export_binfo.libpath.push_back((Path::Path(config.get_option("prefix").value)/"lib").str());
-
-               string optimize=config.get_option("optimize").value;
-               if(lexical_cast<unsigned>(optimize))
-               {
-                       build_info.cflags.push_back("-O"+optimize);
-                       build_info.ldflags.push_back("-O"+optimize);
-                       string cpu=config.get_option("cpu").value;
-                       if(cpu!="auto")
-                               build_info.cflags.push_back("-march="+cpu);
-               }
-
-               if(lexical_cast<bool>(config.get_option("debug").value))
-               {
-                       build_info.cflags.push_back("-ggdb");
-                       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)
-               {
-                       i->create_build_info();
-                       if(i->get_type()==Component::LIBRARY)
-                               export_binfo.libs.push_back(i->get_name());
-               }
-       }
-       else if(name=="fmod4")
-       {
-               export_binfo.libs.push_back("fmodex");
-               if(!path.empty())
-               {
-                       export_binfo.libpath.push_back((path/"api"/"lib").str());
-                       export_binfo.incpath.push_back((path/"api"/"inc").str());
-               }
-       }
-       export_binfo.unique();
-}
-
-
 Package::Loader::Loader(Package &p):
        pkg(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);
-       add("headers",     &Loader::headers);
-       add("build_info",  &Loader::build_info);
-       add("tar_file",    &Loader::tar_file);
+       add("require", &Loader::require);
 }
 
 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);
-       load_sub(prog);
-       pkg.components.push_back(prog);
-}
-
-void Package::Loader::library(const string &n)
-{
-       Component prog(pkg, Component::LIBRARY, n);
-       load_sub(prog);
-       pkg.components.push_back(prog);
-}
-
-void Package::Loader::module(const string &n)
-{
-       Component prog(pkg, Component::MODULE, n);
-       load_sub(prog);
-       pkg.components.push_back(prog);
-}
-
-void Package::Loader::headers(const string &n)
-{
-       Component prog(pkg, Component::HEADERS, n);
-       load_sub(prog);
-       pkg.components.push_back(prog);
-}
-
-void Package::Loader::build_info()
-{
-       load_sub(pkg.build_info);
-}
-
-void Package::Loader::tar_file(const string &f)
-{
-       pkg.tar_files.push_back(pkg.source/f);
-}
index 90ee6bc510abc941262d884146c6d053db32f522..f8ef7451d6c59fed1bd6ac316cd407b86c5d3161 100644 (file)
@@ -12,11 +12,6 @@ Distributed under the LGPL
 #include <string>
 #include <msp/datafile/loader.h>
 #include "buildinfo.h"
-#include "component.h"
-#include "condition.h"
-#include "config.h"
-#include "dependencycache.h"
-#include "feature.h"
 #include "packageref.h"
 
 class Builder;
@@ -32,89 +27,42 @@ to determine where files are installed and which features to include.
 class Package
 {
 public:
-       enum InstallFlags
-       {
-               INCLUDE=1,
-               BIN=2,
-               LIB=4,
-               DATA=8
-       };
-
-       /// Loads a package from a file.
        class Loader: public Msp::DataFile::Loader
        {
        public:
                Loader(Package &);
                Package &get_object() { return pkg; }
-       private:
+       protected:
                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 &);
-               void headers(const std::string &);
-               void build_info();
-               void tar_file(const std::string &);
        };
 
-       Package(Builder &, const std::string &, const Msp::Path::Path &);
-       void                set_path(const Msp::Path::Path &);
        const std::string   &get_name() const           { return name; }
-       const std::string   &get_version() const        { return version; }
-       const std::string   &get_description() const    { return description; }
-       const Msp::Path::Path &get_source() const       { return source; }
-       Msp::Path::Path     get_temp_dir() const;
-       Msp::Path::Path     get_out_dir() const;
-       Msp::Path::Path     get_prefix() const          { return config.get_option("prefix").value; }
-       const ComponentList &get_components() const     { return components; }
-       bool                get_buildable() const       { return buildable; }
-       const Config        &get_config() const         { return config; }
+       Builder             &get_builder() const        { return builder; }
        const PkgRefList    &get_requires() const       { return requires; }
-       const BuildInfo     &get_build_info() const     { return build_info; }
        const BuildInfo     &get_exported_binfo() const { return export_binfo; }
-       Builder             &get_builder() const        { return builder; }
-       bool                get_need_path() const       { return need_path; }
-       unsigned            get_install_flags();
-       bool                get_use_pkgconfig() const   { return use_pkgconfig; }
-       const std::string   &get_arch() const           { return config.get_option("arch").value; }
-       LibMode             get_library_mode() const;
-       const PathList      &get_tar_files() const      { return tar_files; }
-       DependencyCache     &get_deps_cache() const     { return deps_cache; }
-       void                resolve_refs();
-       void                configure(const StringMap &, unsigned);
 
-       static Package *create(Builder &, const std::string &);
-private:
+       /// Indicates whether or not this package supports pkg-config
+       bool get_use_pkgconfig() const { return use_pkgconfig; }
+
+       virtual void        resolve_refs();
+       void                configure(const StringMap &, unsigned);
+       virtual ~Package() { }
+protected:
        Builder       &builder;
-       
+
        std::string   name;
-       std::string   version;
-       std::string   description;
-       
-       bool          buildable;
-       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;
-       mutable DependencyCache deps_cache;
-       PathList      tar_files;
 
        bool          use_pkgconfig;
-       bool          need_path;
-       Msp::Path::Path path;
 
-       Package(Builder &, const std::string &, const std::vector<std::string> &);
-       void     init_config();
-       void     create_build_info();
+       Package(Builder &, const std::string &);
+       virtual void do_configure(const StringMap &, unsigned) { }
+       virtual void create_build_info() { }
 };
 
 #endif
index 8f4578044279d529aab4caf465e5d5bc9895cd1e..d31ab9d2d9ce01cc4d8be570ba37d3fe428ea9f0 100644 (file)
@@ -9,7 +9,7 @@ Distributed under the LGPL
 #include "pkgconfig.h"
 #include "pkgconfigaction.h"
 
-PkgConfig::PkgConfig(Builder &b, const Package &p):
+PkgConfig::PkgConfig(Builder &b, const SourcePackage &p):
        Target(b, &p, (p.get_source()/(p.get_name()+".pc")).str()),
        pkg(p)
 {
index 8baa9d9c10008ffa28f669156dbdb7fc5a5ac4c6..f88e248cb4b5d3327a55a1d825383bf07eb7b83e 100644 (file)
@@ -8,6 +8,7 @@ Distributed under the LGPL
 #ifndef PKGCONFIG_H_
 #define PKGCONFIG_H_
 
+#include "sourcepackage.h"
 #include "target.h"
 
 /**
@@ -16,7 +17,7 @@ Creates a .pc file to enable other packages fetch build options with pkg-config.
 class PkgConfig: public Target
 {
 public:
-       PkgConfig(Builder &, const Package &);
+       PkgConfig(Builder &, const SourcePackage &);
        const char *get_type() const { return "PkgConfig"; }
        Action     *build();
 private:
index b1bebace667a337c22a3372e0473cd6ef3717f52..c390fbd0e0a47dd45ee1e72995513411914e4866 100644 (file)
@@ -17,29 +17,29 @@ using namespace std;
 PkgConfigAction::PkgConfigAction(Builder &b, const PkgConfig &p):
        Action(b)
 {
-       const Package &pkg=*p.get_package();
-       
-       announce(pkg.get_name(), "PC", relative(p.get_name(), pkg.get_source()).str());
-       
+       const SourcePackage &spkg=*static_cast<const SourcePackage *>(p.get_package());
+
+       announce(spkg.get_name(), "PC", relative(p.get_name(), spkg.get_source()).str());
+
        ofstream out(p.get_name().c_str());
        if(out)
        {
                // Prefix is already included in the various paths
                //out<<"prefix="<<pkg.get_prefix()<<"\n\n";
-               out<<"source="<<pkg.get_source()<<"\n\n";
-               
-               out<<"Name: "<<pkg.get_name()<<'\n';
-               out<<"Description: "<<pkg.get_description()<<'\n';
-               out<<"Version: "<<pkg.get_version()<<'\n';
-               
+               out<<"source="<<spkg.get_source()<<"\n\n";
+
+               out<<"Name: "<<spkg.get_name()<<'\n';
+               out<<"Description: "<<spkg.get_description()<<'\n';
+               out<<"Version: "<<spkg.get_version()<<'\n';
+
                out<<"Requires:";
-               const PkgRefList &reqs=pkg.get_requires();
+               const PkgRefList &reqs=spkg.get_requires();
                for(PkgRefList::const_iterator i=reqs.begin(); i!=reqs.end(); ++i)
                        if(i->get_package()->get_use_pkgconfig())
                                out<<' '<<i->get_name();
                out<<'\n';
 
-               const BuildInfo &binfo=pkg.get_exported_binfo();
+               const BuildInfo &binfo=spkg.get_exported_binfo();
                out<<"Libs:";
                for(StringList::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
                        out<<" -L"<<*i;
index 57866aa274565c3b088f285abb1b2c234223f8bf..718a09c48541152d3c15f484b5048ce81017f94e 100644 (file)
@@ -9,8 +9,8 @@ Distributed under the LGPL
 #include <msp/strings/regex.h>
 #include "builder.h"
 #include "component.h"
-#include "package.h"
 #include "sourcefile.h"
+#include "sourcepackage.h"
 
 using namespace std;
 using namespace Msp;
@@ -26,6 +26,9 @@ from Builder.
 */
 void SourceFile::find_depends()
 {
+       if(!comp)
+               return;
+
        DependencyCache &deps_cache=comp->get_package().get_deps_cache();
        if(mtime>deps_cache.get_mtime())
        {
diff --git a/source/sourcepackage.cpp b/source/sourcepackage.cpp
new file mode 100644 (file)
index 0000000..5d1d683
--- /dev/null
@@ -0,0 +1,328 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <iostream>
+#include <msp/strings/lexicalcast.h>
+#include <msp/strings/utils.h>
+#include "binarypackage.h"
+#include "builder.h"
+#include "misc.h"
+#include "sourcepackage.h"
+
+using namespace std;
+using namespace Msp;
+
+/**
+Creates a buildable package.
+*/
+SourcePackage::SourcePackage(Builder &b, const string &n, const Path::Path &s):
+       Package(b, n),
+       source(s),
+       config(*this),
+       deps_cache(*this)
+{
+       tar_files.push_back(source/"Build");
+}
+
+Msp::Path::Path SourcePackage::get_temp_dir() const
+{
+       return source/config.get_option("tempdir").value/config.get_option("profile").value;
+}
+
+Msp::Path::Path SourcePackage::get_out_dir() const
+{
+       return source/config.get_option("outdir").value;
+}
+
+/**
+Checks which kinds of things the components of this package install.
+
+@return  A bitmask of installed things
+*/
+unsigned SourcePackage::get_install_flags()
+{
+       unsigned flags=0;
+       for(ComponentList::iterator i=components.begin(); i!=components.end(); ++i)
+       {
+               if(i->get_install())
+               {
+                       if(i->get_type()==Component::PROGRAM)
+                               flags|=BIN;
+                       else if(i->get_type()==Component::LIBRARY || i->get_type()==Component::MODULE)
+                               flags|=LIB;
+               }
+               if(!i->get_install_headers().empty())
+                       flags|=INCLUDE;
+       }
+
+       return flags;
+}
+
+LibMode SourcePackage::get_library_mode() const
+{
+       const string &mode=config.get_option("staticlibs").value;
+       if(mode=="all")
+               return ALL_STATIC;
+       else if(mode=="local")
+               return LOCAL_STATIC;
+       else if(mode=="none")
+               return DYNAMIC;
+       else
+               throw Exception("Unknown library mode");
+}
+
+/**
+Tries to resolve all references to dependency packages.
+*/
+void SourcePackage::resolve_refs()
+{
+       Package::resolve_refs();
+
+       for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
+               if(i->get_package())
+                       all_reqs.push_back(i->get_package());
+
+       for(ComponentList::iterator i=components.begin(); i!=components.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());
+       }
+
+       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());
+       }
+}
+
+/*** private ***/
+
+/**
+Processes configuration options that were most likely obtained from the command
+line.
+*/
+void SourcePackage::do_configure(const StringMap &opts, unsigned flag)
+{
+       init_config();
+
+       StringMap::const_iterator prof=opts.find("profile");
+       if(prof!=opts.end() && flag)
+               config.select_profile(prof->second);
+       else
+               config.select_last_profile();
+
+       if(flag && config.update(opts))
+       {
+               if(builder.get_verbose()>=2)
+                       cout<<"Configuration of "<<name<<" changed\n";
+               if(!builder.get_dry_run())
+                       config.save();
+       }
+
+       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)
+       {
+               BinaryPackage *bpkg=dynamic_cast<BinaryPackage *>(*i);
+               if(bpkg && bpkg->get_need_path())
+                       bpkg->set_path(config.get_option(bpkg->get_name()+"_path").value);
+       }
+
+       deps_cache.load();
+
+       for(PackageList::iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i)
+               (*i)->configure(opts, flag&2);
+}
+
+/**
+Initializes configuration options.
+*/
+void SourcePackage::init_config()
+{
+       config.add_option("profile",    "default", "Configuration profile");
+       config.add_option("tempdir",    "temp",    "Directory for storing temporary files");
+       config.add_option("outdir",     ".",       "Directory to put build results in");
+       config.add_option("optimize",   "0",       "Apply compiler optimizations");
+       config.add_option("strip",      "0",       "Strip symbols from programs");
+       config.add_option("debug",      "0",       "Produce debugging symbols");
+       config.add_option("cpu",        "auto",    "CPU type to optimize for");
+       config.add_option("arch",       "native",  "Architecture for cross-compiling");
+       config.add_option("staticlibs", "local",   "Use static libraries");
+
+       unsigned flags=get_install_flags();
+       if(flags)
+               config.add_option("prefix",     "$HOME/local",     "Installation prefix");
+       /*if(flags&INCLUDE)
+               config.add_option("includedir", "$prefix/include", "Header installation directory");
+       if(flags&BIN)
+               config.add_option("includedir", "$prefix/bin",     "Binary installation directory");
+       if(flags&LIB)
+               config.add_option("includedir", "$prefix/lib",     "Library installation directory");
+       if(flags&DATA)
+               config.add_option("includedir", "$prefix/share",   "Data installation directory");*/
+
+       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)
+       {
+               BinaryPackage *bpkg=dynamic_cast<BinaryPackage *>(*i);
+               if(bpkg && bpkg->get_need_path())
+                       config.add_option(bpkg->get_name()+"_path", "", "Path for "+bpkg->get_name());
+       }
+}
+
+/**
+Fills in build info based on configuration.  All required packages must be
+configured when this is called.
+*/
+void SourcePackage::create_build_info()
+{
+       for(PkgRefList::iterator i=requires.begin(); i!=requires.end(); ++i)
+       {
+               Package *pkg=i->get_package();
+               if(!pkg)
+                       continue;
+               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");
+       build_info.cflags.push_back("-Wpointer-arith");
+       build_info.cflags.push_back("-Wconversion");
+       build_info.cflags.push_back("-Werror");
+
+       unsigned flags=get_install_flags();
+
+       if(flags&INCLUDE)
+               export_binfo.incpath.push_back((Path::Path(config.get_option("prefix").value)/"include").str());
+       if(flags&LIB)
+               export_binfo.libpath.push_back((Path::Path(config.get_option("prefix").value)/"lib").str());
+
+       string optimize=config.get_option("optimize").value;
+       if(lexical_cast<unsigned>(optimize))
+       {
+               build_info.cflags.push_back("-O"+optimize);
+               build_info.ldflags.push_back("-O"+optimize);
+               string cpu=config.get_option("cpu").value;
+               if(cpu!="auto")
+                       build_info.cflags.push_back("-march="+cpu);
+       }
+
+       if(lexical_cast<bool>(config.get_option("debug").value))
+       {
+               build_info.cflags.push_back("-ggdb");
+               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)
+       {
+               i->create_build_info();
+               if(i->get_type()==Component::LIBRARY)
+                       export_binfo.libs.push_back(i->get_name());
+       }
+
+       export_binfo.unique();
+}
+
+
+SourcePackage::Loader::Loader(Package &p):
+       Package::Loader(p)
+{
+       add("version",     &SourcePackage::version);
+       add("description", &SourcePackage::description);
+       add("build_info",  &Loader::build_info);
+       add("feature",     &Loader::feature);
+       add("if",          &Loader::condition);
+       add("program",     &Loader::program);
+       add("library",     &Loader::library);
+       add("module",      &Loader::module);
+       add("headers",     &Loader::headers);
+       add("tar_file",    &Loader::tar_file);
+}
+
+void SourcePackage::Loader::feature(const string &n, const string &d)
+{
+       static_cast<SourcePackage &>(pkg).features.push_back(Feature(n, d));
+}
+
+void SourcePackage::Loader::condition(const string &c)
+{
+       SourcePackage &spkg=static_cast<SourcePackage &>(pkg);
+       Condition cond(spkg, c);
+       load_sub(cond);
+       spkg.conditions.push_back(cond);
+}
+
+void SourcePackage::Loader::program(const string &n)
+{
+       SourcePackage &spkg=static_cast<SourcePackage &>(pkg);
+       Component prog(spkg, Component::PROGRAM, n);
+       load_sub(prog);
+       spkg.components.push_back(prog);
+}
+
+void SourcePackage::Loader::library(const string &n)
+{
+       SourcePackage &spkg=static_cast<SourcePackage &>(pkg);
+       Component prog(spkg, Component::LIBRARY, n);
+       load_sub(prog);
+       spkg.components.push_back(prog);
+}
+
+void SourcePackage::Loader::module(const string &n)
+{
+       SourcePackage &spkg=static_cast<SourcePackage &>(pkg);
+       Component prog(spkg, Component::MODULE, n);
+       load_sub(prog);
+       spkg.components.push_back(prog);
+}
+
+void SourcePackage::Loader::headers(const string &n)
+{
+       SourcePackage &spkg=static_cast<SourcePackage &>(pkg);
+       Component prog(spkg, Component::HEADERS, n);
+       load_sub(prog);
+       spkg.components.push_back(prog);
+}
+
+void SourcePackage::Loader::build_info()
+{
+       load_sub(static_cast<SourcePackage &>(pkg).build_info);
+}
+
+void SourcePackage::Loader::tar_file(const string &f)
+{
+       SourcePackage &spkg=static_cast<SourcePackage &>(pkg);
+       spkg.tar_files.push_back(spkg.source/f);
+}
diff --git a/source/sourcepackage.h b/source/sourcepackage.h
new file mode 100644 (file)
index 0000000..f4a8e24
--- /dev/null
@@ -0,0 +1,95 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef SOURCEPACKAGE_H_
+#define SOURCEPACKAGE_H_
+
+#include <string>
+#include "buildinfo.h"
+#include "component.h"
+#include "condition.h"
+#include "config.h"
+#include "dependencycache.h"
+#include "feature.h"
+#include "package.h"
+#include "packageref.h"
+
+class Builder;
+
+/**
+A package that can be built by Builder.
+*/
+class SourcePackage: public Package
+{
+public:
+       enum InstallFlags
+       {
+               INCLUDE=1,
+               BIN=2,
+               LIB=4,
+               DATA=8
+       };
+
+       /// Loads a package from a file.
+       class Loader: public Package::Loader
+       {
+       public:
+               Loader(Package &);
+               SourcePackage &get_object() { return static_cast<SourcePackage &>(pkg); }
+       private:
+               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 &);
+               void headers(const std::string &);
+               void build_info();
+               void tar_file(const std::string &);
+       };
+
+       SourcePackage(Builder &, const std::string &, const Msp::Path::Path &);
+       void                set_path(const Msp::Path::Path &);
+       const std::string   &get_name() const           { return name; }
+       const std::string   &get_version() const        { return version; }
+       const std::string   &get_description() const    { return description; }
+       const Msp::Path::Path &get_source() const       { return source; }
+       Msp::Path::Path     get_temp_dir() const;
+       Msp::Path::Path     get_out_dir() const;
+       Msp::Path::Path     get_prefix() const          { return config.get_option("prefix").value; }
+       const ComponentList &get_components() const     { return components; }
+       const Config        &get_config() const         { return config; }
+       const BuildInfo     &get_build_info() const     { return build_info; }
+       const BuildInfo     &get_exported_binfo() const { return export_binfo; }
+       Builder             &get_builder() const        { return builder; }
+       unsigned            get_install_flags();
+       const std::string   &get_arch() const           { return config.get_option("arch").value; }
+       LibMode             get_library_mode() const;
+       const PathList      &get_tar_files() const      { return tar_files; }
+       DependencyCache     &get_deps_cache() const     { return deps_cache; }
+       virtual void        resolve_refs();
+private:
+       std::string   version;
+       std::string   description;
+
+       Msp::Path::Path source;
+       PackageList   all_reqs;
+       FeatureList   features;
+       BuildInfo     build_info;
+       ConditionList conditions;
+       ComponentList components;
+       Config        config;
+       bool          conf_done;
+       mutable DependencyCache deps_cache;
+       PathList      tar_files;
+
+       //Package(Builder &, const std::string &, const std::vector<std::string> &);
+       virtual void do_configure(const StringMap &, unsigned);
+       void         init_config();
+       virtual void create_build_info();
+};
+
+#endif
index 54fd7926f3e0c644bb62a2a464e21135176f1321..56d857e02a1aa049fa4713faea44748223ea6f3a 100644 (file)
@@ -8,7 +8,7 @@ Distributed under the LGPL
 #include "archive.h"
 #include "component.h"
 #include "objectfile.h"
-#include "package.h"
+#include "sourcepackage.h"
 #include "staticlibrary.h"
 
 using namespace std;
index bd29aafc56543547a0f91c5b360398aae2546e48..532b4a73f2ffdb23c553fce21cb1e8f8f8597370 100644 (file)
@@ -8,7 +8,7 @@ Distributed under the LGPL
 #include <iostream>
 #include <msp/path/utils.h>
 #include "builder.h"
-#include "package.h"
+#include "sourcepackage.h"
 #include "tar.h"
 #include "tarball.h"
 
index 348272f064689e473610cb14f4ae17b4358317e7..5d7678d28a79e33f55a076166b8886915365f5c2 100644 (file)
@@ -7,26 +7,33 @@ Distributed under the LGPL
 
 #include "builder.h"
 #include "file.h"
-#include "package.h"
+#include "sourcepackage.h"
 #include "tar.h"
 #include "tarball.h"
 
 using namespace std;
 
-TarBall::TarBall(Builder &b, const Package &p, const string &ev):
+TarBall::TarBall(Builder &b, const SourcePackage &p, const string &ev):
        Target(b, &p, create_target_name(p, ev))
 {
        buildable=true;
 }
 
+const SourcePackage *TarBall::get_package() const
+{
+       return static_cast<const SourcePackage *>(package);
+}
+
 void TarBall::find_depends()
 {
+       const SourcePackage *spkg=dynamic_cast<const SourcePackage *>(package);
+
        const TargetMap &targets=builder.get_targets();
        for(TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
                if(i->second->get_package()==package && i->second!=this && !i->second->get_buildable())
                        add_depend(i->second);
 
-       const PathList &tar_files=package->get_tar_files();
+       const PathList &tar_files=spkg->get_tar_files();
        for(PathList::const_iterator i=tar_files.begin(); i!=tar_files.end(); ++i)
        {
                Target *tgt=builder.get_target(i->str());
@@ -43,7 +50,7 @@ Action *TarBall::build()
        return Target::build(new Tar(builder, *this));
 }
 
-string TarBall::create_target_name(const Package &pkg, const string &extra_ver)
+string TarBall::create_target_name(const SourcePackage &pkg, const string &extra_ver)
 {
        string basename=pkg.get_name()+"-"+pkg.get_version();
        if(!extra_ver.empty())
index 6c36237370149cc1cc944105cb47e25288c92949..04cd661eb7995a88c9187b2db27e5761cf980a93 100644 (file)
@@ -13,14 +13,15 @@ Distributed under the LGPL
 class TarBall: public Target
 {
 public:
-       TarBall(Builder &, const Package &, const std::string & =std::string());
+       TarBall(Builder &, const SourcePackage &, const std::string & =std::string());
        virtual const char *get_type() const { return "TarBall"; }
+       const SourcePackage *get_package() const;
        virtual void find_depends();
        virtual Action *build();
 private:
        std::string tarname;
 
-       std::string create_target_name(const Package &, const std::string &);
+       std::string create_target_name(const SourcePackage &, const std::string &);
 };
 
 #endif
index c9c23ad9116165297d602978b9be04c13f902530..fa63ac4e5154293050db87c91168d4c286690938 100644 (file)
@@ -10,6 +10,7 @@ Distributed under the LGPL
 #include "action.h"
 #include "builder.h"
 #include "package.h"
+#include "sourcepackage.h"
 #include "target.h"
 
 using namespace std;
@@ -137,7 +138,9 @@ void Target::check_rebuild()
                                mark_rebuild(Path::basename((*i)->get_name())+" needs rebuilding");
                }
        }
-       if(!rebuild && package && package->get_config().get_mtime()>mtime)
+
+       const SourcePackage *spkg=dynamic_cast<const SourcePackage *>(package);
+       if(!rebuild && spkg && spkg->get_config().get_mtime()>mtime)
                mark_rebuild("Package options changed");
 }
 
index b9357e64e5af3889b23227d22a3432610d1a7556..2860357475e455d9e650d28d6a163045c995be3b 100644 (file)
@@ -6,16 +6,16 @@ Distributed under the LGPL
 */
 
 #include <msp/path/utils.h>
-#include "package.h"
+#include "sourcepackage.h"
 #include "target.h"
 #include "unlink.h"
 
 Unlink::Unlink(Builder &b, const Target &t):
        Action(b)
 {
-       const Package &pkg=*t.get_package();
+       const SourcePackage &spkg=*static_cast<const SourcePackage *>(t.get_package());
 
-       announce(pkg.get_name(), "RM", relative(t.get_name(), pkg.get_source()).str());
+       announce(spkg.get_name(), "RM", relative(t.get_name(), spkg.get_source()).str());
 
        unlink(t.get_name().c_str());
 }