*/
#include <set>
+#include <cstdlib>
#include <sys/utsname.h>
#include <msp/core/except.h>
#include <msp/core/getopt.h>
const vector<string> &args=getopt.get_args();
for(vector<string>::const_iterator i=args.begin(); i!=args.end(); ++i)
{
- unsigned equal=i->find('=');
+ string::size_type equal=i->find('=');
if(equal!=string::npos)
cmdline_options.insert(StringMap::value_type(i->substr(0, equal), i->substr(equal+1)));
else
native_arch->set_tool("AR", "ar");
load_build_file((FS::get_sys_data_dir(argv[0], "builder")/"builderrc").str());
- load_build_file((FS::get_home_dir()/".builderrc").str());
+ load_build_file((FS::get_user_data_dir("builder")/"rc").str());
if(arch.empty())
current_arch=native_arch;
int Builder::main()
{
+ if(prefix.str()!="/usr")
+ {
+ FS::Path pcdir=prefix/"lib"/"pkgconfig";
+ if(const char *pcp=getenv("PKG_CONFIG_PATH"))
+ {
+ vector<string> path=split(pcp, ':');
+ bool found=false;
+ for(vector<string>::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))
{
if(help)
if(dynamic_cast<SourcePackage *>(*i))
IO::print("*");
unsigned count=0;
- unsigned ood_count=0;
+ unsigned to_be_built=0;
for(TargetMap::iterator j=targets.begin(); j!=targets.end(); ++j)
if(j->second->get_package()==*i)
{
++count;
if(j->second->get_rebuild())
- ++ood_count;
+ ++to_be_built;
}
if(count)
{
IO::print(" (%d targets", count);
- if(ood_count)
- IO::print(", %d out-of-date", ood_count);
+ if(to_be_built)
+ IO::print(", %d to be built", to_be_built);
IO::print(")");
}
IO::print("\n");
IO::print(IO::cerr, "The following problems were detected:\n");
for(ProblemList::iterator i=problems.begin(); i!=problems.end(); ++i)
IO::print(IO::cerr, " %s: %s\n", i->package, i->descr);
- IO::print(IO::cerr, "Please fix them and try again.\n");
+ if(!analyzer)
+ 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)
return exit_code;
}
+string Builder::run_pkgconfig(const string &pkg, const string &what)
+{
+ list<string> 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()));
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;
}
cxx_ver=Regex("[0-9]\\.[0-9.]+").match(run_command(argv))[0].str;
while(!cxx_ver.empty() && !FS::is_dir(FS::Path("/usr/include/c++")/cxx_ver))
{
- unsigned dot=cxx_ver.rfind('.');
+ string::size_type dot=cxx_ver.rfind('.');
if(dot==string::npos)
break;
cxx_ver.erase(dot);
if(verbose>=3)
IO::print("Looking for package %s\n", name);
- // Try to get source directory with pkgconfig
- list<string> argv;
- argv.push_back("pkg-config");
- argv.push_back("--variable=source");
- argv.push_back(name);
- if(verbose>=4)
- IO::print("Running %s\n", join(argv.begin(), argv.end()));
- string srcdir=strip(run_command(argv));
- if(!srcdir.empty())
- return srcdir;
+ try
+ {
+ // Try to get source directory with pkgconfig
+ string srcdir=strip(run_pkgconfig(name, "source"));
+ if(!srcdir.empty())
+ return srcdir;
+ }
+ catch(...)
+ { }
if(pkg_dirs.empty())
{
cmdline->add_depend(tgt);
}
- /* If world is to be built, prepare cmdline. If not, add cmdline to world
- and prepare world. I don't really like this, but it keeps the graph
- acyclic.
-
- XXX Could we skip preparing targets we are not interested in? */
- if(build_world)
- cmdline->prepare();
- else
- {
- world->add_depend(cmdline);
- world->prepare();
- }
+ cmdline->prepare();
for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
if(SourcePackage *spkg=dynamic_cast<SourcePackage *>(i->second))
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;
{
Target *cmdline=get_target("cmdline");
- unsigned total=cmdline->count_rebuild();
+ unsigned total=0;
+ for(map<string, Target *>::const_iterator i=targets.begin(); i!=targets.end(); ++i)
+ if(i->second->is_buildable() && i->second->get_rebuild())
+ ++total;
+
if(!total)
{
IO::print("Already up to date\n");
Target *tgt=queue.front();
queue.erase(queue.begin());
- if(tgt->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();