From 8bc8db44c47cd2906c57dccbfb589e41eff7f694 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 23 Aug 2007 17:18:24 +0000 Subject: [PATCH] Add DependencyCache to speed up build preparation --- source/builder.cpp | 3 ++ source/dependencycache.cpp | 79 ++++++++++++++++++++++++++++++++++++++ source/dependencycache.h | 39 +++++++++++++++++++ source/package.cpp | 7 +++- source/package.h | 3 ++ source/sourcefile.cpp | 22 +++++++---- 6 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 source/dependencycache.cpp create mode 100644 source/dependencycache.h diff --git a/source/builder.cpp b/source/builder.cpp index 98e2a07..353bc29 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -583,6 +583,9 @@ int Builder::create_targets() world->prepare(); } + for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i) + i->second->get_deps_cache().save(); + return 0; } diff --git a/source/dependencycache.cpp b/source/dependencycache.cpp new file mode 100644 index 0000000..cc11383 --- /dev/null +++ b/source/dependencycache.cpp @@ -0,0 +1,79 @@ +/* $Id$ + +This file is part of builder +Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#include "builder.h" +#include "dependencycache.h" +#include "package.h" + +using namespace std; +using namespace Msp; + +DependencyCache::DependencyCache(Package &p): + package(p), + changed(false) +{ } + +const StringList &DependencyCache::get_deps(const string &tgt) const +{ + DepsMap::const_iterator i=deps.find(tgt); + if(i==deps.end()) + { + static StringList dummy; + return dummy; + } + return i->second; +} + +void DependencyCache::set_deps(const string &tgt, const StringList &d) +{ + deps[tgt]=d; + changed=true; +} + +/** +Saves the depencency cache. If there are no cached dependencies or they +haven't been changed, does nothing. +*/ +void DependencyCache::save() const +{ + if(deps.empty() || !changed || package.get_builder().get_dry_run()) + return; + + ofstream out((package.get_source()/".deps").str().c_str()); + if(!out) + return; + + for(DepsMap::const_iterator i=deps.begin(); i!=deps.end(); ++i) + { + out<first; + for(StringList::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) + out<<'|'<<*j; + out<<'\n'; + } +} + +void DependencyCache::load() +{ + string fn=(package.get_source()/".deps").str(); + ifstream in(fn.c_str()); + if(!in) + return; + + string line; + while(getline(in, line)) + { + vector parts=split(line, '|'); + deps[parts[0]]=StringList(parts.begin()+1, parts.end()); + } + + struct stat st; + Path::stat(fn, st); + mtime=Time::TimeStamp::from_unixtime(st.st_mtime); +} diff --git a/source/dependencycache.h b/source/dependencycache.h new file mode 100644 index 0000000..5cde40d --- /dev/null +++ b/source/dependencycache.h @@ -0,0 +1,39 @@ +/* $Id$ + +This file is part of builder +Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef DEPENDENCYCACHE_H_ +#define DEPENDENCYCACHE_H_ + +#include +#include "misc.h" + +class Package; + +/** +Stores dependencies to avoid expensive operations during DAG building phase. +The dependencies are stored in a map with target name as key and a list of +strings as value. The targets are free to store whatever they want here. +*/ +class DependencyCache +{ +public: + DependencyCache(Package &p); + void set_deps(const std::string &tgt, const StringList &d); + const StringList &get_deps(const std::string &tgt) const; + const Msp::Time::TimeStamp &get_mtime() const { return mtime; } + void load(); + void save() const; +private: + typedef std::map DepsMap; + + Package &package; + DepsMap deps; + Msp::Time::TimeStamp mtime; + bool changed; +}; + +#endif diff --git a/source/package.cpp b/source/package.cpp index 372cf28..8fb2b4d 100644 --- a/source/package.cpp +++ b/source/package.cpp @@ -26,6 +26,7 @@ Package::Package(Builder &b, const string &n, const Path::Path &s): source(s), config(*this), conf_done(false), + deps_cache(*this), use_pkgconfig(true), need_path(false) { @@ -167,6 +168,8 @@ void Package::configure(const StringMap &opts, unsigned flag) (*i)->set_path(config.get_option((*i)->get_name()+"_path").value); (*i)->configure(opts, flag&2); } + + deps_cache.load(); } create_build_info(); @@ -225,7 +228,8 @@ Package::Package(Builder &b, const string &n, const vector &info): name(n), buildable(false), config(*this), - conf_done(false) + conf_done(false), + deps_cache(*this) { for(vector::const_iterator i=info.begin(); i!=info.end(); ++i) { @@ -358,6 +362,7 @@ void Package::create_build_info() export_binfo.unique(); } + Package::Loader::Loader(Package &p): pkg(p) { diff --git a/source/package.h b/source/package.h index 68af269..90ee6bc 100644 --- a/source/package.h +++ b/source/package.h @@ -15,6 +15,7 @@ Distributed under the LGPL #include "component.h" #include "condition.h" #include "config.h" +#include "dependencycache.h" #include "feature.h" #include "packageref.h" @@ -81,6 +82,7 @@ public: const std::string &get_arch() const { return config.get_option("arch").value; } LibMode get_library_mode() const; const PathList &get_tar_files() const { return tar_files; } + DependencyCache &get_deps_cache() const { return deps_cache; } void resolve_refs(); void configure(const StringMap &, unsigned); @@ -103,6 +105,7 @@ private: ComponentList components; Config config; bool conf_done; + mutable DependencyCache deps_cache; PathList tar_files; bool use_pkgconfig; diff --git a/source/sourcefile.cpp b/source/sourcefile.cpp index f24dd07..57866aa 100644 --- a/source/sourcefile.cpp +++ b/source/sourcefile.cpp @@ -26,15 +26,23 @@ from Builder. */ void SourceFile::find_depends() { - ifstream in(name.c_str()); - if(!in) return; + DependencyCache &deps_cache=comp->get_package().get_deps_cache(); + if(mtime>deps_cache.get_mtime()) + { + ifstream in(name.c_str()); + if(!in) return; + + Regex r_include("^[ \t]*#include[ \t]+([\"<].*)[\">]"); - Regex r_include("^[ \t]*#include[ \t]+([\"<].*)[\">]"); + string line; + while(getline(in, line)) + if(RegMatch match=r_include.match(line)) + includes.push_back(match[1].str); - string line; - while(getline(in, line)) - if(RegMatch match=r_include.match(line)) - includes.push_back(match[1].str); + deps_cache.set_deps(name, includes); + } + else + includes=deps_cache.get_deps(name); const StringList &incpath=comp->get_build_info().incpath; const string &arch=comp->get_package().get_arch(); -- 2.45.2