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