const list<string> &libs = c->get_build_info().libs;
for(StringList::const_iterator i=libs.begin(); i!=libs.end(); ++i)
{
- Target *lib = builder.get_library(*i, libpath, libmode);
+ Target *lib = builder.get_vfs().find_library(*i, libpath, libmode);
if(lib)
{
dep_libs.push_back(lib);
using namespace std;
using namespace Msp;
-namespace {
-
-void update_hash(string &hash, const string &value)
-{
- for(unsigned i=0; i<value.size(); ++i)
- hash[i%hash.size()] ^= value[i];
-}
-
-}
-
-
Builder::Builder(int argc, char **argv):
main_pkg(0),
native_arch(*this, string()),
+ vfs(*this),
analyzer(0),
build(false),
clean(0),
return 0;
}
-FileTarget *Builder::get_target_by_path(const FS::Path &p) const
-{
- TargetMap::const_iterator i = targets_by_path.find(p.str());
- if(i!=targets_by_path.end())
- return static_cast<FileTarget *>(i->second);
- return 0;
-}
-
-Target *Builder::get_header(const string &include, const FS::Path &from, const list<string> &path)
-{
- string hash(8, 0);
- if(include[0]=='\"')
- update_hash(hash, from.str());
- for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
- update_hash(hash, *i);
-
- string id = hash+include;
- TargetMap::iterator i = includes.find(id);
- if(i!=includes.end())
- return i->second;
-
- static string cxx_ver;
- if(cxx_ver.empty())
- {
- // XXX This needs to go elsewhere
- /*StringList argv;
- argv.push_back(current_arch->get_tool("CXX"));
- argv.push_back("--version");
- if(RegMatch m = Regex("[0-9]\\.[0-9.]+").match(run_command(argv)))
- {
- cxx_ver = m[0].str;
- while(!cxx_ver.empty() && !FS::is_dir(FS::Path("/usr/include/c++")/cxx_ver))
- {
- string::size_type dot = cxx_ver.rfind('.');
- if(dot==string::npos)
- break;
- cxx_ver.erase(dot);
- }
- if(verbose>=5)
- IO::print("C++ version is %s\n", cxx_ver);
- }
- else*/
- cxx_ver = "-";
- }
-
- string fn = include.substr(1);
- if(verbose>=5)
- IO::print("Looking for include %s from %s with path %s\n", fn, from, join(path.begin(), path.end()));
-
- StringList syspath;
- if(current_arch->is_native())
- syspath.push_back("/usr/include");
- else
- syspath.push_back("/usr/"+current_arch->get_cross_prefix()+"/include");
- if(cxx_ver!="-")
- syspath.push_back((FS::Path("/usr/include/c++/")/cxx_ver).str());
-
- Target *tgt = 0;
- if(include[0]=='\"')
- tgt = get_header(FS::Path(from)/fn);
- for(list<string>::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
- tgt = get_header(cwd/ *j/fn);
- for(list<string>::const_iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
- tgt = get_header(FS::Path(*j)/fn);
-
- includes.insert(TargetMap::value_type(id, tgt));
-
- return tgt;
-}
-
-Target *Builder::get_library(const string &lib, const list<string> &path, LibMode mode)
-{
- string hash(8, 0);
- for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
- update_hash(hash, *i);
-
- string id = hash+string(1, mode)+lib;
- TargetMap::iterator i = libraries.find(id);
- if(i!=libraries.end())
- return i->second;
-
- StringList syspath;
- if(current_arch->is_native())
- {
- syspath.push_back("/lib");
- syspath.push_back("/usr/lib");
- if(current_arch->match_name("pc-32-linux"))
- syspath.push_back("/usr/lib/i386-linux-gnu");
- else if(current_arch->match_name("pc-64-linux"))
- syspath.push_back("/usr/lib/x86_64-linux-gnu");
- }
- else
- syspath.push_back("/usr/"+current_arch->get_cross_prefix()+"/lib");
-
- if(verbose>=5)
- IO::print("Looking for library %s with path %s\n", lib, join(path.begin(), path.end()));
-
- Target *tgt = 0;
- for(StringList::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
- tgt = get_library(lib, cwd/ *j, mode);
- for(StringList::iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
- tgt = get_library(lib, *j, mode);
-
- libraries.insert(TargetMap::value_type(id, tgt));
-
- return tgt;
-}
-
void Builder::apply_profile_template(Config &config, const string &pt) const
{
vector<string> parts = split(pt, '-');
new_tgts.push_back(t);
}
-void Builder::register_path(const FS::Path &path, FileTarget *t)
-{
- targets_by_path.insert(TargetMap::value_type(path.str(), t));
-}
-
void Builder::usage(const char *reason, const char *argv0, bool brief)
{
if(reason)
// Apply what-ifs
for(StringList::iterator i=what_if.begin(); i!=what_if.end(); ++i)
{
- FileTarget *tgt = get_target_by_path(cwd/ *i);
+ FileTarget *tgt = vfs.get_target(cwd/ *i);
if(!tgt)
{
IO::print(IO::cerr, "Unknown what-if target %s\n", *i);
{
Target *tgt = get_target(*i);
if(!tgt)
- tgt = get_target_by_path(*i);
+ tgt = vfs.get_target(*i);
if(!tgt)
- tgt = get_target_by_path(cwd/ *i);
+ tgt = vfs.get_target(cwd/ *i);
if(!tgt)
{
IO::print("I don't know anything about %s\n", *i);
return 0;
}
-Target *Builder::get_header(const FS::Path &fn)
-{
- Target *tgt = get_target_by_path(fn);
- if(tgt) return tgt;
-
- if(FS::is_reg(fn))
- {
- tgt = new SystemHeader(*this, fn.str());
- return tgt;
- }
- return 0;
-}
-
-Target *Builder::get_library(const string &lib, const FS::Path &path, LibMode mode)
-{
- // Populate a list of candidate filenames
- StringList candidates;
-
- if(mode!=ALL_STATIC)
- {
- // XXX Should probably let the Architecture populate the list
- if(current_arch->get_system()=="windows")
- {
- candidates.push_back("lib"+lib+".dll");
- candidates.push_back(lib+".dll");
- }
- else
- candidates.push_back("lib"+lib+".so");
- }
-
- /* Static libraries are always considered, since sometimes shared versions
- may not be available */
- candidates.push_back("lib"+lib+".a");
- if(current_arch->get_system()=="windows")
- candidates.push_back("lib"+lib+".dll.a");
-
- for(StringList::iterator i=candidates.begin(); i!=candidates.end(); ++i)
- {
- FS::Path full = path/ *i;
- Target *tgt = get_target_by_path(full);
-
- if(tgt)
- {
- Target *real_tgt = tgt->get_real_target();
-
- /* Ignore dynamic libraries from local packages unless library mode is
- DYNAMIC */
- if(dynamic_cast<SharedLibrary *>(real_tgt) && mode!=DYNAMIC)
- continue;
- else if(tgt)
- return tgt;
- }
- else if(FS::is_reg(full))
- {
- tgt = new SystemLibrary(*this, full.str());
- return tgt;
- }
- }
-
- return 0;
-}
-
int Builder::do_build()
{
Target *cmdline = get_target("cmdline");
#include "problem.h"
#include "target.h"
#include "toolchain.h"
+#include "virtualfilesystem.h"
class Analyzer;
class Config;
bool no_externals;
TargetMap targets;
- TargetMap targets_by_path;
TargetList new_tgts;
- TargetMap includes;
- TargetMap libraries;
Architecture native_arch;
Architecture *current_arch;
StringMap cross_prefixes;
ProfileTemplateMap profile_tmpl;
Toolchain toolchain;
+ VirtualFileSystem vfs;
ProblemList problems;
Analyzer *analyzer;
/** Looks up a target by name. Returns 0 if no such target exists. */
Target *get_target(const std::string &) const;
- FileTarget *get_target_by_path(const Msp::FS::Path &) const;
-
const TargetMap &get_targets() const { return targets; }
- /** Tries to locate a header based on location of including file and include
- 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 *get_header(const std::string &, const Msp::FS::Path &, const StringList &);
-
- /** Tries to locate a library in a library path. The library name should be
- the same as would be given to the linker with -l, i.e. without the "lib"
- prefix or extension. Considers known targets as well as existing files. If
- a matching target is not found but a file exists, a new SystemLibrary target
- will be created and returned. */
- Target *get_library(const std::string &, const StringList &, LibMode);
-
const Msp::FS::Path &get_cwd() const { return cwd; }
const Architecture &get_current_arch() const { return *current_arch; }
const Architecture &get_native_arch() const { return native_arch; }
void apply_profile_template(Config &, const std::string &) const;
const Toolchain &get_toolchain() const { return toolchain; }
+ VirtualFileSystem &get_vfs() { return vfs; }
/** Adds a target to both the target map and the new target queue. Called
from Target constructor. */
shouldn't be attempted. */
int create_targets();
- /**
- Check if a header exists, either as a target or a file. Returns an existing
- target of one was found, or a new SystemHeader target if there was no known
- target but the file exists.
- */
- Target *get_header(const Msp::FS::Path &);
-
- Target *get_library(const std::string &, const Msp::FS::Path &, LibMode);
-
/** Supervises the build process, starting new actions when slots become
available. */
int do_build();
list<Target *> files;
for(PathList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
{
- FileTarget *file = builder.get_target_by_path(*i);
+ FileTarget *file = builder.get_vfs().get_target(*i);
if(!file)
file = new File(builder, *i);
files.push_back(file);
for(PathList::const_iterator i=source_filenames.begin(); i!=source_filenames.end(); ++i)
{
FileTarget *ft;
- if(Target *tgt = builder.get_target_by_path(*i))
+ if(Target *tgt = builder.get_vfs().get_target(*i))
ft = dynamic_cast<FileTarget *>(tgt);
else
ft = new File(builder, pkg, *i);
const Tool &dcomp = toolchain.get_tool("DATA");
File *source;
- if(Target *tgt = builder.get_target_by_path(source_filenames.front()))
+ if(Target *tgt = builder.get_vfs().get_target(source_filenames.front()))
source = dynamic_cast<File *>(tgt);
else
source = new File(builder, pkg, source_filenames.front());
string ext = FS::extpart(FS::basename(*i));
if(ext==".h")
{
- FileTarget *hdr = builder.get_target_by_path(*i);
+ FileTarget *hdr = builder.get_vfs().get_target(*i);
if(!hdr)
hdr = new Header(builder, *this, i->str());
path(a),
size(0)
{
- builder.register_path(path, this);
+ builder.get_vfs().register_path(path, this);
if(FS::Stat st = FS::lstat(path))
{
link = FS::dirname(path)/FS::basename(shlib->get_path());
if(!link.empty())
- builder.register_path(link, this);
+ builder.get_vfs().register_path(link, this);
}
Target *Install::get_real_target()
const list<string> &includes = src->get_includes();
for(list<string>::const_iterator i=includes.begin(); i!=includes.end(); ++i)
{
- Target *hdr = builder.get_header(*i, spath, incpath);
+ Target *hdr = builder.get_vfs().find_header(*i, spath, incpath);
if(hdr && find(depends.begin(), depends.end(), hdr)==depends.end())
add_depend(hdr);
}
FS::Path dir = FS::dirname(path);
for(list<string>::iterator i=includes.begin(); i!=includes.end(); ++i)
{
- Target *hdr = builder.get_header(*i, dir, incpath);
+ Target *hdr = builder.get_vfs().find_header(*i, dir, incpath);
if(hdr)
add_depend(hdr);
}
--- /dev/null
+#include <msp/fs/stat.h>
+#include <msp/io/print.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "misc.h"
+#include "header.h"
+#include "sharedlibrary.h"
+#include "systemlibrary.h"
+#include "virtualfilesystem.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace {
+
+void update_hash(string &hash, const string &value)
+{
+ for(unsigned i=0; i<value.size(); ++i)
+ hash[i%hash.size()] ^= value[i];
+}
+
+}
+
+
+VirtualFileSystem::VirtualFileSystem(Builder &b):
+ builder(b)
+{
+}
+
+FileTarget *VirtualFileSystem::get_target(const FS::Path &p) const
+{
+ TargetMap::const_iterator i = targets.find(p.str());
+ if(i!=targets.end())
+ return static_cast<FileTarget *>(i->second);
+ return 0;
+}
+
+void VirtualFileSystem::register_path(const FS::Path &path, FileTarget *t)
+{
+ targets.insert(TargetMap::value_type(path.str(), t));
+}
+
+FileTarget *VirtualFileSystem::find_header(const string &include, const FS::Path &from, const list<string> &path)
+{
+ string hash(8, 0);
+ if(include[0]=='\"')
+ update_hash(hash, from.str());
+ for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
+ update_hash(hash, *i);
+
+ string id = hash+include;
+ TargetMap::iterator i = include_cache.find(id);
+ if(i!=include_cache.end())
+ return i->second;
+
+ static string cxx_ver;
+ if(cxx_ver.empty())
+ {
+ // XXX This needs to go elsewhere
+ /*StringList argv;
+ argv.push_back(current_arch->get_tool("CXX"));
+ argv.push_back("--version");
+ if(RegMatch m = Regex("[0-9]\\.[0-9.]+").match(run_command(argv)))
+ {
+ cxx_ver = m[0].str;
+ while(!cxx_ver.empty() && !FS::is_dir(FS::Path("/usr/include/c++")/cxx_ver))
+ {
+ string::size_type dot = cxx_ver.rfind('.');
+ if(dot==string::npos)
+ break;
+ cxx_ver.erase(dot);
+ }
+ if(verbose>=5)
+ IO::print("C++ version is %s\n", cxx_ver);
+ }
+ else*/
+ cxx_ver = "-";
+ }
+
+ string fn = include.substr(1);
+ if(builder.get_verbose()>=5)
+ IO::print("Looking for include %s from %s with path %s\n", fn, from, join(path.begin(), path.end()));
+
+ SearchPath syspath;
+ const Architecture &arch = builder.get_current_arch();
+ if(arch.is_native())
+ syspath.push_back("/usr/include");
+ else
+ syspath.push_back("/usr/"+arch.get_cross_prefix()+"/include");
+ if(cxx_ver!="-")
+ syspath.push_back((FS::Path("/usr/include/c++/")/cxx_ver).str());
+
+ FileTarget *tgt = 0;
+ if(include[0]=='\"')
+ tgt = get_header(FS::Path(from)/fn);
+ for(list<string>::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
+ tgt = get_header(FS::Path(*j)/fn);
+ for(list<string>::const_iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
+ tgt = get_header(FS::Path(*j)/fn);
+
+ include_cache.insert(TargetMap::value_type(id, tgt));
+
+ return tgt;
+}
+
+FileTarget *VirtualFileSystem::find_library(const string &lib, const list<string> &path, LibMode mode)
+{
+ string hash(8, 0);
+ for(list<string>::const_iterator i=path.begin(); i!=path.end(); ++i)
+ update_hash(hash, *i);
+
+ string id = hash+string(1, mode)+lib;
+ TargetMap::iterator i = library_cache.find(id);
+ if(i!=library_cache.end())
+ return i->second;
+
+ SearchPath syspath;
+ const Architecture &arch = builder.get_current_arch();
+ if(arch.is_native())
+ {
+ syspath.push_back("/lib");
+ syspath.push_back("/usr/lib");
+ if(arch.match_name("pc-32-linux"))
+ syspath.push_back("/usr/lib/i386-linux-gnu");
+ else if(arch.match_name("pc-64-linux"))
+ syspath.push_back("/usr/lib/x86_64-linux-gnu");
+ }
+ else
+ syspath.push_back("/usr/"+arch.get_cross_prefix()+"/lib");
+
+ if(builder.get_verbose()>=5)
+ IO::print("Looking for library %s with path %s\n", lib, join(path.begin(), path.end()));
+
+ FileTarget *tgt = 0;
+ for(StringList::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j)
+ tgt = get_library(lib, *j, mode);
+ for(StringList::iterator j=syspath.begin(); (!tgt && j!=syspath.end()); ++j)
+ tgt = get_library(lib, *j, mode);
+
+ library_cache.insert(TargetMap::value_type(id, tgt));
+
+ return tgt;
+}
+
+FileTarget *VirtualFileSystem::get_header(const FS::Path &fn)
+{
+ FileTarget *tgt = get_target(fn);
+ if(tgt)
+ return tgt;
+
+ if(FS::is_reg(fn))
+ {
+ tgt = new SystemHeader(builder, fn.str());
+ return tgt;
+ }
+ return 0;
+}
+
+FileTarget *VirtualFileSystem::get_library(const string &lib, const FS::Path &path, LibMode mode)
+{
+ // Populate a list of candidate filenames
+ StringList candidates;
+
+ const Architecture &arch = builder.get_current_arch();
+ if(mode!=ALL_STATIC)
+ {
+ // XXX Should probably let the Architecture populate the list
+ if(arch.get_system()=="windows")
+ {
+ candidates.push_back("lib"+lib+".dll");
+ candidates.push_back(lib+".dll");
+ }
+ else
+ candidates.push_back("lib"+lib+".so");
+ }
+
+ /* Static libraries are always considered, since sometimes shared versions
+ may not be available */
+ candidates.push_back("lib"+lib+".a");
+ if(arch.get_system()=="windows")
+ candidates.push_back("lib"+lib+".dll.a");
+
+ for(StringList::iterator i=candidates.begin(); i!=candidates.end(); ++i)
+ {
+ FS::Path full = path/ *i;
+ FileTarget *tgt = get_target(full);
+
+ if(tgt)
+ {
+ Target *real_tgt = tgt->get_real_target();
+
+ /* Ignore dynamic libraries from local packages unless library mode is
+ DYNAMIC */
+ if(dynamic_cast<SharedLibrary *>(real_tgt) && mode!=DYNAMIC)
+ continue;
+ else if(tgt)
+ return tgt;
+ }
+ else if(FS::is_reg(full))
+ {
+ tgt = new SystemLibrary(builder, full.str());
+ return tgt;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef VIRTUALFILESYSTEM_H_
+#define VIRTUALFILESYSTEM_H_
+
+#include <list>
+#include <map>
+#include <msp/fs/path.h>
+
+class Builder;
+class FileTarget;
+
+class VirtualFileSystem
+{
+public:
+ typedef std::list<std::string> SearchPath;
+
+private:
+ typedef std::map<std::string, FileTarget *> TargetMap;
+
+ Builder &builder;
+ TargetMap targets;
+ TargetMap include_cache;
+ TargetMap library_cache;
+
+public:
+ VirtualFileSystem(Builder &);
+
+ FileTarget *get_target(const Msp::FS::Path &) const;
+
+ void register_path(const Msp::FS::Path &, FileTarget *);
+
+ /** Tries to locate a header based on location of including file and include
+ 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. */
+ FileTarget *find_header(const std::string &, const Msp::FS::Path &, const SearchPath &);
+
+ /** Tries to locate a library in a library path. The library name should be
+ the same as would be given to the linker with -l, i.e. without the "lib"
+ prefix or extension. Considers known targets as well as existing files. If
+ a matching target is not found but a file exists, a new SystemLibrary target
+ will be created and returned. */
+ FileTarget *find_library(const std::string &, const SearchPath &, LibMode);
+
+private:
+ /**
+ Check if a header exists, either as a target or a file. Returns an existing
+ target of one was found, or a new SystemHeader target if there was no known
+ target but the file exists.
+ */
+ FileTarget *get_header(const Msp::FS::Path &);
+
+ FileTarget *get_library(const std::string &, const Msp::FS::Path &, LibMode);
+};
+
+#endif