From 9fa5f73d00905568e8979d0c93ec4a8f645c81d5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 9 Aug 2016 11:31:53 +0200 Subject: Implement support for C compilation We now have two new modules: cc (c-common) and c. --- build2/c/init | 37 +++++++++ build2/c/init.cxx | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ build2/c/target | 22 +++++ 3 files changed, 299 insertions(+) create mode 100644 build2/c/init create mode 100644 build2/c/init.cxx create mode 100644 build2/c/target (limited to 'build2/c') diff --git a/build2/c/init b/build2/c/init new file mode 100644 index 0000000..04f193e --- /dev/null +++ b/build2/c/init @@ -0,0 +1,37 @@ +// file : build2/c/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_C_INIT +#define BUILD2_C_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace c + { + 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 diff --git a/build2/c/init.cxx b/build2/c/init.cxx new file mode 100644 index 0000000..7795181 --- /dev/null +++ b/build2/c/init.cxx @@ -0,0 +1,240 @@ +// file : build2/c/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include + +#include + +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace c + { + using cc::config_module; + + class module: public cc::module + { + public: + explicit + module (data&& d): common (move (d)), cc::module (move (d)) {} + + bool + translate_std (string&, scope&, const value&) const override; + }; + + bool module:: + translate_std (string& s, scope& r, const value& val) const + { + const string& v (cast (val)); + + if (cid == "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. + // + if (v != "90") + { + uint64_t cver (cast (r[x_version_major])); + + if ((v == "99" && cver < 16) || // Since VS2010/10.0. + (v == "11" && cver < 17)) // Since VS2012/11.0. + { + fail << "C" << v << " is not supported by " + << cast (r[x_signature]) << + info << "required by " << project (r) << '@' << r.out_path (); + } + } + + return false; + } + else + { + // 90 and 89 are the same standard. Translate 99 to 9x and 11 to 1x + // for compatibility with older versions of the compilers. + // + s = "-std="; + + if (v == "90") + s += "c90"; + else if (v == "99") + s += "c9x"; + else if (v == "11") + s += "c1x"; + else + s += v; // In case the user specifies something like 'gnu11'. + + return true; + } + } + + bool + config_init (scope& r, + scope& b, + const location& loc, + unique_ptr& m, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("c::config_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + if (first) + { + // Load cc.vars so that we can cache all the cc.* variables. + // + if (!cast_false (b["cc.vars.loaded"])) + load_module ("cc.vars", r, b, loc); + + // Enter all the variables and initialize the module data. + // + auto& v (var_pool); + + cc::config_data d { + cc::lang::c, + + "c", + "c", + "gcc", + + // Note: some overridable, some not. + // + v.insert ("config.c", true), + v.insert ("config.c.poptions", true), + v.insert ("config.c.coptions", true), + v.insert ("config.c.loptions", true), + v.insert ("config.c.libs", true), + + v.insert ("c.poptions"), + v.insert ("c.coptions"), + v.insert ("c.loptions"), + v.insert ("c.libs"), + + v["cc.poptions"], + v["cc.coptions"], + v["cc.loptions"], + 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 ("c.std", true), + + v.insert ("c.id"), + v.insert ("c.id.type"), + v.insert ("c.id.variant"), + + 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.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") + }; + + assert (m == nullptr); + m.reset (new config_module (move (d))); + } + + static_cast (*m).init (r, b, loc, first, hints); + return true; + } + + static const target_type* hdr[] = + { + &h::static_type, + nullptr + }; + + static const target_type* inc[] = + { + &h::static_type, + &c::static_type, + nullptr + }; + + bool + init (scope& r, + scope& b, + const location& loc, + unique_ptr& m, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("c::init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Load c.config. + // + if (!cast_false (b["c.config.loaded"])) + load_module ("c.config", r, b, loc, false, hints); + + if (first) + { + config_module& cm (*r.modules.lookup ("c.config")); + + cc::data d { + cm, + + "c.compile", + "c.link", + "c.install", + + cast (r[cm.x_id]), + cast (r[cm.x_target]), + cast (r[cm.x_target_system]), + cast (r[cm.x_target_class]), + + c::static_type, + hdr, + inc + }; + + assert (m == nullptr); + m.reset (new module (move (d))); + } + + static_cast (*m).init (r, b, loc, first, hints); + return true; + } + } +} diff --git a/build2/c/target b/build2/c/target new file mode 100644 index 0000000..bf40306 --- /dev/null +++ b/build2/c/target @@ -0,0 +1,22 @@ +// file : build2/c/target -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_C_TARGET +#define BUILD2_C_TARGET + +#include +#include + +#include + +namespace build2 +{ + namespace c + { + using cc::h; + using cc::c; + } +} + +#endif // BUILD2_C_TARGET -- cgit v1.1