diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-06-22 13:24:59 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-06-22 13:24:59 +0200 |
commit | 9a00b8ccfef1d13088be2d76fefcb320c269732a (patch) | |
tree | 40a7efc0bc0116cbbf035310b9341d83a0793a07 | |
parent | e52f8358ce533742a0357fabebd96fb7f5b2609a (diff) |
Add extra support for symbol exporting in modularized projects
Since modules don't see each other's macros, we can use a single, keyword-
like macro for dll-exporting that is managed by the build system (so no
need for an "export" header). For example:
cxx.features.symexport = true
export __symexport void f ();
-rw-r--r-- | build2/c/init.cxx | 1 | ||||
-rw-r--r-- | build2/cc/common.hxx | 5 | ||||
-rw-r--r-- | build2/cc/compile.cxx | 26 | ||||
-rw-r--r-- | build2/cc/compile.hxx | 3 | ||||
-rw-r--r-- | build2/cxx/init.cxx | 11 | ||||
-rw-r--r-- | tests/cc/modules/testscript | 32 |
6 files changed, 74 insertions, 4 deletions
diff --git a/build2/c/init.cxx b/build2/c/init.cxx index 3461086..159c0b8 100644 --- a/build2/c/init.cxx +++ b/build2/c/init.cxx @@ -264,6 +264,7 @@ namespace build2 cm.tstd, false, // No C modules yet. + false, // No __symexport support since no modules. cast_null<process_path> (rs["pkgconfig.path"]), cast<dir_paths> (rs[cm.x_sys_lib_dirs]), diff --git a/build2/cc/common.hxx b/build2/cc/common.hxx index 24262b7..abeadfc 100644 --- a/build2/cc/common.hxx +++ b/build2/cc/common.hxx @@ -115,7 +115,8 @@ namespace build2 const strings& tstd; // Translated x_std value (options). - bool modules; // x.feaures.modules + bool modules; // x.features.modules + bool symexport; // x.features.symexport const process_path* pkgconfig; // pkgconfig.path (can be NULL). const dir_paths& sys_lib_dirs; // x.sys_lib_dirs @@ -159,6 +160,7 @@ namespace build2 const target_triplet& tg, const strings& std, bool fm, + bool fs, const process_path* pkgc, const dir_paths& sld, const dir_paths& sid, @@ -175,6 +177,7 @@ namespace build2 ctg (tg), tsys (ctg.system), tclass (ctg.class_), tstd (std), modules (fm), + symexport (fs), pkgconfig (pkgc), sys_lib_dirs (sld), sys_inc_dirs (sid), x_src (src), x_mod (mod), x_hdr (hdr), x_inc (inc) {} }; diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index dc669ce..eddd465 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -196,6 +196,18 @@ namespace build2 return nullptr; } + inline void compile:: + append_symexport_options (cstrings& args, const target& t) const + { + // With VC if a BMI is compiled with dllexport, then when such BMI is + // imported, it is auto-magically treated as dllimport. Let's hope + // other compilers follow suit. + // + args.push_back (t.is_a<bmis> () && tclass == "windows" + ? "-D__symexport=__declspec(dllexport)" + : "-D__symexport="); + } + match_result compile:: match (action act, target& t, const string&) const { @@ -683,10 +695,11 @@ namespace build2 // sha256 cs; - // This affects how we compile the source as well as the format of - // depdb so factor it in. + // These flags affect how we compile the source and/or the format of + // depdb so factor them in. // cs.append (&md.pp, sizeof (md.pp)); + cs.append (&symexport, sizeof (symexport)); if (md.pp != preprocessed::all) { @@ -1392,6 +1405,9 @@ namespace build2 args.push_back (d.string ().c_str ()); } + if (symexport && md.mod) + append_symexport_options (args, t); + // Some compile options (e.g., -std, -m) affect the preprocessor. // // Currently Clang supports importing "header modules" even when in @@ -2272,6 +2288,9 @@ namespace build2 args.push_back (d.string ().c_str ()); } + if (symexport && md.mod) + append_symexport_options (args, t); + append_options (args, t, c_coptions); append_options (args, t, x_coptions); append_options (args, tstd, @@ -3108,6 +3127,9 @@ namespace build2 args.push_back ("-I"); args.push_back (d.string ().c_str ()); } + + if (symexport && md.mod) + append_symexport_options (args, t); } append_options (args, t, c_coptions); diff --git a/build2/cc/compile.hxx b/build2/cc/compile.hxx index be4a2e2..ed9c18d 100644 --- a/build2/cc/compile.hxx +++ b/build2/cc/compile.hxx @@ -123,6 +123,9 @@ namespace build2 const char* langopt (const match_data&) const; + void + append_symexport_options (cstrings&, const target&) const; + private: const string rule_id; }; diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx index 2c59f2c..53ee2d2 100644 --- a/build2/cxx/init.cxx +++ b/build2/cxx/init.cxx @@ -55,8 +55,8 @@ namespace build2 return var_pool.rw (rs).insert<bool> (v, variable_visibility::project); }; - bool modules (false); auto& v_m (enter ("cxx.features.modules")); //bool concepts (false); auto& v_c (enter ("cxx.features.concepts")); + bool modules (false); auto& v_m (enter ("cxx.features.modules")); // Translate "latest" and "experimental" to the compiler/version- // appropriate option(s). @@ -429,8 +429,16 @@ namespace build2 if (!cast_false<bool> (rs["cxx.config.loaded"])) load_module (rs, rs, "cxx.config", loc, false, hints); + auto& vp (var_pool.rw (rs)); + bool modules (cast<bool> (rs["cxx.features.modules"])); + bool symexport ( + modules && + cast_false<bool> ( + rs[vp.insert<bool> ("cxx.features.symexport", + variable_visibility::project)])); + config_module& cm (*rs.modules.lookup<config_module> ("cxx.config")); cc::data d { @@ -451,6 +459,7 @@ namespace build2 cm.tstd, modules, + symexport, cast_null<process_path> (rs["pkgconfig.path"]), cast<dir_paths> (rs[cm.x_sys_lib_dirs]), diff --git a/tests/cc/modules/testscript b/tests/cc/modules/testscript index 23f8946..a65bdac 100644 --- a/tests/cc/modules/testscript +++ b/tests/cc/modules/testscript @@ -14,6 +14,8 @@ EOI +cat <<EOI >=build/root.build cxx.std = experimental +cxx.features.symexport = true + # Force modules. # cxx.features.modules = true @@ -313,3 +315,33 @@ $* test clean <<EOI exe{test}: cxx{driver} {mxx cxx}{core} bmie{foo-core}: mxx{foo-core} EOI + +: symexport +: +: Test the __symexport feature. +: +cat <<EOI >=core.mxx; + #if __cpp_modules >= 201704 + export + #endif + module foo.core; + + export __symexport int f (int); + + __symexport int g_impl (int i) {return i - 1;} + export __symexport inline int g (int i) {return g_impl (i);} + EOI +ln -s ../core.cxx core-f.cxx; +cat <<EOI >=core-g.cxx; + module foo.core; + int g_impl (int i) {return i - 1;} + EOI +cat <<EOI >=driver.cxx; + import foo.core; + int main (int argc, char*[]) {return f (argc) + g (argc);} + EOI +$* test clean <<EOI + ./: lib{foo} exe{test} # Full build. + exe{test}: cxx{driver} lib{foo} + lib{foo}: mxx{core} cxx{core-f} # core-g @@ VC + EOI |