diff options
32 files changed, 324 insertions, 146 deletions
diff --git a/bootstrap-mingw.bat b/bootstrap-mingw.bat index 73b76f3..5061753 100644 --- a/bootstrap-mingw.bat +++ b/bootstrap-mingw.bat @@ -66,7 +66,6 @@ set "src=%src% build2\c" set "src=%src% build2\cc" set "src=%src% build2\cxx" set "src=%src% build2\version" -set "src=%src% build2\in" set "src=%src% libbuild2" set "src=%src% libbuild2\config" @@ -74,6 +73,7 @@ set "src=%src% libbuild2\dist" set "src=%src% libbuild2\test" set "src=%src% libbuild2\test\script" set "src=%src% libbuild2\install" +set "src=%src% libbuild2\in" set "src=%src% %libbutl%\libbutl" diff --git a/bootstrap-msvc.bat b/bootstrap-msvc.bat index a011162..e4e2a66 100644 --- a/bootstrap-msvc.bat +++ b/bootstrap-msvc.bat @@ -97,7 +97,6 @@ set "src=%src% build2\c" set "src=%src% build2\cc" set "src=%src% build2\cxx" set "src=%src% build2\version" -set "src=%src% build2\in" set "src=%src% libbuild2" set "src=%src% libbuild2\config" @@ -105,6 +104,7 @@ set "src=%src% libbuild2\dist" set "src=%src% libbuild2\test" set "src=%src% libbuild2\test\script" set "src=%src% libbuild2\install" +set "src=%src% libbuild2\in" set "src=%src% %libbutl%\libbutl" diff --git a/bootstrap.gmake b/bootstrap.gmake index 04716be..793f3d0 100644 --- a/bootstrap.gmake +++ b/bootstrap.gmake @@ -134,15 +134,15 @@ bin \ c \ cc \ cxx \ -version \ -in +version libbuild2_sub := \ config \ dist \ test/script \ test \ -install +install \ +in build2_src := $(wildcard $(src_root)/build2/*.cxx) build2_src += $(foreach d,$(build2_sub),$(wildcard $(src_root)/build2/$d/*.cxx)) diff --git a/bootstrap.sh b/bootstrap.sh index 51e5e9d..7e754b0 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -123,7 +123,6 @@ src="$src build2/cc/*.cxx" src="$src build2/cxx/*.cxx" src="$src build2/cli/*.cxx" src="$src build2/version/*.cxx" -src="$src build2/in/*.cxx" src="$src build2/bash/*.cxx" src="$src libbuild2/*.cxx" @@ -132,6 +131,7 @@ src="$src libbuild2/dist/*.cxx" src="$src libbuild2/test/*.cxx" src="$src libbuild2/test/script/*.cxx" src="$src libbuild2/install/*.cxx" +src="$src libbuild2/in/*.cxx" src="$src $libbutl/libbutl/*.cxx" diff --git a/build/export.build b/build/export.build index 4847950..345baf0 100644 --- a/build/export.build +++ b/build/export.build @@ -11,12 +11,20 @@ if ($import.target == exe{b}) export $out_root/build2/exe{b} } -elif ($import.target == lib{build2}) +else { $out_root/ { include libbuild2/ } - export $out_root/libbuild2/lib{build2} + d = [dir_path] $out_root/libbuild2/ + if ($import.target != lib{build2}) + { + # Assume one of the modules. + # + d += $regex.replace($name($import.target), '^build2-(.+)', '\1') + } + + export $d/$import.target } diff --git a/build2/b.cxx b/build2/b.cxx index a76a8e4..907784b 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -42,20 +42,18 @@ #include <libbuild2/parser.hxx> +#include <build2/b-options.hxx> + +// Build system modules. +// #include <libbuild2/dist/init.hxx> #include <libbuild2/test/init.hxx> #include <libbuild2/config/init.hxx> #include <libbuild2/install/init.hxx> -#include <build2/b-options.hxx> - -using namespace butl; -using namespace std; - +#include <libbuild2/in/init.hxx> #include <build2/version/init.hxx> -#include <build2/in/init.hxx> - #include <build2/bin/init.hxx> #include <build2/c/init.hxx> #include <build2/cc/init.hxx> @@ -66,6 +64,9 @@ using namespace std; # include <build2/bash/init.hxx> #endif +using namespace butl; +using namespace std; + namespace build2 { static options ops; @@ -437,46 +438,51 @@ main (int argc, char* argv[]) using mf = module_functions; auto& bm (builtin_modules); - bm["config"] = config::build2_config_load (); - bm["dist"] = dist::build2_dist_load (); - bm["test"] = test::build2_test_load (); - bm["install"] = install::build2_install_load (); - - bm["version"] = mf {&version::boot, &version::init}; - - bm["in.base"] = mf {nullptr, &in::base_init}; - bm["in"] = mf {nullptr, &in::init}; - - bm["bin.vars"] = mf {nullptr, &bin::vars_init}; - bm["bin.config"] = mf {nullptr, &bin::config_init}; - bm["bin"] = mf {nullptr, &bin::init}; - bm["bin.ar.config"] = mf {nullptr, &bin::ar_config_init}; - bm["bin.ar"] = mf {nullptr, &bin::ar_init}; - bm["bin.ld.config"] = mf {nullptr, &bin::ld_config_init}; - bm["bin.ld"] = mf {nullptr, &bin::ld_init}; - bm["bin.rc.config"] = mf {nullptr, &bin::rc_config_init}; - bm["bin.rc"] = mf {nullptr, &bin::rc_init}; - - bm["cc.core.vars"] = mf {nullptr, &cc::core_vars_init}; - bm["cc.core.guess"] = mf {nullptr, &cc::core_guess_init}; - bm["cc.core.config"] = mf {nullptr, &cc::core_config_init}; - bm["cc.core"] = mf {nullptr, &cc::core_init}; - bm["cc.config"] = mf {nullptr, &cc::config_init}; - bm["cc"] = mf {nullptr, &cc::init}; - - bm["c.guess"] = mf {nullptr, &c::guess_init}; - bm["c.config"] = mf {nullptr, &c::config_init}; - bm["c"] = mf {nullptr, &c::init}; - - bm["cxx.guess"] = mf {nullptr, &cxx::guess_init}; - bm["cxx.config"] = mf {nullptr, &cxx::config_init}; - bm["cxx"] = mf {nullptr, &cxx::init}; + auto reg = [] (module_load_function* lf) + { + for (const module_functions* i (lf ()); i->name != nullptr; ++i) + builtin_modules[i->name] = *i; + }; + + reg (&config::build2_config_load); + reg (&dist::build2_dist_load); + reg (&test::build2_test_load); + reg (&install::build2_install_load); + + bm["version"] = mf {"version", &version::boot, &version::init}; + + reg (&in::build2_in_load); + + bm["bin.vars"] = mf {"bin.vars", nullptr, &bin::vars_init}; + bm["bin.config"] = mf {"bin.config", nullptr, &bin::config_init}; + bm["bin"] = mf {"bin", nullptr, &bin::init}; + bm["bin.ar.config"] = mf {"bin.ar.config", nullptr, &bin::ar_config_init}; + bm["bin.ar"] = mf {"bin.ar", nullptr, &bin::ar_init}; + bm["bin.ld.config"] = mf {"bin.ld.config", nullptr, &bin::ld_config_init}; + bm["bin.ld"] = mf {"bin.ld", nullptr, &bin::ld_init}; + bm["bin.rc.config"] = mf {"bin.rc.config", nullptr, &bin::rc_config_init}; + bm["bin.rc"] = mf {"bin.rc", nullptr, &bin::rc_init}; + + bm["cc.core.vars"] = mf {"cc.core.vars", nullptr, &cc::core_vars_init}; + bm["cc.core.guess"] = mf {"cc.core.guess", nullptr, &cc::core_guess_init}; + bm["cc.core.config"] = mf {"cc.core.config", nullptr, &cc::core_config_init}; + bm["cc.core"] = mf {"cc.core", nullptr, &cc::core_init}; + bm["cc.config"] = mf {"cc.config", nullptr, &cc::config_init}; + bm["cc"] = mf {"cc", nullptr, &cc::init}; + + bm["c.guess"] = mf {"c.guess", nullptr, &c::guess_init}; + bm["c.config"] = mf {"c.config", nullptr, &c::config_init}; + bm["c"] = mf {"c", nullptr, &c::init}; + + bm["cxx.guess"] = mf {"cxx.guess", nullptr, &cxx::guess_init}; + bm["cxx.config"] = mf {"cxx.config", nullptr, &cxx::config_init}; + bm["cxx"] = mf {"cxx", nullptr, &cxx::init}; #ifndef BUILD2_BOOTSTRAP - bm["cli.config"] = mf {nullptr, &cli::config_init}; - bm["cli"] = mf {nullptr, &cli::init}; + bm["cli.config"] = mf {"cli.config", nullptr, &cli::config_init}; + bm["cli"] = mf {"cli", nullptr, &cli::init}; - bm["bash"] = mf {nullptr, &bash::init}; + bm["bash"] = mf {"bash", nullptr, &bash::init}; #endif } diff --git a/build2/bash/rule.cxx b/build2/bash/rule.cxx index 72e3219..a612d23 100644 --- a/build2/bash/rule.cxx +++ b/build2/bash/rule.cxx @@ -11,7 +11,7 @@ #include <libbuild2/algorithm.hxx> #include <libbuild2/diagnostics.hxx> -#include <build2/in/target.hxx> +#include <libbuild2/in/target.hxx> #include <build2/bash/target.hxx> #include <build2/bash/utility.hxx> diff --git a/build2/bash/rule.hxx b/build2/bash/rule.hxx index a6ec235..c160bb7 100644 --- a/build2/bash/rule.hxx +++ b/build2/bash/rule.hxx @@ -10,7 +10,7 @@ #include <libbuild2/install/rule.hxx> -#include <build2/in/rule.hxx> +#include <libbuild2/in/rule.hxx> namespace build2 { diff --git a/build2/buildfile b/build2/buildfile index eb22266..a940793 100644 --- a/build2/buildfile +++ b/build2/buildfile @@ -6,12 +6,19 @@ import libs = libbutl%lib{butl} import libs += libpkgconf%lib{pkgconf} include ../libbuild2/ +libs += ../libbuild2/lib{build2} + +for m: in +{ + include ../libbuild2/in/ + libs += ../libbuild2/$m/lib{build2-$m} +} ./: exe{b}: {hxx ixx txx cxx}{+b} libue{b} libue{b}: {hxx ixx txx cxx}{** -b -b-options -**.test...} \ {hxx ixx cxx}{b-options} \ - ../libbuild2/lib{build2} $libs + $libs # Unit tests. # diff --git a/build2/in/init.hxx b/build2/in/init.hxx deleted file mode 100644 index 3cf8ebf..0000000 --- a/build2/in/init.hxx +++ /dev/null @@ -1,37 +0,0 @@ -// file : build2/in/init.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_IN_INIT_HXX -#define BUILD2_IN_INIT_HXX - -#include <libbuild2/types.hxx> -#include <libbuild2/utility.hxx> - -#include <libbuild2/module.hxx> - -namespace build2 -{ - namespace in - { - bool - base_init (scope&, - scope&, - const location&, - unique_ptr<module_base>&, - bool, - bool, - const variable_map&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr<module_base>&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_IN_INIT_HXX diff --git a/build2/version/rule.cxx b/build2/version/rule.cxx index 912efe3..f110e3e 100644 --- a/build2/version/rule.cxx +++ b/build2/version/rule.cxx @@ -8,7 +8,7 @@ #include <libbuild2/target.hxx> #include <libbuild2/diagnostics.hxx> -#include <build2/in/target.hxx> +#include <libbuild2/in/target.hxx> #include <build2/version/module.hxx> #include <build2/version/utility.hxx> diff --git a/build2/version/rule.hxx b/build2/version/rule.hxx index 6d841df..7bfb783 100644 --- a/build2/version/rule.hxx +++ b/build2/version/rule.hxx @@ -10,7 +10,7 @@ #include <libbuild2/install/rule.hxx> -#include <build2/in/rule.hxx> +#include <libbuild2/in/rule.hxx> namespace build2 { diff --git a/libbuild2/buildfile b/libbuild2/buildfile index f23f023..edabfc3 100644 --- a/libbuild2/buildfile +++ b/libbuild2/buildfile @@ -2,17 +2,21 @@ # copyright : Copyright (c) 2014-2019 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file +./: lib{build2} in/ + import int_libs = libbutl%lib{butl} -# The config, test, install, and dist are "core modules" that come bundled -# with libbuild2. Note that the core can still function without them or with -# their alternative implementations. +lib{build2}: libul{build2}: {hxx ixx txx cxx}{* -config -version -*.test...} \ + {hxx}{config version} + +# 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. # -./: lib{build2}: libul{build2}: {hxx ixx txx cxx}{** -config \ - -version \ - -**.test...} \ - {hxx}{config version} \ - $int_libs +for m: config dist install test + libul{build2}: $m/{hxx ixx txx cxx}{** -**.test...} + +libul{build2}: $int_libs # Include the generated config and version headers into the distribution (so # that we don't pick up installed ones) and don't remove them when cleaning in @@ -35,7 +39,11 @@ exe{*.test}: install = false } -for t: cxx{**.test...} +for t: cxx{ *.test...} \ + config/cxx{**.test...} \ + dist/cxx{**.test...} \ + install/cxx{**.test...} \ + test/cxx{**.test...} { d = $directory($t) n = $name($t)... diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 73275c6..b790569 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -145,15 +145,21 @@ namespace build2 return true; } - module_functions + static const module_functions mod_functions[] = + { + {"config", &boot, &init}, + {nullptr, nullptr, nullptr} + }; + + const module_functions* build2_config_load () { // Initialize the config entry points in the build system core. // - config_save_variable = &config::save_variable; - config_preprocess_create = &config::preprocess_create; + config_save_variable = &save_variable; + config_preprocess_create = &preprocess_create; - return module_functions {&boot, &init}; + return mod_functions; } } } diff --git a/libbuild2/config/init.hxx b/libbuild2/config/init.hxx index ff5e923..f900801 100644 --- a/libbuild2/config/init.hxx +++ b/libbuild2/config/init.hxx @@ -28,7 +28,7 @@ namespace build2 bool, const variable_map&); - extern "C" LIBBUILD2_SYMEXPORT module_functions + extern "C" LIBBUILD2_SYMEXPORT const module_functions* build2_config_load (); } } diff --git a/libbuild2/dist/init.cxx b/libbuild2/dist/init.cxx index 959b2dd..4729938 100644 --- a/libbuild2/dist/init.cxx +++ b/libbuild2/dist/init.cxx @@ -183,10 +183,16 @@ namespace build2 return true; } - module_functions + static const module_functions mod_functions[] = + { + {"dist", &boot, &init}, + {nullptr, nullptr, nullptr} + }; + + const module_functions* build2_dist_load () { - return module_functions {&boot, &init}; + return mod_functions; } } } diff --git a/libbuild2/dist/init.hxx b/libbuild2/dist/init.hxx index 41c82a7..cfcb3af 100644 --- a/libbuild2/dist/init.hxx +++ b/libbuild2/dist/init.hxx @@ -28,7 +28,7 @@ namespace build2 bool, const variable_map&); - extern "C" LIBBUILD2_SYMEXPORT module_functions + extern "C" LIBBUILD2_SYMEXPORT const module_functions* build2_dist_load (); } } diff --git a/libbuild2/in/buildfile b/libbuild2/in/buildfile new file mode 100644 index 0000000..ae07e27 --- /dev/null +++ b/libbuild2/in/buildfile @@ -0,0 +1,62 @@ +# file : libbuild2/in/buildfile +# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +import int_libs = libbutl%lib{butl} + +include ../ +int_libs += ../lib{build2} + +./: lib{build2-in}: libul{build2-in}: {hxx ixx txx cxx}{** -**.test...} \ + $int_libs + +# Unit tests. +# +exe{*.test}: +{ + test = true + install = false +} + +for t: cxx{**.test...} +{ + d = $directory($t) + n = $name($t)... + + ./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n} + $d/exe{$n}: libul{build2-in}: bin.whole = false +} + +# Build options. +# +obja{*}: cxx.poptions += -DLIBBUILD2_IN_STATIC_BUILD +objs{*}: cxx.poptions += -DLIBBUILD2_IN_SHARED_BUILD + +# Export options. +# +lib{build2-in}: +{ + cxx.export.poptions = "-I$out_root" "-I$src_root" + cxx.export.libs = $int_libs +} + +liba{build2-in}: cxx.export.poptions += -DLIBBUILD2_IN_STATIC +libs{build2-in}: cxx.export.poptions += -DLIBBUILD2_IN_SHARED + +# For pre-releases use the complete version to make sure they cannot be used +# in place of another pre-release or the final version. See the version module +# for details on the version.* variable values. +# +if $version.pre_release + lib{build2-in}: bin.lib.version = @"-$version.project_id" +else + lib{build2-in}: bin.lib.version = @"-$version.major.$version.minor" + +# Install into the libbuild2/in/ subdirectory of, say, /usr/include/ +# recreating subdirectories. +# +{hxx ixx txx}{*}: +{ + install = include/libbuild2/in/ + install.subdirs = true +} diff --git a/libbuild2/in/export.hxx b/libbuild2/in/export.hxx new file mode 100644 index 0000000..47909e7 --- /dev/null +++ b/libbuild2/in/export.hxx @@ -0,0 +1,34 @@ +#pragma once + +// Normally we don't export class templates (but do complete specializations), +// inline functions, and classes with only inline member functions. Exporting +// classes that inherit from non-exported/imported bases (e.g., std::string) +// will end up badly. The only known workarounds are to not inherit or to not +// export. Also, MinGW GCC doesn't like seeing non-exported functions being +// used before their inline definition. The workaround is to reorder code. In +// the end it's all trial and error. + +#if defined(LIBBUILD2_IN_STATIC) // Using static. +# define LIBBUILD2_IN_SYMEXPORT +#elif defined(LIBBUILD2_IN_STATIC_BUILD) // Building static. +# define LIBBUILD2_IN_SYMEXPORT +#elif defined(LIBBUILD2_IN_SHARED) // Using shared. +# ifdef _WIN32 +# define LIBBUILD2_IN_SYMEXPORT __declspec(dllimport) +# else +# define LIBBUILD2_IN_SYMEXPORT +# endif +#elif defined(LIBBUILD2_IN_SHARED_BUILD) // Building shared. +# ifdef _WIN32 +# define LIBBUILD2_IN_SYMEXPORT __declspec(dllexport) +# else +# define LIBBUILD2_IN_SYMEXPORT +# endif +#else +// If none of the above macros are defined, then we assume we are being used +// by some third-party build system that cannot/doesn't signal the library +// type. Note that this fallback works for both static and shared but in case +// of shared will be sub-optimal compared to having dllimport. +// +# define LIBBUILD2_IN_SYMEXPORT // Using static or shared. +#endif diff --git a/build2/in/init.cxx b/libbuild2/in/init.cxx index f01fe20..6ef996b 100644 --- a/build2/in/init.cxx +++ b/libbuild2/in/init.cxx @@ -1,16 +1,16 @@ -// file : build2/in/init.cxx -*- C++ -*- +// file : libbuild2/in/init.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <build2/in/init.hxx> +#include <libbuild2/in/init.hxx> #include <libbuild2/scope.hxx> #include <libbuild2/context.hxx> #include <libbuild2/variable.hxx> #include <libbuild2/diagnostics.hxx> -#include <build2/in/rule.hxx> -#include <build2/in/target.hxx> +#include <libbuild2/in/rule.hxx> +#include <libbuild2/in/target.hxx> using namespace std; @@ -106,5 +106,21 @@ namespace build2 return true; } + + static const module_functions mod_functions[] = + { + // NOTE: don't forget to also update the documentation in init.hxx if + // changing anything here. + + {"in.base", nullptr, base_init}, + {"in", nullptr, init}, + {nullptr, nullptr, nullptr} + }; + + const module_functions* + build2_in_load () + { + return mod_functions; + } } } diff --git a/libbuild2/in/init.hxx b/libbuild2/in/init.hxx new file mode 100644 index 0000000..b82c77e --- /dev/null +++ b/libbuild2/in/init.hxx @@ -0,0 +1,30 @@ +// file : libbuild2/in/init.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef LIBBUILD2_IN_INIT_HXX +#define LIBBUILD2_IN_INIT_HXX + +#include <libbuild2/types.hxx> +#include <libbuild2/utility.hxx> + +#include <libbuild2/module.hxx> + +#include <libbuild2/in/export.hxx> + +namespace build2 +{ + namespace in + { + // Module `in` does not require bootstrapping. + // + // Submodules: + // + // `in.base` -- only variables and target types. + // + extern "C" LIBBUILD2_IN_SYMEXPORT const module_functions* + build2_in_load (); + } +} + +#endif // LIBBUILD2_IN_INIT_HXX diff --git a/build2/in/rule.cxx b/libbuild2/in/rule.cxx index 8a3244d..bdc9b24 100644 --- a/build2/in/rule.cxx +++ b/libbuild2/in/rule.cxx @@ -1,8 +1,8 @@ -// file : build2/in/rule.cxx -*- C++ -*- +// file : libbuild2/in/rule.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <build2/in/rule.hxx> +#include <libbuild2/in/rule.hxx> #include <cstdlib> // strtoull() @@ -14,7 +14,7 @@ #include <libbuild2/filesystem.hxx> #include <libbuild2/diagnostics.hxx> -#include <build2/in/target.hxx> +#include <libbuild2/in/target.hxx> using namespace std; using namespace butl; diff --git a/build2/in/rule.hxx b/libbuild2/in/rule.hxx index 71dc032..0daf6c0 100644 --- a/build2/in/rule.hxx +++ b/libbuild2/in/rule.hxx @@ -1,15 +1,17 @@ -// file : build2/in/rule.hxx -*- C++ -*- +// file : libbuild2/in/rule.hxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#ifndef BUILD2_IN_RULE_HXX -#define BUILD2_IN_RULE_HXX +#ifndef LIBBUILD2_IN_RULE_HXX +#define LIBBUILD2_IN_RULE_HXX #include <libbuild2/types.hxx> #include <libbuild2/utility.hxx> #include <libbuild2/rule.hxx> +#include <libbuild2/in/export.hxx> + namespace build2 { namespace in @@ -22,7 +24,7 @@ namespace build2 // Note also that currently this rule ignores the dry-run mode (see // perform_update() for the rationale). // - class rule: public build2::rule + class LIBBUILD2_IN_SYMEXPORT rule: public build2::rule { public: // The rule id is used to form the rule name/version entry in depdb. The @@ -85,4 +87,4 @@ namespace build2 } } -#endif // BUILD2_IN_RULE_HXX +#endif // LIBBUILD2_IN_RULE_HXX diff --git a/build2/in/target.cxx b/libbuild2/in/target.cxx index 8dc520b..490ab10 100644 --- a/build2/in/target.cxx +++ b/libbuild2/in/target.cxx @@ -1,8 +1,8 @@ -// file : build2/in/target.cxx -*- C++ -*- +// file : libbuild2/in/target.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <build2/in/target.hxx> +#include <libbuild2/in/target.hxx> using namespace std; diff --git a/build2/in/target.hxx b/libbuild2/in/target.hxx index 47b0eed..5e3438d 100644 --- a/build2/in/target.hxx +++ b/libbuild2/in/target.hxx @@ -1,15 +1,17 @@ -// file : build2/in/target.hxx -*- C++ -*- +// file : libbuild2/in/target.hxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#ifndef BUILD2_IN_TARGET_HXX -#define BUILD2_IN_TARGET_HXX +#ifndef LIBBUILD2_IN_TARGET_HXX +#define LIBBUILD2_IN_TARGET_HXX #include <libbuild2/types.hxx> #include <libbuild2/utility.hxx> #include <libbuild2/target.hxx> +#include <libbuild2/in/export.hxx> + namespace build2 { namespace in @@ -31,7 +33,7 @@ namespace build2 // the target-dependent search comes in: we take into account the target // we are a prerequisite of. // - class in: public file + class LIBBUILD2_IN_SYMEXPORT in: public file { public: using file::file; @@ -43,4 +45,4 @@ namespace build2 } } -#endif // BUILD2_IN_TARGET_HXX +#endif // LIBBUILD2_IN_TARGET_HXX diff --git a/libbuild2/install/init.cxx b/libbuild2/install/init.cxx index fb3d9ea..060007b 100644 --- a/libbuild2/install/init.cxx +++ b/libbuild2/install/init.cxx @@ -300,10 +300,16 @@ namespace build2 return true; } - module_functions + static const module_functions mod_functions[] = + { + {"install", &boot, &init}, + {nullptr, nullptr, nullptr} + }; + + const module_functions* build2_install_load () { - return module_functions {&boot, &init}; + return mod_functions; } } } diff --git a/libbuild2/install/init.hxx b/libbuild2/install/init.hxx index fa0a1e1..b2daea0 100644 --- a/libbuild2/install/init.hxx +++ b/libbuild2/install/init.hxx @@ -28,7 +28,7 @@ namespace build2 bool, const variable_map&); - extern "C" LIBBUILD2_SYMEXPORT module_functions + extern "C" LIBBUILD2_SYMEXPORT const module_functions* build2_install_load (); } } diff --git a/libbuild2/module.hxx b/libbuild2/module.hxx index 7d94837..c32fc9a 100644 --- a/libbuild2/module.hxx +++ b/libbuild2/module.hxx @@ -50,24 +50,31 @@ namespace build2 bool optional, // Loaded with using? (optional module). const variable_map& hints); // Configuration hints (see below). + // If the boot function is not NULL, then such a module is said to require + // bootstrapping and must be loaded in bootstrap.build. + // struct module_functions { - module_boot_function* boot; - module_init_function* init; + const char* name = nullptr; // Module/submodule name. + module_boot_function* boot = nullptr; + module_init_function* init = nullptr; }; - // The build2_<modname>_load() function will be written in C++ and will be + // The build2_<name>_load() function will be written in C++ and will be // called from C++ but we need to suppress name mangling to be able to use - // dlsym() or equivalent. + // dlsym() or equivalent, thus extern "C". // - // Note that the load() function is guaranteed to be called during serial - // execution (either from main() or during the load phase). + // The <name> part in the function name is the main module name without + // submodule components (for example, `c` in `c.config`) and the load + // function is expected to return boot/init functions for all its submodules + // (if any) as well as for the module itself as an array of module_functions + // terminated with an all-NULL entry. // - // @@ I wonder if returning a "C++ struct" (it contains pointer to functions - // with signatures containing C++ type) is kosher. + // Note that the load function is guaranteed to be called during serial + // execution (either from main() or during the load phase). // extern "C" - using module_load_function = module_functions (); + using module_load_function = const module_functions* (); // Loaded modules state. // @@ -119,6 +126,9 @@ namespace build2 // Builtin modules. // + // @@ Maybe this should be renamed to loaded modules? + // @@ We can also change it to std::map<const char*, const module_functions*> + // using available_module_map = std::map<string, module_functions>; LIBBUILD2_SYMEXPORT extern available_module_map builtin_modules; } diff --git a/libbuild2/test/init.cxx b/libbuild2/test/init.cxx index 3d13acc..a5afea0 100644 --- a/libbuild2/test/init.cxx +++ b/libbuild2/test/init.cxx @@ -220,12 +220,18 @@ namespace build2 return true; } - module_functions + static const module_functions mod_functions[] = + { + {"test", &boot, &init}, + {nullptr, nullptr, nullptr} + }; + + const module_functions* build2_test_load () { script::regex::init (); - return module_functions {&boot, &init}; + return mod_functions; } } } diff --git a/libbuild2/test/init.hxx b/libbuild2/test/init.hxx index a76b720..57f6bfa 100644 --- a/libbuild2/test/init.hxx +++ b/libbuild2/test/init.hxx @@ -28,7 +28,7 @@ namespace build2 bool, const variable_map&); - extern "C" LIBBUILD2_SYMEXPORT module_functions + extern "C" LIBBUILD2_SYMEXPORT const module_functions* build2_test_load (); } } diff --git a/tests/libbuild2/buildfile b/tests/libbuild2/buildfile index 4d3a42f..51b2f5b 100644 --- a/tests/libbuild2/buildfile +++ b/tests/libbuild2/buildfile @@ -2,7 +2,8 @@ # copyright : Copyright (c) 2014-2019 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file -import libs = build2%lib{build2} +import libs = build2%lib{build2} +import libs += build2%lib{build2-in} exe{driver}: {hxx cxx}{*} $libs testscript diff --git a/tests/libbuild2/driver.cxx b/tests/libbuild2/driver.cxx index 3df2fbe..d9c086a 100644 --- a/tests/libbuild2/driver.cxx +++ b/tests/libbuild2/driver.cxx @@ -8,6 +8,8 @@ #include <libbuild2/context.hxx> // sched, reset() #include <libbuild2/scheduler.hxx> +#include <libbuild2/in/init.hxx> + using namespace build2; int @@ -17,6 +19,9 @@ main (int, char* argv[]) // init_diag (1); init (argv[0]); + + in::build2_in_load (); + sched.startup (1); // Serial execution. reset (strings ()); // No command line variables. |