From: Mikko Rasa Date: Sat, 21 Feb 2009 00:45:50 +0000 (+0000) Subject: Rework the Target class hierarchy X-Git-Tag: 1.0~19 X-Git-Url: http://git.tdb.fi/?p=builder.git;a=commitdiff_plain;h=66d1078c04849ec17a7343d0494d6ed087e04318 Rework the Target class hierarchy - Introduce FileTarget and move the stat call there - More senseful relationships between executable and library targets - Some related minor cleanups --- diff --git a/source/analyzer.cpp b/source/analyzer.cpp index 3481ec8..6664477 100644 --- a/source/analyzer.cpp +++ b/source/analyzer.cpp @@ -14,6 +14,7 @@ Distributed under the LGPL #include "install.h" #include "objectfile.h" #include "package.h" +#include "sourcefile.h" #include "target.h" using namespace std; @@ -45,10 +46,10 @@ void Analyzer::build_depend_table(Target &tgt, unsigned depth) if(mode!=REBUILD && mode!=ALLDEPS) { // Skip trivial targets - if(dynamic_cast(&tgt)) - return build_depend_table(*tgt.get_depends().front(), depth); - else if(dynamic_cast(&tgt)) - return build_depend_table(*tgt.get_depends().front(), depth); + if(ObjectFile *obj=dynamic_cast(&tgt)) + return build_depend_table(obj->get_source(), depth); + else if(Install *inst=dynamic_cast(&tgt)) + return build_depend_table(inst->get_source(), depth); } else if(mode==REBUILD && !tgt.get_rebuild()) /* All targets that depend on to-be-built targets will be rebuilt diff --git a/source/archive.cpp b/source/archive.cpp index 204b202..8b36391 100644 --- a/source/archive.cpp +++ b/source/archive.cpp @@ -28,13 +28,13 @@ Archive::Archive(Builder &b, const StaticLibrary &lib): argv.push_back(builder.get_current_arch().get_tool(tool)); argv.push_back("rc"); - argv.push_back(relative(lib.get_name(), work_dir).str()); + argv.push_back(relative(lib.get_path(), work_dir).str()); const TargetList &deps=lib.get_depends(); for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i) - if(dynamic_cast(*i)) - argv.push_back(relative((*i)->get_name(), work_dir).str()); + if(ObjectFile *obj=dynamic_cast(*i)) + argv.push_back(relative(obj->get_path(), work_dir).str()); - FS::Path lpath=lib.get_name(); + FS::Path lpath=lib.get_path(); if(!builder.get_dry_run()) FS::mkpath(FS::dirname(lpath), 0755); diff --git a/source/binary.cpp b/source/binary.cpp new file mode 100644 index 0000000..591e934 --- /dev/null +++ b/source/binary.cpp @@ -0,0 +1,108 @@ +/* $Id$ + +This file is part of builder +Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include "binary.h" +#include "builder.h" +#include "component.h" +#include "install.h" +#include "link.h" +#include "objectfile.h" +#include "package.h" +#include "sharedlibrary.h" +#include "staticlibrary.h" + +using namespace std; +using namespace Msp; + +Binary::Binary(Builder &b, const Component &c, const list &objs): + FileTarget(b, &c.get_package(), generate_target_path(c)), + comp(c) +{ + buildable=true; + for(list::const_iterator i=objs.begin(); i!=objs.end(); ++i) + add_depend(*i); +} + +void Binary::find_depends() +{ + LibMode libmode=comp.get_package().get_library_mode(); + if(dynamic_cast(this)) + libmode=DYNAMIC; + + list queue; + list dep_libs; + queue.push_back(&comp); + while(!queue.empty()) + { + const Component *c=queue.front(); + queue.erase(queue.begin()); + + const StringList &libpath=c->get_build_info().libpath; + + 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); + if(lib) + { + dep_libs.push_back(lib); + + if(Install *inst=dynamic_cast(lib)) + lib=&inst->get_source(); + if(StaticLibrary *stlib=dynamic_cast(lib)) + queue.push_back(&stlib->get_component()); + } + else + builder.problem(comp.get_package().get_name(), format("Couldn't find library %s for %s", *i, FS::basename(name))); + } + } + + /* Add only the last occurrence of each library to the actual dependencies. + This ensures that static library ordering is correct. */ + for(list::iterator i=dep_libs.begin(); i!=dep_libs.end(); ++i) + { + bool last=true; + for(list::iterator j=i; (last && j!=dep_libs.end()); ++j) + last=(j==i || *j!=*i); + if(last) + add_depend(*i); + } + + deps_ready=true; +} + +Action *Binary::create_action() +{ + return new Link(builder, *this); +} + +FS::Path Binary::generate_target_path(const Component &c) +{ + const SourcePackage &pkg=c.get_package(); + string prefix, suffix; + const string &arch=pkg.get_builder().get_current_arch().get_name(); + + if(c.get_type()==Component::LIBRARY) + { + prefix="lib"; + if(arch=="win32") + suffix=".dll"; + else + suffix=".so"; + } + else if(c.get_type()==Component::MODULE) + suffix=".m"; + else if(c.get_type()==Component::PROGRAM) + { + if(arch=="win32") + suffix=".exe"; + } + + return pkg.get_out_dir()/(prefix+c.get_name()+suffix); +} diff --git a/source/binary.h b/source/binary.h new file mode 100644 index 0000000..cb9a56e --- /dev/null +++ b/source/binary.h @@ -0,0 +1,37 @@ +/* $Id$ + +This file is part of builder +Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef BINARY_H_ +#define BINARY_H_ + +#include "filetarget.h" + +class Component; +class ObjectFile; + +/** +Produces a binary file, which may be either a standalone executable or a shared +library. +*/ +class Binary: public virtual FileTarget +{ +protected: + const Component ∁ + + Binary(Builder &, const Component &, const std::list &); +public: + const Component &get_component() const { return comp; } + virtual void find_depends(); +protected: + virtual Action *create_action(); + + /** Returns the path for the binary. We can't do this in the constructor + since we need to pass the value to the Target c'tor. */ + static Msp::FS::Path generate_target_path(const Component &); +}; + +#endif diff --git a/source/builder.cpp b/source/builder.cpp index 3838ae5..bbf6eb1 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -134,7 +134,7 @@ Builder::Builder(int argc, char **argv): cmdline_targets.push_back("default"); if(!work_dir.empty()) - chdir(work_dir.c_str()); + FS::chdir(work_dir); cwd=FS::getcwd(); @@ -300,17 +300,18 @@ Package *Builder::get_package(const string &name) Target *Builder::get_target(const string &n) const { + // XXX Used for getting targets by path. get_target(const FS::Path &)? TargetMap::const_iterator i=targets.find(n); if(i!=targets.end()) return i->second; return 0; } -Target *Builder::get_header(const string &include, const string &from, const list &path) +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); + update_hash(hash, from.str()); for(list::const_iterator i=path.begin(); i!=path.end(); ++i) update_hash(hash, *i); @@ -669,8 +670,8 @@ Target *Builder::get_library(const string &lib, const FS::Path &path, LibMode mo if(tgt) { Target *real_tgt=tgt; - if(dynamic_cast(tgt)) - real_tgt=real_tgt->get_depends().front(); + if(Install *inst=dynamic_cast(tgt)) + real_tgt=&inst->get_source(); /* Ignore dynamic libraries from local packages unless library mode is DYNAMIC */ @@ -784,11 +785,12 @@ int Builder::do_clean() } for(set::iterator i=clean_tgts.begin(); i!=clean_tgts.end(); ++i) - { - Action *action=new Unlink(*this, **i); - while(action->check()<0) ; - delete action; - } + if(FileTarget *ft=dynamic_cast(*i)) + { + Action *action=new Unlink(*this, *ft); + while(action->check()<0) ; + delete action; + } return 0; } diff --git a/source/builder.h b/source/builder.h index 90a8a7c..0ebf2df 100644 --- a/source/builder.h +++ b/source/builder.h @@ -124,7 +124,7 @@ public: 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 std::string &, const StringList &); + 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" diff --git a/source/compile.cpp b/source/compile.cpp index 4157ccb..da1cfef 100644 --- a/source/compile.cpp +++ b/source/compile.cpp @@ -12,6 +12,7 @@ Distributed under the LGPL #include "compile.h" #include "component.h" #include "objectfile.h" +#include "sourcefile.h" #include "sourcepackage.h" using namespace std; @@ -24,8 +25,7 @@ Compile::Compile(Builder &b, const ObjectFile &obj): work_dir=comp.get_package().get_source(); - const TargetList &deps=obj.get_depends(); - FS::Path spath=deps.front()->get_name(); + FS::Path spath=obj.get_source().get_path(); string ext=FS::extpart(spath.str()); const char *tool=0; @@ -47,7 +47,7 @@ Compile::Compile(Builder &b, const ObjectFile &obj): for(list::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i) argv.push_back("-D"+*i); - FS::Path opath=obj.get_name(); + FS::Path opath=obj.get_path(); argv.push_back("-o"); argv.push_back(relative(opath, work_dir).str()); argv.push_back(relative(spath, work_dir).str()); diff --git a/source/component.cpp b/source/component.cpp index dcbaf37..dd33941 100644 --- a/source/component.cpp +++ b/source/component.cpp @@ -12,6 +12,7 @@ Distributed under the LGPL #include #include "builder.h" #include "component.h" +#include "executable.h" #include "header.h" #include "install.h" #include "objectfile.h" @@ -89,7 +90,7 @@ void Component::create_targets() const bool build_exe=(type!=HEADERS); list objs; - list inst_tgts; + list inst_tgts; for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i) { string ext=FS::extpart(FS::basename(*i)); @@ -103,7 +104,7 @@ void Component::create_targets() const } else if(ext==".h") { - Target *hdr=builder.get_target(i->str()); + FileTarget *hdr=dynamic_cast(builder.get_target(i->str())); if(!hdr) hdr=new Header(builder, this, i->str()); @@ -115,37 +116,37 @@ void Component::create_targets() const if(build_exe) { - Executable *exe=0; + Binary *bin=0; StaticLibrary *slib=0; if(type==LIBRARY) { - exe=new SharedLibrary(builder, *this, objs); + bin=new SharedLibrary(builder, *this, objs); slib=new StaticLibrary(builder, *this, objs); } else - exe=new Executable(builder, *this, objs); + bin=new Executable(builder, *this, objs); if(&pkg==builder.get_main_package() && deflt) { - def_tgt->add_depend(exe); + def_tgt->add_depend(bin); if(slib) def_tgt->add_depend(slib); } else { - world->add_depend(exe); + world->add_depend(bin); if(slib) world->add_depend(slib); } if(install) { - inst_tgts.push_back(exe); + inst_tgts.push_back(bin); 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) + for(list::const_iterator i=inst_tgts.begin(); i!=inst_tgts.end(); ++i) inst_tgt->add_depend(new Install(builder, pkg, **i)); } diff --git a/source/executable.cpp b/source/executable.cpp index 50ac3d3..44d4612 100644 --- a/source/executable.cpp +++ b/source/executable.cpp @@ -1,108 +1,15 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ -#include -#include -#include "builder.h" #include "component.h" #include "executable.h" -#include "install.h" -#include "link.h" -#include "objectfile.h" -#include "package.h" -#include "sharedlibrary.h" -#include "staticlibrary.h" +#include "sourcepackage.h" -using namespace std; -using namespace Msp; - -Executable::Executable(Builder &b, const Component &c, const list &objs): - Target(b, &c.get_package(), generate_target_name(c)), - comp(c) -{ - buildable=true; - for(list::const_iterator i=objs.begin(); i!=objs.end(); ++i) - add_depend(*i); -} - -void Executable::find_depends() -{ - LibMode libmode=comp.get_package().get_library_mode(); - if(dynamic_cast(this)) - libmode=DYNAMIC; - - list queue; - list dep_libs; - queue.push_back(&comp); - while(!queue.empty()) - { - const Component *c=queue.front(); - queue.erase(queue.begin()); - - const StringList &libpath=c->get_build_info().libpath; - - 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); - if(lib) - { - dep_libs.push_back(lib); - - if(dynamic_cast(lib)) - lib=lib->get_depends().front(); - if(StaticLibrary *stlib=dynamic_cast(lib)) - queue.push_back(&stlib->get_component()); - } - else - builder.problem(comp.get_package().get_name(), format("Couldn't find library %s for %s", *i, FS::basename(name))); - } - } - - /* Add only the last occurrence of each library to the actual dependencies. - This ensures that static library ordering is correct. */ - for(list::iterator i=dep_libs.begin(); i!=dep_libs.end(); ++i) - { - bool last=true; - for(list::iterator j=i; (last && j!=dep_libs.end()); ++j) - last=(j==i || *j!=*i); - if(last) - add_depend(*i); - } - - deps_ready=true; -} - -Action *Executable::create_action() -{ - return new Link(builder, *this); -} - -string Executable::generate_target_name(const Component &c) -{ - const SourcePackage &pkg=c.get_package(); - string prefix, suffix; - const string &arch=pkg.get_builder().get_current_arch().get_name(); - - if(c.get_type()==Component::LIBRARY) - { - prefix="lib"; - if(arch=="win32") - suffix=".dll"; - else - suffix=".so"; - } - else if(c.get_type()==Component::MODULE) - suffix=".m"; - else if(c.get_type()==Component::PROGRAM) - { - if(arch=="win32") - suffix=".exe"; - } - - return (pkg.get_out_dir()/(prefix+c.get_name()+suffix)).str(); -} +Executable::Executable(Builder &b, const Component &c, const std::list &objs): + FileTarget(b, &c.get_package(), generate_target_path(c)), + Binary(b, c, objs) +{ } diff --git a/source/executable.h b/source/executable.h index a6ebb97..0dc4fc5 100644 --- a/source/executable.h +++ b/source/executable.h @@ -1,38 +1,20 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ #ifndef EXECUTABLE_H_ #define EXECUTABLE_H_ -#include "target.h" +#include "binary.h" -class Component; -class ObjectFile; - -/** -Produces a binary file, which may be either a standalone executable or a shared -library. -*/ -class Executable: public Target +class Executable: public Binary { -private: - const Component ∁ - public: Executable(Builder &, const Component &, const std::list &); virtual const char *get_type() const { return "Executable"; } - const Component &get_component() const { return comp; } - virtual void find_depends(); -private: - virtual Action *create_action(); - - /** Returns the name for the executable. We can't do this in the - constructor since we need to pass the value to the Target c'tor. */ - static std::string generate_target_name(const Component &); }; #endif diff --git a/source/file.cpp b/source/file.cpp index e2b3c27..4a870e7 100644 --- a/source/file.cpp +++ b/source/file.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007, 2009 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -10,5 +10,5 @@ Distributed under the LGPL using namespace std; File::File(Builder &b, const string &n): - Target(b, 0, n) + FileTarget(b, 0, n) { } diff --git a/source/file.h b/source/file.h index bc71df8..19d14af 100644 --- a/source/file.h +++ b/source/file.h @@ -8,9 +8,12 @@ Distributed under the LGPL #ifndef FILE_H_ #define FILE_H_ -#include "target.h" +#include "filetarget.h" -class File: public Target +/** +Just a file. Any file, not attached to a package. +*/ +class File: public FileTarget { public: File(Builder &, const std::string &); diff --git a/source/filetarget.cpp b/source/filetarget.cpp new file mode 100644 index 0000000..ed3e66b --- /dev/null +++ b/source/filetarget.cpp @@ -0,0 +1,23 @@ +/* $Id$ + +This file is part of builder +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include "file.h" + +using namespace std; +using namespace Msp; + +FileTarget::FileTarget(Builder &b, const Package *p, const FS::Path &a): + // XXX Builder depends on target name being its path for locating file targets + Target(b, p, /*FS::basename*/(a.str())), + path(a) +{ + struct stat st; + if(!FS::stat(path, st)) + mtime=Time::TimeStamp::from_unixtime(st.st_mtime); +} diff --git a/source/filetarget.h b/source/filetarget.h new file mode 100644 index 0000000..3b8bfcc --- /dev/null +++ b/source/filetarget.h @@ -0,0 +1,28 @@ +/* $Id$ + +This file is part of builder +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef FILETARGET_H_ +#define FILETARGET_H_ + +#include +#include "target.h" + +/** +An intermediate base class for targets that represent files. Almost all target +classes are derived from this. +*/ +class FileTarget: public Target +{ +protected: + Msp::FS::Path path; + + FileTarget(Builder &, const Package *, const Msp::FS::Path &); +public: + const Msp::FS::Path &get_path() const { return path; } +}; + +#endif diff --git a/source/install.cpp b/source/install.cpp index d30eea0..1eb510e 100644 --- a/source/install.cpp +++ b/source/install.cpp @@ -13,54 +13,52 @@ Distributed under the LGPL #include "install.h" #include "package.h" #include "pkgconfig.h" +#include "sharedlibrary.h" #include "staticlibrary.h" using namespace std; using namespace Msp; -Install::Install(Builder &b, const SourcePackage &p, Target &tgt): - Target(b, &p, generate_target_name(tgt)) +Install::Install(Builder &b, const SourcePackage &p, FileTarget &s): + FileTarget(b, &p, generate_target_path(s)), + source(s) { buildable=true; - add_depend(&tgt); + add_depend(&source); } void Install::check_rebuild() { if(!mtime) mark_rebuild("Does not exist"); - else - { - Target *dep=depends.front(); - if(dep->get_mtime()>mtime) - mark_rebuild(FS::basename(dep->get_name())+" has changed"); - else if(dep->get_rebuild()) - mark_rebuild(FS::basename(dep->get_name())+" needs rebuilding"); - } + else if(source.get_mtime()>mtime) + mark_rebuild(FS::basename(source.get_name())+" has changed"); + else if(source.get_rebuild()) + mark_rebuild(FS::basename(source.get_name())+" needs rebuilding"); } Action *Install::create_action() { - return new Copy(builder, *package, depends.front()->get_name(), name); + return new Copy(builder, *package, source.get_path(), path); } -string Install::generate_target_name(const Target &tgt) +FS::Path Install::generate_target_path(const FileTarget &tgt) { const SourcePackage *spkg=dynamic_cast(tgt.get_package()); FS::Path base=spkg->get_builder().get_prefix(); - string tgtname=tgt.get_name().substr(tgt.get_name().rfind('/')+1); + string tgtname=FS::basename(tgt.get_path()); 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)) + else if(dynamic_cast(&tgt)) + mid="bin"; + else if(const SharedLibrary *shlib=dynamic_cast(&tgt)) { - const Component &comp=exe->get_component(); + const Component &comp=shlib->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(); } diff --git a/source/install.h b/source/install.h index 41b4382..764d9a1 100644 --- a/source/install.h +++ b/source/install.h @@ -9,21 +9,25 @@ Distributed under the LGPL #define INSTALL_H_ #include "sourcepackage.h" -#include "target.h" +#include "filetarget.h" /** Represents the installation of a file. */ -class Install: public Target +class Install: public FileTarget { +private: + FileTarget &source; + public: - Install(Builder &, const SourcePackage &, Target &); + Install(Builder &, const SourcePackage &, FileTarget &); virtual const char *get_type() const { return "Install"; } + FileTarget &get_source() const { return source; } private: virtual void check_rebuild(); virtual Action *create_action(); - static std::string generate_target_name(const Target &); + static Msp::FS::Path generate_target_path(const FileTarget &); }; #endif diff --git a/source/library.cpp b/source/library.cpp new file mode 100644 index 0000000..23604eb --- /dev/null +++ b/source/library.cpp @@ -0,0 +1,13 @@ +/* $Id$ + +This file is part of builder +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include "library.h" + +Library::Library(Builder &b, const Package *p, const Msp::FS::Path &a, const std::string &l): + FileTarget(b, p, a), + libname(l) +{ } diff --git a/source/library.h b/source/library.h new file mode 100644 index 0000000..8d8f13d --- /dev/null +++ b/source/library.h @@ -0,0 +1,23 @@ +/* $Id$ + +This file is part of builder +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef LIBRARY_H_ +#define LIBRARY_H_ + +#include "filetarget.h" + +class Library: public virtual FileTarget +{ +protected: + std::string libname; + + Library(Builder &, const Package *, const Msp::FS::Path &, const std::string &); +public: + const std::string &get_libname() const { return libname; } +}; + +#endif diff --git a/source/link.cpp b/source/link.cpp index 25713e1..b165bad 100644 --- a/source/link.cpp +++ b/source/link.cpp @@ -21,10 +21,10 @@ Distributed under the LGPL using namespace std; using namespace Msp; -Link::Link(Builder &b, const Executable &exe): +Link::Link(Builder &b, const Binary &bin): ExternalAction(b) { - const Component &comp=exe.get_component(); + const Component &comp=bin.get_component(); work_dir=comp.get_package().get_source(); @@ -44,29 +44,27 @@ Link::Link(Builder &b, const Executable &exe): argv.push_back("-L"+*i); argv.push_back("-o"); - argv.push_back(relative(exe.get_name(), work_dir).str()); - const TargetList &deps=exe.get_depends(); + argv.push_back(relative(bin.get_path(), work_dir).str()); + const TargetList &deps=bin.get_depends(); for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i) { Target *tgt=*i; - if(dynamic_cast(tgt)) - tgt=tgt->get_depends().front(); + if(Install *inst=dynamic_cast(tgt)) + tgt=&inst->get_source(); - if(dynamic_cast(tgt)) - argv.push_back(relative((*i)->get_name(), work_dir).str()); - else if(SharedLibrary *shlib=dynamic_cast(tgt)) - argv.push_back("-l"+shlib->get_libname()); - else if(dynamic_cast(tgt)) - argv.push_back((*i)->get_name()); - else if(SystemLibrary *syslib=dynamic_cast(tgt)) - argv.push_back("-l"+syslib->get_libname()); + if(ObjectFile *obj=dynamic_cast(tgt)) + argv.push_back(relative(obj->get_path(), work_dir).str()); + else if(StaticLibrary *stlib=dynamic_cast(tgt)) + argv.push_back(stlib->get_path().str()); + else if(Library *lib=dynamic_cast(tgt)) + argv.push_back("-l"+lib->get_libname()); } - FS::Path epath=exe.get_name(); + FS::Path binpath=bin.get_path(); if(!builder.get_dry_run()) - FS::mkpath(FS::dirname(epath), 0755); + FS::mkpath(FS::dirname(binpath), 0755); - announce(comp.get_package().get_name(), tool, relative(epath, work_dir).str()); + announce(comp.get_package().get_name(), tool, relative(binpath, work_dir).str()); launch(); } diff --git a/source/link.h b/source/link.h index d58d821..ec227c5 100644 --- a/source/link.h +++ b/source/link.h @@ -18,7 +18,7 @@ Links object files and libraries to produce an executable. class Link: public ExternalAction { public: - Link(Builder &, const Executable &); + Link(Builder &, const Binary &); }; #endif diff --git a/source/objectfile.cpp b/source/objectfile.cpp index 683c724..fd1c975 100644 --- a/source/objectfile.cpp +++ b/source/objectfile.cpp @@ -18,12 +18,13 @@ Distributed under the LGPL using namespace std; using namespace Msp; -ObjectFile::ObjectFile(Builder &b, const Component &c, SourceFile &src): - Target(b, &c.get_package(), generate_target_name(c, src.get_name())), - comp(c) +ObjectFile::ObjectFile(Builder &b, const Component &c, SourceFile &s): + FileTarget(b, &c.get_package(), generate_target_path(c, FS::basename(s.get_path()))), + comp(c), + source(s) { buildable=true; - add_depend(&src); + add_depend(&source); } void ObjectFile::find_depends() @@ -46,25 +47,22 @@ void ObjectFile::find_depends() void ObjectFile::find_depends(Target *tgt) { - const string &tname=tgt->get_name(); - string path=tname.substr(0, tname.rfind('/')); - SourceFile *src=dynamic_cast(tgt); if(!src) { - Install *inst=dynamic_cast(tgt); - if(inst) - src=dynamic_cast(inst->get_depends().front()); + if(Install *inst=dynamic_cast(tgt)) + src=dynamic_cast(&inst->get_source()); } if(!src) return; + FS::Path spath=src->get_path(); const StringList &incpath=comp.get_build_info().incpath; const list &includes=src->get_includes(); for(list::const_iterator i=includes.begin(); i!=includes.end(); ++i) { - Target *hdr2=builder.get_header(*i, path, incpath); + Target *hdr2=builder.get_header(*i, spath, incpath); if(hdr2 && find(depends.begin(), depends.end(), hdr2)==depends.end()) add_depend(hdr2); } @@ -81,8 +79,8 @@ Action *ObjectFile::create_action() return new Compile(builder, *this); } -string ObjectFile::generate_target_name(const Component &comp, const string &src) +FS::Path ObjectFile::generate_target_path(const Component &comp, const string &src) { const SourcePackage &pkg=comp.get_package(); - return (pkg.get_temp_dir()/comp.get_name()/(FS::basepart(FS::basename(src))+".o")).str(); + return pkg.get_temp_dir()/comp.get_name()/(FS::basepart(src)+".o"); } diff --git a/source/objectfile.h b/source/objectfile.h index 4845a0f..7cc6f60 100644 --- a/source/objectfile.h +++ b/source/objectfile.h @@ -8,7 +8,7 @@ Distributed under the LGPL #ifndef OBJECTFILE_H_ #define OBJECTFILE_H_ -#include "target.h" +#include "filetarget.h" class Component; class SourceFile; @@ -16,16 +16,18 @@ class SourceFile; /** Object files are compiled from source files. */ -class ObjectFile: public Target +class ObjectFile: public FileTarget { private: const Component ∁ + SourceFile &source; TargetList new_deps; public: ObjectFile(Builder &, const Component &, SourceFile &); virtual const char *get_type() const { return "ObjectFile"; } const Component &get_component() const { return comp; } + SourceFile &get_source() const { return source; } /** Processes as many new dependences as possible. Some may be created on the fly and can't be processed until their own dependencies are ready. In @@ -41,7 +43,7 @@ private: void add_depend(Target *); virtual Action *create_action(); - static std::string generate_target_name(const Component &, const std::string &); + static Msp::FS::Path generate_target_path(const Component &, const std::string &); }; #endif diff --git a/source/pkgconfig.cpp b/source/pkgconfig.cpp index b38da6a..5daf455 100644 --- a/source/pkgconfig.cpp +++ b/source/pkgconfig.cpp @@ -10,8 +10,7 @@ Distributed under the LGPL #include "pkgconfigaction.h" PkgConfig::PkgConfig(Builder &b, const SourcePackage &p): - Target(b, &p, (p.get_source()/(p.get_name()+".pc")).str()), - pkg(p) + FileTarget(b, &p, p.get_source()/(p.get_name()+".pc")) { buildable=true; } diff --git a/source/pkgconfig.h b/source/pkgconfig.h index b4d4d3b..75280dc 100644 --- a/source/pkgconfig.h +++ b/source/pkgconfig.h @@ -9,16 +9,13 @@ Distributed under the LGPL #define PKGCONFIG_H_ #include "sourcepackage.h" -#include "target.h" +#include "filetarget.h" /** Creates a .pc file to enable other packages fetch build options with pkg-config. */ -class PkgConfig: public Target +class PkgConfig: public FileTarget { -private: - const Package &pkg; - public: PkgConfig(Builder &, const SourcePackage &); virtual const char *get_type() const { return "PkgConfig"; } diff --git a/source/pkgconfigaction.cpp b/source/pkgconfigaction.cpp index ddc6742..b21c6b7 100644 --- a/source/pkgconfigaction.cpp +++ b/source/pkgconfigaction.cpp @@ -21,9 +21,9 @@ PkgConfigAction::PkgConfigAction(Builder &b, const PkgConfig &p): { const SourcePackage &spkg=*static_cast(p.get_package()); - announce(spkg.get_name(), "PC", relative(p.get_name(), spkg.get_source()).str()); + announce(spkg.get_name(), "PC", relative(p.get_path(), spkg.get_source()).str()); - IO::BufferedFile out(p.get_name(), IO::M_WRITE); + IO::BufferedFile out(p.get_path().str(), IO::M_WRITE); // Prefix is already included in the various paths //IO::print(out, "prefix=%s\n", pkg.get_prefix()); IO::print(out, "source=%s\n\n", spkg.get_source()); diff --git a/source/sharedlibrary.cpp b/source/sharedlibrary.cpp index 25034f3..5c2d26f 100644 --- a/source/sharedlibrary.cpp +++ b/source/sharedlibrary.cpp @@ -6,13 +6,13 @@ Distributed under the LGPL */ #include "component.h" -#include "package.h" #include "sharedlibrary.h" +#include "sourcepackage.h" using namespace std; SharedLibrary::SharedLibrary(Builder &b, const Component &c, const list &objs): - Executable(b, c, objs), - libname(c.get_name()) + FileTarget(b, &c.get_package(), generate_target_path(c)), + Binary(b, c, objs), + Library(b, &c.get_package(), path, c.get_name()) { } - diff --git a/source/sharedlibrary.h b/source/sharedlibrary.h index f86fa81..13e358f 100644 --- a/source/sharedlibrary.h +++ b/source/sharedlibrary.h @@ -8,21 +8,18 @@ Distributed under the LGPL #ifndef SHAREDLIB_H_ #define SHAREDLIB_H_ -#include "executable.h" +#include "binary.h" +#include "library.h" /** Represents a shared library. Mainly exists to give extra information to the user. */ -class SharedLibrary: public Executable +class SharedLibrary: public Binary, public Library { -private: - std::string libname; - public: SharedLibrary(Builder &, const Component &, const std::list &); virtual const char *get_type() const { return "SharedLibrary"; } - const std::string &get_libname() const { return libname; } }; #endif diff --git a/source/sourcefile.cpp b/source/sourcefile.cpp index 6c2cb76..cadd133 100644 --- a/source/sourcefile.cpp +++ b/source/sourcefile.cpp @@ -17,8 +17,8 @@ Distributed under the LGPL using namespace std; using namespace Msp; -SourceFile::SourceFile(Builder &b, const Component *c, const string &n): - Target(b, c?&c->get_package():0, n), +SourceFile::SourceFile(Builder &b, const Component *c, const FS::Path &p): + FileTarget(b, (c ? &c->get_package() : 0), p), comp(c) { } @@ -68,7 +68,7 @@ void SourceFile::find_depends() const StringList &incpath=comp->get_build_info().incpath; - string path=name.substr(0, name.rfind('/')); + FS::Path dir=FS::dirname(path); for(list::iterator i=includes.begin(); i!=includes.end(); ++i) { Target *hdr=builder.get_header(*i, path, incpath); diff --git a/source/sourcefile.h b/source/sourcefile.h index ec81d24..cbfd934 100644 --- a/source/sourcefile.h +++ b/source/sourcefile.h @@ -8,21 +8,21 @@ Distributed under the LGPL #ifndef SOURCEFILE_H_ #define SOURCEFILE_H_ -#include "target.h" +#include "filetarget.h" class Component; /** Represents a C or C++ source file. */ -class SourceFile: public Target +class SourceFile: public FileTarget { private: const Component *comp; StringList includes; public: - SourceFile(Builder &, const Component *, const std::string &); + SourceFile(Builder &, const Component *, const Msp::FS::Path &); virtual const char *get_type() const { return "SourceFile"; } const StringList &get_includes() const { return includes; } const Component *get_component() const { return comp; } diff --git a/source/staticlibrary.cpp b/source/staticlibrary.cpp index a72f8e0..b7e4eff 100644 --- a/source/staticlibrary.cpp +++ b/source/staticlibrary.cpp @@ -13,8 +13,9 @@ Distributed under the LGPL using namespace std; -StaticLibrary::StaticLibrary(Builder &b, const Component &c, const std::list &objs): - Target(b, &c.get_package(), generate_target_name(c)), +StaticLibrary::StaticLibrary(Builder &b, const Component &c, const list &objs): + FileTarget(b, &c.get_package(), generate_target_path(c)), + Library(b, package, path, c.get_name()), comp(c) { buildable=true; @@ -27,7 +28,7 @@ Action *StaticLibrary::create_action() return new Archive(builder, *this); } -string StaticLibrary::generate_target_name(const Component &c) +Msp::FS::Path StaticLibrary::generate_target_path(const Component &c) { - return (c.get_package().get_out_dir()/("lib"+c.get_name()+".a")).str(); + return c.get_package().get_out_dir()/("lib"+c.get_name()+".a"); } diff --git a/source/staticlibrary.h b/source/staticlibrary.h index e3bd4e3..efd4833 100644 --- a/source/staticlibrary.h +++ b/source/staticlibrary.h @@ -8,7 +8,7 @@ Distributed under the LGPL #ifndef STATICLIB_H_ #define STATICLIB_H_ -#include "target.h" +#include "library.h" class Component; class ObjectFile; @@ -16,7 +16,7 @@ class ObjectFile; /** A static library target. */ -class StaticLibrary: public Target +class StaticLibrary: public Library { private: const Component ∁ @@ -28,7 +28,7 @@ public: private: virtual Action *create_action(); - static std::string generate_target_name(const Component &); + static Msp::FS::Path generate_target_path(const Component &); }; #endif diff --git a/source/systemlibrary.cpp b/source/systemlibrary.cpp index 2df0eb5..2bfc04b 100644 --- a/source/systemlibrary.cpp +++ b/source/systemlibrary.cpp @@ -12,10 +12,15 @@ Distributed under the LGPL using namespace std; using namespace Msp; -SystemLibrary::SystemLibrary(Builder &b, const string &n): - Target(b, 0, n) +SystemLibrary::SystemLibrary(Builder &b, const Msp::FS::Path &p): + FileTarget(b, 0, p), + Library(b, 0, p, extract_libname(p)) +{ } + +string SystemLibrary::extract_libname(const Msp::FS::Path &p) { - libname=FS::basepart(FS::basename(n)); - if(!libname.compare(0, 3, "lib")) - libname.erase(0, 3); + string result=FS::basepart(FS::basename(p)); + if(!result.compare(0, 3, "lib")) + result.erase(0, 3); + return result; } diff --git a/source/systemlibrary.h b/source/systemlibrary.h index c49c9e4..9048a69 100644 --- a/source/systemlibrary.h +++ b/source/systemlibrary.h @@ -8,22 +8,20 @@ Distributed under the LGPL #ifndef SYSTEMLIBRARY_H_ #define SYSTEMLIBRARY_H_ -#include "target.h" +#include "library.h" /** A library that doesn't belong to any known package. */ -class SystemLibrary: public Target +class SystemLibrary: public Library { -private: - std::string libname; - public: - SystemLibrary(Builder &, const std::string &); + SystemLibrary(Builder &, const Msp::FS::Path &); virtual const char *get_type() const { return "SystemLibrary"; } - const std::string &get_libname() const { return libname; } private: virtual Action *create_action() { return 0; } + + static std::string extract_libname(const Msp::FS::Path &); }; #endif diff --git a/source/tar.cpp b/source/tar.cpp index 797bf24..6f7b154 100644 --- a/source/tar.cpp +++ b/source/tar.cpp @@ -22,7 +22,7 @@ Tar::Tar(Builder &b, const TarBall &t): InternalAction(b), tarball(t) { - string basename=tarball.get_name().substr(tarball.get_name().rfind('/')+1); + string basename=FS::basename(tarball.get_path()); announce(tarball.get_package()->get_name(), "TAR ", basename); if(builder.get_verbose()>=2) cout<<"Create "<get_source(); - FS::Path basedir=FS::basepart(FS::basename(tar.tarball.get_name())); + FS::Path basedir=FS::basepart(FS::basename(tar.tarball.get_path())); - IO::File out(tar.tarball.get_name(), IO::M_WRITE); + IO::File out(tar.tarball.get_path().str(), IO::M_WRITE); const TargetList &deps=tar.tarball.get_depends(); for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i) { + FileTarget *ft=dynamic_cast(*i); + if(!ft) + continue; + char buf[4096]; memset(buf, 0, 512); - string rel_path=(basedir/relative((*i)->get_name(), pkg_src)).str(); + string rel_path=(basedir/relative(ft->get_path(), pkg_src)).str(); if(rel_path.size()>99) { cout<<"Can't store "<get_name()); + struct stat st=FS::stat(ft->get_path()); store_number(buf+100, st.st_mode, 7); store_number(buf+108, st.st_uid, 7); store_number(buf+116, st.st_gid, 7); @@ -76,7 +80,7 @@ void Tar::Worker::main() buf[155]=0; out.write(buf, 512); - IO::File in((*i)->get_name()); + IO::File in(ft->get_path().str()); for(int j=0; j #include "action.h" #include "builder.h" +#include "filetarget.h" #include "package.h" #include "sourcepackage.h" #include "target.h" @@ -29,10 +30,6 @@ Target::Target(Builder &b, const Package *p, const string &n): counted(false) { builder.add_target(this); - - struct stat st; - if(!FS::stat(name, st)) - mtime=Time::TimeStamp::from_unixtime(st.st_mtime); } Target *Target::get_buildable_target() @@ -85,8 +82,9 @@ Action *Target::build() return 0; } - if(!builder.get_dry_run() && FS::exists(name)) - FS::unlink(name); + if(FileTarget *ft=dynamic_cast(this)) + if(!builder.get_dry_run() && FS::exists(ft->get_path())) + FS::unlink(ft->get_path()); Action *action=create_action(); if(action) diff --git a/source/unlink.cpp b/source/unlink.cpp index 208fcf9..458f5a9 100644 --- a/source/unlink.cpp +++ b/source/unlink.cpp @@ -6,18 +6,18 @@ Distributed under the LGPL */ #include +#include "filetarget.h" #include "sourcepackage.h" -#include "target.h" #include "unlink.h" -Unlink::Unlink(Builder &b, const Target &t): +Unlink::Unlink(Builder &b, const FileTarget &t): Action(b) { const SourcePackage &spkg=*static_cast(t.get_package()); - announce(spkg.get_name(), "RM", relative(t.get_name(), spkg.get_source()).str()); + announce(spkg.get_name(), "RM", relative(t.get_path(), spkg.get_source()).str()); - unlink(t.get_name().c_str()); + unlink(t.get_path()); } int Unlink::check() diff --git a/source/unlink.h b/source/unlink.h index f26d163..a26ca0e 100644 --- a/source/unlink.h +++ b/source/unlink.h @@ -10,12 +10,12 @@ Distributed under the LGPL #include "action.h" -class Target; +class FileTarget; class Unlink: public Action { public: - Unlink(Builder &, const Target &); + Unlink(Builder &, const FileTarget &); virtual int check(); };