aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-05-10 23:38:44 -0400
committerGitHub <noreply@github.com>2022-05-10 23:38:44 -0400
commitf5edf78eea403c14635a05e1729672cfb50aca89 (patch)
tree1661a15b3ee4427ce6a4286f4c972be49e9f572c
parent458943e324e81762a9a2aa839d2fa3c851068e6f (diff)
parent45415093c655d30ec226172695248fbf28941667 (diff)
downloadzig-f5edf78eea403c14635a05e1729672cfb50aca89.tar.gz
zig-f5edf78eea403c14635a05e1729672cfb50aca89.zip
Merge pull request #10143 from nuald/single-threaded-cpp1
Normalized C++ compilation options for single-threaded targets
-rw-r--r--src/Compilation.zig13
-rw-r--r--src/libcxx.zig24
-rw-r--r--test/standalone/c_compiler/build.zig2
-rw-r--r--test/standalone/c_compiler/test.c23
-rw-r--r--test/standalone/c_compiler/test.cpp76
5 files changed, 106 insertions, 32 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 9126289804..5e4ab0ec12 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1180,6 +1180,15 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
if (must_single_thread and !single_threaded) {
return error.TargetRequiresSingleThreaded;
}
+ if (!single_threaded and options.link_libcpp) {
+ if (options.target.cpu.arch.isARM()) {
+ log.warn(
+ \\libc++ does not work on multi-threaded ARM yet.
+ \\For more details: https://github.com/ziglang/zig/issues/6573
+ , .{});
+ return error.TargetRequiresSingleThreaded;
+ }
+ }
const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: {
var buf = std.ArrayList(u8).init(arena);
@@ -3803,6 +3812,10 @@ pub fn addCCArgs(
try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");
+
+ if (comp.bin_file.options.single_threaded) {
+ try argv.append("-D_LIBCPP_HAS_NO_THREADS");
+ }
}
if (comp.bin_file.options.link_libunwind) {
diff --git a/src/libcxx.zig b/src/libcxx.zig
index b2974e24c9..a5ab242339 100644
--- a/src/libcxx.zig
+++ b/src/libcxx.zig
@@ -128,6 +128,12 @@ pub fn buildLibCXX(comp: *Compilation) !void {
continue;
if (std.mem.startsWith(u8, cxx_src, "src/support/ibm/") and target.os.tag != .zos)
continue;
+ if (comp.bin_file.options.single_threaded) {
+ if (std.mem.startsWith(u8, cxx_src, "src/support/win32/thread_win32.cpp")) {
+ continue;
+ }
+ try cflags.append("-D_LIBCPP_HAS_NO_THREADS");
+ }
try cflags.append("-DNDEBUG");
try cflags.append("-D_LIBCPP_BUILDING_LIBRARY");
@@ -145,8 +151,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
}
if (target.os.tag == .wasi) {
- // WASI doesn't support thread and exception yet.
- try cflags.append("-D_LIBCPP_HAS_NO_THREADS");
+ // WASI doesn't support exceptions yet.
try cflags.append("-fno-exceptions");
}
@@ -264,13 +269,20 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
var cflags = std.ArrayList([]const u8).init(arena);
if (target.os.tag == .wasi) {
- // WASI doesn't support thread and exception yet.
- if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_thread_atexit.cpp") or
- std.mem.startsWith(u8, cxxabi_src, "src/cxa_exception.cpp") or
+ // WASI doesn't support exceptions yet.
+ if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_exception.cpp") or
std.mem.startsWith(u8, cxxabi_src, "src/cxa_personality.cpp"))
continue;
- try cflags.append("-D_LIBCXXABI_HAS_NO_THREADS");
try cflags.append("-fno-exceptions");
+ }
+
+ // WASM targets are single threaded.
+ if (comp.bin_file.options.single_threaded) {
+ if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_thread_atexit.cpp")) {
+ continue;
+ }
+ try cflags.append("-D_LIBCXXABI_HAS_NO_THREADS");
+ try cflags.append("-D_LIBCPP_HAS_NO_THREADS");
} else {
try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
}
diff --git a/test/standalone/c_compiler/build.zig b/test/standalone/c_compiler/build.zig
index ad500c3eb3..240d535182 100644
--- a/test/standalone/c_compiler/build.zig
+++ b/test/standalone/c_compiler/build.zig
@@ -29,7 +29,7 @@ pub fn build(b: *Builder) void {
exe_cpp.addCSourceFile("test.cpp", &[0][]const u8{});
exe_cpp.setBuildMode(mode);
exe_cpp.setTarget(target);
- exe_cpp.linkSystemLibrary("c++");
+ exe_cpp.linkLibCpp();
switch (target.getOsTag()) {
.windows => {
diff --git a/test/standalone/c_compiler/test.c b/test/standalone/c_compiler/test.c
index 842a63fc67..da0a137798 100644
--- a/test/standalone/c_compiler/test.c
+++ b/test/standalone/c_compiler/test.c
@@ -1,25 +1,28 @@
#include <assert.h>
#include <stdio.h>
+#include <stdlib.h>
-typedef struct {
- int val;
+typedef struct {
+ int val;
} STest;
int getVal(STest* data) { return data->val; }
int main (int argc, char *argv[])
{
- STest* data = (STest*)malloc(sizeof(STest));
- data->val = 123;
+ STest* data = (STest*)malloc(sizeof(STest));
+ data->val = 123;
- assert(getVal(data) != 456);
- int ok = (getVal(data) == 123);
+ assert(getVal(data) != 456);
+ int ok = (getVal(data) == 123);
- if (argc>1) fprintf(stdout, "val=%d\n", data->val);
+ if (argc > 1) {
+ fprintf(stdout, "val=%d\n", data->val);
+ }
- free(data);
+ free(data);
- if (!ok) abort();
+ if (!ok) abort();
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/test/standalone/c_compiler/test.cpp b/test/standalone/c_compiler/test.cpp
index 8c533d02cc..1f3fe173d2 100644
--- a/test/standalone/c_compiler/test.cpp
+++ b/test/standalone/c_compiler/test.cpp
@@ -1,33 +1,79 @@
-#include <iostream>
#include <cassert>
+#include <iostream>
+
+#ifndef _LIBCPP_HAS_NO_THREADS
+#include <future>
+#endif
+
+thread_local unsigned int tls_counter = 1;
+
+// a non-optimized way of checking for prime numbers:
+bool is_prime(int x) {
+ for (int i = 2; i <x ; ++i) {
+ if (x % i == 0) {
+ return false;
+ }
+ }
+ return true;
+}
class CTest {
public:
- CTest(int val) : m_val(val) {};
- virtual ~CTest() {}
+ CTest(int val) : m_val(val) {
+ tls_counter++;
+ };
+ virtual ~CTest() {}
- virtual int getVal() const { return m_val; }
- virtual void printVal() { std::cout << "val=" << m_val << std::endl; }
+ virtual int getVal() const { return m_val; }
+ virtual void printVal() { std::cout << "val=" << m_val << std::endl; }
private:
- int m_val;
+ int m_val;
+};
+
+class GlobalConstructorTest {
+public:
+ GlobalConstructorTest(int val) : m_val(val) {};
+ virtual ~GlobalConstructorTest() {}
+
+ virtual int getVal() const { return m_val; }
+ virtual void printVal() { std::cout << "val=" << m_val << std::endl; }
+private:
+ int m_val;
};
volatile int runtime_val = 456;
-CTest global(runtime_val); // test if global initializers are called.
+GlobalConstructorTest global(runtime_val); // test if global initializers are called.
int main (int argc, char *argv[])
{
- assert(global.getVal() == 456);
+ assert(global.getVal() == 456);
+
+ auto t = std::make_unique<CTest>(123);
+ assert(t->getVal() != 456);
+ assert(tls_counter == 2);
+ if (argc > 1) {
+ t->printVal();
+ }
+ bool ok = t->getVal() == 123;
- auto* t = new CTest(123);
- assert(t->getVal()!=456);
+ if (!ok) abort();
- if (argc>1) t->printVal();
- bool ok = t->getVal() == 123;
- delete t;
+#ifndef _LIBCPP_HAS_NO_THREADS
+ std::future<bool> fut = std::async(is_prime, 313);
+ bool ret = fut.get();
+ assert(ret);
+#endif
- if (!ok) abort();
+#if !defined(__wasm__) && !defined(__APPLE__)
+ // WASM and macOS are not passing this yet.
+ // TODO file an issue for this and link it here.
+ try {
+ throw 20;
+ } catch (int e) {
+ assert(e == 20);
+ }
+#endif
- return 0;
+ return EXIT_SUCCESS;
}