]> git.tdb.fi Git - builder.git/commitdiff
Add tarball building
authorMikko Rasa <tdb@tdb.fi>
Fri, 17 Aug 2007 15:55:04 +0000 (15:55 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 17 Aug 2007 15:55:04 +0000 (15:55 +0000)
source/builder.cpp
source/builder.h
source/file.cpp [new file with mode: 0644]
source/file.h [new file with mode: 0644]
source/package.cpp
source/package.h
source/tar.cpp [new file with mode: 0644]
source/tar.h [new file with mode: 0644]
source/tarball.cpp [new file with mode: 0644]
source/tarball.h [new file with mode: 0644]
source/target.h

index 553a3e159afbe01e7487ad35b6cf337ae909974c..336cc8453c118e519b266c8a2ebc8c757385e9dc 100644 (file)
@@ -25,6 +25,7 @@ Distributed under the LGPL
 #include "pkgconfig.h"
 #include "sharedlibrary.h"
 #include "systemlibrary.h"
+#include "tarball.h"
 #include "unlink.h"
 #include "virtualtarget.h"
 
@@ -508,6 +509,9 @@ int Builder::create_targets()
        Target *install=new VirtualTarget(*this, "install");
        world->add_depend(install);
 
+       Target *tarballs=new VirtualTarget(*this, "tarballs");
+       world->add_depend(tarballs);
+
        for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
        {
                if(!i->second)
@@ -524,6 +528,8 @@ int Builder::create_targets()
                        PkgConfig *pc=new PkgConfig(*this, *i->second);
                        install->add_depend(new Install(*this, *i->second, *pc));
                }
+
+               tarballs->add_depend(new TarBall(*this, *i->second));
        }
 
        // Find dependencies until no new targets are created
index 291c14b66662b1a68d37efa480e0dff6d6511333..ba20fe3234f2987916bd00dedab1bf2dc961134f 100644 (file)
@@ -35,6 +35,7 @@ public:
        Package  *get_package(const std::string &);
        Package  *get_default_package() const { return default_pkg; }
        Target   *get_target(const std::string &) const;
+       const TargetMap &get_targets() const { return targets; }
        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; }
@@ -60,7 +61,6 @@ private:
 
        typedef std::list<Package *>               PackageList;
        typedef std::map<std::string, Package *>   PackageMap;
-       typedef std::map<std::string, Target *>    TargetMap;
        typedef std::map<std::string, StringMap>   ToolMap;
        typedef std::map<std::string, StringMap>   ProfileTemplateMap;
 
diff --git a/source/file.cpp b/source/file.cpp
new file mode 100644 (file)
index 0000000..e2b3c27
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "file.h"
+
+using namespace std;
+
+File::File(Builder &b, const string &n):
+       Target(b, 0, n)
+{ }
diff --git a/source/file.h b/source/file.h
new file mode 100644 (file)
index 0000000..35c1087
--- /dev/null
@@ -0,0 +1,21 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef FILE_H_
+#define FILE_H_
+
+#include "target.h"
+
+class File: public Target
+{
+public:
+       File(Builder &, const std::string &);
+       virtual const char *get_type() const { return "File"; }
+       virtual Action *build() { return 0; }
+};
+
+#endif
index 949bd8e7755b6c7b0a0a348624b3b709b612c7c1..372cf2807be01997fed3733c81cc81d558516a03 100644 (file)
@@ -29,6 +29,8 @@ Package::Package(Builder &b, const string &n, const Path::Path &s):
        use_pkgconfig(true),
        need_path(false)
 {
+       tar_files.push_back(source/"Build");
+
        if(builder.get_verbose()>=4)
                cout<<"Created buildable package "<<n<<" at "<<s<<'\n';
 }
@@ -369,6 +371,7 @@ Package::Loader::Loader(Package &p):
        add("module",      &Loader::module);
        add("headers",     &Loader::headers);
        add("build_info",  &Loader::build_info);
+       add("tar_file",    &Loader::tar_file);
 }
 
 void Package::Loader::require(const string &n)
@@ -420,3 +423,8 @@ void Package::Loader::build_info()
 {
        load_sub(pkg.build_info);
 }
+
+void Package::Loader::tar_file(const string &f)
+{
+       pkg.tar_files.push_back(pkg.source/f);
+}
index 0bd678a9c77a01ff4391eabc296e46c3e9d33733..1aebf163865a98c290d5a668a55cf8ffc790b9d3 100644 (file)
@@ -57,6 +57,7 @@ public:
                void module(const std::string &);
                void headers(const std::string &);
                void build_info();
+               void tar_file(const std::string &);
        };
 
        Package(Builder &, const std::string &, const Msp::Path::Path &);
@@ -80,6 +81,7 @@ public:
        bool                get_use_pkgconfig() const   { return use_pkgconfig; }
        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; }
        void                resolve_refs();
        void                configure(const StringMap &, unsigned);
 
@@ -102,6 +104,7 @@ private:
        ComponentList components;
        Config        config;
        bool          conf_done;
+       PathList      tar_files;
 
        bool          use_pkgconfig;
        bool          need_path;
diff --git a/source/tar.cpp b/source/tar.cpp
new file mode 100644 (file)
index 0000000..0b0c38d
--- /dev/null
@@ -0,0 +1,123 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <iostream>
+#include <msp/path/utils.h>
+#include "builder.h"
+#include "package.h"
+#include "tar.h"
+#include "tarball.h"
+
+using namespace std;
+using namespace Msp;
+
+Tar::Tar(Builder &b, const TarBall &t):
+       Action(b),
+       tarball(t),
+       worker(0)
+{
+       string basename=tarball.get_name().substr(tarball.get_name().rfind('/')+1);
+       announce(tarball.get_package()->get_name(), "TAR ", basename);
+       if(builder.get_verbose()>=2)
+               cout<<"Create "<<basename<<'\n';
+       
+       if(!builder.get_dry_run())
+               worker=new Worker(*this);
+}
+
+Tar::~Tar()
+{
+       delete worker;
+}
+
+int Tar::check()
+{
+       if(!worker)  // True for dry run
+       {
+               signal_done.emit();
+               return 0;
+       }
+       
+       if(worker->get_done())
+       {
+               signal_done.emit();
+               worker->join();
+               return worker->get_error()?1:0;
+       }
+       
+       return -1;
+}
+
+
+Tar::Worker::Worker(Tar &t):
+       tar(t),
+       done(false),
+       error(false)
+{
+       launch();
+}
+
+void Tar::Worker::main()
+{
+       const Path::Path &pkg_src=tar.tarball.get_package()->get_source();
+       Path::Path basedir=Path::splitext(Path::basename(tar.tarball.get_name())).base;
+
+       ofstream out(tar.tarball.get_name().c_str());
+       const TargetList &deps=tar.tarball.get_depends();
+       for(TargetList::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+       {
+               char buf[4096];
+               memset(buf, 0, 512);
+
+               string rel_path=(basedir/relative((*i)->get_name(), pkg_src)).str();
+               if(rel_path.size()>99)
+               {
+                       cout<<"Can't store "<<rel_path<<" in tar archive - too long name\n";
+                       error=true;
+                       break;
+               }
+
+               memcpy(buf, rel_path.data(), rel_path.size());
+
+               struct stat st;
+               Path::stat((*i)->get_name(), st);
+               store_number(buf+100, st.st_mode, 7);
+               store_number(buf+108, st.st_uid, 7);
+               store_number(buf+116, st.st_gid, 7);
+               store_number(buf+124, st.st_size, 11);
+               store_number(buf+136, st.st_mtime, 11);
+               buf[156]='0';
+
+               memset(buf+148, ' ', 8);
+               unsigned chk=0;
+               for(unsigned j=0; j<512; ++j)
+                       chk+=static_cast<unsigned char>(buf[j]);
+               store_number(buf+148, chk, 7);
+               buf[155]=0;
+
+               out.write(buf, 512);
+               ifstream in((*i)->get_name().c_str());
+               for(int j=0; j<st.st_size; j+=4096)
+               {
+                       in.read(buf, 4096);
+                       unsigned len=in.gcount();
+                       len+=((~len)+1)&0777;
+                       out.write(buf, len);
+               }
+       }
+
+       done=true;
+}
+
+void Tar::Worker::store_number(char *buf, unsigned value, unsigned length)
+{
+       for(unsigned i=length; i--;)
+       {
+               buf[i]='0'+value%8;
+               value/=8;
+       }
+}
diff --git a/source/tar.h b/source/tar.h
new file mode 100644 (file)
index 0000000..137a7ee
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef TAR_H_
+#define TAR_H_
+
+#include <msp/core/thread.h>
+#include "action.h"
+#include "misc.h"
+
+class TarBall;
+
+class Tar: public Action
+{
+public:
+       Tar(Builder &, const TarBall &);
+       ~Tar();
+
+       virtual int check();
+private:
+       class Worker: public Msp::Thread
+       {
+       public:
+               Worker(Tar &);
+               bool get_done() const { return done; }
+               bool get_error() const { return error; }
+       private:
+               Tar &tar;
+               bool done;
+               bool error;
+
+               void main();
+               void store_number(char *, unsigned, unsigned);
+       };
+
+       const TarBall &tarball;
+       StringList files;
+       Worker *worker;
+};
+
+#endif
diff --git a/source/tarball.cpp b/source/tarball.cpp
new file mode 100644 (file)
index 0000000..348272f
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "builder.h"
+#include "file.h"
+#include "package.h"
+#include "tar.h"
+#include "tarball.h"
+
+using namespace std;
+
+TarBall::TarBall(Builder &b, const Package &p, const string &ev):
+       Target(b, &p, create_target_name(p, ev))
+{
+       buildable=true;
+}
+
+void TarBall::find_depends()
+{
+       const TargetMap &targets=builder.get_targets();
+       for(TargetMap::const_iterator i=targets.begin(); i!=targets.end(); ++i)
+               if(i->second->get_package()==package && i->second!=this && !i->second->get_buildable())
+                       add_depend(i->second);
+
+       const PathList &tar_files=package->get_tar_files();
+       for(PathList::const_iterator i=tar_files.begin(); i!=tar_files.end(); ++i)
+       {
+               Target *tgt=builder.get_target(i->str());
+               if(!tgt)
+                       tgt=new File(builder, i->str());
+               add_depend(tgt);
+       }
+
+       deps_ready=true;
+}
+
+Action *TarBall::build()
+{
+       return Target::build(new Tar(builder, *this));
+}
+
+string TarBall::create_target_name(const Package &pkg, const string &extra_ver)
+{
+       string basename=pkg.get_name()+"-"+pkg.get_version();
+       if(!extra_ver.empty())
+               basename+="-"+extra_ver;
+       basename+=".tar";
+
+       return (pkg.get_source()/basename).str();
+}
diff --git a/source/tarball.h b/source/tarball.h
new file mode 100644 (file)
index 0000000..6c36237
--- /dev/null
@@ -0,0 +1,26 @@
+/* $Id$
+
+This file is part of builder
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef TARBALL_H_
+#define TARBALL_H_
+
+#include "target.h"
+
+class TarBall: public Target
+{
+public:
+       TarBall(Builder &, const Package &, const std::string & =std::string());
+       virtual const char *get_type() const { return "TarBall"; }
+       virtual void find_depends();
+       virtual Action *build();
+private:
+       std::string tarname;
+
+       std::string create_target_name(const Package &, const std::string &);
+};
+
+#endif
index 605b328badef68faaca64c0c6f2b84c61f9de98d..cf1d18651c9ed5f92c0ac0792b1ae6d75bf153a8 100644 (file)
@@ -9,6 +9,7 @@ Distributed under the LGPL
 #define TARGET_H_
 
 #include <list>
+#include <map>
 #include <string>
 #include <msp/time/timestamp.h>
 
@@ -37,9 +38,14 @@ public:
        const Package      *get_package() const        { return package; }
        bool               get_depends_ready() const   { return deps_ready; }
        void               add_depend(Target *);
-       virtual void       find_depends()              { deps_ready=true; }
        virtual void       prepare();
 
+       /**
+       Finds dependencies for the target.  When all dependencies have been found,
+       the function should set deps_ready to true.
+       */
+       virtual void       find_depends()              { deps_ready=true; }
+
        /**
        Creates and returns an Action suitable for building this target.
        */
@@ -74,4 +80,6 @@ protected:
        virtual void build_done();
 };
 
+typedef std::map<std::string, Target *> TargetMap;
+
 #endif