]> git.tdb.fi Git - builder.git/commitdiff
Add Symlink target and associated action
authorMikko Rasa <tdb@tdb.fi>
Fri, 5 Feb 2010 21:33:49 +0000 (21:33 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 5 Feb 2010 21:33:49 +0000 (21:33 +0000)
More generic mechanism for figuring out real targets behind proxies
Give the -soname option to linker when appropriate
Install libraries with versioned names

15 files changed:
source/binary.cpp
source/builder.cpp
source/component.cpp
source/filetarget.cpp
source/install.cpp
source/install.h
source/link.cpp
source/makesymlink.cpp [new file with mode: 0644]
source/makesymlink.h [new file with mode: 0644]
source/objectfile.cpp
source/sharedlibrary.cpp
source/sharedlibrary.h
source/symlink.cpp [new file with mode: 0644]
source/symlink.h [new file with mode: 0644]
source/target.h

index 590471f3a0f75e286f55c6afd4f04f2c62a4b447..636def98a295f318e0926cec71b39a277b7f3e21 100644 (file)
@@ -53,8 +53,7 @@ void Binary::find_depends()
                        {
                                dep_libs.push_back(lib);
 
-                               if(Install *inst = dynamic_cast<Install *>(lib))
-                                       lib = &inst->get_source();
+                               lib = lib->get_real_target();
                                if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(lib))
                                        queue.push_back(&stlib->get_component());
                        }
index f08b27aec69d667ac2eef6d1fdcfa09bf83292c5..17fbd32e2efece9636ea39f0ed05a589a572f8af 100644 (file)
@@ -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<Install *>(tgt))
-                               real_tgt = &inst->get_source();
+                       Target *real_tgt = tgt->get_real_target();
 
                        /* Ignore dynamic libraries from local packages unless library mode is
                        DYNAMIC */
index 5c1d9f6b6b6a9d3ab35d83cc1258a4921557b6d3..cf4234607e978d1f6399a2732adaded39496602d 100644 (file)
@@ -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<FileTarget *>::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<SharedLibrary *>(*i))
+                               inst_tgt->add_depend(new Symlink(builder, pkg, *inst, shlib->get_name()));
+       }
 }
 
 PathList Component::collect_source_files() const
index e7cfc6c10ce638fcd643a3158ab7d4fcff3eb72e..7ba81b28cf5a626340c3a9de707b23846c9688d1 100644 (file)
@@ -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;
index e59e0d93b090d802e26ed9949eedbb036238826d..2b2a5c94f0bae872039104bbfb638cfa4de2b6f2 100644 (file)
@@ -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();
        }
index 7cf56bb80fec36b7841f339d5909558df484bf05..6c81af9e416e8d18ce915f1228918a3e6c4e76ad 100644 (file)
@@ -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();
index b6537d987a143e9551d893680be91f8eb29f08c8..b3e5152204b73d632478fe91a979a200e5f86b12 100644 (file)
@@ -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<const SharedLibrary *>(&bin))
+               if(!lib->get_soname().empty())
+                       argv.push_back("-Wl,-soname,"+lib->get_soname());
+
        const BuildInfo &binfo = comp.get_build_info();
        for(list<string>::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<Install *>(tgt))
-                       tgt = &inst->get_source();
+               Target *tgt = (*i)->get_real_target();
 
                if(ObjectFile *obj = dynamic_cast<ObjectFile *>(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 (file)
index 0000000..b7f64de
--- /dev/null
@@ -0,0 +1,35 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <unistd.h>
+#include <msp/fs/utils.h>
+#include <msp/io/print.h>
+#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 (file)
index 0000000..556dbdf
--- /dev/null
@@ -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
index 766188b5ad313bc73dd5e3db1660c36e637aa785..f3d6183afa6b01161b1039af0bb6f838d571e5d8 100644 (file)
@@ -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<SourceFile *>(tgt);
-       FileTarget *file = src;
-       if(!src)
-       {
-               if(Install *inst = dynamic_cast<Install *>(tgt))
-               {
-                       file = inst;
-                       src = dynamic_cast<SourceFile *>(&inst->get_source());
-               }
-       }
-       if(!src)
+       SourceFile *src = dynamic_cast<SourceFile *>(tgt->get_real_target());
+       FileTarget *file = dynamic_cast<FileTarget *>(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<string> &includes = src->get_includes();
        for(list<string>::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);
        }
 }
 
index 5c2d26fea27f799521c6697fc3803db959ea23f4..a3225171836eafb10a67f30e3191ccc660d8901c 100644 (file)
@@ -5,14 +5,36 @@ Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
+#include <msp/strings/formatter.h>
 #include "component.h"
 #include "sharedlibrary.h"
 #include "sourcepackage.h"
 
 using namespace std;
+using namespace Msp;
 
 SharedLibrary::SharedLibrary(Builder &b, const Component &c, const list<ObjectFile *> &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<ver.size(); ++i)
+               if(ver[i]=='.')
+               {
+                       ++dots;
+                       if(dots>=2)
+                               break;
+               }
+
+       return format("%s.%s", name, ver.substr(0, i));
+}
index 13e358fe069f21def86727194abc8195aa21a76f..d8fa41bcdf7593caeba4f7ab012b1b8e0549acc4 100644 (file)
@@ -17,9 +17,16 @@ user.
 */
 class SharedLibrary: public Binary, public Library
 {
+private:
+       std::string soname;
+
 public:
        SharedLibrary(Builder &, const Component &, const std::list<ObjectFile *> &);
        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 (file)
index 0000000..f962b25
--- /dev/null
@@ -0,0 +1,36 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/fs/utils.h>
+#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 (file)
index 0000000..b381eba
--- /dev/null
@@ -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 &target;
+       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
index 01b115a7a6b5ddf2e008f39299c7c392ae84bcd2..edfd60cebe7f8f655a5c8011512d05b80b481d9b 100644 (file)
@@ -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; }