From f7adb1ce7a13753a6acf5c9eeb9577ecdada630c Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 24 Aug 2019 22:10:09 +0300 Subject: Move c build system module to separate library --- bootstrap-mingw.bat | 2 +- bootstrap-msvc.bat | 2 +- bootstrap.gmake | 2 +- bootstrap.sh | 2 +- build2/b.cxx | 7 +- build2/buildfile | 5 +- build2/c/init.cxx | 358 ------------------------------------------- build2/c/init.hxx | 46 ------ build2/c/target.hxx | 22 --- libbuild2/buildfile | 2 +- libbuild2/c/buildfile | 90 +++++++++++ libbuild2/c/export.hxx | 38 +++++ libbuild2/c/init.cxx | 375 +++++++++++++++++++++++++++++++++++++++++++++ libbuild2/c/init.hxx | 32 ++++ libbuild2/c/target.hxx | 22 +++ libbuild2/module.cxx | 1 + tests/libbuild2/buildfile | 2 +- tests/libbuild2/driver.cxx | 2 + 18 files changed, 569 insertions(+), 441 deletions(-) delete mode 100644 build2/c/init.cxx delete mode 100644 build2/c/init.hxx delete mode 100644 build2/c/target.hxx create mode 100644 libbuild2/c/buildfile create mode 100644 libbuild2/c/export.hxx create mode 100644 libbuild2/c/init.cxx create mode 100644 libbuild2/c/init.hxx create mode 100644 libbuild2/c/target.hxx diff --git a/bootstrap-mingw.bat b/bootstrap-mingw.bat index fc3c9ff..43cc84f 100644 --- a/bootstrap-mingw.bat +++ b/bootstrap-mingw.bat @@ -61,7 +61,6 @@ if "_%libbutl%_" == "__" ( rem All the source directories. rem set "src=build2" -set "src=%src% build2\c" set "src=%src% build2\cxx" set "src=%src% libbuild2" @@ -71,6 +70,7 @@ set "src=%src% libbuild2\test" set "src=%src% libbuild2\test\script" set "src=%src% libbuild2\install" set "src=%src% libbuild2\bin" +set "src=%src% libbuild2\c" set "src=%src% libbuild2\cc" set "src=%src% libbuild2\version" set "src=%src% libbuild2\in" diff --git a/bootstrap-msvc.bat b/bootstrap-msvc.bat index 7526b0c..8da8769 100644 --- a/bootstrap-msvc.bat +++ b/bootstrap-msvc.bat @@ -92,7 +92,6 @@ if "_%libbutl%_" == "__" ( rem All the source directories. rem set "src=build2" -set "src=%src% build2\c" set "src=%src% build2\cxx" set "src=%src% libbuild2" @@ -102,6 +101,7 @@ set "src=%src% libbuild2\test" set "src=%src% libbuild2\test\script" set "src=%src% libbuild2\install" set "src=%src% libbuild2\bin" +set "src=%src% libbuild2\c" set "src=%src% libbuild2\cc" set "src=%src% libbuild2\version" set "src=%src% libbuild2\in" diff --git a/bootstrap.gmake b/bootstrap.gmake index 0cafedf..0e3126e 100644 --- a/bootstrap.gmake +++ b/bootstrap.gmake @@ -130,7 +130,6 @@ endif # Note: list nested subdirectories first (used in clean). # build2_sub := \ -c \ cxx libbuild2_sub := \ @@ -140,6 +139,7 @@ test/script \ test \ install \ bin \ +c \ cc \ version \ in diff --git a/bootstrap.sh b/bootstrap.sh index f227d82..368a549 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -117,7 +117,6 @@ if test -z "$libbutl"; then fi src="build2/*.cxx" -src="$src build2/c/*.cxx" src="$src build2/cxx/*.cxx" src="$src libbuild2/*.cxx" @@ -127,6 +126,7 @@ src="$src libbuild2/test/*.cxx" src="$src libbuild2/test/script/*.cxx" src="$src libbuild2/install/*.cxx" src="$src libbuild2/bin/*.cxx" +src="$src libbuild2/c/*.cxx" src="$src libbuild2/cc/*.cxx" src="$src libbuild2/version/*.cxx" src="$src libbuild2/in/*.cxx" diff --git a/build2/b.cxx b/build2/b.cxx index be67a8c..1fd6b5a 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -54,6 +54,7 @@ #include #include +#include #include #include @@ -63,7 +64,6 @@ # include #endif -#include #include using namespace butl; @@ -521,13 +521,10 @@ main (int argc, char* argv[]) load (&bin::build2_bin_load); load (&cc::build2_cc_load); + load (&c::build2_c_load); load (&version::build2_version_load); load (&in::build2_in_load); - TMP_LOAD (c_guess, "c.guess", c::guess_init); - TMP_LOAD (c_config, "c.config", c::config_init); - TMP_LOAD (c, "c", c::init); - TMP_LOAD (cxx_guess, "cxx.guess", cxx::guess_init); TMP_LOAD (cxx_config, "cxx.config", cxx::config_init); TMP_LOAD (cxx, "cxx", cxx::init); diff --git a/build2/buildfile b/build2/buildfile index cfc46e5..7f4187e 100644 --- a/build2/buildfile +++ b/build2/buildfile @@ -7,7 +7,7 @@ import libs = libbutl%lib{butl} include ../libbuild2/ libs += ../libbuild2/lib{build2} -for m: bash bin cc in version +for m: bash bin c cc in version { include ../libbuild2/$m/ libs += ../libbuild2/$m/lib{build2-$m} @@ -48,9 +48,6 @@ obj{b}: cxx.poptions += -DBUILD2_HOST_TRIPLET=\"$cxx.target\" # if ($cxx.target == $build.host) { - c/obj{init}: cxx.poptions += \ - -DBUILD2_NATIVE_C=\"$regex.replace($recall($c.path), '\\', '\\\\')\" - cxx/obj{init}: cxx.poptions += \ -DBUILD2_NATIVE_CXX=\"$regex.replace($recall($cxx.path), '\\', '\\\\')\" } diff --git a/build2/c/init.cxx b/build2/c/init.cxx deleted file mode 100644 index 6d271a7..0000000 --- a/build2/c/init.cxx +++ /dev/null @@ -1,358 +0,0 @@ -// file : build2/c/init.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include - -#include -#include - -#include - -#ifndef BUILD2_DEFAULT_C -# ifdef BUILD2_NATIVE_C -# define BUILD2_DEFAULT_C BUILD2_NATIVE_C -# else -# define BUILD2_DEFAULT_C "" -# endif -#endif - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace c - { - using cc::compiler_id; - using cc::compiler_class; - using cc::compiler_info; - - class config_module: public cc::config_module - { - public: - explicit - config_module (config_data&& d) - : config_data (move (d)), cc::config_module (move (d)) {} - - virtual strings - translate_std (const compiler_info&, - scope&, - const string*) const override; - }; - - using cc::module; - - strings config_module:: - translate_std (const compiler_info& ci, scope& rs, const string* v) const - { - strings r; - - switch (ci.class_) - { - case compiler_class::msvc: - { - // Standard-wise, with VC you get what you get. The question is - // whether we should verify that the requested standard is provided - // by this VC version. And if so, from which version should we say - // VC supports 90, 99, and 11? We should probably be as loose as - // possible here since the author will always be able to tighten - // (but not loosen) this in the buildfile (i.e., detect unsupported - // versions). - // - // The state of affairs seem to be (from Herb Sutter's blog): - // - // 10.0 - most of C95 plus a few C99 features - // 11.0 - partial support for the C++11 subset of C11 - // 12.0 - more C11 features from the C++11 subset, most of C99 - // - // So let's say C99 is supported from 10.0 and C11 from 11.0. And - // C90 is supported by everything we care to support. - // - // C17 is a bug-fix version of C11 so here we assume it is the same - // as C11. - // - if (v == nullptr) - ; - else if (*v != "90") - { - uint64_t cver (ci.version.major); - - if ((*v == "99" && cver < 16) || // Since VS2010/10.0. - ((*v == "11" || - *v == "17") && cver < 17)) // Since VS2012/11.0. - { - fail << "C" << *v << " is not supported by " << ci.signature << - info << "required by " << project (rs) << '@' << rs; - } - } - break; - } - case compiler_class::gcc: - { - // 90 and 89 are the same standard. Translate 99 to 9x and 11 to 1x - // for compatibility with older versions of the compilers. - // - if (v == nullptr) - ; - else - { - string o ("-std="); - - if (*v == "90") o += "c90"; - else if (*v == "99") o += "c9x"; - else if (*v == "11") o += "c1x"; - else if (*v == "17") o += "c17"; // GCC 8, Clang 6. - else o += *v; // In case the user specifies e.g., 'gnu11'. - - r.push_back (move (o)); - } - break; - } - } - - return r; - } - - static const char* const hinters[] = {"cxx", nullptr}; - - // See cc::module for details on guess_init vs config_init. - // - bool - guess_init (scope& rs, - scope& bs, - const location& loc, - unique_ptr& mod, - bool, - bool, - const variable_map& hints) - { - tracer trace ("c::guess_init"); - l5 ([&]{trace << "for " << bs;}); - - // We only support root loading (which means there can only be one). - // - if (&rs != &bs) - fail (loc) << "c.guess module must be loaded in project root"; - - // Load cc.core.vars so that we can cache all the cc.* variables. - // - if (!cast_false (rs["cc.core.vars.loaded"])) - load_module (rs, rs, "cc.core.vars", loc); - - // Enter all the variables and initialize the module data. - // - auto& v (rs.ctx.var_pool.rw (rs)); - - cc::config_data d { - cc::lang::c, - - "c", - "c", - BUILD2_DEFAULT_C, - ".i", - - hinters, - - // Note: some overridable, some not. - // - v.insert ("config.c", true), - v.insert ("config.c.id", true), - v.insert ("config.c.version", true), - v.insert ("config.c.target", true), - v.insert ("config.c.std", true), - v.insert ("config.c.poptions", true), - v.insert ("config.c.coptions", true), - v.insert ("config.c.loptions", true), - v.insert ("config.c.aoptions", true), - v.insert ("config.c.libs", true), - nullptr /* config.c.importable_headers */, - - v.insert ("c.path"), - v.insert ("c.sys_lib_dirs"), - v.insert ("c.sys_inc_dirs"), - - v.insert ("c.std", variable_visibility::project), - - v.insert ("c.poptions"), - v.insert ("c.coptions"), - v.insert ("c.loptions"), - v.insert ("c.aoptions"), - v.insert ("c.libs"), - - nullptr /* c.importable_headers */, - - v["cc.poptions"], - v["cc.coptions"], - v["cc.loptions"], - v["cc.aoptions"], - v["cc.libs"], - - v.insert ("c.export.poptions"), - v.insert ("c.export.coptions"), - v.insert ("c.export.loptions"), - v.insert> ("c.export.libs"), - - v["cc.export.poptions"], - v["cc.export.coptions"], - v["cc.export.loptions"], - v["cc.export.libs"], - - v.insert_alias (v["cc.stdlib"], "c.stdlib"), // Same as cc.stdlib. - - v["cc.runtime"], - v["cc.stdlib"], - - v["cc.type"], - v["cc.system"], - v["cc.module_name"], - v["cc.reprocess"], - - v.insert ("c.preprocessed"), // See cxx.preprocessed. - nullptr, // No __symexport (no modules). - - v.insert ("c.id"), - v.insert ("c.id.type"), - v.insert ("c.id.variant"), - - v.insert ("c.class"), - - v.insert ("c.version"), - v.insert ("c.version.major"), - v.insert ("c.version.minor"), - v.insert ("c.version.patch"), - v.insert ("c.version.build"), - - v.insert ("c.signature"), - v.insert ("c.checksum"), - - v.insert ("c.pattern"), - - v.insert ("c.target"), - - v.insert ("c.target.cpu"), - v.insert ("c.target.vendor"), - v.insert ("c.target.system"), - v.insert ("c.target.version"), - v.insert ("c.target.class") - }; - - // Alias some cc. variables as c. - // - v.insert_alias (d.c_runtime, "c.runtime"); - - assert (mod == nullptr); - config_module* m (new config_module (move (d))); - mod.reset (m); - m->guess (rs, loc, hints); - return true; - } - - bool - config_init (scope& rs, - scope& bs, - const location& loc, - unique_ptr&, - bool, - bool, - const variable_map& hints) - { - tracer trace ("c::config_init"); - l5 ([&]{trace << "for " << bs;}); - - // We only support root loading (which means there can only be one). - // - if (&rs != &bs) - fail (loc) << "c.config module must be loaded in project root"; - - // Load c.guess. - // - if (!cast_false (rs["c.guess.loaded"])) - load_module (rs, rs, "c.guess", loc, false, hints); - - config_module& cm (*rs.lookup_module ("c.guess")); - cm.init (rs, loc, hints); - return true; - } - - static const target_type* const hdr[] = - { - &h::static_type, - nullptr - }; - - static const target_type* const inc[] = - { - &h::static_type, - &c::static_type, - nullptr - }; - - bool - init (scope& rs, - scope& bs, - const location& loc, - unique_ptr& mod, - bool, - bool, - const variable_map& hints) - { - tracer trace ("c::init"); - l5 ([&]{trace << "for " << bs;}); - - // We only support root loading (which means there can only be one). - // - if (&rs != &bs) - fail (loc) << "c module must be loaded in project root"; - - // Load c.config. - // - if (!cast_false (rs["c.config.loaded"])) - load_module (rs, rs, "c.config", loc, false, hints); - - config_module& cm (*rs.lookup_module ("c.guess")); - - cc::data d { - cm, - - "c.compile", - "c.link", - "c.install", - "c.uninstall", - - cm.ci_->id.type, - cm.ci_->id.variant, - cm.ci_->class_, - cm.ci_->version.major, - cm.ci_->version.minor, - cast (rs[cm.x_path]), - cast (rs[cm.x_target]), - - cm.tstd, - - false, // No C modules yet. - false, // No __symexport support since no modules. - - cast (rs[cm.x_sys_lib_dirs]), - cast (rs[cm.x_sys_inc_dirs]), - - cm.sys_lib_dirs_extra, - cm.sys_inc_dirs_extra, - - c::static_type, - nullptr, // No C modules yet. - hdr, - inc - }; - - assert (mod == nullptr); - module* m; - mod.reset (m = new module (move (d))); - m->init (rs, loc, hints); - return true; - } - } -} diff --git a/build2/c/init.hxx b/build2/c/init.hxx deleted file mode 100644 index 77119a9..0000000 --- a/build2/c/init.hxx +++ /dev/null @@ -1,46 +0,0 @@ -// file : build2/c/init.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_C_INIT_HXX -#define BUILD2_C_INIT_HXX - -#include -#include - -#include - -namespace build2 -{ - namespace c - { - bool - guess_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - config_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_C_INIT_HXX diff --git a/build2/c/target.hxx b/build2/c/target.hxx deleted file mode 100644 index 88e2ef4..0000000 --- a/build2/c/target.hxx +++ /dev/null @@ -1,22 +0,0 @@ -// file : build2/c/target.hxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_C_TARGET_HXX -#define BUILD2_C_TARGET_HXX - -#include -#include - -#include - -namespace build2 -{ - namespace c - { - using cc::h; - using cc::c; - } -} - -#endif // BUILD2_C_TARGET_HXX diff --git a/libbuild2/buildfile b/libbuild2/buildfile index aad4e78..75731fc 100644 --- a/libbuild2/buildfile +++ b/libbuild2/buildfile @@ -5,7 +5,7 @@ # NOTE: remember to update bundled_modules in libbuild2/modules.cxx if adding # a new module. # -./: lib{build2} bash/ bin/ cc/ in/ version/ +./: lib{build2} bash/ bin/ c/ cc/ in/ version/ import int_libs = libbutl%lib{butl} diff --git a/libbuild2/c/buildfile b/libbuild2/c/buildfile new file mode 100644 index 0000000..39a5d7a --- /dev/null +++ b/libbuild2/c/buildfile @@ -0,0 +1,90 @@ +# file : libbuild2/c/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} + +include ../cc/ +int_libs += ../cc/lib{build2-cc} + +./: lib{build2-c}: libul{build2-c}: {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-c}: bin.whole = false +} + +# Build options. +# +obja{*}: cxx.poptions += -DLIBBUILD2_C_STATIC_BUILD +objs{*}: cxx.poptions += -DLIBBUILD2_C_SHARED_BUILD + +# Note that we used to compare complete target triplets but that proved too +# strict (see libbuild2/buildfile for details). +# +cross = ($cxx.target.cpu != $build.host.cpu || \ + $cxx.target.system != $build.host.system) + +# Pass native C compiler path (not forgetting to escape backslashes on +# Windows). It is used as defaults for BUILD2_DEFAULT_C. +# +if! $cross +{ + obj{init}: cxx.poptions += \ + -DBUILD2_NATIVE_C=\"$regex.replace($recall($c.path), '\\', '\\\\')\" + + obja{init}: cxx.poptions += -DLIBBUILD2_C_STATIC_BUILD + objs{init}: cxx.poptions += -DLIBBUILD2_C_SHARED_BUILD +} + +# Export options. +# +lib{build2-c}: +{ + cxx.export.poptions = "-I$out_root" "-I$src_root" + cxx.export.libs = $int_libs +} + +liba{build2-c}: cxx.export.poptions += -DLIBBUILD2_C_STATIC +libs{build2-c}: cxx.export.poptions += -DLIBBUILD2_C_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. +# +# And because this is a build system module, we also embed the same value as +# the interface version (note that we cannot use build.version.interface for +# bundled modules because we could be built with a different version of the +# build system). +# +ver = ($version.pre_release \ + ? "$version.project_id" \ + : "$version.major.$version.minor") + +lib{build2-c}: bin.lib.version = @"-$ver" +libs{build2-c}: bin.lib.load_suffix = "-$ver" + +# Install into the libbuild2/c/ subdirectory of, say, /usr/include/ +# recreating subdirectories. +# +{hxx ixx txx}{*}: +{ + install = include/libbuild2/c/ + install.subdirs = true +} diff --git a/libbuild2/c/export.hxx b/libbuild2/c/export.hxx new file mode 100644 index 0000000..6fe3203 --- /dev/null +++ b/libbuild2/c/export.hxx @@ -0,0 +1,38 @@ +// file : libbuild2/c/export.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#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_C_STATIC) // Using static. +# define LIBBUILD2_C_SYMEXPORT +#elif defined(LIBBUILD2_C_STATIC_BUILD) // Building static. +# define LIBBUILD2_C_SYMEXPORT +#elif defined(LIBBUILD2_C_SHARED) // Using shared. +# ifdef _WIN32 +# define LIBBUILD2_C_SYMEXPORT __declspec(dllimport) +# else +# define LIBBUILD2_C_SYMEXPORT +# endif +#elif defined(LIBBUILD2_C_SHARED_BUILD) // Building shared. +# ifdef _WIN32 +# define LIBBUILD2_C_SYMEXPORT __declspec(dllexport) +# else +# define LIBBUILD2_C_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_C_SYMEXPORT // Using static or shared. +#endif diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx new file mode 100644 index 0000000..43d647f --- /dev/null +++ b/libbuild2/c/init.cxx @@ -0,0 +1,375 @@ +// file : libbuild2/c/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +#include + +#ifndef BUILD2_DEFAULT_C +# ifdef BUILD2_NATIVE_C +# define BUILD2_DEFAULT_C BUILD2_NATIVE_C +# else +# define BUILD2_DEFAULT_C "" +# endif +#endif + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace c + { + using cc::compiler_id; + using cc::compiler_class; + using cc::compiler_info; + + class config_module: public cc::config_module + { + public: + explicit + config_module (config_data&& d) + : config_data (move (d)), cc::config_module (move (d)) {} + + virtual strings + translate_std (const compiler_info&, + scope&, + const string*) const override; + }; + + using cc::module; + + strings config_module:: + translate_std (const compiler_info& ci, scope& rs, const string* v) const + { + strings r; + + switch (ci.class_) + { + case compiler_class::msvc: + { + // Standard-wise, with VC you get what you get. The question is + // whether we should verify that the requested standard is provided + // by this VC version. And if so, from which version should we say + // VC supports 90, 99, and 11? We should probably be as loose as + // possible here since the author will always be able to tighten + // (but not loosen) this in the buildfile (i.e., detect unsupported + // versions). + // + // The state of affairs seem to be (from Herb Sutter's blog): + // + // 10.0 - most of C95 plus a few C99 features + // 11.0 - partial support for the C++11 subset of C11 + // 12.0 - more C11 features from the C++11 subset, most of C99 + // + // So let's say C99 is supported from 10.0 and C11 from 11.0. And + // C90 is supported by everything we care to support. + // + // C17 is a bug-fix version of C11 so here we assume it is the same + // as C11. + // + if (v == nullptr) + ; + else if (*v != "90") + { + uint64_t cver (ci.version.major); + + if ((*v == "99" && cver < 16) || // Since VS2010/10.0. + ((*v == "11" || + *v == "17") && cver < 17)) // Since VS2012/11.0. + { + fail << "C" << *v << " is not supported by " << ci.signature << + info << "required by " << project (rs) << '@' << rs; + } + } + break; + } + case compiler_class::gcc: + { + // 90 and 89 are the same standard. Translate 99 to 9x and 11 to 1x + // for compatibility with older versions of the compilers. + // + if (v == nullptr) + ; + else + { + string o ("-std="); + + if (*v == "90") o += "c90"; + else if (*v == "99") o += "c9x"; + else if (*v == "11") o += "c1x"; + else if (*v == "17") o += "c17"; // GCC 8, Clang 6. + else o += *v; // In case the user specifies e.g., 'gnu11'. + + r.push_back (move (o)); + } + break; + } + } + + return r; + } + + static const char* const hinters[] = {"cxx", nullptr}; + + // See cc::module for details on guess_init vs config_init. + // + bool + guess_init (scope& rs, + scope& bs, + const location& loc, + unique_ptr& mod, + bool, + bool, + const variable_map& hints) + { + tracer trace ("c::guess_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (&rs != &bs) + fail (loc) << "c.guess module must be loaded in project root"; + + // Load cc.core.vars so that we can cache all the cc.* variables. + // + if (!cast_false (rs["cc.core.vars.loaded"])) + load_module (rs, rs, "cc.core.vars", loc); + + // Enter all the variables and initialize the module data. + // + auto& v (rs.ctx.var_pool.rw (rs)); + + cc::config_data d { + cc::lang::c, + + "c", + "c", + BUILD2_DEFAULT_C, + ".i", + + hinters, + + // Note: some overridable, some not. + // + v.insert ("config.c", true), + v.insert ("config.c.id", true), + v.insert ("config.c.version", true), + v.insert ("config.c.target", true), + v.insert ("config.c.std", true), + v.insert ("config.c.poptions", true), + v.insert ("config.c.coptions", true), + v.insert ("config.c.loptions", true), + v.insert ("config.c.aoptions", true), + v.insert ("config.c.libs", true), + nullptr /* config.c.importable_headers */, + + v.insert ("c.path"), + v.insert ("c.sys_lib_dirs"), + v.insert ("c.sys_inc_dirs"), + + v.insert ("c.std", variable_visibility::project), + + v.insert ("c.poptions"), + v.insert ("c.coptions"), + v.insert ("c.loptions"), + v.insert ("c.aoptions"), + v.insert ("c.libs"), + + nullptr /* c.importable_headers */, + + v["cc.poptions"], + v["cc.coptions"], + v["cc.loptions"], + v["cc.aoptions"], + v["cc.libs"], + + v.insert ("c.export.poptions"), + v.insert ("c.export.coptions"), + v.insert ("c.export.loptions"), + v.insert> ("c.export.libs"), + + v["cc.export.poptions"], + v["cc.export.coptions"], + v["cc.export.loptions"], + v["cc.export.libs"], + + v.insert_alias (v["cc.stdlib"], "c.stdlib"), // Same as cc.stdlib. + + v["cc.runtime"], + v["cc.stdlib"], + + v["cc.type"], + v["cc.system"], + v["cc.module_name"], + v["cc.reprocess"], + + v.insert ("c.preprocessed"), // See cxx.preprocessed. + nullptr, // No __symexport (no modules). + + v.insert ("c.id"), + v.insert ("c.id.type"), + v.insert ("c.id.variant"), + + v.insert ("c.class"), + + v.insert ("c.version"), + v.insert ("c.version.major"), + v.insert ("c.version.minor"), + v.insert ("c.version.patch"), + v.insert ("c.version.build"), + + v.insert ("c.signature"), + v.insert ("c.checksum"), + + v.insert ("c.pattern"), + + v.insert ("c.target"), + + v.insert ("c.target.cpu"), + v.insert ("c.target.vendor"), + v.insert ("c.target.system"), + v.insert ("c.target.version"), + v.insert ("c.target.class") + }; + + // Alias some cc. variables as c. + // + v.insert_alias (d.c_runtime, "c.runtime"); + + assert (mod == nullptr); + config_module* m (new config_module (move (d))); + mod.reset (m); + m->guess (rs, loc, hints); + return true; + } + + bool + config_init (scope& rs, + scope& bs, + const location& loc, + unique_ptr&, + bool, + bool, + const variable_map& hints) + { + tracer trace ("c::config_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (&rs != &bs) + fail (loc) << "c.config module must be loaded in project root"; + + // Load c.guess. + // + if (!cast_false (rs["c.guess.loaded"])) + load_module (rs, rs, "c.guess", loc, false, hints); + + config_module& cm (*rs.lookup_module ("c.guess")); + cm.init (rs, loc, hints); + return true; + } + + static const target_type* const hdr[] = + { + &h::static_type, + nullptr + }; + + static const target_type* const inc[] = + { + &h::static_type, + &c::static_type, + nullptr + }; + + bool + init (scope& rs, + scope& bs, + const location& loc, + unique_ptr& mod, + bool, + bool, + const variable_map& hints) + { + tracer trace ("c::init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (&rs != &bs) + fail (loc) << "c module must be loaded in project root"; + + // Load c.config. + // + if (!cast_false (rs["c.config.loaded"])) + load_module (rs, rs, "c.config", loc, false, hints); + + config_module& cm (*rs.lookup_module ("c.guess")); + + cc::data d { + cm, + + "c.compile", + "c.link", + "c.install", + "c.uninstall", + + cm.ci_->id.type, + cm.ci_->id.variant, + cm.ci_->class_, + cm.ci_->version.major, + cm.ci_->version.minor, + cast (rs[cm.x_path]), + cast (rs[cm.x_target]), + + cm.tstd, + + false, // No C modules yet. + false, // No __symexport support since no modules. + + cast (rs[cm.x_sys_lib_dirs]), + cast (rs[cm.x_sys_inc_dirs]), + + cm.sys_lib_dirs_extra, + cm.sys_inc_dirs_extra, + + c::static_type, + nullptr, // No C modules yet. + hdr, + inc + }; + + assert (mod == nullptr); + module* m; + mod.reset (m = new module (move (d))); + m->init (rs, loc, hints); + return true; + } + + static const module_functions mod_functions[] = + { + // NOTE: don't forget to also update the documentation in init.hxx if + // changing anything here. + + {"c.guess", nullptr, guess_init}, + {"c.config", nullptr, config_init}, + {"c", nullptr, init}, + {nullptr, nullptr, nullptr} + }; + + const module_functions* + build2_c_load () + { + return mod_functions; + } + } +} diff --git a/libbuild2/c/init.hxx b/libbuild2/c/init.hxx new file mode 100644 index 0000000..92d12a3 --- /dev/null +++ b/libbuild2/c/init.hxx @@ -0,0 +1,32 @@ +// file : libbuild2/c/init.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef LIBBUILD2_C_INIT_HXX +#define LIBBUILD2_C_INIT_HXX + +#include +#include + +#include + +#include + +namespace build2 +{ + namespace c + { + // Module `c` does not require bootstrapping. + // + // Submodules: + // + // `c.guess` -- registers and sets some variables. + // `c.config` -- loads c.guess and sets more variables. + // `c` -- loads c.config and registers target types and rules. + // + extern "C" LIBBUILD2_C_SYMEXPORT const module_functions* + build2_c_load (); + } +} + +#endif // LIBBUILD2_C_INIT_HXX diff --git a/libbuild2/c/target.hxx b/libbuild2/c/target.hxx new file mode 100644 index 0000000..b35beab --- /dev/null +++ b/libbuild2/c/target.hxx @@ -0,0 +1,22 @@ +// file : libbuild2/c/target.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef LIBBUILD2_C_TARGET_HXX +#define LIBBUILD2_C_TARGET_HXX + +#include +#include + +#include + +namespace build2 +{ + namespace c + { + using cc::h; + using cc::c; + } +} + +#endif // LIBBUILD2_C_TARGET_HXX diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx index 4e7080a..37bc817 100644 --- a/libbuild2/module.cxx +++ b/libbuild2/module.cxx @@ -39,6 +39,7 @@ namespace build2 static const char* bundled_modules[] = { "bash", "bin", + "c", "cc", "in", "version" diff --git a/tests/libbuild2/buildfile b/tests/libbuild2/buildfile index 1a2d594..1d7faf7 100644 --- a/tests/libbuild2/buildfile +++ b/tests/libbuild2/buildfile @@ -4,7 +4,7 @@ import libs = build2%lib{build2} -for m: bash bin cc in version +for m: bash bin c cc in version import libs += build2%lib{build2-$m} exe{driver}: {hxx cxx}{*} $libs testscript diff --git a/tests/libbuild2/driver.cxx b/tests/libbuild2/driver.cxx index 679b0a4..e17cdc5 100644 --- a/tests/libbuild2/driver.cxx +++ b/tests/libbuild2/driver.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,7 @@ main (int, char* argv[]) bin::build2_bin_load (); cc::build2_cc_load (); + c::build2_c_load (); version::build2_version_load (); in::build2_in_load (); bash::build2_bash_load (); -- cgit v1.1