#include "pkgconfig.h"
#include "sharedlibrary.h"
#include "systemlibrary.h"
+#include "tarball.h"
#include "unlink.h"
#include "virtualtarget.h"
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)
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
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; }
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;
--- /dev/null
+/* $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)
+{ }
--- /dev/null
+/* $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
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';
}
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)
{
load_sub(pkg.build_info);
}
+
+void Package::Loader::tar_file(const string &f)
+{
+ pkg.tar_files.push_back(pkg.source/f);
+}
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 &);
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);
ComponentList components;
Config config;
bool conf_done;
+ PathList tar_files;
bool use_pkgconfig;
bool need_path;
--- /dev/null
+/* $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;
+ }
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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();
+}
--- /dev/null
+/* $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
#define TARGET_H_
#include <list>
+#include <map>
#include <string>
#include <msp/time/timestamp.h>
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.
*/
virtual void build_done();
};
+typedef std::map<std::string, Target *> TargetMap;
+
#endif