#include "action.h"
#include "analyzer.h"
#include "builder.h"
-#include "executable.h"
#include "header.h"
#include "install.h"
#include "misc.h"
-#include "objectfile.h"
#include "package.h"
#include "pkgconfig.h"
#include "sharedlibrary.h"
-#include "staticlibrary.h"
#include "systemlibrary.h"
#include "unlink.h"
#include "virtualtarget.h"
/**
Returns the target with the given name, or 0 if no such target exists.
*/
-Target *Builder::get_target(const string &n)
+Target *Builder::get_target(const string &n) const
{
- TargetMap::iterator i=targets.find(n);
+ TargetMap::const_iterator i=targets.find(n);
if(i!=targets.end())
return i->second;
return 0;
}
}
+/**
+Adds a target to both the target map and the new target queue. Called from
+Target constructor.
+*/
+void Builder::add_target(Target *t)
+{
+ targets.insert(TargetMap::value_type(t->get_name(), t));
+ new_tgts.push_back(t);
+}
+
int Builder::main()
{
if(load_build_file(cwd/build_file))
int Builder::create_targets()
{
Target *world=new VirtualTarget(*this, "world");
- add_target(world);
Target *def_tgt=new VirtualTarget(*this, "default");
- add_target(def_tgt);
world->add_depend(def_tgt);
Target *install=new VirtualTarget(*this, "install");
- add_target(install);
world->add_depend(install);
for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
if(!i->second->get_buildable())
continue;
- Path::Path inst_base;
- if(i->second->get_buildable() && i->second->get_install_flags())
- inst_base=i->second->get_prefix();
-
const ComponentList &components=i->second->get_components();
for(ComponentList::const_iterator j=components.begin(); j!=components.end(); ++j)
- {
- // Collect all files belonging to the component
- PathList files;
- const PathList &sources=j->get_sources();
- for(PathList::const_iterator k=sources.begin(); k!=sources.end(); ++k)
- {
- struct stat st;
- stat(*k, st);
- if(S_ISDIR(st.st_mode))
- {
- list<string> sfiles=list_files(*k);
- for(list<string>::iterator l=sfiles.begin(); l!=sfiles.end(); ++l)
- files.push_back(*k / *l);
- }
- else
- files.push_back(*k);
- }
-
- bool build_exe=j->get_type()!=Component::HEADERS;
-
- list<ObjectFile *> objs;
- for(PathList::iterator k=files.begin(); k!=files.end(); ++k)
- {
- string basename=(*k)[-1];
- string ext=Path::splitext(basename).ext;
- if((ext==".cpp" || ext==".c") && build_exe)
- {
- SourceFile *src=new SourceFile(*this, &*j, k->str());
- add_target(src);
-
- // Compile sources
- ObjectFile *obj=new ObjectFile(*this, *j, *src);
- add_target(obj);
- objs.push_back(obj);
- }
- else if(ext==".h")
- {
- Target *hdr=get_target(k->str());
- if(!hdr)
- {
- hdr=new Header(*this, &*j, k->str());
- add_target(hdr);
- }
-
- // Install headers if requested
- if(!j->get_install_headers().empty())
- {
- Path::Path inst_path=inst_base/"include"/j->get_install_headers()/basename;
- Install *inst=new Install(*this, *i->second, *hdr, inst_path.str());
- add_target(inst);
- install->add_depend(inst);
- }
- }
- }
-
- if(build_exe)
- {
- Executable *exe=0;
- StaticLibrary *slib=0;
- if(j->get_type()==Component::LIBRARY)
- {
- exe=new SharedLibrary(*this, *j, objs);
- slib=new StaticLibrary(*this, *j, objs);
- add_target(slib);
- }
- else
- exe=new Executable(*this, *j, objs);
-
- add_target(exe);
- if(i->second==default_pkg && j->get_default())
- {
- def_tgt->add_depend(exe);
- if(slib) def_tgt->add_depend(slib);
- }
- else
- {
- world->add_depend(exe);
- if(slib) world->add_depend(slib);
- }
-
- if(j->get_install())
- {
- string inst_dir;
- if(j->get_type()==Component::PROGRAM)
- inst_dir="bin";
- else if(j->get_type()==Component::LIBRARY)
- inst_dir="lib";
- if(!inst_dir.empty())
- {
- Install *inst=new Install(*this, *i->second, *exe, (inst_base/inst_dir/Path::basename(exe->get_name())).str());
- add_target(inst);
- install->add_depend(inst);
-
- if(slib)
- {
- inst=new Install(*this, *i->second, *slib, (inst_base/inst_dir/Path::basename(slib->get_name())).str());
- add_target(inst);
- install->add_depend(inst);
- }
- }
- }
- }
- }
+ j->create_targets();
if(i->second->get_install_flags()&(Package::LIB|Package::INCLUDE))
{
PkgConfig *pc=new PkgConfig(*this, *i->second);
- add_target(pc);
- Install *inst=new Install(*this, *i->second, *pc, (inst_base/"lib"/"pkgconfig"/Path::basename(pc->get_name())).str());
- add_target(inst);
- install->add_depend(inst);
+ install->add_depend(new Install(*this, *i->second, *pc));
}
}
// Make the cmdline target depend on all targets mentioned on the command line
Target *cmdline=new VirtualTarget(*this, "cmdline");
- add_target(cmdline);
bool build_world=false;
for(list<string>::iterator i=cmdline_targets.begin(); i!=cmdline_targets.end(); ++i)
{
if(Path::exists(fn))
{
- add_target(tgt=new SystemHeader(*this, fn.str()));
+ tgt=new SystemHeader(*this, fn.str());
return tgt;
}
return 0;
else if(Path::exists(full))
{
tgt=new SystemLibrary(*this, full);
- add_target(tgt);
return tgt;
}
}
return 0;
}
-/**
-Adds a target to both the target map and the new target queue.
-*/
-void Builder::add_target(Target *t)
-{
- targets.insert(TargetMap::value_type(t->get_name(), t));
- new_tgts.push_back(t);
-}
-
/**
Updates a hash with a string. This is used from get_header and get_library.
*/
bool get_dry_run() const { return dry_run; }
bool get_build_all() const { return build_all; }
Package *get_package(const std::string &);
- Target *get_target(const std::string &);
+ Package *get_default_package() const { return default_pkg; }
+ Target *get_target(const std::string &) const;
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; }
const std::string &get_arch_prefix(const std::string &) const;
std::string get_tool(const std::string &, const std::string &);
void apply_profile_template(Config &, const std::string &) const;
+ void add_target(Target *);
int main();
~Builder();
int create_targets();
Target *get_header(const Msp::Path::Path &);
Target *get_library(const std::string &, const std::string &, const Msp::Path::Path &, LibMode);
- void add_target(Target *);
void update_hash(std::string &, const std::string &);
int do_build();
int do_clean();
#include <msp/core/error.h>
+#include <msp/path/utils.h>
+#include "builder.h"
#include "component.h"
+#include "header.h"
+#include "install.h"
+#include "objectfile.h"
#include "package.h"
+#include "sharedlibrary.h"
+#include "staticlibrary.h"
+#include "target.h"
using namespace std;
+using namespace Msp;
Component::Component(Package &p, Type t, const string &n):
pkg(p),
build_info.unique();
}
+/**
+Creates all targets needed for building this component.
+*/
+void Component::create_targets() const
+{
+ Builder &builder=pkg.get_builder();
+ Target *world=builder.get_target("world");
+ Target *def_tgt=builder.get_target("default");
+
+ PathList files=collect_source_files();
+
+ bool build_exe=(type!=Component::HEADERS);
+
+ list<ObjectFile *> objs;
+ list<Target *> inst_tgts;
+ for(PathList::const_iterator i=files.begin(); i!=files.end(); ++i)
+ {
+ string basename=(*i)[-1];
+ string ext=Path::splitext(basename).ext;
+ if((ext==".cpp" || ext==".c") && build_exe)
+ {
+ SourceFile *src=new SourceFile(builder, this, i->str());
+
+ // Compile sources
+ ObjectFile *obj=new ObjectFile(builder, *this, *src);
+ objs.push_back(obj);
+ }
+ else if(ext==".h")
+ {
+ Target *hdr=builder.get_target(i->str());
+ if(!hdr)
+ hdr=new Header(builder, this, i->str());
+
+ // Install headers if requested
+ if(!install_headers.empty())
+ inst_tgts.push_back(hdr);
+ }
+ }
+
+ if(build_exe)
+ {
+ Executable *exe=0;
+ StaticLibrary *slib=0;
+ if(type==Component::LIBRARY)
+ {
+ exe=new SharedLibrary(builder, *this, objs);
+ slib=new StaticLibrary(builder, *this, objs);
+ }
+ else
+ exe=new Executable(builder, *this, objs);
+
+ if(&pkg==builder.get_default_package() && deflt)
+ {
+ def_tgt->add_depend(exe);
+ if(slib) def_tgt->add_depend(slib);
+ }
+ else
+ {
+ world->add_depend(exe);
+ if(slib) world->add_depend(slib);
+ }
+
+ if(install)
+ {
+ inst_tgts.push_back(exe);
+ 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)
+ inst_tgt->add_depend(new Install(builder, pkg, **i));
+}
+
+/**
+Collects all files belonging to the component.
+*/
+PathList Component::collect_source_files() const
+{
+ PathList files;
+ for(PathList::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+ {
+ struct stat st;
+ stat(*i, st);
+ if(S_ISDIR(st.st_mode))
+ {
+ list<string> sfiles=list_files(*i);
+ for(list<string>::iterator j=sfiles.begin(); j!=sfiles.end(); ++j)
+ files.push_back(*i / *j);
+ }
+ else
+ files.push_back(*i);
+ }
+
+ return files;
+}
+
+
Component::Loader::Loader(Component &c):
comp(c)
{
bool get_default() const { return deflt; }
void resolve_refs();
void create_build_info();
+ void create_targets() const;
protected:
Package &pkg;
Type type;
BuildInfo build_info;
PkgRefList requires;
bool deflt;
+
+ PathList collect_source_files() const;
};
typedef std::list<Component> ComponentList;
#include <msp/path/utils.h>
#include "builder.h"
#include "copy.h"
+#include "executable.h"
#include "header.h"
#include "install.h"
#include "package.h"
+#include "pkgconfig.h"
+#include "staticlibrary.h"
using namespace std;
using namespace Msp;
-Install::Install(Builder &b, const Package &p, Target &tgt, const string &n):
- Target(b, &p, n)
+Install::Install(Builder &b, const Package &p, Target &tgt):
+ Target(b, &p, generate_target_name(tgt))
{
buildable=true;
add_depend(&tgt);
{
return Target::build(new Copy(builder, *package, depends.front()->get_name(), name));
}
+
+string Install::generate_target_name(const Target &tgt)
+{
+ Path::Path base=tgt.get_package()->get_prefix();
+ string tgtname=tgt.get_name().substr(tgt.get_name().rfind('/')+1);
+
+ string mid;
+ if(const Header *hdr=dynamic_cast<const Header *>(&tgt))
+ mid="include/"+hdr->get_component()->get_install_headers();
+ else if(const Executable *exe=dynamic_cast<const Executable *>(&tgt))
+ {
+ const Component &comp=exe->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();
+ }
+ else if(dynamic_cast<const StaticLibrary *>(&tgt))
+ mid="lib";
+ else if(dynamic_cast<const PkgConfig *>(&tgt))
+ mid="lib/pkgconfig";
+
+ if(mid.empty())
+ throw InvalidParameterValue("Don't know where to install "+tgtname);
+
+ return (base/mid/tgtname).str();
+}
class Install: public Target
{
public:
- Install(Builder &, const Package &, Target &, const std::string &);
+ Install(Builder &, const Package &, Target &);
const char *get_type() const { return "Install"; }
void check_rebuild();
Action *build();
private:
+ std::string generate_target_name(const Target &);
};
#endif
SourceFile(Builder &, const Component *, const std::string &);
const StringList &get_includes() const { return includes; }
const char *get_type() const { return "SourceFile"; }
+ const Component *get_component() const { return comp; }
void find_depends();
Action *build() { return 0; }
private:
prepared(false),
counted(false)
{
+ builder.add_target(this);
+
struct stat st;
if(!Path::stat(name, st))
mtime=Time::TimeStamp::from_unixtime(st.st_mtime);