aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/buildfile4
-rw-r--r--libbuild2/cc/compile-rule.cxx6
-rw-r--r--libbuild2/config/init.cxx3
-rw-r--r--libbuild2/config/module.cxx16
-rw-r--r--libbuild2/config/module.hxx26
-rw-r--r--libbuild2/config/operation.cxx4
-rw-r--r--libbuild2/config/utility.cxx180
-rw-r--r--libbuild2/config/utility.hxx106
-rw-r--r--libbuild2/config/utility.txx3
-rw-r--r--libbuild2/context.cxx10
-rw-r--r--libbuild2/context.hxx12
-rw-r--r--libbuild2/file.cxx162
-rw-r--r--libbuild2/file.hxx14
13 files changed, 289 insertions, 257 deletions
diff --git a/libbuild2/buildfile b/libbuild2/buildfile
index 63078ea..a253ab1 100644
--- a/libbuild2/buildfile
+++ b/libbuild2/buildfile
@@ -34,7 +34,9 @@ lib{build2}: cxx{utility-uninstalled}: for_install = false
# These are "core modules" that come bundled with libbuild2 (see also unit
# tests loop below). Note that the build system core can still function
-# without them or with their alternative implementations.
+# without them or with their alternative implementations. Also note that
+# config/utility.?xx are part of the build system core (see comments in the
+# header for details).
#
# NOTE: remember to update import_modules() in libbuild2/modules.cxx if adding
# a new such module.
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index a5c4cfb..1cefcc5 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -15,8 +15,6 @@
#include <libbuild2/filesystem.hxx> // mtime()
#include <libbuild2/diagnostics.hxx>
-#include <libbuild2/config/utility.hxx> // create_project()
-
#include <libbuild2/bin/target.hxx>
#include <libbuild2/cc/parser.hxx>
@@ -5316,14 +5314,14 @@ namespace build2
extra += string (x) + ".features.modules = true";
- config::create_project (
+ create_project (
pd,
as->out_path ().relative (pd), /* amalgamation */
{}, /* boot_modules */
extra, /* root_pre */
{string (x) + '.'}, /* root_modules */
"", /* root_post */
- false, /* config */
+ nullopt, /* config */
false, /* buildfile */
"the cc module",
2); /* verbosity */
diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx
index 8dd4d8b..ca34d52 100644
--- a/libbuild2/config/init.cxx
+++ b/libbuild2/config/init.cxx
@@ -300,7 +300,8 @@ namespace build2
{
// Initialize the config entry points in the build system core.
//
- config_save_variable = &save_variable;
+ config_save_variable = &module::save_variable;
+ config_save_module = &module::save_module;
config_preprocess_create = &preprocess_create;
return mod_functions;
diff --git a/libbuild2/config/module.cxx b/libbuild2/config/module.cxx
index 176eef0..96107cc 100644
--- a/libbuild2/config/module.cxx
+++ b/libbuild2/config/module.cxx
@@ -3,6 +3,8 @@
#include <libbuild2/config/module.hxx>
+#include <libbuild2/scope.hxx>
+
using namespace std;
namespace build2
@@ -45,12 +47,26 @@ namespace build2
return true;
}
+ void module::
+ save_variable (scope& rs, const variable& var, uint64_t flags)
+ {
+ if (module* m = rs.find_module<module> (module::name))
+ m->save_variable (var, flags);
+ }
+
bool module::
save_module (const char* name, int prio)
{
return saved_modules.insert (string ("config.") += name, prio).second;
}
+ void module::
+ save_module (scope& rs, const char* name, int prio)
+ {
+ if (module* m = rs.find_module<module> (module::name))
+ m->save_module (name, prio);
+ }
+
const string module::name ("config");
const uint64_t module::version (1);
}
diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx
index 28c73a3..ade75cd 100644
--- a/libbuild2/config/module.hxx
+++ b/libbuild2/config/module.hxx
@@ -11,6 +11,7 @@
#include <libbuild2/types.hxx>
#include <libbuild2/utility.hxx>
+#include <libbuild2/scope.hxx>
#include <libbuild2/module.hxx>
#include <libbuild2/variable.hxx>
@@ -51,14 +52,6 @@ namespace build2
// Priority order with INT32_MIN being the highest. Modules with the
// same priority are saved in the order inserted.
//
- // Generally, the idea is that we want higher-level modules at the top
- // of the file since that's the configuration that we usualy want to
- // change. So we have the following priority bands/defaults:
- //
- // 101-200/150 - code generators (e.g., yacc, bison)
- // 201-300/250 - compilers (e.g., C, C++),
- // 301-400/350 - binutils (ar, ld)
- //
std::multimap<std::int32_t, const_iterator> order;
pair<iterator, bool>
@@ -82,9 +75,15 @@ namespace build2
bool
save_variable (const variable&, uint64_t flags = 0);
+ static void
+ save_variable (scope&, const variable&, uint64_t);
+
bool
save_module (const char* name, int prio = 0);
+ static void
+ save_module (scope&, const char*, int);
+
// Return true if the variable is already saved.
//
bool
@@ -102,6 +101,17 @@ namespace build2
static const string name;
static const uint64_t version;
};
+
+ // Implementation-specific utilities.
+ //
+
+ inline path
+ config_file (const scope& rs)
+ {
+ return (rs.out_path () /
+ rs.root_extra->build_dir /
+ "config." + rs.root_extra->build_ext);
+ }
}
}
diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx
index 2138986..07110e0 100644
--- a/libbuild2/config/operation.cxx
+++ b/libbuild2/config/operation.cxx
@@ -13,7 +13,7 @@
#include <libbuild2/diagnostics.hxx>
#include <libbuild2/config/module.hxx>
-#include <libbuild2/config/utility.hxx>
+#include <libbuild2/config/utility.hxx> // save_*
using namespace std;
using namespace butl;
@@ -1224,7 +1224,7 @@ namespace build2
"", /* root_pre */
rmod,
"", /* root_post */
- true, /* config */
+ "config", /* config */
true, /* buildfile */
"the create meta-operation");
diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx
index a39d3e0..b9fc513 100644
--- a/libbuild2/config/utility.cxx
+++ b/libbuild2/config/utility.cxx
@@ -3,17 +3,17 @@
#include <libbuild2/config/utility.hxx>
-#include <libbuild2/file.hxx>
-#include <libbuild2/context.hxx>
-#include <libbuild2/filesystem.hxx>
-#include <libbuild2/diagnostics.hxx>
-
-#include <libbuild2/config/module.hxx>
-
using namespace std;
namespace build2
{
+ void (*config_save_variable) (scope&, const variable&, uint64_t);
+ void (*config_save_module) (scope&, const char*, int);
+ const string& (*config_preprocess_create) (context&,
+ values&,
+ vector_view<opspec>&,
+ bool,
+ const location&);
namespace config
{
pair<lookup, bool>
@@ -126,171 +126,5 @@ namespace build2
else
return false;
}
-
- void
- save_variable (scope& rs, const variable& var, uint64_t flags)
- {
- if (module* m = rs.find_module<module> (module::name))
- m->save_variable (var, flags);
- }
-
- void
- save_module (scope& rs, const char* name, int prio)
- {
- if (module* m = rs.find_module<module> (module::name))
- m->save_module (name, prio);
- }
-
- void
- create_project (const dir_path& d,
- const build2::optional<dir_path>& amal,
- const strings& bmod,
- const string& rpre,
- const strings& rmod,
- const string& rpos,
- bool config,
- bool buildfile,
- const char* who,
- uint16_t verbosity)
- {
- string hdr ("# Generated by " + string (who) + ". Edit if you know"
- " what you are doing.\n"
- "#");
-
- // If the directory exists, verify it's empty. Otherwise, create it.
- //
- if (exists (d))
- {
- if (!empty (d))
- fail << "directory " << d << " exists and is not empty";
- }
- else
- mkdir_p (d, verbosity);
-
- // Create the build/ subdirectory.
- //
- // Note that for now we use the standard build file/directory scheme.
- //
- mkdir (d / std_build_dir, verbosity);
-
- // Write build/bootstrap.build.
- //
- {
- path f (d / std_bootstrap_file);
-
- if (verb >= verbosity)
- text << (verb >= 2 ? "cat >" : "save ") << f;
-
- try
- {
- ofdstream ofs (f);
-
- ofs << hdr << endl
- << "project =" << endl;
-
- if (amal)
- {
- ofs << "amalgamation =";
-
- if (!amal->empty ())
- {
- ofs << ' ';
- to_stream (ofs, *amal, true /* representation */);
- }
-
- ofs << endl;
- }
-
- ofs << endl;
-
- if (config)
- ofs << "using config" << endl;
-
- for (const string& m: bmod)
- {
- if (!config || m != "config")
- ofs << "using " << m << endl;
- }
-
- ofs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to write to " << f << ": " << e;
- }
- }
-
- // Write build/root.build.
- //
- {
- path f (d / std_root_file);
-
- if (verb >= verbosity)
- text << (verb >= 2 ? "cat >" : "save ") << f;
-
- try
- {
- ofdstream ofs (f);
-
- ofs << hdr << endl;
-
- if (!rpre.empty ())
- ofs << rpre << endl
- << endl;
-
- for (const string& cm: rmod)
- {
- // If the module name start with '?', then use optional load.
- //
- bool opt (cm.front () == '?');
- string m (cm, opt ? 1 : 0);
-
- // Append .config unless the module name ends with '.', in which
- // case strip it.
- //
- if (m.back () == '.')
- m.pop_back ();
- else
- m += ".config";
-
- ofs << "using" << (opt ? "?" : "") << " " << m << endl;
- }
-
- if (!rpos.empty ())
- ofs << endl
- << rpre << endl;
-
- ofs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to write to " << f << ": " << e;
- }
- }
-
- // Write root buildfile.
- //
- if (buildfile)
- {
- path f (d / std_buildfile_file);
-
- if (verb >= verbosity)
- text << (verb >= 2 ? "cat >" : "save ") << f;
-
- try
- {
- ofdstream ofs (f);
-
- ofs << hdr << endl
- << "./: {*/ -build/}" << endl;
-
- ofs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to write to " << f << ": " << e;
- }
- }
- }
}
}
diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx
index 3e01cd1..493d296 100644
--- a/libbuild2/config/utility.hxx
+++ b/libbuild2/config/utility.hxx
@@ -10,14 +10,73 @@
#include <libbuild2/scope.hxx>
#include <libbuild2/variable.hxx>
-#include <libbuild2/diagnostics.hxx>
#include <libbuild2/export.hxx>
namespace build2
{
+ // Note that the utility functions in this file are part of the build system
+ // core rather than the config module. They define the basic configuration
+ // semantics that should be applicable to both transient configurations as
+ // well as to other implementations of configuration persistence.
+ //
+ // The only persistence-specific aspects of this functionality are marking
+ // of the variables as to be persisted (saved, potentially with flags),
+ // establishing the module saving order (priority), and configuration
+ // creation (the create meta-operation implementation) These are accessed
+ // through the config module entry points (which are NULL for transient
+ // configurations). Note also that the exact interpretation of the save
+ // flags and module order depends on the config module implementation (which
+ // may ignore them as not applicable). An implementation may also define
+ // custom save flags (for example, accessible through the config.save
+ // attribute). Such flags should start from 0x100000000.
+ //
+ LIBBUILD2_SYMEXPORT extern void
+ (*config_save_variable) (scope&, const variable&, uint64_t);
+
+ LIBBUILD2_SYMEXPORT extern void
+ (*config_save_module) (scope&, const char*, int);
+
+ LIBBUILD2_SYMEXPORT extern const string&
+ (*config_preprocess_create) (context&,
+ values&,
+ vector_view<opspec>&,
+ bool,
+ const location&);
+
namespace config
{
+ // Mark the variable to be saved during configuration.
+ //
+ const uint64_t save_default_commented = 0x01; // Based on value::extra.
+ const uint64_t save_null_omitted = 0x02; // Treat NULL as undefined.
+
+ inline void
+ save_variable (scope& rs, const variable& var, uint64_t flags = 0)
+ {
+ if (config_save_variable != nullptr)
+ config_save_variable (rs, var, flags);
+ }
+
+ // Establish module save order/priority with INT32_MIN being the highest.
+ // Modules with the same priority are saved in the order inserted.
+ //
+ // Generally, for user-editable persisten configuration, we want higher-
+ // level modules at the top of the file since that's the configuration
+ // that the user usually wants to change. As a result, we define the
+ // following priority bands/defaults:
+ //
+ // 101-200/150 - code generators (e.g., yacc, bison)
+ // 201-300/250 - compilers (e.g., C, C++),
+ // 301-400/350 - binutils (ar, ld)
+ //
+ inline void
+ save_module (scope& rs, const char* module, int prio = 0)
+ {
+ if (config_save_module != nullptr)
+ config_save_module (rs, module, prio);
+ }
+
// Set, if necessary, a required config.* variable.
//
// If override is true and the variable doesn't come from this root scope
@@ -33,9 +92,12 @@ namespace build2
// (always defined) to pass along its location (could be used to detect
// inheritance, etc).
//
- // Note also that if save_flags has save_commented, then a default value
- // is never considered "new" since for such variables absence of a value
- // means the default value.
+ // Note also that if save_flags has save_default_commented, then a default
+ // value is never considered "new" since for such variables absence of a
+ // value means the default value.
+ //
+ // @@ Should save_null_omitted be interpreted to treat null as undefined?
+ // Sounds logical.
//
template <typename T>
pair<lookup, bool>
@@ -139,42 +201,6 @@ namespace build2
//
LIBBUILD2_SYMEXPORT bool
unconfigured (scope& rs, const string& var, bool value);
-
- // Enter the variable so that it is saved during configuration. See
- // config::module for details.
- //
- const uint64_t save_default_commented = 0x01; // Based on value::extra.
- const uint64_t save_null_omitted = 0x02; // Treat NULL as undefined.
-
- LIBBUILD2_SYMEXPORT void
- save_variable (scope& rs, const variable&, uint64_t flags = 0);
-
- // Establish module order/priority. See config::module for details.
- //
- LIBBUILD2_SYMEXPORT void
- save_module (scope& rs, const char* module, int prio = 0);
-
- // Create a project in the specified directory.
- //
- LIBBUILD2_SYMEXPORT void
- create_project (const dir_path& d,
- const build2::optional<dir_path>& amalgamation,
- const strings& boot_modules, // Bootstrap modules.
- const string& root_pre, // Extra root.build text.
- const strings& root_modules, // Root modules.
- const string& root_post, // Extra root.build text.
- bool config, // Load config module.
- bool buildfile, // Create root buildfile.
- const char* who, // Who is creating it.
- uint16_t verbosity = 1); // Diagnostic verbosity.
-
- inline path
- config_file (const scope& rs)
- {
- return (rs.out_path () /
- rs.root_extra->build_dir /
- "config." + rs.root_extra->build_ext);
- }
}
}
diff --git a/libbuild2/config/utility.txx b/libbuild2/config/utility.txx
index 670a701..f52df8d 100644
--- a/libbuild2/config/utility.txx
+++ b/libbuild2/config/utility.txx
@@ -1,9 +1,6 @@
// file : libbuild2/config/utility.txx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <libbuild2/scope.hxx>
-#include <libbuild2/context.hxx> // current_mif
-
namespace build2
{
namespace config
diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx
index 4082e0c..827894b 100644
--- a/libbuild2/context.cxx
+++ b/libbuild2/context.cxx
@@ -21,6 +21,8 @@
#include <libbuild2/lexer.hxx>
#include <libbuild2/parser.hxx>
+#include <libbuild2/config/utility.hxx> // config_preprocess_create
+
using namespace std;
using namespace butl;
@@ -892,12 +894,4 @@ namespace build2
//text << this_thread::get_id () << " phase restore " << n << " " << o;
}
-
- void (*config_save_variable) (scope&, const variable&, uint64_t);
-
- const string& (*config_preprocess_create) (context&,
- values&,
- vector_view<opspec>&,
- bool,
- const location&);
}
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index a2bfe3d..ea2c017 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -589,18 +589,6 @@ namespace build2
atomic_count* task_count;
bool phase;
};
-
- // Config module entry points.
- //
- LIBBUILD2_SYMEXPORT extern void (*config_save_variable) (
- scope&, const variable&, uint64_t flags);
-
- LIBBUILD2_SYMEXPORT extern const string& (*config_preprocess_create) (
- context&,
- values&,
- vector_view<opspec>&,
- bool lifted,
- const location&);
}
#include <libbuild2/context.ixx>
diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx
index 225c506..7903918 100644
--- a/libbuild2/file.cxx
+++ b/libbuild2/file.cxx
@@ -6,7 +6,7 @@
#include <libbuild2/scope.hxx>
#include <libbuild2/target.hxx>
#include <libbuild2/context.hxx>
-#include <libbuild2/filesystem.hxx> // exists()
+#include <libbuild2/filesystem.hxx>
#include <libbuild2/prerequisite.hxx>
#include <libbuild2/diagnostics.hxx>
@@ -14,6 +14,8 @@
#include <libbuild2/lexer.hxx>
#include <libbuild2/parser.hxx>
+#include <libbuild2/config/utility.hxx> // save_variable()
+
using namespace std;
using namespace butl;
@@ -1369,8 +1371,7 @@ namespace build2
// Mark as part of config.
//
- if (config_save_variable != nullptr)
- config_save_variable (iroot, var, 0 /* flags */);
+ config::save_variable (iroot, var);
// Empty config.import.* value means don't look in subprojects or
// amalgamations and go straight to the rule-specific import (e.g.,
@@ -1405,8 +1406,7 @@ namespace build2
if (r.empty ())
fail (loc) << "empty path in " << var.name;
- if (config_save_variable != nullptr)
- config_save_variable (iroot, var, 0 /* flags */);
+ config::save_variable (iroot, var);
}
return r;
@@ -1786,4 +1786,156 @@ namespace build2
dr << endf;
}
+
+ void
+ create_project (const dir_path& d,
+ const optional<dir_path>& amal,
+ const strings& bmod,
+ const string& rpre,
+ const strings& rmod,
+ const string& rpos,
+ const optional<string>& config,
+ bool buildfile,
+ const char* who,
+ uint16_t verbosity)
+ {
+ string hdr ("# Generated by " + string (who) + ". Edit if you know"
+ " what you are doing.\n"
+ "#");
+
+ // If the directory exists, verify it's empty. Otherwise, create it.
+ //
+ if (exists (d))
+ {
+ if (!empty (d))
+ fail << "directory " << d << " exists and is not empty";
+ }
+ else
+ mkdir_p (d, verbosity);
+
+ // Create the build/ subdirectory.
+ //
+ // Note that for now we use the standard build file/directory scheme.
+ //
+ mkdir (d / std_build_dir, verbosity);
+
+ // Write build/bootstrap.build.
+ //
+ {
+ path f (d / std_bootstrap_file);
+
+ if (verb >= verbosity)
+ text << (verb >= 2 ? "cat >" : "save ") << f;
+
+ try
+ {
+ ofdstream ofs (f);
+
+ ofs << hdr << endl
+ << "project =" << endl;
+
+ if (amal)
+ {
+ ofs << "amalgamation =";
+
+ if (!amal->empty ())
+ {
+ ofs << ' ';
+ to_stream (ofs, *amal, true /* representation */);
+ }
+
+ ofs << endl;
+ }
+
+ ofs << endl;
+
+ if (config)
+ ofs << "using " << *config << endl;
+
+ for (const string& m: bmod)
+ {
+ if (!config || m != *config)
+ ofs << "using " << m << endl;
+ }
+
+ ofs.close ();
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write to " << f << ": " << e;
+ }
+ }
+
+ // Write build/root.build.
+ //
+ {
+ path f (d / std_root_file);
+
+ if (verb >= verbosity)
+ text << (verb >= 2 ? "cat >" : "save ") << f;
+
+ try
+ {
+ ofdstream ofs (f);
+
+ ofs << hdr << endl;
+
+ if (!rpre.empty ())
+ ofs << rpre << endl
+ << endl;
+
+ for (const string& cm: rmod)
+ {
+ // If the module name start with '?', then use optional load.
+ //
+ bool opt (cm.front () == '?');
+ string m (cm, opt ? 1 : 0);
+
+ // Append .config unless the module name ends with '.', in which
+ // case strip it.
+ //
+ if (m.back () == '.')
+ m.pop_back ();
+ else
+ m += ".config";
+
+ ofs << "using" << (opt ? "?" : "") << " " << m << endl;
+ }
+
+ if (!rpos.empty ())
+ ofs << endl
+ << rpre << endl;
+
+ ofs.close ();
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write to " << f << ": " << e;
+ }
+ }
+
+ // Write root buildfile.
+ //
+ if (buildfile)
+ {
+ path f (d / std_buildfile_file);
+
+ if (verb >= verbosity)
+ text << (verb >= 2 ? "cat >" : "save ") << f;
+
+ try
+ {
+ ofdstream ofs (f);
+
+ ofs << hdr << endl
+ << "./: {*/ -build/}" << endl;
+
+ ofs.close ();
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write to " << f << ": " << e;
+ }
+ }
+ }
}
diff --git a/libbuild2/file.hxx b/libbuild2/file.hxx
index 2e7eddd..d3c6787 100644
--- a/libbuild2/file.hxx
+++ b/libbuild2/file.hxx
@@ -261,6 +261,20 @@ namespace build2
//
const target*
import_existing (context&, const prerequisite_key&);
+
+ // Create a build system project in the specified directory.
+ //
+ LIBBUILD2_SYMEXPORT void
+ create_project (const dir_path&,
+ const optional<dir_path>& amalgamation,
+ const strings& boot_modules, // Bootstrap modules.
+ const string& root_pre, // Extra root.build text.
+ const strings& root_modules, // Root modules.
+ const string& root_post, // Extra root.build text.
+ const optional<string>& config, // Config module to load.
+ bool buildfile, // Create root buildfile.
+ const char* who, // Who is creating it.
+ uint16_t verbosity = 1); // Diagnostic verbosity.
}
#include <libbuild2/file.ixx>