aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-06-22 13:24:59 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-06-22 13:24:59 +0200
commit9a00b8ccfef1d13088be2d76fefcb320c269732a (patch)
tree40a7efc0bc0116cbbf035310b9341d83a0793a07
parente52f8358ce533742a0357fabebd96fb7f5b2609a (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.cxx1
-rw-r--r--build2/cc/common.hxx5
-rw-r--r--build2/cc/compile.cxx26
-rw-r--r--build2/cc/compile.hxx3
-rw-r--r--build2/cxx/init.cxx11
-rw-r--r--tests/cc/modules/testscript32
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