From 05a2b9dabd01414e9e9a91f9d69babaca4ccb32d Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 5 Feb 2010 21:33:49 +0000 Subject: [PATCH] Add Symlink target and associated action More generic mechanism for figuring out real targets behind proxies Give the -soname option to linker when appropriate Install libraries with versioned names --- source/binary.cpp | 3 +-- source/builder.cpp | 4 +--- source/component.cpp | 12 ++++++++++-- source/filetarget.cpp | 4 ++-- source/install.cpp | 10 +++++++++- source/install.h | 3 ++- source/link.cpp | 10 ++++++---- source/makesymlink.cpp | 35 +++++++++++++++++++++++++++++++++++ source/makesymlink.h | 22 ++++++++++++++++++++++ source/objectfile.cpp | 22 +++++++--------------- source/sharedlibrary.cpp | 24 +++++++++++++++++++++++- source/sharedlibrary.h | 7 +++++++ source/symlink.cpp | 36 ++++++++++++++++++++++++++++++++++++ source/symlink.h | 33 +++++++++++++++++++++++++++++++++ source/target.h | 10 +++++++++- 15 files changed, 203 insertions(+), 32 deletions(-) create mode 100644 source/makesymlink.cpp create mode 100644 source/makesymlink.h create mode 100644 source/symlink.cpp create mode 100644 source/symlink.h diff --git a/source/binary.cpp b/source/binary.cpp index 590471f..636def9 100644 --- a/source/binary.cpp +++ b/source/binary.cpp @@ -53,8 +53,7 @@ void Binary::find_depends() { dep_libs.push_back(lib); - if(Install *inst = dynamic_cast(lib)) - lib = &inst->get_source(); + lib = lib->get_real_target(); if(StaticLibrary *stlib = dynamic_cast(lib)) queue.push_back(&stlib->get_component()); } diff --git a/source/builder.cpp b/source/builder.cpp index f08b27a..17fbd32 100644 --- a/source/builder.cpp +++ b/source/builder.cpp @@ -705,9 +705,7 @@ Target *Builder::get_library(const string &lib, const FS::Path &path, LibMode mo if(tgt) { - Target *real_tgt = tgt; - if(Install *inst = dynamic_cast(tgt)) - real_tgt = &inst->get_source(); + Target *real_tgt = tgt->get_real_target(); /* Ignore dynamic libraries from local packages unless library mode is DYNAMIC */ diff --git a/source/component.cpp b/source/component.cpp index 5c1d9f6..cf42346 100644 --- a/source/component.cpp +++ b/source/component.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -22,6 +22,7 @@ Distributed under the LGPL #include "sharedlibrary.h" #include "sourcepackage.h" #include "staticlibrary.h" +#include "symlink.h" #include "tarball.h" #include "target.h" @@ -211,7 +212,14 @@ void Component::create_targets() const Target *inst_tgt = builder.get_target("install"); for(list::const_iterator i=inst_list.begin(); i!=inst_list.end(); ++i) - inst_tgt->add_depend(new Install(builder, pkg, **i, inst_loc)); + { + Install *inst = new Install(builder, pkg, **i, inst_loc); + inst_tgt->add_depend(inst); + + if(type==LIBRARY) + if(SharedLibrary *shlib = dynamic_cast(*i)) + inst_tgt->add_depend(new Symlink(builder, pkg, *inst, shlib->get_name())); + } } PathList Component::collect_source_files() const diff --git a/source/filetarget.cpp b/source/filetarget.cpp index e7cfc6c..7ba81b2 100644 --- a/source/filetarget.cpp +++ b/source/filetarget.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -23,7 +23,7 @@ FileTarget::FileTarget(Builder &b, const Package *p, const FS::Path &a): builder.add_target(this); struct stat st; - if(!FS::stat(path, st)) + if(!FS::lstat(path, st)) { mtime = Time::TimeStamp::from_unixtime(st.st_mtime); size = st.st_size; diff --git a/source/install.cpp b/source/install.cpp index e59e0d9..2b2a5c9 100644 --- a/source/install.cpp +++ b/source/install.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -28,6 +28,11 @@ Install::Install(Builder &b, const SourcePackage &p, FileTarget &s, const std::s add_depend(&source); } +Target *Install::get_real_target() +{ + return source.get_real_target(); +} + void Install::check_rebuild() { if(!mtime) @@ -66,7 +71,10 @@ FS::Path Install::generate_target_path(const FileTarget &tgt, const std::string { const Component &comp = shlib->get_component(); if(comp.get_type()==Component::LIBRARY) + { mid = "lib"; + tgtname = shlib->get_soname(); + } 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 7cf56bb..6c81af9 100644 --- a/source/install.h +++ b/source/install.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -23,6 +23,7 @@ public: Install(Builder &, const SourcePackage &, FileTarget &, const std::string & =std::string()); virtual const char *get_type() const { return "Install"; } FileTarget &get_source() const { return source; } + virtual Target *get_real_target(); private: virtual void check_rebuild(); virtual Action *create_action(); diff --git a/source/link.cpp b/source/link.cpp index b6537d9..b3e5152 100644 --- a/source/link.cpp +++ b/source/link.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -37,6 +37,10 @@ Link::Link(Builder &b, const Binary &bin): else if(comp.get_package().get_library_mode()==ALL_STATIC) argv.push_back("-static"); + if(const SharedLibrary *lib = dynamic_cast(&bin)) + if(!lib->get_soname().empty()) + argv.push_back("-Wl,-soname,"+lib->get_soname()); + const BuildInfo &binfo = comp.get_build_info(); for(list::const_iterator i=binfo.ldflags.begin(); i!=binfo.ldflags.end(); ++i) argv.push_back(*i); @@ -48,9 +52,7 @@ Link::Link(Builder &b, const Binary &bin): const TargetList &deps = bin.get_depends(); for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i) { - Target *tgt = *i; - if(Install *inst = dynamic_cast(tgt)) - tgt = &inst->get_source(); + Target *tgt = (*i)->get_real_target(); if(ObjectFile *obj = dynamic_cast(tgt)) argv.push_back(relative(obj->get_path(), work_dir).str()); diff --git a/source/makesymlink.cpp b/source/makesymlink.cpp new file mode 100644 index 0000000..b7f64de --- /dev/null +++ b/source/makesymlink.cpp @@ -0,0 +1,35 @@ +/* $Id$ + +This file is part of builder +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#include "builder.h" +#include "package.h" +#include "makesymlink.h" +#include "symlink.h" + +using namespace Msp; + +MakeSymlink::MakeSymlink(Builder &b, const Symlink &sl): + Action(b) +{ + FS::Path relpath = FS::relative(sl.get_target().get_path(), FS::dirname(sl.get_path())); + + announce(sl.get_package()->get_name(), "LN", sl.get_path().str()); + if(builder.get_verbose()>=2) + IO::print("%s -> %s\n", sl.get_name(), relpath.str()); + + if(!builder.get_dry_run()) + symlink(relpath.str().c_str(), sl.get_path().str().c_str()); +} + +int MakeSymlink::check() +{ + signal_done.emit(); + return 0; +} diff --git a/source/makesymlink.h b/source/makesymlink.h new file mode 100644 index 0000000..556dbdf --- /dev/null +++ b/source/makesymlink.h @@ -0,0 +1,22 @@ +/* $Id$ + +This file is part of builder +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef MAKESYMLINK_H_ +#define MAKESYMLINK_H_ + +#include "action.h" + +class Symlink; + +class MakeSymlink: public Action +{ +public: + MakeSymlink(Builder &, const Symlink &); + virtual int check(); +}; + +#endif diff --git a/source/objectfile.cpp b/source/objectfile.cpp index 766188b..f3d6183 100644 --- a/source/objectfile.cpp +++ b/source/objectfile.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -47,17 +47,9 @@ void ObjectFile::find_depends() void ObjectFile::find_depends(Target *tgt) { - SourceFile *src = dynamic_cast(tgt); - FileTarget *file = src; - if(!src) - { - if(Install *inst = dynamic_cast(tgt)) - { - file = inst; - src = dynamic_cast(&inst->get_source()); - } - } - if(!src) + SourceFile *src = dynamic_cast(tgt->get_real_target()); + FileTarget *file = dynamic_cast(tgt); + if(!src || !file) return; FS::Path spath = FS::dirname(file->get_path()); @@ -66,9 +58,9 @@ void ObjectFile::find_depends(Target *tgt) const list &includes = src->get_includes(); for(list::const_iterator i=includes.begin(); i!=includes.end(); ++i) { - Target *hdr2 = builder.get_header(*i, spath, incpath); - if(hdr2 && find(depends.begin(), depends.end(), hdr2)==depends.end()) - add_depend(hdr2); + Target *hdr = builder.get_header(*i, spath, incpath); + if(hdr && find(depends.begin(), depends.end(), hdr)==depends.end()) + add_depend(hdr); } } diff --git a/source/sharedlibrary.cpp b/source/sharedlibrary.cpp index 5c2d26f..a322517 100644 --- a/source/sharedlibrary.cpp +++ b/source/sharedlibrary.cpp @@ -5,14 +5,36 @@ Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ +#include #include "component.h" #include "sharedlibrary.h" #include "sourcepackage.h" using namespace std; +using namespace Msp; SharedLibrary::SharedLibrary(Builder &b, const Component &c, const list &objs): FileTarget(b, &c.get_package(), generate_target_path(c)), Binary(b, c, objs), - Library(b, &c.get_package(), path, c.get_name()) + Library(b, &c.get_package(), path, c.get_name()), + soname(create_soname(c)) { } + +string SharedLibrary::create_soname(const Component &c) +{ + const string &ver = c.get_package().get_version(); + if(ver.empty()) + return string(); + + unsigned dots = 0; + unsigned i = 0; + for(; i=2) + break; + } + + return format("%s.%s", name, ver.substr(0, i)); +} diff --git a/source/sharedlibrary.h b/source/sharedlibrary.h index 13e358f..d8fa41b 100644 --- a/source/sharedlibrary.h +++ b/source/sharedlibrary.h @@ -17,9 +17,16 @@ user. */ class SharedLibrary: public Binary, public Library { +private: + std::string soname; + public: SharedLibrary(Builder &, const Component &, const std::list &); virtual const char *get_type() const { return "SharedLibrary"; } + const std::string &get_soname() const { return soname; } + +private: + std::string create_soname(const Component &); }; #endif diff --git a/source/symlink.cpp b/source/symlink.cpp new file mode 100644 index 0000000..f962b25 --- /dev/null +++ b/source/symlink.cpp @@ -0,0 +1,36 @@ +/* $Id$ + +This file is part of builder +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include "makesymlink.h" +#include "symlink.h" + +using namespace std; +using namespace Msp; + +Symlink::Symlink(Builder &b, const Package &p, FileTarget &t, const string &n): + FileTarget(b, &p, FS::dirname(t.get_path())/n), + target(t) +{ + buildable = true; +} + +Target *Symlink::get_real_target() +{ + return target.get_real_target(); +} + +void Symlink::check_rebuild() +{ + if(!mtime) + mark_rebuild("Does not exist"); +} + +Action *Symlink::create_action() +{ + return new MakeSymlink(builder, *this); +} diff --git a/source/symlink.h b/source/symlink.h new file mode 100644 index 0000000..b381eba --- /dev/null +++ b/source/symlink.h @@ -0,0 +1,33 @@ +/* $Id$ + +This file is part of builder +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef SYMLINK_H_ +#define SYMLINK_H_ + +#include "filetarget.h" + +/** +Symbolic link. +*/ +class Symlink: public FileTarget +{ +private: + FileTarget ⌖ + bool relative; + +public: + Symlink(Builder &, const Package &, FileTarget &, const std::string &); + + virtual const char *get_type() const { return "Symlink";} + FileTarget &get_target() const { return target; } + virtual Target *get_real_target(); +private: + virtual void check_rebuild(); + virtual Action *create_action(); +}; + +#endif diff --git a/source/target.h b/source/target.h index 01b115a..edfd60c 100644 --- a/source/target.h +++ b/source/target.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of builder -Copyright © 2006-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2006-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -58,6 +58,14 @@ public: */ Target *get_buildable_target(); + /** + If this target is a proxy for another (such as Install or Symlink), return + that target. Otherwise, return the target itself. + + Implementors should call the function recursively to find the final target. + */ + virtual Target *get_real_target() { return this; } + bool is_buildable() const { return buildable; } bool get_rebuild() const { return rebuild; } const std::string &get_rebuild_reason() const { return rebuild_reason; } -- 2.45.2