From bd2a50ecb9f582c6e9569ffc9f33d41f10363c5f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 10 Apr 2012 18:07:22 +0300 Subject: [PATCH] Move file-to-target mapping to a separate class --- source/binary.cpp | 2 +- source/builder.cpp | 193 +------------------------------- source/builder.h | 30 +---- source/component.cpp | 8 +- source/filetarget.cpp | 2 +- source/install.cpp | 2 +- source/objectfile.cpp | 2 +- source/sourcefile.cpp | 2 +- source/virtualfilesystem.cpp | 207 +++++++++++++++++++++++++++++++++++ source/virtualfilesystem.h | 55 ++++++++++ 10 files changed, 278 insertions(+), 225 deletions(-) create mode 100644 source/virtualfilesystem.cpp create mode 100644 source/virtualfilesystem.h diff --git a/source/binary.cpp b/source/binary.cpp index 41db493..4728cd1 100644 --- a/source/binary.cpp +++ b/source/binary.cpp @@ -41,7 +41,7 @@ void Binary::find_depends() 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, libpath, libmode); + Target *lib = builder.get_vfs().find_library(*i, libpath, libmode); if(lib) { dep_libs.push_back(lib); diff --git a/source/builder.cpp b/source/builder.cpp index 57764b7..bd1ee1a 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -37,20 +37,10 @@ using namespace std; using namespace Msp; -namespace { - -void update_hash(string &hash, const string &value) -{ - for(unsigned i=0; i(i->second); - return 0; -} - -Target *Builder::get_header(const string &include, const FS::Path &from, const list &path) -{ - string hash(8, 0); - if(include[0]=='\"') - update_hash(hash, from.str()); - for(list::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::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j) - tgt = get_header(cwd/ *j/fn); - for(list::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 &path, LibMode mode) -{ - string hash(8, 0); - for(list::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 parts = split(pt, '-'); @@ -517,11 +399,6 @@ void Builder::add_target(Target *t) 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) @@ -647,7 +524,7 @@ int Builder::create_targets() // 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); @@ -662,9 +539,9 @@ int Builder::create_targets() { 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); @@ -683,68 +560,6 @@ int Builder::create_targets() 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(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"); diff --git a/source/builder.h b/source/builder.h index 25f0645..fc160d3 100644 --- a/source/builder.h +++ b/source/builder.h @@ -13,6 +13,7 @@ #include "problem.h" #include "target.h" #include "toolchain.h" +#include "virtualfilesystem.h" class Analyzer; class Config; @@ -72,16 +73,14 @@ private: 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; @@ -124,23 +123,8 @@ public: /** 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; } @@ -149,6 +133,7 @@ public: 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. */ @@ -173,15 +158,6 @@ private: 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(); diff --git a/source/component.cpp b/source/component.cpp index 24dce77..a7dfc34 100644 --- a/source/component.cpp +++ b/source/component.cpp @@ -120,7 +120,7 @@ void Component::create_targets() const list 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); @@ -149,7 +149,7 @@ void Component::create_targets() const 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(tgt); else ft = new File(builder, pkg, *i); @@ -161,7 +161,7 @@ void Component::create_targets() const 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(tgt); else source = new File(builder, pkg, source_filenames.front()); @@ -181,7 +181,7 @@ void Component::create_targets() const 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()); diff --git a/source/filetarget.cpp b/source/filetarget.cpp index 1deead0..bc4e110 100644 --- a/source/filetarget.cpp +++ b/source/filetarget.cpp @@ -14,7 +14,7 @@ FileTarget::FileTarget(Builder &b, const Package *p, const FS::Path &a): path(a), size(0) { - builder.register_path(path, this); + builder.get_vfs().register_path(path, this); if(FS::Stat st = FS::lstat(path)) { diff --git a/source/install.cpp b/source/install.cpp index 4040d19..7c39ed6 100644 --- a/source/install.cpp +++ b/source/install.cpp @@ -25,7 +25,7 @@ Install::Install(Builder &b, const SourcePackage &p, FileTarget &s, const std::s 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() diff --git a/source/objectfile.cpp b/source/objectfile.cpp index 4fb2ee4..e13b082 100644 --- a/source/objectfile.cpp +++ b/source/objectfile.cpp @@ -50,7 +50,7 @@ void ObjectFile::find_depends(Target *tgt) const list &includes = src->get_includes(); for(list::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); } diff --git a/source/sourcefile.cpp b/source/sourcefile.cpp index 58c498e..062665c 100644 --- a/source/sourcefile.cpp +++ b/source/sourcefile.cpp @@ -75,7 +75,7 @@ void SourceFile::find_depends() FS::Path dir = FS::dirname(path); for(list::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); } diff --git a/source/virtualfilesystem.cpp b/source/virtualfilesystem.cpp new file mode 100644 index 0000000..e89b2dd --- /dev/null +++ b/source/virtualfilesystem.cpp @@ -0,0 +1,207 @@ +#include +#include +#include +#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(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 &path) +{ + string hash(8, 0); + if(include[0]=='\"') + update_hash(hash, from.str()); + for(list::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::const_iterator j=path.begin(); (!tgt && j!=path.end()); ++j) + tgt = get_header(FS::Path(*j)/fn); + for(list::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 &path, LibMode mode) +{ + string hash(8, 0); + for(list::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(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; +} diff --git a/source/virtualfilesystem.h b/source/virtualfilesystem.h new file mode 100644 index 0000000..16f8c6d --- /dev/null +++ b/source/virtualfilesystem.h @@ -0,0 +1,55 @@ +#ifndef VIRTUALFILESYSTEM_H_ +#define VIRTUALFILESYSTEM_H_ + +#include +#include +#include + +class Builder; +class FileTarget; + +class VirtualFileSystem +{ +public: + typedef std::list SearchPath; + +private: + typedef std::map 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 -- 2.45.2