Merge pull request #10143 from nuald/single-threaded-cpp1

Normalized C++ compilation options for single-threaded targets
This commit is contained in:
Andrew Kelley 2022-05-10 23:38:44 -04:00 committed by GitHub
commit f5edf78eea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 32 deletions

View File

@ -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) {

View File

@ -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");
}

View File

@ -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 => {

View File

@ -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;
}

View File

@ -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 = new CTest(123);
assert(t->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;
if (argc>1) t->printVal();
bool ok = t->getVal() == 123;
delete t;
if (!ok) abort();
if (!ok) abort();
#ifndef _LIBCPP_HAS_NO_THREADS
std::future<bool> fut = std::async(is_prime, 313);
bool ret = fut.get();
assert(ret);
#endif
return 0;
#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 EXIT_SUCCESS;
}