aboutsummaryrefslogtreecommitdiff
path: root/build2/config/operation.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build2/config/operation.cxx')
-rw-r--r--build2/config/operation.cxx997
1 files changed, 0 insertions, 997 deletions
diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx
deleted file mode 100644
index ff5b44a..0000000
--- a/build2/config/operation.cxx
+++ /dev/null
@@ -1,997 +0,0 @@
-// file : build2/config/operation.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build2/config/operation.hxx>
-
-#include <set>
-
-#include <libbuild2/file.hxx>
-#include <libbuild2/spec.hxx>
-#include <libbuild2/scope.hxx>
-#include <libbuild2/target.hxx>
-#include <libbuild2/context.hxx>
-#include <libbuild2/algorithm.hxx>
-#include <libbuild2/filesystem.hxx>
-#include <libbuild2/diagnostics.hxx>
-
-#include <build2/config/module.hxx>
-#include <build2/config/utility.hxx>
-
-using namespace std;
-using namespace butl;
-
-namespace build2
-{
- namespace config
- {
- // configure
- //
- static void
- save_src_root (const scope& root)
- {
- const dir_path& out_root (root.out_path ());
- const dir_path& src_root (root.src_path ());
-
- path f (out_root / root.root_extra->src_root_file);
-
- if (verb >= 2)
- text << "cat >" << f;
-
- try
- {
- ofdstream ofs (f);
-
- ofs << "# Created automatically by the config module." << endl
- << "#" << endl
- << "src_root = ";
- to_stream (ofs, name (src_root), true, '@'); // Quote.
- ofs << endl;
-
- ofs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to write " << f << ": " << e;
- }
- }
-
- static void
- save_out_root (const scope& root)
- {
- const dir_path& out_root (root.out_path ());
- const dir_path& src_root (root.src_path ());
-
- path f (src_root / root.root_extra->out_root_file);
-
- if (verb)
- text << (verb >= 2 ? "cat >" : "save ") << f;
-
- try
- {
- ofdstream ofs (f);
-
- ofs << "# Created automatically by the config module." << endl
- << "#" << endl
- << "out_root = ";
- to_stream (ofs, name (out_root), true, '@'); // Quote.
- ofs << endl;
-
- ofs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to write " << f << ": " << e;
- }
- }
-
- using project_set = set<const scope*>; // Use pointers to get comparison.
-
- static void
- save_config (const scope& root, const project_set& projects)
- {
- path f (config_file (root));
-
- if (verb)
- text << (verb >= 2 ? "cat >" : "save ") << f;
-
- const module& mod (*root.lookup_module<const module> (module::name));
-
- try
- {
- ofdstream ofs (f);
-
- ofs << "# Created automatically by the config module, but feel " <<
- "free to edit." << endl
- << "#" << endl;
-
- ofs << "config.version = " << module::version << endl;
-
- if (auto l = root.vars[var_amalgamation])
- {
- const dir_path& d (cast<dir_path> (l));
-
- ofs << endl
- << "# Base configuration inherited from " << d << endl
- << "#" << endl;
- }
-
- // Save config variables.
- //
- names storage;
-
- for (auto p: mod.saved_modules.order)
- {
- const string& sname (p.second->first);
- const saved_variables& svars (p.second->second);
-
- bool first (true); // Separate modules with a blank line.
- for (const saved_variable& sv: svars)
- {
- const variable& var (sv.var);
-
- pair<lookup, size_t> org (root.find_original (var));
- pair<lookup, size_t> ovr (var.overrides == nullptr
- ? org
- : root.find_override (var, org));
- const lookup& l (ovr.first);
-
- // We definitely write values that are set on our root scope or
- // are global overrides. Anything in-between is presumably
- // inherited. We might also not have any value at all (see
- // unconfigured()).
- //
- if (!l.defined ())
- continue;
-
- if (!(l.belongs (root) || l.belongs (*global_scope)))
- {
- // This is presumably an inherited value. But it could also be
- // some left-over garbage. For example, an amalgamation could
- // have used a module but then dropped it while its config
- // values are still lingering in config.build. They are probably
- // still valid and we should probably continue using them but we
- // definitely want to move them to our config.build since they
- // will be dropped from the amalgamation's config.build. Let's
- // also warn the user just in case.
- //
- // There is also another case that falls under this now that
- // overrides are by default amalgamation-wide rather than just
- // "project and subprojects": we may be (re-)configuring a
- // subproject but the override is now set on the outer project's
- // root.
- //
- bool found (false);
- const scope* r (&root);
- while ((r = r->parent_scope ()->root_scope ()) != nullptr)
- {
- if (l.belongs (*r))
- {
- // Find the config module.
- //
- if (auto* m = r->lookup_module<const module> (module::name))
- {
- // Find the corresponding saved module.
- //
- auto i (m->saved_modules.find (sname));
-
- if (i != m->saved_modules.end ())
- {
- // Find the variable.
- //
- const saved_variables& sv (i->second);
- found = sv.find (var) != sv.end ();
-
- // Handle that other case: if this is an override but
- // the outer project itself is not being configured,
- // then we need to save this override.
- //
- // One problem with using the already configured project
- // set is that the outer project may be configured only
- // after us in which case both projects will save the
- // value. But perhaps this is a feature, not a bug since
- // this is how project-local (%) override behaves.
- //
- if (found &&
- org.first != ovr.first &&
- projects.find (r) == projects.end ())
- found = false;
- }
- }
-
- break;
- }
- }
-
- if (found) // Inherited.
- continue;
-
- location loc (&f);
-
- // If this value is not defined in a project's root scope, then
- // something is broken.
- //
- if (r == nullptr)
- fail (loc) << "inherited variable " << var << " value "
- << "is not from a root scope";
-
- // If none of the outer project's configurations use this value,
- // then we warn and save as our own. One special case where we
- // don't want to warn the user is if the variable is overriden.
- //
- if (org.first == ovr.first)
- {
- diag_record dr;
- dr << warn (loc) << "saving previously inherited variable "
- << var;
-
- dr << info (loc) << "because project " << *r
- << " no longer uses it in its configuration";
-
- if (verb >= 2)
- {
- dr << info (loc) << "variable value: ";
-
- if (*l)
- {
- storage.clear ();
- dr << "'" << reverse (*l, storage) << "'";
- }
- else
- dr << "[null]";
- }
- }
- }
-
- const string& n (var.name);
- const value& v (*l);
-
- // We will only write config.*.configured if it is false (true is
- // implied by its absence). We will also ignore false values if
- // there is any other value for this module (see unconfigured()).
- //
- if (n.size () > 11 &&
- n.compare (n.size () - 11, 11, ".configured") == 0)
- {
- if (cast<bool> (v) || svars.size () != 1)
- continue;
- }
-
- // If we got here then we are saving this variable. Handle the
- // blank line.
- //
- if (first)
- {
- ofs << endl;
- first = false;
- }
-
- // Handle the save_commented flag.
- //
- if ((org.first.defined () && org.first->extra) && // Default value.
- org.first == ovr.first && // Not overriden.
- (sv.flags & save_commented) == save_commented)
- {
- ofs << '#' << n << " =" << endl;
- continue;
- }
-
- if (v)
- {
- storage.clear ();
- names_view ns (reverse (v, storage));
-
- ofs << n;
-
- if (ns.empty ())
- ofs << " =";
- else
- {
- ofs << " = ";
- to_stream (ofs, ns, true, '@'); // Quote.
- }
-
- ofs << endl;
- }
- else
- ofs << n << " = [null]" << endl;
- }
- }
-
- ofs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to write " << f << ": " << e;
- }
- }
-
- static void
- configure_project (action a, const scope& root, project_set& projects)
- {
- tracer trace ("configure_project");
-
- const dir_path& out_root (root.out_path ());
- const dir_path& src_root (root.src_path ());
-
- if (!projects.insert (&root).second)
- {
- l5 ([&]{trace << "skipping already configured " << out_root;});
- return;
- }
-
- // Make sure the directories exist.
- //
- if (out_root != src_root)
- {
- mkdir_p (out_root / root.root_extra->build_dir);
- mkdir (out_root / root.root_extra->bootstrap_dir, 2);
- }
-
- // We distinguish between a complete configure and operation-
- // specific.
- //
- if (a.operation () == default_id)
- {
- l5 ([&]{trace << "completely configuring " << out_root;});
-
- // Save src-root.build unless out_root is the same as src.
- //
- if (out_root != src_root)
- save_src_root (root);
-
- // Save config.build.
- //
- save_config (root, projects);
- }
- else
- {
- }
-
- // Configure subprojects that have been loaded.
- //
- if (auto l = root.vars[var_subprojects])
- {
- for (auto p: cast<subprojects> (l))
- {
- const dir_path& pd (p.second);
- dir_path out_nroot (out_root / pd);
- const scope& nroot (scopes.find (out_nroot));
-
- // @@ Strictly speaking we need to check whether the config
- // module was loaded for this subproject.
- //
- if (nroot.out_path () != out_nroot) // This subproject not loaded.
- continue;
-
- configure_project (a, nroot, projects);
- }
- }
- }
-
- static void
- configure_forward (const scope& root, project_set& projects)
- {
- tracer trace ("configure_forward");
-
- const dir_path& out_root (root.out_path ());
- const dir_path& src_root (root.src_path ());
-
- if (!projects.insert (&root).second)
- {
- l5 ([&]{trace << "skipping already configured " << src_root;});
- return;
- }
-
- mkdir (src_root / root.root_extra->bootstrap_dir, 2); // Make sure exists.
- save_out_root (root);
-
- // Configure subprojects. Since we don't load buildfiles if configuring
- // a forward, we do it for all known subprojects.
- //
- if (auto l = root.vars[var_subprojects])
- {
- for (auto p: cast<subprojects> (l))
- {
- dir_path out_nroot (out_root / p.second);
- const scope& nroot (scopes.find (out_nroot));
- assert (nroot.out_path () == out_nroot);
-
- configure_forward (nroot, projects);
- }
- }
- }
-
- operation_id (*pre) (const values&, meta_operation_id, const location&);
-
- static operation_id
- configure_operation_pre (const values&, operation_id o)
- {
- // Don't translate default to update. In our case unspecified
- // means configure everything.
- //
- return o;
- }
-
- // The (vague) idea is that in the future we may turn this into to some
- // sort of key-value sequence (similar to the config initializer idea),
- // for example:
- //
- // configure(out/@src/, forward foo bar@123)
- //
- // Though using commas instead spaces and '=' instead of '@' would have
- // been nicer.
- //
- static bool
- forward (const values& params,
- const char* mo = nullptr,
- const location& l = location ())
- {
- if (params.size () == 1)
- {
- const names& ns (cast<names> (params[0]));
-
- if (ns.size () == 1 && ns[0].simple () && ns[0].value == "forward")
- return true;
- else if (!ns.empty ())
- fail (l) << "unexpected parameter '" << ns << "' for "
- << "meta-operation " << mo;
- }
- else if (!params.empty ())
- fail (l) << "unexpected parameters for meta-operation " << mo;
-
- return false;
- }
-
- static void
- configure_pre (const values& params, const location& l)
- {
- forward (params, "configure", l); // Validate.
- }
-
- static void
- configure_load (const values& params,
- scope& root,
- const path& buildfile,
- const dir_path& out_base,
- const dir_path& src_base,
- const location& l)
- {
- if (forward (params))
- {
- // We don't need to load the buildfiles in order to configure
- // forwarding but in order to configure subprojects we have to
- // bootstrap them (similar to disfigure).
- //
- create_bootstrap_inner (root);
-
- if (root.out_path () == root.src_path ())
- fail (l) << "forwarding to source directory " << root.src_path ();
- }
- else
- load (params, root, buildfile, out_base, src_base, l); // Normal load.
- }
-
- static void
- configure_search (const values& params,
- const scope& root,
- const scope& base,
- const path& bf,
- const target_key& tk,
- const location& l,
- action_targets& ts)
- {
- if (forward (params))
- {
- // For forwarding we only collect the projects (again, similar to
- // disfigure).
- //
- ts.push_back (&root);
- }
- else
- search (params, root, base, bf, tk, l, ts); // Normal search.
- }
-
- static void
- configure_match (const values&, action, action_targets&, uint16_t, bool)
- {
- // Don't match anything -- see execute ().
- }
-
- static void
- configure_execute (const values& params,
- action a,
- action_targets& ts,
- uint16_t,
- bool)
- {
- bool fwd (forward (params));
-
- project_set projects;
-
- for (const action_target& at: ts)
- {
- if (fwd)
- {
- // Forward configuration.
- //
- const scope& root (*static_cast<const scope*> (at.target));
- configure_forward (root, projects);
- continue;
- }
-
- // Normal configuration.
- //
- // Match rules to configure every operation supported by each project.
- // Note that we are not calling operation_pre/post() callbacks here
- // since the meta operation is configure and we know what we are
- // doing.
- //
- // Note that we cannot do this in parallel. We cannot parallelize the
- // outer loop because we should match for a single action at a time.
- // And we cannot swap the loops because the list of operations is
- // target-specific. However, inside match(), things can proceed in
- // parallel.
- //
- const target& t (at.as_target ());
- const scope* rs (t.base_scope ().root_scope ());
-
- if (rs == nullptr)
- fail << "out of project target " << t;
-
- const operations& ops (rs->root_extra->operations);
-
- for (operation_id id (default_id + 1); // Skip default_id.
- id < ops.size ();
- ++id)
- {
- if (const operation_info* oif = ops[id])
- {
- // Skip aliases (e.g., update-for-install).
- //
- if (oif->id != id)
- continue;
-
- set_current_oif (*oif);
-
- phase_lock pl (run_phase::match);
- match (action (configure_id, id), t);
- }
- }
-
- configure_project (a, *rs, projects);
- }
- }
-
- const meta_operation_info mo_configure {
- configure_id,
- "configure",
- "configure",
- "configuring",
- "configured",
- "is configured",
- true, // bootstrap_outer
- &configure_pre, // meta-operation pre
- &configure_operation_pre,
- &configure_load, // normal load unless configuring forward
- &configure_search, // normal search unless configuring forward
- &configure_match,
- &configure_execute,
- nullptr, // operation post
- nullptr, // meta-operation post
- nullptr // include
- };
-
- // disfigure
- //
-
- static bool
- disfigure_project (action a, const scope& root, project_set& projects)
- {
- tracer trace ("disfigure_project");
-
- const dir_path& out_root (root.out_path ());
- const dir_path& src_root (root.src_path ());
-
- if (!projects.insert (&root).second)
- {
- l5 ([&]{trace << "skipping already disfigured " << out_root;});
- return false;
- }
-
- bool r (false); // Keep track of whether we actually did anything.
-
- // Disfigure subprojects. Since we don't load buildfiles during
- // disfigure, we do it for all known subprojects.
- //
- if (auto l = root.vars[var_subprojects])
- {
- for (auto p: cast<subprojects> (l))
- {
- const dir_path& pd (p.second);
- dir_path out_nroot (out_root / pd);
- const scope& nroot (scopes.find (out_nroot));
- assert (nroot.out_path () == out_nroot); // See disfigure_load().
-
- r = disfigure_project (a, nroot, projects) || r;
-
- // We use mkdir_p() to create the out_root of a subproject
- // which means there could be empty parent directories left
- // behind. Clean them up.
- //
- if (!pd.simple () && out_root != src_root)
- {
- for (dir_path d (pd.directory ());
- !d.empty ();
- d = d.directory ())
- {
- rmdir_status s (rmdir (out_root / d, 2));
-
- if (s == rmdir_status::not_empty)
- break; // No use trying do remove parent ones.
-
- r = (s == rmdir_status::success) || r;
- }
- }
- }
- }
-
- // We distinguish between a complete disfigure and operation-
- // specific.
- //
- if (a.operation () == default_id)
- {
- l5 ([&]{trace << "completely disfiguring " << out_root;});
-
- r = rmfile (config_file (root)) || r;
-
- if (out_root != src_root)
- {
- r = rmfile (out_root / root.root_extra->src_root_file, 2) || r;
-
- // Clean up the directories.
- //
- // Note: try to remove the root/ hooks directory if it is empty.
- //
- r = rmdir (out_root / root.root_extra->root_dir, 2) || r;
- r = rmdir (out_root / root.root_extra->bootstrap_dir, 2) || r;
- r = rmdir (out_root / root.root_extra->build_dir, 2) || r;
-
- switch (rmdir (out_root))
- {
- case rmdir_status::not_empty:
- {
- // We used to issue a warning but it is actually a valid usecase
- // to leave the build output around in case, for example, of a
- // reconfigure.
- //
- if (verb)
- info << "directory " << out_root << " is "
- << (out_root == work
- ? "current working directory"
- : "not empty") << ", not removing";
- break;
- }
- case rmdir_status::success:
- r = true;
- default:
- break;
- }
- }
- }
- else
- {
- }
-
- return r;
- }
-
- static bool
- disfigure_forward (const scope& root, project_set& projects)
- {
- // Pretty similar logic to disfigure_project().
- //
- tracer trace ("disfigure_forward");
-
- const dir_path& out_root (root.out_path ());
- const dir_path& src_root (root.src_path ());
-
- if (!projects.insert (&root).second)
- {
- l5 ([&]{trace << "skipping already disfigured " << src_root;});
- return false;
- }
-
- bool r (false);
-
- if (auto l = root.vars[var_subprojects])
- {
- for (auto p: cast<subprojects> (l))
- {
- dir_path out_nroot (out_root / p.second);
- const scope& nroot (scopes.find (out_nroot));
- assert (nroot.out_path () == out_nroot);
-
- r = disfigure_forward (nroot, projects) || r;
- }
- }
-
- // Remove the out-root.build file and try to remove the bootstrap/
- // directory if it is empty.
- //
- r = rmfile (src_root / root.root_extra->out_root_file) || r;
- r = rmdir (src_root / root.root_extra->bootstrap_dir, 2) || r;
-
- return r;
- }
-
- static void
- disfigure_pre (const values& params, const location& l)
- {
- forward (params, "disfigure", l); // Validate.
- }
-
- static operation_id
- disfigure_operation_pre (const values&, operation_id o)
- {
- // Don't translate default to update. In our case unspecified
- // means disfigure everything.
- //
- return o;
- }
-
- static void
- disfigure_load (const values&,
- scope& root,
- const path&,
- const dir_path&,
- const dir_path&,
- const location&)
- {
- // Since we don't load buildfiles during disfigure but still want to
- // disfigure all the subprojects (see disfigure_project() below), we
- // bootstrap all the known subprojects.
- //
- create_bootstrap_inner (root);
- }
-
- static void
- disfigure_search (const values&,
- const scope& root,
- const scope&,
- const path&,
- const target_key&,
- const location&,
- action_targets& ts)
- {
- ts.push_back (&root);
- }
-
- static void
- disfigure_match (const values&, action, action_targets&, uint16_t, bool)
- {
- }
-
- static void
- disfigure_execute (const values& params,
- action a,
- action_targets& ts,
- uint16_t diag,
- bool)
- {
- tracer trace ("disfigure_execute");
-
- bool fwd (forward (params));
-
- project_set projects;
-
- // Note: doing everything in the load phase (disfigure_project () does
- // modify the build state).
- //
- for (const action_target& at: ts)
- {
- const scope& root (*static_cast<const scope*> (at.target));
-
- if (!(fwd
- ? disfigure_forward ( root, projects)
- : disfigure_project (a, root, projects)))
- {
- // Create a dir{$out_root/} target to signify the project's root in
- // diagnostics. Not very clean but seems harmless.
- //
- target& t (
- targets.insert (dir::static_type,
- fwd ? root.src_path () : root.out_path (),
- dir_path (), // Out tree.
- "",
- nullopt,
- true, // Implied.
- trace).first);
-
- if (verb != 0 && diag >= 2)
- info << diag_done (a, t);
- }
- }
- }
-
- const meta_operation_info mo_disfigure {
- disfigure_id,
- "disfigure",
- "disfigure",
- "disfiguring",
- "disfigured",
- "is disfigured",
- false, // bootstrap_outer
- disfigure_pre, // meta-operation pre
- &disfigure_operation_pre,
- &disfigure_load,
- &disfigure_search,
- &disfigure_match,
- &disfigure_execute,
- nullptr, // operation post
- nullptr, // meta-operation post
- nullptr // include
- };
-
- // create
- //
- static void
- save_config (const dir_path& d, const variable_overrides& var_ovs)
- {
- // Since there aren't any sub-projects yet, any config.import.* values
- // that the user may want to specify won't be saved in config.build. So
- // let's go ahead and mark them all to be saved. To do this, however, we
- // need the config module (which is where this information is stored).
- // And the module is created by init() during bootstrap. So what we are
- // going to do is bootstrap the newly created project, similar to the
- // way main() does it.
- //
- scope& gs (*scope::global_);
- scope& rs (load_project (gs, d, d, false /* fwd */, false /* load */));
- module& m (*rs.lookup_module<module> (module::name));
-
- // Save all the global config.import.* variables.
- //
- variable_pool& vp (var_pool.rw (rs));
- for (auto p (gs.vars.find_namespace (vp.insert ("config.import")));
- p.first != p.second;
- ++p.first)
- {
- const variable& var (p.first->first);
-
- // Annoyingly, this can be (always is?) one of the overrides
- // (__override, __prefix, etc).
- //
- size_t n (var.override ());
- m.save_variable (n != 0 ? *vp.find (string (var.name, 0, n)) : var);
- }
-
- // Now project-specific. For now we just save all of them and let
- // save_config() above weed out the ones that don't apply.
- //
- for (const variable_override& vo: var_ovs)
- {
- const variable& var (vo.var);
-
- if (var.name.compare (0, 14, "config.import.") == 0)
- m.save_variable (var);
- }
- }
-
- const string&
- preprocess_create (const variable_overrides& var_ovs,
- values& params,
- vector_view<opspec>& spec,
- bool lifted,
- const location& l)
- {
- tracer trace ("preprocess_create");
-
- // The overall plan is to create the project(s), update the buildspec,
- // clear the parameters, and then continue as if we were the configure
- // meta-operation.
-
- // Start with process parameters. The first parameter, if any, is a list
- // of root.build modules. The second parameter, if any, is a list of
- // bootstrap.build modules. If the second is not specified, then the
- // default is test, dist, and install (config is mandatory).
- //
- strings bmod {"test", "dist", "install"};
- strings rmod;
- try
- {
- size_t n (params.size ());
-
- if (n > 0)
- rmod = convert<strings> (move (params[0]));
-
- if (n > 1)
- bmod = convert<strings> (move (params[1]));
-
- if (n > 2)
- fail (l) << "unexpected parameters for meta-operation create";
- }
- catch (const invalid_argument& e)
- {
- fail (l) << "invalid module name: " << e.what ();
- }
-
- current_oname = empty_string; // Make sure valid.
-
- // Now handle each target in each operation spec.
- //
- for (const opspec& os: spec)
- {
- // First do some sanity checks: there should be no explicit operation
- // and our targets should all be directories.
- //
- if (!lifted && !os.name.empty ())
- fail (l) << "explicit operation specified for meta-operation create";
-
- for (const targetspec& ts: os)
- {
- const name& tn (ts.name);
-
- // Figure out the project directory. This logic must be consistent
- // with find_target_type() and other places (grep for "..").
- //
- dir_path d;
-
- if (tn.simple () &&
- (tn.empty () || tn.value == "." || tn.value == ".."))
- d = dir_path (tn.value);
- else if (tn.directory ())
- d = tn.dir;
- else if (tn.typed () && tn.type == "dir")
- d = tn.dir / dir_path (tn.value);
- else
- fail(l) << "non-directory target '" << ts << "' in "
- << "meta-operation create";
-
- if (d.relative ())
- d = work / d;
-
- d.normalize (true);
-
- // If src_base was explicitly specified, make sure it is the same as
- // the project directory.
- //
- if (!ts.src_base.empty ())
- {
- dir_path s (ts.src_base);
-
- if (s.relative ())
- s = work / s;
-
- s.normalize (true);
-
- if (s != d)
- fail(l) << "different src/out directories for target '" << ts
- << "' in meta-operation create";
- }
-
- l5 ([&]{trace << "creating project in " << d;});
-
- // For now we disable amalgamating this project. Sooner or later
- // someone will probably want to do this, though (i.e., nested
- // configurations).
- //
- create_project (d,
- dir_path (), /* amalgamation */
- bmod,
- "", /* root_pre */
- rmod,
- "", /* root_post */
- true, /* config */
- true, /* buildfile */
- "the create meta-operation");
-
- save_config (d, var_ovs);
- }
- }
-
- params.clear ();
- return mo_configure.name;
- }
- }
-}