From: Mikko Rasa Date: Wed, 15 Aug 2007 09:40:23 +0000 (+0000) Subject: Move the logic for creating targets into the Component class X-Git-Tag: 0.9~31 X-Git-Url: http://git.tdb.fi/?p=builder.git;a=commitdiff_plain;h=b5ad62c2c4c7eeadd881e3f157bde96e4dd2cc0e Move the logic for creating targets into the Component class Make Install target figure out the installation path by itself Add targets to Builder automatically from Target constructor --- diff --git a/source/builder.cpp b/source/builder.cpp index 38a7139..9624296 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -11,15 +11,12 @@ #include "action.h" #include "analyzer.h" #include "builder.h" -#include "executable.h" #include "header.h" #include "install.h" #include "misc.h" -#include "objectfile.h" #include "package.h" #include "pkgconfig.h" #include "sharedlibrary.h" -#include "staticlibrary.h" #include "systemlibrary.h" #include "unlink.h" #include "virtualtarget.h" @@ -190,9 +187,9 @@ Package *Builder::get_package(const string &n) /** Returns the target with the given name, or 0 if no such target exists. */ -Target *Builder::get_target(const string &n) +Target *Builder::get_target(const string &n) const { - TargetMap::iterator i=targets.find(n); + TargetMap::const_iterator i=targets.find(n); if(i!=targets.end()) return i->second; return 0; @@ -321,6 +318,16 @@ void Builder::apply_profile_template(Config &config, const string &pt) const } } +/** +Adds a target to both the target map and the new target queue. Called from +Target constructor. +*/ +void Builder::add_target(Target *t) +{ + targets.insert(TargetMap::value_type(t->get_name(), t)); + new_tgts.push_back(t); +} + int Builder::main() { if(load_build_file(cwd/build_file)) @@ -487,14 +494,11 @@ Creates targets for all packages and prepares them for building. int Builder::create_targets() { Target *world=new VirtualTarget(*this, "world"); - add_target(world); Target *def_tgt=new VirtualTarget(*this, "default"); - add_target(def_tgt); world->add_depend(def_tgt); Target *install=new VirtualTarget(*this, "install"); - add_target(install); world->add_depend(install); for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i) @@ -504,123 +508,14 @@ int Builder::create_targets() if(!i->second->get_buildable()) continue; - Path::Path inst_base; - if(i->second->get_buildable() && i->second->get_install_flags()) - inst_base=i->second->get_prefix(); - const ComponentList &components=i->second->get_components(); for(ComponentList::const_iterator j=components.begin(); j!=components.end(); ++j) - { - // Collect all files belonging to the component - PathList files; - const PathList &sources=j->get_sources(); - for(PathList::const_iterator k=sources.begin(); k!=sources.end(); ++k) - { - struct stat st; - stat(*k, st); - if(S_ISDIR(st.st_mode)) - { - list sfiles=list_files(*k); - for(list::iterator l=sfiles.begin(); l!=sfiles.end(); ++l) - files.push_back(*k / *l); - } - else - files.push_back(*k); - } - - bool build_exe=j->get_type()!=Component::HEADERS; - - list objs; - for(PathList::iterator k=files.begin(); k!=files.end(); ++k) - { - string basename=(*k)[-1]; - string ext=Path::splitext(basename).ext; - if((ext==".cpp" || ext==".c") && build_exe) - { - SourceFile *src=new SourceFile(*this, &*j, k->str()); - add_target(src); - - // Compile sources - ObjectFile *obj=new ObjectFile(*this, *j, *src); - add_target(obj); - objs.push_back(obj); - } - else if(ext==".h") - { - Target *hdr=get_target(k->str()); - if(!hdr) - { - hdr=new Header(*this, &*j, k->str()); - add_target(hdr); - } - - // Install headers if requested - if(!j->get_install_headers().empty()) - { - Path::Path inst_path=inst_base/"include"/j->get_install_headers()/basename; - Install *inst=new Install(*this, *i->second, *hdr, inst_path.str()); - add_target(inst); - install->add_depend(inst); - } - } - } - - if(build_exe) - { - Executable *exe=0; - StaticLibrary *slib=0; - if(j->get_type()==Component::LIBRARY) - { - exe=new SharedLibrary(*this, *j, objs); - slib=new StaticLibrary(*this, *j, objs); - add_target(slib); - } - else - exe=new Executable(*this, *j, objs); - - add_target(exe); - if(i->second==default_pkg && j->get_default()) - { - def_tgt->add_depend(exe); - if(slib) def_tgt->add_depend(slib); - } - else - { - world->add_depend(exe); - if(slib) world->add_depend(slib); - } - - if(j->get_install()) - { - string inst_dir; - if(j->get_type()==Component::PROGRAM) - inst_dir="bin"; - else if(j->get_type()==Component::LIBRARY) - inst_dir="lib"; - if(!inst_dir.empty()) - { - Install *inst=new Install(*this, *i->second, *exe, (inst_base/inst_dir/Path::basename(exe->get_name())).str()); - add_target(inst); - install->add_depend(inst); - - if(slib) - { - inst=new Install(*this, *i->second, *slib, (inst_base/inst_dir/Path::basename(slib->get_name())).str()); - add_target(inst); - install->add_depend(inst); - } - } - } - } - } + j->create_targets(); if(i->second->get_install_flags()&(Package::LIB|Package::INCLUDE)) { PkgConfig *pc=new PkgConfig(*this, *i->second); - add_target(pc); - Install *inst=new Install(*this, *i->second, *pc, (inst_base/"lib"/"pkgconfig"/Path::basename(pc->get_name())).str()); - add_target(inst); - install->add_depend(inst); + install->add_depend(new Install(*this, *i->second, *pc)); } } @@ -648,7 +543,6 @@ int Builder::create_targets() // Make the cmdline target depend on all targets mentioned on the command line Target *cmdline=new VirtualTarget(*this, "cmdline"); - add_target(cmdline); bool build_world=false; for(list::iterator i=cmdline_targets.begin(); i!=cmdline_targets.end(); ++i) { @@ -690,7 +584,7 @@ Target *Builder::get_header(const Msp::Path::Path &fn) if(Path::exists(fn)) { - add_target(tgt=new SystemHeader(*this, fn.str())); + tgt=new SystemHeader(*this, fn.str()); return tgt; } return 0; @@ -736,7 +630,6 @@ Target *Builder::get_library(const string &lib, const string &arch, const Path:: else if(Path::exists(full)) { tgt=new SystemLibrary(*this, full); - add_target(tgt); return tgt; } } @@ -744,15 +637,6 @@ Target *Builder::get_library(const string &lib, const string &arch, const Path:: return 0; } -/** -Adds a target to both the target map and the new target queue. -*/ -void Builder::add_target(Target *t) -{ - targets.insert(TargetMap::value_type(t->get_name(), t)); - new_tgts.push_back(t); -} - /** Updates a hash with a string. This is used from get_header and get_library. */ diff --git a/source/builder.h b/source/builder.h index 6985db8..21973eb 100644 --- a/source/builder.h +++ b/source/builder.h @@ -26,13 +26,15 @@ public: bool get_dry_run() const { return dry_run; } bool get_build_all() const { return build_all; } Package *get_package(const std::string &); - Target *get_target(const std::string &); + Package *get_default_package() const { return default_pkg; } + Target *get_target(const std::string &) const; Target *get_header(const std::string &, const std::string &, const std::string &, const StringList &); Target *get_library(const std::string &, const std::string &, const StringList &, LibMode); const Msp::Path::Path &get_cwd() const { return cwd; } const std::string &get_arch_prefix(const std::string &) const; std::string get_tool(const std::string &, const std::string &); void apply_profile_template(Config &, const std::string &) const; + void add_target(Target *); int main(); ~Builder(); @@ -91,7 +93,6 @@ private: int create_targets(); Target *get_header(const Msp::Path::Path &); Target *get_library(const std::string &, const std::string &, const Msp::Path::Path &, LibMode); - void add_target(Target *); void update_hash(std::string &, const std::string &); int do_build(); int do_clean(); diff --git a/source/component.cpp b/source/component.cpp index 4bdff21..b2ac62c 100644 --- a/source/component.cpp +++ b/source/component.cpp @@ -1,8 +1,17 @@ #include +#include +#include "builder.h" #include "component.h" +#include "header.h" +#include "install.h" +#include "objectfile.h" #include "package.h" +#include "sharedlibrary.h" +#include "staticlibrary.h" +#include "target.h" using namespace std; +using namespace Msp; Component::Component(Package &p, Type t, const string &n): pkg(p), @@ -53,6 +62,105 @@ void Component::create_build_info() build_info.unique(); } +/** +Creates all targets needed for building this component. +*/ +void Component::create_targets() const +{ + Builder &builder=pkg.get_builder(); + Target *world=builder.get_target("world"); + Target *def_tgt=builder.get_target("default"); + + PathList files=collect_source_files(); + + bool build_exe=(type!=Component::HEADERS); + + list objs; + list inst_tgts; + for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i) + { + string basename=(*i)[-1]; + string ext=Path::splitext(basename).ext; + if((ext==".cpp" || ext==".c") && build_exe) + { + SourceFile *src=new SourceFile(builder, this, i->str()); + + // Compile sources + ObjectFile *obj=new ObjectFile(builder, *this, *src); + objs.push_back(obj); + } + else if(ext==".h") + { + Target *hdr=builder.get_target(i->str()); + if(!hdr) + hdr=new Header(builder, this, i->str()); + + // Install headers if requested + if(!install_headers.empty()) + inst_tgts.push_back(hdr); + } + } + + if(build_exe) + { + Executable *exe=0; + StaticLibrary *slib=0; + if(type==Component::LIBRARY) + { + exe=new SharedLibrary(builder, *this, objs); + slib=new StaticLibrary(builder, *this, objs); + } + else + exe=new Executable(builder, *this, objs); + + if(&pkg==builder.get_default_package() && deflt) + { + def_tgt->add_depend(exe); + if(slib) def_tgt->add_depend(slib); + } + else + { + world->add_depend(exe); + if(slib) world->add_depend(slib); + } + + if(install) + { + inst_tgts.push_back(exe); + if(slib) + inst_tgts.push_back(slib); + } + } + + Target *inst_tgt=builder.get_target("install"); + for(TargetList::const_iterator i=inst_tgts.begin(); i!=inst_tgts.end(); ++i) + inst_tgt->add_depend(new Install(builder, pkg, **i)); +} + +/** +Collects all files belonging to the component. +*/ +PathList Component::collect_source_files() const +{ + PathList files; + for(PathList::const_iterator i=sources.begin(); i!=sources.end(); ++i) + { + struct stat st; + stat(*i, st); + if(S_ISDIR(st.st_mode)) + { + list sfiles=list_files(*i); + for(list::iterator j=sfiles.begin(); j!=sfiles.end(); ++j) + files.push_back(*i / *j); + } + else + files.push_back(*i); + } + + return files; +} + + Component::Loader::Loader(Component &c): comp(c) { diff --git a/source/component.h b/source/component.h index e505735..f96f800 100644 --- a/source/component.h +++ b/source/component.h @@ -56,6 +56,7 @@ public: bool get_default() const { return deflt; } void resolve_refs(); void create_build_info(); + void create_targets() const; protected: Package &pkg; Type type; @@ -68,6 +69,8 @@ protected: BuildInfo build_info; PkgRefList requires; bool deflt; + + PathList collect_source_files() const; }; typedef std::list ComponentList; diff --git a/source/install.cpp b/source/install.cpp index 658a6fb..ca32348 100644 --- a/source/install.cpp +++ b/source/install.cpp @@ -1,15 +1,18 @@ #include #include "builder.h" #include "copy.h" +#include "executable.h" #include "header.h" #include "install.h" #include "package.h" +#include "pkgconfig.h" +#include "staticlibrary.h" using namespace std; using namespace Msp; -Install::Install(Builder &b, const Package &p, Target &tgt, const string &n): - Target(b, &p, n) +Install::Install(Builder &b, const Package &p, Target &tgt): + Target(b, &p, generate_target_name(tgt)) { buildable=true; add_depend(&tgt); @@ -33,3 +36,32 @@ Action *Install::build() { return Target::build(new Copy(builder, *package, depends.front()->get_name(), name)); } + +string Install::generate_target_name(const Target &tgt) +{ + Path::Path base=tgt.get_package()->get_prefix(); + string tgtname=tgt.get_name().substr(tgt.get_name().rfind('/')+1); + + string mid; + if(const Header *hdr=dynamic_cast(&tgt)) + mid="include/"+hdr->get_component()->get_install_headers(); + else if(const Executable *exe=dynamic_cast(&tgt)) + { + const Component &comp=exe->get_component(); + if(comp.get_type()==Component::LIBRARY) + mid="lib"; + else if(comp.get_type()==Component::PROGRAM) + mid="bin"; + else if(comp.get_type()==Component::MODULE) + mid="lib/"+tgt.get_package()->get_name(); + } + else if(dynamic_cast(&tgt)) + mid="lib"; + else if(dynamic_cast(&tgt)) + mid="lib/pkgconfig"; + + if(mid.empty()) + throw InvalidParameterValue("Don't know where to install "+tgtname); + + return (base/mid/tgtname).str(); +} diff --git a/source/install.h b/source/install.h index fd6472f..b50bb7f 100644 --- a/source/install.h +++ b/source/install.h @@ -9,11 +9,12 @@ Represents the installation of a file. class Install: public Target { public: - Install(Builder &, const Package &, Target &, const std::string &); + Install(Builder &, const Package &, Target &); const char *get_type() const { return "Install"; } void check_rebuild(); Action *build(); private: + std::string generate_target_name(const Target &); }; #endif diff --git a/source/sourcefile.h b/source/sourcefile.h index 381d593..d50612a 100644 --- a/source/sourcefile.h +++ b/source/sourcefile.h @@ -14,6 +14,7 @@ public: SourceFile(Builder &, const Component *, const std::string &); const StringList &get_includes() const { return includes; } const char *get_type() const { return "SourceFile"; } + const Component *get_component() const { return comp; } void find_depends(); Action *build() { return 0; } private: diff --git a/source/target.cpp b/source/target.cpp index 3b16853..f33e141 100644 --- a/source/target.cpp +++ b/source/target.cpp @@ -95,6 +95,8 @@ Target::Target(Builder &b, const Package *p, const string &n): prepared(false), counted(false) { + builder.add_target(this); + struct stat st; if(!Path::stat(name, st)) mtime=Time::TimeStamp::from_unixtime(st.st_mtime);