aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-03-27 22:35:13 -0400
committerGitHub <noreply@github.com>2020-03-27 22:35:13 -0400
commit107b5196f65c4e77c6c61ff830d6eb7de8b8842b (patch)
tree1993c71221ff70dc6abacb3c360b03909fd5ca89 /src
parent33819ecfbcde6a96262c4ec5cb38e3228ead83c7 (diff)
parenta25874108470f97c5c58d72b2df49a9085c79b2e (diff)
downloadzig-107b5196f65c4e77c6c61ff830d6eb7de8b8842b.tar.gz
zig-107b5196f65c4e77c6c61ff830d6eb7de8b8842b.zip
Merge pull request #4827 from ziglang/zig-cpp
support compiling and linking c++ code
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp3
-rw-r--r--src/analyze.cpp6
-rw-r--r--src/analyze.hpp1
-rw-r--r--src/codegen.cpp37
-rw-r--r--src/error.cpp1
-rw-r--r--src/install_files.h63
-rw-r--r--src/link.cpp164
-rw-r--r--src/main.cpp36
-rw-r--r--src/stage2.h7
-rw-r--r--src/target.cpp7
-rw-r--r--src/target.hpp1
11 files changed, 320 insertions, 6 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index b2abd17f99..6c7b465025 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2019,6 +2019,7 @@ struct CodeGen {
ZigLLVMDICompileUnit *compile_unit;
ZigLLVMDIFile *compile_unit_file;
LinkLib *libc_link_lib;
+ LinkLib *libcpp_link_lib;
LLVMTargetDataRef target_data_ref;
LLVMTargetMachineRef target_machine;
ZigLLVMDIFile *dummy_di_file;
@@ -2261,6 +2262,8 @@ struct CodeGen {
bool emit_asm;
bool emit_llvm_ir;
bool test_is_evented;
+ bool cpp_rtti;
+ bool cpp_exceptions;
CodeModel code_model;
Buf *root_out_name;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 77d3f33331..df7bcdf9de 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -7756,10 +7756,14 @@ LinkLib *create_link_lib(Buf *name) {
LinkLib *add_link_lib(CodeGen *g, Buf *name) {
bool is_libc = buf_eql_str(name, "c");
+ bool is_libcpp = buf_eql_str(name, "c++") || buf_eql_str(name, "c++abi");
if (is_libc && g->libc_link_lib != nullptr)
return g->libc_link_lib;
+ if (is_libcpp && g->libcpp_link_lib != nullptr)
+ return g->libcpp_link_lib;
+
for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
LinkLib *existing_lib = g->link_libs_list.at(i);
if (buf_eql_buf(existing_lib->name, name)) {
@@ -7772,6 +7776,8 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
if (is_libc)
g->libc_link_lib = link_lib;
+ if (is_libcpp)
+ g->libcpp_link_lib = link_lib;
return link_lib;
}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index a7828663b0..ee069427bd 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -260,6 +260,7 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
enum CSourceKind {
CSourceKindAsm,
CSourceKindC,
+ CSourceKindCpp,
};
void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c,
diff --git a/src/codegen.cpp b/src/codegen.cpp
index cb1ab6b6b8..f02253fb1a 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8448,6 +8448,8 @@ static bool detect_dynamic_link(CodeGen *g) {
LinkLib *link_lib = g->link_libs_list.at(i);
if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name)))
continue;
+ if (target_is_libcpp_lib_name(g->zig_target, buf_ptr(link_lib->name)))
+ continue;
return true;
}
return false;
@@ -8700,6 +8702,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
+ buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->libcpp_link_lib != nullptr));
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
@@ -8781,6 +8784,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_bool(&cache_hash, g->is_test_build);
cache_bool(&cache_hash, g->is_single_threaded);
cache_bool(&cache_hash, g->test_is_evented);
+ cache_bool(&cache_hash, g->cpp_rtti);
+ cache_bool(&cache_hash, g->cpp_exceptions);
cache_int(&cache_hash, g->code_model);
cache_int(&cache_hash, g->zig_target->is_native_os);
cache_int(&cache_hash, g->zig_target->is_native_cpu);
@@ -8798,6 +8803,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
}
cache_bool(&cache_hash, g->have_err_ret_tracing);
cache_bool(&cache_hash, g->libc_link_lib != nullptr);
+ cache_bool(&cache_hash, g->libcpp_link_lib != nullptr);
cache_bool(&cache_hash, g->valgrind_support);
cache_bool(&cache_hash, g->link_eh_frame_hdr);
cache_int(&cache_hash, detect_subsystem(g));
@@ -9179,7 +9185,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
}
if (translate_c) {
- if (source_kind == CSourceKindC) {
+ if (source_kind != CSourceKindAsm) {
// this gives us access to preprocessing entities, presumably at
// the cost of performance
args.append("-Xclang");
@@ -9205,6 +9211,20 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
args.append(g->framework_dirs.at(i));
}
+ if (g->libcpp_link_lib != nullptr) {
+ const char *libcxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
+ buf_ptr(g->zig_lib_dir)));
+
+ args.append("-isystem");
+ args.append(libcxx_include_path);
+
+ if (target_abi_is_musl(g->zig_target->abi)) {
+ args.append("-D_LIBCPP_HAS_MUSL_LIBC");
+ }
+ args.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
+ args.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+ }
+
// According to Rich Felker libc headers are supposed to go before C language headers.
// However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
// and other compiler specific items.
@@ -9222,6 +9242,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
switch (source_kind) {
case CSourceKindC:
+ case CSourceKindCpp:
if (g->zig_target->llvm_cpu_name != nullptr) {
args.append("-Xclang");
args.append("-target-cpu");
@@ -9238,6 +9259,14 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
case CSourceKindAsm:
break;
}
+ if (source_kind == CSourceKindCpp) {
+ if (!g->cpp_rtti) {
+ args.append("-fno-rtti");
+ }
+ if (!g->cpp_exceptions) {
+ args.append("-fno-exceptions");
+ }
+ }
for (size_t i = 0; i < g->zig_target->llvm_cpu_features_asm_len; i += 1) {
args.append(g->zig_target->llvm_cpu_features_asm_ptr[i]);
}
@@ -9685,6 +9714,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
cache_bool(cache_hash, g->have_sanitize_c);
cache_bool(cache_hash, want_valgrind_support(g));
cache_bool(cache_hash, g->function_sections);
+ cache_bool(cache_hash, g->cpp_rtti);
+ cache_bool(cache_hash, g->cpp_exceptions);
cache_int(cache_hash, g->code_model);
for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
@@ -10519,6 +10550,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->emit_bin);
cache_bool(ch, g->emit_llvm_ir);
cache_bool(ch, g->emit_asm);
+ cache_bool(ch, g->cpp_rtti);
+ cache_bool(ch, g->cpp_exceptions);
cache_usize(ch, g->version_major);
cache_usize(ch, g->version_minor);
cache_usize(ch, g->version_patch);
@@ -10823,6 +10856,8 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_global_cache_dir(), false, child_progress_node);
child_gen->root_out_name = buf_create_from_str(name);
child_gen->disable_gen_h = true;
+ child_gen->cpp_rtti = parent_gen->cpp_rtti;
+ child_gen->cpp_exceptions = parent_gen->cpp_exceptions;
child_gen->want_stack_check = WantStackCheckDisabled;
child_gen->want_sanitize_c = WantCSanitizeDisabled;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
diff --git a/src/error.cpp b/src/error.cpp
index c246ea5f31..76b510ecf3 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -84,6 +84,7 @@ const char *err_str(Error err) {
case ErrorInvalidAbiVersion: return "invalid C ABI version";
case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";
case ErrorUnknownClangOption: return "unknown Clang option";
+ case ErrorNestedResponseFile: return "nested response file";
}
return "(invalid error)";
}
diff --git a/src/install_files.h b/src/install_files.h
index 8c81a3fc80..8e7431145e 100644
--- a/src/install_files.h
+++ b/src/install_files.h
@@ -1841,4 +1841,67 @@ static const char *ZIG_MUSL_COMPAT_TIME32_FILES[] = {
"musl/compat/time32/wait3_time32.c",
"musl/compat/time32/wait4_time32.c",
};
+static const char *ZIG_LIBCXXABI_FILES[] = {
+"src/abort_message.cpp",
+"src/cxa_aux_runtime.cpp",
+"src/cxa_default_handlers.cpp",
+"src/cxa_demangle.cpp",
+"src/cxa_exception.cpp",
+"src/cxa_exception_storage.cpp",
+"src/cxa_guard.cpp",
+"src/cxa_handlers.cpp",
+"src/cxa_noexception.cpp",
+"src/cxa_personality.cpp",
+"src/cxa_thread_atexit.cpp",
+"src/cxa_unexpected.cpp",
+"src/cxa_vector.cpp",
+"src/cxa_virtual.cpp",
+"src/fallback_malloc.cpp",
+"src/private_typeinfo.cpp",
+"src/stdlib_exception.cpp",
+"src/stdlib_stdexcept.cpp",
+"src/stdlib_typeinfo.cpp",
+};
+static const char *ZIG_LIBCXX_FILES[] = {
+"src/algorithm.cpp",
+"src/any.cpp",
+"src/bind.cpp",
+"src/charconv.cpp",
+"src/chrono.cpp",
+"src/condition_variable.cpp",
+"src/condition_variable_destructor.cpp",
+"src/debug.cpp",
+"src/exception.cpp",
+"src/experimental/memory_resource.cpp",
+"src/filesystem/directory_iterator.cpp",
+"src/filesystem/operations.cpp",
+"src/functional.cpp",
+"src/future.cpp",
+"src/hash.cpp",
+"src/ios.cpp",
+"src/iostream.cpp",
+"src/locale.cpp",
+"src/memory.cpp",
+"src/mutex.cpp",
+"src/mutex_destructor.cpp",
+"src/new.cpp",
+"src/optional.cpp",
+"src/random.cpp",
+"src/regex.cpp",
+"src/shared_mutex.cpp",
+"src/stdexcept.cpp",
+"src/string.cpp",
+"src/strstream.cpp",
+"src/support/solaris/xlocale.cpp",
+"src/support/win32/locale_win32.cpp",
+"src/support/win32/support.cpp",
+"src/support/win32/thread_win32.cpp",
+"src/system_error.cpp",
+"src/thread.cpp",
+"src/typeinfo.cpp",
+"src/utility.cpp",
+"src/valarray.cpp",
+"src/variant.cpp",
+"src/vector.cpp",
+};
#endif
diff --git a/src/link.cpp b/src/link.cpp
index 25b913be21..d9b784129d 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -14,6 +14,8 @@
#include "glibc.hpp"
static const char *msvcrt_common_src[] = {
+ "misc" OS_SEP "_create_locale.c",
+ "misc" OS_SEP "_free_locale.c",
"misc" OS_SEP "onexit_table.c",
"misc" OS_SEP "register_tls_atexit.c",
"stdio" OS_SEP "acrt_iob_func.c",
@@ -632,12 +634,17 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress
}
c_file->args.append("-I");
c_file->args.append(path_from_libunwind(parent, "include"));
- c_file->args.append("-fPIC");
+ if (target_supports_fpic(parent->zig_target)) {
+ c_file->args.append("-fPIC");
+ }
c_file->args.append("-D_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS");
c_file->args.append("-Wa,--noexecstack");
- if (parent->zig_target->is_native_os && parent->zig_target->is_native_cpu) {
- c_file->args.append("-D_LIBUNWIND_IS_NATIVE_ONLY");
- }
+
+ // This is intentionally always defined because the macro definition means, should it only
+ // build for the target specified by compiler defines. Since we pass -target the compiler
+ // defines will be correct.
+ c_file->args.append("-D_LIBUNWIND_IS_NATIVE_ONLY");
+
if (parent->build_mode == BuildModeDebug) {
c_file->args.append("-D_DEBUG");
}
@@ -1107,6 +1114,128 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node
return buf_ptr(&child_gen->bin_file_output_path);
}
+static const char *build_libcxxabi(CodeGen *parent, Stage2ProgressNode *progress_node) {
+ CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c++abi", progress_node);
+ codegen_add_link_lib(child_gen, buf_create_from_str("c"));
+
+ ZigList<CFile *> c_source_files = {0};
+
+ const char *cxxabi_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "include",
+ buf_ptr(parent->zig_lib_dir)));
+ const char *cxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
+ buf_ptr(parent->zig_lib_dir)));
+
+ for (size_t i = 0; i < array_length(ZIG_LIBCXXABI_FILES); i += 1) {
+ const char *rel_src_path = ZIG_LIBCXXABI_FILES[i];
+
+ CFile *c_file = heap::c_allocator.create<CFile>();
+ c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "%s",
+ buf_ptr(parent->zig_lib_dir), rel_src_path));
+
+ c_file->args.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
+ c_file->args.append("-D_LIBCPP_DISABLE_EXTERN_TEMPLATE");
+ c_file->args.append("-D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS");
+ c_file->args.append("-D_LIBCXXABI_BUILDING_LIBRARY");
+ c_file->args.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+ c_file->args.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
+
+ if (target_abi_is_musl(parent->zig_target->abi)) {
+ c_file->args.append("-D_LIBCPP_HAS_MUSL_LIBC");
+ }
+
+ c_file->args.append("-I");
+ c_file->args.append(cxxabi_include_path);
+
+ c_file->args.append("-I");
+ c_file->args.append(cxx_include_path);
+
+ c_file->args.append("-O3");
+ c_file->args.append("-DNDEBUG");
+ if (target_supports_fpic(parent->zig_target)) {
+ c_file->args.append("-fPIC");
+ }
+ c_file->args.append("-nostdinc++");
+ c_file->args.append("-fstrict-aliasing");
+ c_file->args.append("-funwind-tables");
+ c_file->args.append("-D_DEBUG");
+ c_file->args.append("-UNDEBUG");
+ c_file->args.append("-std=c++11");
+
+ c_source_files.append(c_file);
+ }
+
+
+ child_gen->c_source_files = c_source_files;
+ codegen_build_and_link(child_gen);
+ return buf_ptr(&child_gen->bin_file_output_path);
+}
+
+static const char *build_libcxx(CodeGen *parent, Stage2ProgressNode *progress_node) {
+ CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c++", progress_node);
+ codegen_add_link_lib(child_gen, buf_create_from_str("c"));
+
+ ZigList<CFile *> c_source_files = {0};
+
+ const char *cxxabi_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "include",
+ buf_ptr(parent->zig_lib_dir)));
+ const char *cxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
+ buf_ptr(parent->zig_lib_dir)));
+
+ for (size_t i = 0; i < array_length(ZIG_LIBCXX_FILES); i += 1) {
+ const char *rel_src_path = ZIG_LIBCXX_FILES[i];
+
+ Buf *src_path_buf = buf_create_from_str(rel_src_path);
+ if (parent->zig_target->os == OsWindows) {
+ // filesystem stuff isn't supported on Windows
+ if (buf_starts_with_str(src_path_buf, "src/filesystem/")) {
+ continue;
+ }
+ } else {
+ if (buf_starts_with_str(src_path_buf, "src/support/win32/")) {
+ continue;
+ }
+ }
+
+ CFile *c_file = heap::c_allocator.create<CFile>();
+ c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "%s",
+ buf_ptr(parent->zig_lib_dir), rel_src_path));
+
+ c_file->args.append("-DNDEBUG");
+ c_file->args.append("-D_LIBCPP_BUILDING_LIBRARY");
+ c_file->args.append("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER");
+ c_file->args.append("-DLIBCXX_BUILDING_LIBCXXABI");
+ c_file->args.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+ c_file->args.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
+
+ if (target_abi_is_musl(parent->zig_target->abi)) {
+ c_file->args.append("-D_LIBCPP_HAS_MUSL_LIBC");
+ }
+
+ c_file->args.append("-I");
+ c_file->args.append(cxx_include_path);
+
+ c_file->args.append("-I");
+ c_file->args.append(cxxabi_include_path);
+
+ c_file->args.append("-O3");
+ c_file->args.append("-DNDEBUG");
+ if (target_supports_fpic(parent->zig_target)) {
+ c_file->args.append("-fPIC");
+ }
+ c_file->args.append("-nostdinc++");
+ c_file->args.append("-fvisibility-inlines-hidden");
+ c_file->args.append("-std=c++14");
+ c_file->args.append("-Wno-user-defined-literals");
+
+ c_source_files.append(c_file);
+ }
+
+
+ child_gen->c_source_files = c_source_files;
+ codegen_build_and_link(child_gen);
+ return buf_ptr(&child_gen->bin_file_output_path);
+}
+
static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) {
CFile *c_file = heap::c_allocator.create<CFile>();
c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s",
@@ -1770,6 +1899,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
// libc is linked specially
continue;
}
+ if (buf_eql_str(link_lib->name, "c++") || buf_eql_str(link_lib->name, "c++abi")) {
+ // libc++ is linked specially
+ continue;
+ }
if (g->libc == nullptr && target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
// these libraries are always linked below when targeting glibc
continue;
@@ -1785,6 +1918,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append(buf_ptr(arg));
}
+ // libc++ dep
+ if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
+ lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
+ lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
+ }
// libc dep
if (g->libc_link_lib != nullptr && g->out_type != OutTypeObj) {
@@ -1815,6 +1953,8 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append(build_libunwind(g, lj->build_dep_prog_node));
}
lj->args.append(build_musl(g, lj->build_dep_prog_node));
+ } else if (g->libcpp_link_lib != nullptr) {
+ lj->args.append(build_libunwind(g, lj->build_dep_prog_node));
} else {
zig_unreachable();
}
@@ -2303,6 +2443,13 @@ static void construct_linker_job_coff(LinkJob *lj) {
break;
}
+ // libc++ dep
+ if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
+ lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
+ lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
+ lj->args.append(build_libunwind(g, lj->build_dep_prog_node));
+ }
+
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node);
@@ -2319,6 +2466,9 @@ static void construct_linker_job_coff(LinkJob *lj) {
if (buf_eql_str(link_lib->name, "c")) {
continue;
}
+ if (buf_eql_str(link_lib->name, "c++") || buf_eql_str(link_lib->name, "c++abi")) {
+ continue;
+ }
bool is_sys_lib = is_mingw_link_lib(link_lib->name);
if (have_windows_dll_import_libs && is_sys_lib) {
continue;
@@ -2454,6 +2604,12 @@ static void construct_linker_job_macho(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
+ // libc++ dep
+ if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
+ lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
+ lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
+ }
+
// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
if (g->out_type == OutTypeExe || is_dyn_lib) {
Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);
diff --git a/src/main.cpp b/src/main.cpp
index a543b43579..d2936c3b52 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -412,6 +412,7 @@ static int main0(int argc, char **argv) {
ZigList<const char *> framework_dirs = {0};
ZigList<const char *> frameworks = {0};
bool have_libc = false;
+ bool have_libcpp = false;
const char *target_string = nullptr;
bool rdynamic = false;
const char *linker_script = nullptr;
@@ -456,6 +457,9 @@ static int main0(int argc, char **argv) {
const char *override_soname = nullptr;
bool only_preprocess = false;
bool ensure_libc_on_non_freestanding = false;
+ bool ensure_libcpp_on_non_freestanding = false;
+ bool cpp_rtti = true;
+ bool cpp_exceptions = true;
ZigList<const char *> llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
@@ -580,10 +584,11 @@ static int main0(int argc, char **argv) {
return (term.how == TerminationIdClean) ? term.code : -1;
} else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
return stage2_fmt(argc, argv);
- } else if (argc >= 2 && strcmp(argv[1], "cc") == 0) {
+ } else if (argc >= 2 && (strcmp(argv[1], "cc") == 0 || strcmp(argv[1], "c++") == 0)) {
emit_h = false;
strip = true;
ensure_libc_on_non_freestanding = true;
+ ensure_libcpp_on_non_freestanding = (strcmp(argv[1], "c++") == 0);
bool c_arg = false;
Stage2ClangArgIterator it;
@@ -632,6 +637,8 @@ static int main0(int argc, char **argv) {
case Stage2ClangArgL: // -l
if (strcmp(it.only_arg, "c") == 0)
have_libc = true;
+ if (strcmp(it.only_arg, "c++") == 0)
+ have_libcpp = true;
link_libs.append(it.only_arg);
break;
case Stage2ClangArgIgnore:
@@ -648,6 +655,9 @@ static int main0(int argc, char **argv) {
case Stage2ClangArgNoStdLib:
ensure_libc_on_non_freestanding = false;
break;
+ case Stage2ClangArgNoStdLibCpp:
+ ensure_libcpp_on_non_freestanding = false;
+ break;
case Stage2ClangArgShared:
is_dynamic = true;
is_shared_lib = true;
@@ -712,6 +722,18 @@ static int main0(int argc, char **argv) {
verbose_cc = true;
verbose_link = true;
break;
+ case Stage2ClangArgExceptions:
+ cpp_exceptions = true;
+ break;
+ case Stage2ClangArgNoExceptions:
+ cpp_exceptions = false;
+ break;
+ case Stage2ClangArgRtti:
+ cpp_rtti = true;
+ break;
+ case Stage2ClangArgNoRtti:
+ cpp_rtti = false;
+ break;
}
}
// Parse linker args
@@ -916,6 +938,8 @@ static int main0(int argc, char **argv) {
const char *l = &arg[2];
if (strcmp(l, "c") == 0)
have_libc = true;
+ if (strcmp(l, "c++") == 0)
+ have_libcpp = true;
link_libs.append(l);
} else if (arg[1] == 'I' && arg[2] != 0) {
clang_argv.append("-I");
@@ -1057,6 +1081,8 @@ static int main0(int argc, char **argv) {
} else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) {
if (strcmp(argv[i], "c") == 0)
have_libc = true;
+ if (strcmp(argv[i], "c++") == 0)
+ have_libcpp = true;
link_libs.append(argv[i]);
} else if (strcmp(arg, "--forbid-library") == 0) {
forbidden_link_libs.append(argv[i]);
@@ -1221,6 +1247,10 @@ static int main0(int argc, char **argv) {
have_libc = true;
link_libs.append("c");
}
+ if (!have_libcpp && ensure_libcpp_on_non_freestanding && target.os != OsFreestanding) {
+ have_libcpp = true;
+ link_libs.append("c++");
+ }
Buf zig_triple_buf = BUF_INIT;
target_triple_zig(&zig_triple_buf, &target);
@@ -1287,6 +1317,8 @@ static int main0(int argc, char **argv) {
LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));
link_lib->provided_explicitly = true;
}
+ g->cpp_rtti = cpp_rtti;
+ g->cpp_exceptions = cpp_exceptions;
g->subsystem = subsystem;
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
@@ -1433,6 +1465,8 @@ static int main0(int argc, char **argv) {
}
CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
override_lib_dir, libc, cache_dir_buf, cmd == CmdTest, root_progress_node);
+ g->cpp_rtti = cpp_rtti;
+ g->cpp_exceptions = cpp_exceptions;
if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
g->valgrind_support = valgrind_support;
g->link_eh_frame_hdr = link_eh_frame_hdr;
diff --git a/src/stage2.h b/src/stage2.h
index 4b86fdc059..ed7caebcb0 100644
--- a/src/stage2.h
+++ b/src/stage2.h
@@ -106,6 +106,7 @@ enum Error {
ErrorInvalidAbiVersion,
ErrorInvalidOperatingSystemVersion,
ErrorUnknownClangOption,
+ ErrorNestedResponseFile,
};
// ABI warning
@@ -334,6 +335,7 @@ enum Stage2ClangArg {
Stage2ClangArgPIC,
Stage2ClangArgNoPIC,
Stage2ClangArgNoStdLib,
+ Stage2ClangArgNoStdLibCpp,
Stage2ClangArgShared,
Stage2ClangArgRDynamic,
Stage2ClangArgWL,
@@ -343,6 +345,10 @@ enum Stage2ClangArg {
Stage2ClangArgSanitize,
Stage2ClangArgLinkerScript,
Stage2ClangArgVerboseCmds,
+ Stage2ClangArgExceptions,
+ Stage2ClangArgNoExceptions,
+ Stage2ClangArgRtti,
+ Stage2ClangArgNoRtti,
};
// ABI warning
@@ -356,6 +362,7 @@ struct Stage2ClangArgIterator {
const char **argv_ptr;
size_t argv_len;
size_t next_index;
+ size_t root_args;
};
// ABI warning
diff --git a/src/target.cpp b/src/target.cpp
index 63360fc029..59b1addc33 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -1229,6 +1229,13 @@ bool target_is_libc_lib_name(const ZigTarget *target, const char *name) {
return false;
}
+bool target_is_libcpp_lib_name(const ZigTarget *target, const char *name) {
+ if (strcmp(name, "c++") == 0 || strcmp(name, "c++abi") == 0)
+ return true;
+
+ return false;
+}
+
size_t target_libc_count(void) {
return array_length(libcs_available);
}
diff --git a/src/target.hpp b/src/target.hpp
index 01f2c6b168..c3f8530e02 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -102,6 +102,7 @@ bool target_os_requires_libc(Os os);
bool target_can_build_libc(const ZigTarget *target);
const char *target_libc_generic_name(const ZigTarget *target);
bool target_is_libc_lib_name(const ZigTarget *target, const char *name);
+bool target_is_libcpp_lib_name(const ZigTarget *target, const char *name);
bool target_supports_fpic(const ZigTarget *target);
bool target_supports_clang_march_native(const ZigTarget *target);
bool target_requires_pic(const ZigTarget *target, bool linking_libc);