prefix "i586-mingw32msvc";
};
-profile "debug"
+build_type "debug"
{
- option "debug" "yes";
- option "outdir" "$profile";
+ build_info
+ {
+ debug true;
+ define "DEBUG" "1";
+ };
+};
+
+build_type "optimized_debug"
+{
+ build_info
+ {
+ debug true;
+ optimize 2;
+ };
};
-profile "release"
+build_type "release"
{
- option "optimize" "3";
- option "strip" "yes";
- option "outdir" "$profile";
+ build_info
+ {
+ optimize 3;
+ strip true;
+ };
};
package_manager(*this),
main_pkg(0),
native_arch(*this, string()),
+ build_type(0),
vfs(*this),
analyzer(0),
build(false),
unsigned verbose = 1;
bool silent = false;
list<string> log_channels;
+ string build_type_name;
GetOpt getopt;
getopt.add_option('a', "analyze", analyze_mode, GetOpt::REQUIRED_ARG).set_help("Perform analysis. MODE can be deps, alldeps or rebuild.", "MODE");
getopt.add_option('l', "log", log_channels, GetOpt::REQUIRED_ARG).set_help("Set log channels to be displayed.", "LIST");
getopt.add_option('n', "dry-run", dry_run, GetOpt::NO_ARG).set_help("Don't actually do anything, only show what would be done.");
getopt.add_option('s', "silent", silent, GetOpt::NO_ARG).set_help("Don't print any messages other than errors.");
+ getopt.add_option('t', "build-type", build_type_name, GetOpt::REQUIRED_ARG).set_help("Set build type.", "TYPE");
getopt.add_option('v', "verbose", verbose, GetOpt::NO_ARG).set_help("Print more information about what's going on.");
getopt.add_option('x', "no-externals", no_externals, GetOpt::NO_ARG).set_help("Do not load external source packages.");
getopt.add_option('A', "conf-all", conf_all, GetOpt::NO_ARG).set_help("Apply configuration to all packages.");
else
prefix = FS::getcwd()/prfx;
+ if(!build_type_name.empty())
+ {
+ BuildTypeMap::iterator i = build_types.find(build_type_name);
+ if(i==build_types.end())
+ throw usage_error("Unknown build type");
+ build_type = &i->second;
+ }
+
warnings.push_back("all");
warnings.push_back("extra");
warnings.push_back("shadow");
logger.log("environment", format("Building on %s, for %s%s", native_arch.get_name(),
current_arch->get_name(), (current_arch->is_native() ? " (native)" : "")));
logger.log("environment", format("Prefix is %s", prefix));
+ if(build_type)
+ logger.log("environment", format("Build type is %s", build_type->get_name()));
const PackageManager::PackageMap &packages = package_manager.get_packages();
list<string> package_details;
return 0;
}
-void Builder::apply_profile_template(Config &config, const string &pt) const
-{
- vector<string> parts = split(pt, '-');
-
- for(vector<string>::iterator i=parts.begin(); i!=parts.end(); ++i)
- {
- ProfileTemplateMap::const_iterator j = profile_tmpl.find(*i);
- if(j==profile_tmpl.end())
- continue;
-
- config.update(j->second);
- }
-}
-
void Builder::problem(const string &p, const string &d)
{
problems.push_back(Problem(p, d));
{
add("architecture", &Loader::architecture);
add("binary_package", &Loader::binpkg);
+ add("build_type", &Loader::build_type);
add("profile", &Loader::profile);
add("package", &Loader::package);
}
load_sub(*pkg);
}
-void Builder::Loader::profile(const string &n)
+void Builder::Loader::build_type(const string &n)
{
- StringMap prf;
- ProfileLoader ldr(prf);
- load_sub_with(ldr);
- obj.profile_tmpl.insert(ProfileTemplateMap::value_type(n, prf));
+ BuildType btype(n);
+ load_sub(btype);
+ BuildTypeMap::iterator i = obj.build_types.insert(BuildTypeMap::value_type(n, btype)).first;
+ if(!obj.build_type)
+ obj.build_type = &i->second;
+}
+
+void Builder::Loader::profile(const string &)
+{
+ IO::print("Profiles are deprecated\n");
}
void Builder::Loader::package(const string &n)
obj.main_pkg = pkg;
load_sub(*pkg);
-}
-
-
-Builder::ProfileLoader::ProfileLoader(StringMap &p):
- profile(p)
-{
- add("option", &ProfileLoader::option);
-}
-
-void Builder::ProfileLoader::option(const string &o, const string &v)
-{
- profile.insert(StringMap::value_type(o, v));
+ if(obj.build_type)
+ pkg->set_build_type(*obj.build_type);
}
#include <msp/datafile/loader.h>
#include <msp/fs/path.h>
#include "architecture.h"
+#include "buildtype.h"
#include "config.h"
#include "logger.h"
#include "misc.h"
private:
void architecture(const std::string &);
void binpkg(const std::string &);
+ void build_type(const std::string &);
void profile(const std::string &);
void package(const std::string &);
};
- class ProfileLoader: public Msp::DataFile::Loader
- {
- private:
- StringMap &profile;
-
- public:
- ProfileLoader(StringMap &);
- private:
- void option(const std::string &, const std::string &);
- };
-
public:
typedef std::map<std::string, Target *> TargetMap;
private:
- typedef std::map<std::string, StringMap> ProfileTemplateMap;
+ typedef std::map<std::string, BuildType> BuildTypeMap;
StringList cmdline_targets;
StringMap cmdline_options;
Architecture native_arch;
Architecture *current_arch;
- ProfileTemplateMap profile_tmpl;
+ BuildTypeMap build_types;
+ BuildType *build_type;
Toolchain toolchain;
VirtualFileSystem vfs;
Logger logger;
const Architecture &get_native_arch() const { return native_arch; }
const Msp::FS::Path &get_prefix() const { return prefix; }
const StringList &get_warnings() const { return warnings; }
- void apply_profile_template(Config &, const std::string &) const;
const Toolchain &get_toolchain() const { return toolchain; }
VirtualFileSystem &get_vfs() { return vfs; }
--- /dev/null
+#include "buildtype.h"
+
+using namespace std;
+using namespace Msp;
+
+BuildType::BuildType(const string &n):
+ name(n)
+{ }
+
+
+BuildType::Loader::Loader(BuildType &b):
+ DataFile::ObjectLoader<BuildType>(b)
+{
+ add("build_info", &Loader::build_info);
+}
+
+void BuildType::Loader::build_info()
+{
+ load_sub(obj.build_info);
+}
--- /dev/null
+#ifndef BUILDTYPE_H_
+#define BUILDTYPE_H_
+
+#include <string>
+#include <msp/datafile/objectloader.h>
+#include "buildinfo.h"
+
+class BuildType
+{
+public:
+ class Loader: public Msp::DataFile::ObjectLoader<BuildType>
+ {
+ public:
+ Loader(BuildType &);
+
+ private:
+ void build_info();
+ };
+
+private:
+ std::string name;
+ BuildInfo build_info;
+
+public:
+ BuildType(const std::string &);
+
+ const std::string &get_name() const { return name; }
+ const BuildInfo &get_build_info() const { return build_info; }
+};
+
+#endif
build_info.libpath.insert(build_info.libpath.end(), ebi.libpath.begin(), ebi.libpath.end());
}
}
-
- if(type==PROGRAM)
- build_info.strip = lexical_cast<bool>(pkg.get_config().get_option("strip").value);
}
void Component::create_targets() const
Config::Config(SourcePackage &p):
package(p),
- freeze_mtime(false),
changed(false)
{ }
return options.count(name);
}
-void Config::select_last_profile()
-{
- FS::Path profile_cache_fn = package.get_source()/".profile";
- if(FS::exists(profile_cache_fn))
- {
- IO::BufferedFile in(profile_cache_fn.str());
- string profile;
- in.getline(profile);
- set_option("profile", profile);
- }
-
- freeze_mtime = true;
- package.get_builder().apply_profile_template(*this, get_option("profile").value);
- freeze_mtime = false;
-
- load();
-}
-
-void Config::select_profile(const string &profile)
-{
- set_option("profile", profile);
-
- freeze_mtime = true;
- package.get_builder().apply_profile_template(*this, profile);
- freeze_mtime = false;
-
- load();
-}
-
bool Config::update(const StringMap &opts)
{
bool changed_now = false;
changed_now = true;
}
- if(changed_now && !freeze_mtime)
+ if(changed_now)
{
mtime = Time::now();
changed = true;
if(!changed)
return;
- FS::Path fn = package.get_source()/".options";
-
- OptionMap::const_iterator i = options.find("profile");
- if(i!=options.end())
- {
- fn = package.get_source()/(".options."+i->second.value);
-
- IO::BufferedFile profile_out((package.get_source()/".profile").str(), IO::M_WRITE);
- IO::print(profile_out, "%s\n", i->second.value);
- }
+ FS::Path fn = package.get_source()/".config";
IO::BufferedFile out(fn.str(), IO::M_WRITE);
- for(i=options.begin(); i!=options.end(); ++i)
+ for(OptionMap::const_iterator i=options.begin(); i!=options.end(); ++i)
IO::print(out, "option \"%s\" \"%s\";\n", i->second.name, i->second.value);
}
void Config::load()
{
- FS::Path fn = package.get_source()/(".options."+get_option("profile").value);
+ FS::Path fn = package.get_source()/".config";
FS::Stat stat = FS::stat(fn);
if(stat)
SourcePackage &package;
OptionMap options;
Msp::Time::TimeStamp mtime;
- bool freeze_mtime;
bool changed;
public:
/** Checks whether an option exists. */
bool is_option(const std::string &) const;
- /** Selects the last profile used. If the profile cache file is not
- present, the default profile is assumed. */
- void select_last_profile();
-
- /** Selects a profile. */
- void select_profile(const std::string &);
-
/** Processes options from the given raw option map. Nonexistent options
are ignored. If any options were changed, the mtime of the configuration is
updated to the current time. Return value indicates whether any options
void save() const;
private:
bool set_option(const std::string &, const std::string &);
+public:
void load();
};
SourcePackage::SourcePackage(Builder &b, const string &n, const FS::Path &s):
Package(b, n),
source(s),
+ build_type(0),
config(*this),
deps_cache(*this)
{
components.push_back(Component(*this, Component::TARBALL, "@src"));
}
+void SourcePackage::set_build_type(const BuildType &t)
+{
+ build_type = &t;
+}
+
FS::Path SourcePackage::get_temp_dir() const
{
- string subdir = format("%s.%s", builder.get_current_arch().get_name(), config.get_option("profile").value);
+ string subdir = builder.get_current_arch().get_name();
+ if(build_type)
+ {
+ subdir += '.';
+ subdir += build_type->get_name();
+ }
return source/config.get_option("tempdir").value/subdir;
}
FS::Path SourcePackage::get_out_dir() const
{
const Architecture &arch = builder.get_current_arch();
+ string detail = (build_type ? build_type->get_name() : string());
if(arch.is_native())
- return source/config.get_option("outdir").value;
+ return source/detail;
else
- return source/arch.get_name()/config.get_option("outdir").value;
+ return source/arch.get_name()/detail;
}
LibMode SourcePackage::get_library_mode() const
{
init_config();
- StringMap::const_iterator prof = opts.find("profile");
- if(prof!=opts.end() && flag)
- config.select_profile(prof->second);
- else
- config.select_last_profile();
+ config.load();
if(flag && config.update(opts))
builder.get_logger().log("configure", format("Configuration of %s changed", name));
void SourcePackage::init_config()
{
- config.add_option("profile", "default", "Configuration profile");
config.add_option("tempdir", "temp", "Directory for storing temporary files");
- config.add_option("outdir", ".", "Directory to put build results in");
- config.add_option("optimize", "0", "Compiler optimization level");
- config.add_option("strip", "no", "Strip symbols from programs");
- config.add_option("debug", "no", "Produce debugging symbols");
config.add_option("staticlibs", "local", "Use static libraries");
for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i)
void SourcePackage::create_build_info()
{
+ if(build_type)
+ build_info.update_from(build_type->get_build_info());
+
// XXX Currently, a package-specific settings will override cmdline. This might or might not be desirable.
const StringList &warnings = builder.get_warnings();
build_info.warnings.insert(build_info.warnings.begin(), warnings.begin(), warnings.end());
export_binfo.libpath.push_back((builder.get_prefix()/"lib").str());
}
- string optimize = config.get_option("optimize").value;
- if(!optimize.empty() && optimize!="0")
- {
- if(optimize=="s" || optimize=="size")
- build_info.optimize = -1;
- else
- build_info.optimize = lexical_cast<unsigned>(optimize);
- }
-
- if(lexical_cast<bool>(config.get_option("debug").value))
- {
- build_info.debug = true;
- build_info.defines["DEBUG"] = "1";
- }
-
for(FeatureList::iterator i=features.begin(); i!=features.end(); ++i)
if(lexical_cast<bool>(config.get_option("with_"+i->name).value))
build_info.defines["WITH_"+toupper(i->name)] = "1";
#include "package.h"
class Builder;
+class BuildType;
class bad_expansion: public std::runtime_error
{
std::string description;
Msp::FS::Path source;
+ const BuildType *build_type;
FeatureList features;
BuildInfo build_info;
ConditionList conditions;
Msp::FS::Path get_out_dir() const;
const ComponentList &get_components() const { return components; }
const Config &get_config() const { return config; }
+ void set_build_type(const BuildType &);
const BuildInfo &get_build_info() const { return build_info; }
Builder &get_builder() const { return builder; }