From 654de39b62a9a58fd8e1b5a557361d628345788b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 9 Sep 2007 10:10:29 +0000 Subject: [PATCH] Split class Package into SourcePackage and BinaryPackage Load vertain data from a builderrc file --- builderrc | 72 +++++++ source/archive.cpp | 4 +- source/binarypackage.cpp | 87 +++++++++ source/binarypackage.h | 41 ++++ source/builder.cpp | 98 ++++++---- source/builder.h | 18 +- source/compile.cpp | 4 +- source/component.cpp | 16 +- source/component.h | 8 +- source/condition.cpp | 8 +- source/condition.h | 5 +- source/config.cpp | 4 +- source/config.h | 8 +- source/dependencycache.cpp | 4 +- source/dependencycache.h | 4 +- source/executable.cpp | 2 +- source/install.cpp | 6 +- source/install.h | 3 +- source/link.cpp | 2 +- source/objectfile.cpp | 2 +- source/package.cpp | 380 +------------------------------------ source/package.h | 82 ++------ source/pkgconfig.cpp | 2 +- source/pkgconfig.h | 3 +- source/pkgconfigaction.cpp | 24 +-- source/sourcefile.cpp | 5 +- source/sourcepackage.cpp | 328 ++++++++++++++++++++++++++++++++ source/sourcepackage.h | 95 ++++++++++ source/staticlibrary.cpp | 2 +- source/tar.cpp | 2 +- source/tarball.cpp | 15 +- source/tarball.h | 5 +- source/target.cpp | 5 +- source/unlink.cpp | 6 +- 34 files changed, 811 insertions(+), 539 deletions(-) create mode 100644 builderrc create mode 100644 source/binarypackage.cpp create mode 100644 source/binarypackage.h create mode 100644 source/sourcepackage.cpp create mode 100644 source/sourcepackage.h diff --git a/builderrc b/builderrc new file mode 100644 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"; +}; diff --git a/source/archive.cpp b/source/archive.cpp index b6c9582..4dee508 100644 --- a/source/archive.cpp +++ b/source/archive.cpp @@ -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 index 0000000..c2c1886 --- /dev/null +++ b/source/binarypackage.cpp @@ -0,0 +1,87 @@ +/* $Id$ + +This file is part of builder +Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#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 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 flags=split(info); + for(vector::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(pkg).export_binfo); +} diff --git a/source/binarypackage.h b/source/binarypackage.h new file mode 100644 index 0000000..b10331b --- /dev/null +++ b/source/binarypackage.h @@ -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(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 diff --git a/source/builder.cpp b/source/builder.cpp index 353bc29..f10f0eb 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -17,6 +17,7 @@ Distributed under the LGPL #include #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(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<<' '<second->get_name(); - if(i->second->get_buildable()) + if(dynamic_cast(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 "<second) - continue; - if(!i->second->get_buildable()) + SourcePackage *spkg=dynamic_cast(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(i->second)) + spkg->get_deps_cache().save(); return 0; } @@ -802,18 +791,55 @@ void Builder::package_help() Application::RegApp 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(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)); +} diff --git a/source/builder.h b/source/builder.h index d2d7598..879781d 100644 --- a/source/builder.h +++ b/source/builder.h @@ -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 PackageList; typedef std::map PackageMap; typedef std::map ToolMap; @@ -70,7 +84,7 @@ private: PackageMap packages; PackageList new_pkgs; - Package *default_pkg; + SourcePackage *default_pkg; TargetMap targets; TargetList new_tgts; diff --git a/source/compile.cpp b/source/compile.cpp index 67278d1..d07f3ef 100644 --- a/source/compile.cpp +++ b/source/compile.cpp @@ -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(); diff --git a/source/component.cpp b/source/component.cpp index 6a3796d..6272321 100644 --- a/source/component.cpp +++ b/source/component.cpp @@ -7,20 +7,21 @@ Distributed under the LGPL #include #include +#include #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(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 objs; list 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); diff --git a/source/component.h b/source/component.h index 36cd83e..387de4c 100644 --- a/source/component.h +++ b/source/component.h @@ -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; diff --git a/source/condition.cpp b/source/condition.cpp index b5833e9..c4c01b2 100644 --- a/source/condition.cpp +++ b/source/condition.cpp @@ -7,14 +7,12 @@ Distributed under the LGPL #include #include "condition.h" -#include "package.h" +#include "sourcepackage.h" using namespace std; using namespace Msp; -#include - -Condition::Condition(Package &p, const string &expr): +Condition::Condition(SourcePackage &p, const string &expr): pkg(p) { vector 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")); diff --git a/source/condition.h b/source/condition.h index baf718c..433c0c8 100644 --- a/source/condition.h +++ b/source/condition.h @@ -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; diff --git a/source/config.cpp b/source/config.cpp index 74c3741..0e8e6c2 100644 --- a/source/config.cpp +++ b/source/config.cpp @@ -11,12 +11,12 @@ Distributed under the LGPL #include #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) { } diff --git a/source/config.h b/source/config.h index 1b7f853..ba23462 100644 --- a/source/config.h +++ b/source/config.h @@ -15,7 +15,7 @@ Distributed under the LGPL #include #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 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; diff --git a/source/dependencycache.cpp b/source/dependencycache.cpp index cc11383..0d82d70 100644 --- a/source/dependencycache.cpp +++ b/source/dependencycache.cpp @@ -10,12 +10,12 @@ Distributed under the LGPL #include #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) { } diff --git a/source/dependencycache.h b/source/dependencycache.h index 5cde40d..f182f31 100644 --- a/source/dependencycache.h +++ b/source/dependencycache.h @@ -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 DepsMap; - Package &package; + SourcePackage &package; DepsMap deps; Msp::Time::TimeStamp mtime; bool changed; diff --git a/source/executable.cpp b/source/executable.cpp index ff13122..d1cc59a 100644 --- a/source/executable.cpp +++ b/source/executable.cpp @@ -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 queue; list dep_libs; diff --git a/source/install.cpp b/source/install.cpp index e9be682..2cdd1aa 100644 --- a/source/install.cpp +++ b/source/install.cpp @@ -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(tgt.get_package()); + + Path::Path base=spkg->get_prefix(); string tgtname=tgt.get_name().substr(tgt.get_name().rfind('/')+1); string mid; diff --git a/source/install.h b/source/install.h index bdabc6e..6721615 100644 --- a/source/install.h +++ b/source/install.h @@ -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(); diff --git a/source/link.cpp b/source/link.cpp index 30fecfb..a7ea2c5 100644 --- a/source/link.cpp +++ b/source/link.cpp @@ -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"); diff --git a/source/objectfile.cpp b/source/objectfile.cpp index 5022bdd..809e70d 100644 --- a/source/objectfile.cpp +++ b/source/objectfile.cpp @@ -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; diff --git a/source/package.cpp b/source/package.cpp index 8fb2b4d..23a8d9c 100644 --- a/source/package.cpp +++ b/source/package.cpp @@ -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 "<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 "<second); - else - config.select_last_profile(); - - if(flag && config.update(opts)) - { - if(builder.get_verbose()>=2) - cout<<"Configuration of "<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 argv; - argv.push_back("pkg-config"); - argv.push_back("--silence-errors"); - argv.push_back("--cflags"); - argv.push_back("--libs"); - argv.push_back(name); - vector 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 &info): - builder(b), - name(n), - buildable(false), - config(*this), - conf_done(false), - deps_cache(*this) -{ - for(vector::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 "<::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(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(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(config.get_option("with_"+i->name).value)) - build_info.cflags.push_back("-DWITH_"+toupper(i->name)); - - build_info.unique(); - - for(list::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); -} diff --git a/source/package.h b/source/package.h index 90ee6bc..f8ef745 100644 --- a/source/package.h +++ b/source/package.h @@ -12,11 +12,6 @@ Distributed under the LGPL #include #include #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 &); - 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 diff --git a/source/pkgconfig.cpp b/source/pkgconfig.cpp index 8f45780..d31ab9d 100644 --- a/source/pkgconfig.cpp +++ b/source/pkgconfig.cpp @@ -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) { diff --git a/source/pkgconfig.h b/source/pkgconfig.h index 8baa9d9..f88e248 100644 --- a/source/pkgconfig.h +++ b/source/pkgconfig.h @@ -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: diff --git a/source/pkgconfigaction.cpp b/source/pkgconfigaction.cpp index b1bebac..c390fbd 100644 --- a/source/pkgconfigaction.cpp +++ b/source/pkgconfigaction.cpp @@ -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(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="<get_package()->get_use_pkgconfig()) out<<' '<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; diff --git a/source/sourcefile.cpp b/source/sourcefile.cpp index 57866aa..718a09c 100644 --- a/source/sourcefile.cpp +++ b/source/sourcefile.cpp @@ -9,8 +9,8 @@ Distributed under the LGPL #include #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 index 0000000..5d1d683 --- /dev/null +++ b/source/sourcepackage.cpp @@ -0,0 +1,328 @@ +/* $Id$ + +This file is part of builder +Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#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 "<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(*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(*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(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(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(config.get_option("with_"+i->name).value)) + build_info.cflags.push_back("-DWITH_"+toupper(i->name)); + + build_info.unique(); + + for(list::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(pkg).features.push_back(Feature(n, d)); +} + +void SourcePackage::Loader::condition(const string &c) +{ + SourcePackage &spkg=static_cast(pkg); + Condition cond(spkg, c); + load_sub(cond); + spkg.conditions.push_back(cond); +} + +void SourcePackage::Loader::program(const string &n) +{ + SourcePackage &spkg=static_cast(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(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(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(pkg); + Component prog(spkg, Component::HEADERS, n); + load_sub(prog); + spkg.components.push_back(prog); +} + +void SourcePackage::Loader::build_info() +{ + load_sub(static_cast(pkg).build_info); +} + +void SourcePackage::Loader::tar_file(const string &f) +{ + SourcePackage &spkg=static_cast(pkg); + spkg.tar_files.push_back(spkg.source/f); +} diff --git a/source/sourcepackage.h b/source/sourcepackage.h new file mode 100644 index 0000000..f4a8e24 --- /dev/null +++ b/source/sourcepackage.h @@ -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 +#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(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 &); + virtual void do_configure(const StringMap &, unsigned); + void init_config(); + virtual void create_build_info(); +}; + +#endif diff --git a/source/staticlibrary.cpp b/source/staticlibrary.cpp index 54fd792..56d857e 100644 --- a/source/staticlibrary.cpp +++ b/source/staticlibrary.cpp @@ -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; diff --git a/source/tar.cpp b/source/tar.cpp index bd29aaf..532b4a7 100644 --- a/source/tar.cpp +++ b/source/tar.cpp @@ -8,7 +8,7 @@ Distributed under the LGPL #include #include #include "builder.h" -#include "package.h" +#include "sourcepackage.h" #include "tar.h" #include "tarball.h" diff --git a/source/tarball.cpp b/source/tarball.cpp index 348272f..5d7678d 100644 --- a/source/tarball.cpp +++ b/source/tarball.cpp @@ -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(package); +} + void TarBall::find_depends() { + const SourcePackage *spkg=dynamic_cast(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()) diff --git a/source/tarball.h b/source/tarball.h index 6c36237..04cd661 100644 --- a/source/tarball.h +++ b/source/tarball.h @@ -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 diff --git a/source/target.cpp b/source/target.cpp index c9c23ad..fa63ac4 100644 --- a/source/target.cpp +++ b/source/target.cpp @@ -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(package); + if(!rebuild && spkg && spkg->get_config().get_mtime()>mtime) mark_rebuild("Package options changed"); } diff --git a/source/unlink.cpp b/source/unlink.cpp index b9357e6..2860357 100644 --- a/source/unlink.cpp +++ b/source/unlink.cpp @@ -6,16 +6,16 @@ Distributed under the LGPL */ #include -#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(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()); } -- 2.43.0