X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuilder.cpp;h=7135a8d97b1a42a4e6aa24860ade31c32fa4f9b4;hb=83d2a8a39e0a09733ffc666d7f885fc328b831f2;hp=cf335c1a93a6c0f7248e20b2f46cb19d3c4efafb;hpb=3aad704c2d2fac737424a0a2697874927bd95c37;p=builder.git diff --git a/source/builder.cpp b/source/builder.cpp index cf335c1..7135a8d 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -5,8 +5,8 @@ Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ -#include #include +#include #include #include #include @@ -17,6 +17,7 @@ Distributed under the LGPL #include #include #include +#include #include #include #include @@ -34,7 +35,6 @@ Distributed under the LGPL #include "sharedlibrary.h" #include "sourcepackage.h" #include "systemlibrary.h" -#include "tarball.h" #include "unlink.h" #include "virtualtarget.h" @@ -77,26 +77,27 @@ Builder::Builder(int argc, char **argv): string arch; GetOpt getopt; - getopt.add_option('a', "analyze", analyze_mode, GetOpt::REQUIRED_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); - getopt.add_option('n', "dry-run", dry_run, GetOpt::NO_ARG); - getopt.add_option('v', "verbose", verbose, GetOpt::NO_ARG); - getopt.add_option('A', "conf-all", conf_all, GetOpt::NO_ARG); - getopt.add_option('B', "build-all", build_all, GetOpt::NO_ARG); - getopt.add_option('C', "chdir", work_dir, GetOpt::REQUIRED_ARG); - getopt.add_option('P', "progress", show_progress, GetOpt::NO_ARG); - getopt.add_option('W', "what-if", what_if, GetOpt::REQUIRED_ARG); - getopt.add_option( "arch", arch, GetOpt::REQUIRED_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.add_option( "prefix", prfx, GetOpt::REQUIRED_ARG); - getopt.add_option( "warnings", cmdline_warn, GetOpt::REQUIRED_ARG); + getopt.add_option('a', "analyze", analyze_mode, GetOpt::REQUIRED_ARG).set_help("Perform analysis. MODE can be deps, alldeps or rebuild.", "MODE"); + getopt.add_option('b', "build", build, GetOpt::NO_ARG).set_help("Perform build even if doing analysis."); + getopt.add_option('c', "clean", clean, GetOpt::NO_ARG).set_help("Clean buildable targets."); + getopt.add_option('f', "file", build_file, GetOpt::REQUIRED_ARG).set_help("Read info from FILE instead of Build.", "FILE"); + getopt.add_option('h', "help", help, GetOpt::NO_ARG).set_help("Print this message."); + getopt.add_option('j', "jobs", jobs, GetOpt::REQUIRED_ARG).set_help("Run NUM commands at once, whenever possible.", "NUM"); + getopt.add_option('n', "dry-run", dry_run, GetOpt::NO_ARG).set_help("Don't actually do anything, only show what would be done."); + getopt.add_option('v', "verbose", verbose, GetOpt::NO_ARG).set_help("Print more information about what's going on."); + getopt.add_option('A', "conf-all", conf_all, GetOpt::NO_ARG).set_help("Apply configuration to all packages."); + getopt.add_option('B', "build-all", build_all, GetOpt::NO_ARG).set_help("Build all targets unconditionally."); + getopt.add_option('C', "chdir", work_dir, GetOpt::REQUIRED_ARG).set_help("Change to DIR before doing anything else.", "DIR"); + getopt.add_option('P', "progress", show_progress, GetOpt::NO_ARG).set_help("Display progress while building."); + getopt.add_option('W', "what-if", what_if, GetOpt::REQUIRED_ARG).set_help("Pretend that FILE has changed.", "FILE"); + getopt.add_option( "arch", arch, GetOpt::REQUIRED_ARG).set_help("Architecture to build for.", "ARCH"); + getopt.add_option( "conf-only", conf_only, GetOpt::NO_ARG).set_help("Stop after configuring packages."); + getopt.add_option( "full-paths", full_paths, GetOpt::NO_ARG).set_help("Output full paths in analysis."); + getopt.add_option( "max-depth", max_depth, GetOpt::REQUIRED_ARG).set_help("Maximum depth to show in analysis.", "NUM"); + getopt.add_option( "prefix", prfx, GetOpt::REQUIRED_ARG).set_help("Directory to install things to.", "DIR"); + getopt.add_option( "warnings", cmdline_warn, GetOpt::REQUIRED_ARG).set_help("Compiler warnings to use.", "LIST"); + usagemsg=getopt.generate_usage(argv[0])+" [ ...]"; + helpmsg=getopt.generate_help(); getopt(argc, argv); if(!analyze_mode.empty()) @@ -194,10 +195,37 @@ Builder::~Builder() int Builder::main() { + if(prefix.str()!="/usr") + { + FS::Path pcdir=prefix/"lib"/"pkgconfig"; + if(const char *pcp=getenv("PKG_CONFIG_PATH")) + { + vector path=split(pcp, ':'); + bool found=false; + for(vector::const_iterator i=path.begin(); (!found && i!=path.end()); ++i) + found=(*i==pcdir.str()); + if(!found) + { + path.push_back(pcdir.str()); + setenv("PKG_CONFIG_PATH", join(path.begin(), path.end(), ":").c_str(), true); + } + } + else + setenv("PKG_CONFIG_PATH", pcdir.str().c_str(), true); + } + if(load_build_file(cwd/build_file)) { - cerr<<"No build info here.\n"; - return 1; + if(help) + { + usage(0, "builder", false); + return 0; + } + else + { + IO::print(IO::cerr, "No build info here.\n"); + return 1; + } } main_pkg->configure(cmdline_options, conf_all?2:1); @@ -205,7 +233,7 @@ int Builder::main() if(help) { usage(0, "builder", false); - cout<<'\n'; + IO::print("\n"); package_help(); return 0; } @@ -219,16 +247,16 @@ int Builder::main() return 0; if(verbose>=2) - cout<<"Building on "<get_name()<<", for "<get_name()<<'\n'; + IO::print("Building on %s, for %s\n", native_arch->get_name(), current_arch->get_name()); if(verbose>=1) - cout<=2) { for(PackageList::const_iterator i=all_reqs.begin(); i!=all_reqs.end(); ++i) { - cout<<' '<<(*i)->get_name(); + IO::print(" %s", (*i)->get_name()); if(dynamic_cast(*i)) - cout<<'*'; + IO::print("*"); unsigned count=0; unsigned ood_count=0; for(TargetMap::iterator j=targets.begin(); j!=targets.end(); ++j) @@ -240,12 +268,12 @@ int Builder::main() } if(count) { - cout<<" ("<package<<": "<descr<<'\n'; - cerr<<"Please fix them and try again.\n"; + IO::print(IO::cerr, " %s: %s\n", i->package, i->descr); + IO::print(IO::cerr, "Please fix them and try again.\n"); return 1; } - //if(create_makefile - if(clean) exit_code=do_clean(); else if(build) @@ -271,6 +297,32 @@ int Builder::main() return exit_code; } +string Builder::run_pkgconfig(const string &pkg, const string &what) +{ + list argv; + argv.push_back("pkg-config"); + if(what=="cflags" || what=="libs") + argv.push_back("--"+what); + else if(what=="flags") + { + argv.push_back("--cflags"); + argv.push_back("--libs"); + } + else + argv.push_back("--variable="+what); + argv.push_back(pkg); + + if(verbose>=4) + IO::print("Running %s\n", join(argv.begin(), argv.end())); + + int status; + string res=run_command(argv, &status); + if(status) + throw Exception(format("pkg-config for package %s failed", pkg)); + + return res; +} + Package *Builder::get_package(const string &name) { PackageMap::iterator i=packages.find(format("%s/%s", name, current_arch->get_name())); @@ -287,14 +339,19 @@ Package *Builder::get_package(const string &name) return i->second; } - // Package source not found - create a binary package - Package *pkg=BinaryPackage::from_pkgconfig(*this, name); + Package *pkg=0; + try + { + // Package source not found - create a binary package + pkg=BinaryPackage::from_pkgconfig(*this, name); + } + catch(...) + { + problem(name, "not found"); + } packages.insert(PackageMap::value_type(name, pkg)); - if(!pkg) - problem(name, "not found"); - return pkg; } @@ -335,12 +392,12 @@ Target *Builder::get_header(const string &include, const FS::Path &from, const l cxx_ver.erase(dot); } if(verbose>=5) - cout<<"C++ version is "<=5) - cout<<"Looking for include "<is_native()) @@ -383,7 +440,7 @@ Target *Builder::get_library(const string &lib, const list &path, LibMod syspath.push_back("/usr/"+current_arch->get_prefix()+"/lib"); if(verbose>=5) - cout<<"Looking for library "< ...]\n"; + IO::print(IO::cerr, "Usage: %s\n", usagemsg); else { - cerr<< - "Usage: "< ...]\n" - "\n" - "Options:\n" - " -a, --analyze MODE Perform analysis. MODE can be deps, alldeps or rebuild.\n" - " -b, --build Perform build even if doing analysis.\n" - " -c, --clean Clean buildable targets.\n" - " -f, --file FILE Read info from FILE instead of Build.\n" - " -h, --help Print this message.\n" - " -j, --jobs NUM Run NUM commands at once, whenever possible.\n" - " -n, --dry-run Don't actually do anything, only show what would be done.\n" - " -v, --verbose Print more information about what's going on.\n" - " -A, --conf-all Apply configuration to all packages.\n" - " -B, --build-all Build all targets unconditionally.\n" - " -C, --chdir DIR Change to DIR before doing anything else.\n" - " -P, --progress Display progress while building.\n" - " -W, --what-if FILE Pretend that FILE has changed.\n" - " --arch ARCH Architecture to build for.\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" - " --prefix DIR Directory to install things to.\n" - " --warnings LIST Compiler warnings to use.\n"; + IO::print(IO::cerr, "Usage: %s [options] [ ...]\n\n", argv0); + IO::print(IO::cerr, "Options:\n"); + IO::print(IO::cerr, helpmsg); } } FS::Path Builder::get_package_location(const string &name) { if(verbose>=3) - cout<<"Looking for package "< argv; - argv.push_back("pkg-config"); - argv.push_back("--variable=source"); - argv.push_back(name); - if(verbose>=4) - cout<<"Running "<=3) - cout<=3) - cout<<"Reading "<add_depend(new Install(*this, *spkg, *pc)); } - - tarballs->add_depend(new TarBall(*this, *spkg)); } // Find dependencies until no new targets are created @@ -583,7 +616,7 @@ int Builder::create_targets() Target *tgt=get_target((cwd/ *i).str()); if(!tgt) { - cerr<<"Unknown what-if target "<<*i<<'\n'; + IO::print(IO::cerr, "Unknown what-if target %s\n", *i); return -1; } tgt->touch(); @@ -599,7 +632,7 @@ int Builder::create_targets() tgt=get_target((cwd/ *i).str()); if(!tgt) { - cerr<<"I don't know anything about "<<*i<<'\n'; + IO::print("I don't know anything about %s\n", *i); return -1; } if(tgt==world) @@ -627,7 +660,7 @@ int Builder::create_targets() return 0; } -Target *Builder::get_header(const Msp::FS::Path &fn) +Target *Builder::get_header(const FS::Path &fn) { Target *tgt=get_target(fn.str()); if(tgt) return tgt; @@ -697,11 +730,11 @@ int Builder::do_build() unsigned total=cmdline->count_rebuild(); if(!total) { - cout<<"Already up to date\n"; + IO::print("Already up to date\n"); return 0; } if(verbose>=1) - cout<<"Will build "< actions; @@ -722,10 +755,7 @@ int Builder::do_build() actions.push_back(action); if(show_progress) - { - cout<get_buildable() && (tgt->get_package()==main_pkg || clean>=2)) + if(tgt->is_buildable() && (tgt->get_package()==main_pkg || clean>=2)) clean_tgts.insert(tgt); const TargetList &deps=tgt->get_depends(); @@ -800,24 +830,28 @@ void Builder::package_help() const Config &config=main_pkg->get_config(); const Config::OptionMap &options=config.get_options(); - cout<<"Required packages:\n "; + IO::print("Required packages:\n "); const PackageList &requires=main_pkg->get_requires(); for(PackageList::const_iterator i=requires.begin(); i!=requires.end(); ++i) { if(i!=requires.begin()) - cout<<", "; - cout<<(*i)->get_name(); + IO::print(", "); + IO::print((*i)->get_name()); } - cout<<"\n\n"; - cout<<"Package configuration:\n"; + IO::print("\n\nPackage configuration:\n"); for(Config::OptionMap::const_iterator i=options.begin(); i!=options.end(); ++i) { const Config::Option &opt=i->second; - cout<<" "< Builder::reg; +string Builder::usagemsg; +string Builder::helpmsg; Builder::Loader::Loader(Builder &b, const FS::Path &s):