authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-26 22:48:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-26 22:48:37-04:00
logdb17c0d88c44183b3060993d85657e7637b43d68
tree5a267a81e6e28ecc1e46842696fd735a24757845
parented0dbe1a64a80dc329daab3776bda9d3fa54c9f8
signaturelock-open Commit is signed but in an unrecognized format.

ability to compile c++ hello world with `zig c++`

closes #4786

10 files changed, 221 insertions(+), 2 deletions(-)

src-self-hosted/clang_options_data.zig+8-1
......@@ -3752,7 +3752,14 @@ flagpd1("nostdinc++"),
37523752 .psl = false,
37533753},
37543754flagpd1("nostdlibinc"),
3755flagpd1("nostdlib++"),
3755.{
3756 .name = "nostdlib++",
3757 .syntax = .flag,
3758 .zig_equivalent = .nostdlib_cpp,
3759 .pd1 = true,
3760 .pd2 = false,
3761 .psl = false,
3762},
37563763flagpd1("nostdsysteminc"),
37573764flagpd1("objcmt-atomic-property"),
37583765flagpd1("objcmt-migrate-all"),
src-self-hosted/stage2.zig+1
......@@ -1273,6 +1273,7 @@ pub const ClangArgIterator = extern struct {
12731273 pic,
12741274 no_pic,
12751275 nostdlib,
1276 nostdlib_cpp,
12761277 shared,
12771278 rdynamic,
12781279 wl,
src/all_types.hpp+1
......@@ -2019,6 +2019,7 @@ struct CodeGen {
20192019 ZigLLVMDICompileUnit *compile_unit;
20202020 ZigLLVMDIFile *compile_unit_file;
20212021 LinkLib *libc_link_lib;
2022 LinkLib *libcpp_link_lib;
20222023 LLVMTargetDataRef target_data_ref;
20232024 LLVMTargetMachineRef target_machine;
20242025 ZigLLVMDIFile *dummy_di_file;
src/analyze.cpp+6
......@@ -7756,10 +7756,14 @@ LinkLib *create_link_lib(Buf *name) {
77567756
77577757LinkLib *add_link_lib(CodeGen *g, Buf *name) {
77587758 bool is_libc = buf_eql_str(name, "c");
7759 bool is_libcpp = buf_eql_str(name, "c++") || buf_eql_str(name, "c++abi");
77597760
77607761 if (is_libc && g->libc_link_lib != nullptr)
77617762 return g->libc_link_lib;
77627763
7764 if (is_libcpp && g->libcpp_link_lib != nullptr)
7765 return g->libcpp_link_lib;
7766
77637767 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
77647768 LinkLib *existing_lib = g->link_libs_list.at(i);
77657769 if (buf_eql_buf(existing_lib->name, name)) {
......@@ -7772,6 +7776,8 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
77727776
77737777 if (is_libc)
77747778 g->libc_link_lib = link_lib;
7779 if (is_libcpp)
7780 g->libcpp_link_lib = link_lib;
77757781
77767782 return link_lib;
77777783}
src/codegen.cpp+10
......@@ -8700,6 +8700,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
87008700 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
87018701 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
87028702 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
8703 buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->libcpp_link_lib != nullptr));
87038704 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
87048705 buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
87058706 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
......@@ -8798,6 +8799,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
87988799 }
87998800 cache_bool(&cache_hash, g->have_err_ret_tracing);
88008801 cache_bool(&cache_hash, g->libc_link_lib != nullptr);
8802 cache_bool(&cache_hash, g->libcpp_link_lib != nullptr);
88018803 cache_bool(&cache_hash, g->valgrind_support);
88028804 cache_bool(&cache_hash, g->link_eh_frame_hdr);
88038805 cache_int(&cache_hash, detect_subsystem(g));
......@@ -9205,6 +9207,14 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
92059207 args.append(g->framework_dirs.at(i));
92069208 }
92079209
9210 if (g->libcpp_link_lib != nullptr) {
9211 const char *libcxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
9212 buf_ptr(g->zig_lib_dir)));
9213
9214 args.append("-isystem");
9215 args.append(libcxx_include_path);
9216 }
9217
92089218 // According to Rich Felker libc headers are supposed to go before C language headers.
92099219 // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
92109220 // and other compiler specific items.
src/install_files.h+65
......@@ -1841,4 +1841,69 @@ static const char *ZIG_MUSL_COMPAT_TIME32_FILES[] = {
18411841"musl/compat/time32/wait3_time32.c",
18421842"musl/compat/time32/wait4_time32.c",
18431843};
1844static const char *ZIG_LIBCXXABI_FILES[] = {
1845"src/abort_message.cpp",
1846"src/cxa_aux_runtime.cpp",
1847"src/cxa_default_handlers.cpp",
1848"src/cxa_demangle.cpp",
1849"src/cxa_exception.cpp",
1850"src/cxa_exception_storage.cpp",
1851"src/cxa_guard.cpp",
1852"src/cxa_handlers.cpp",
1853"src/cxa_noexception.cpp",
1854"src/cxa_personality.cpp",
1855"src/cxa_thread_atexit.cpp",
1856"src/cxa_unexpected.cpp",
1857"src/cxa_vector.cpp",
1858"src/cxa_virtual.cpp",
1859"src/fallback_malloc.cpp",
1860"src/private_typeinfo.cpp",
1861"src/stdlib_exception.cpp",
1862"src/stdlib_new_delete.cpp",
1863"src/stdlib_stdexcept.cpp",
1864"src/stdlib_typeinfo.cpp",
1865};
1866static const char *ZIG_LIBCXX_FILES[] = {
1867"src/algorithm.cpp",
1868"src/any.cpp",
1869"src/bind.cpp",
1870"src/charconv.cpp",
1871"src/chrono.cpp",
1872"src/condition_variable.cpp",
1873"src/condition_variable_destructor.cpp",
1874"src/debug.cpp",
1875"src/exception.cpp",
1876"src/experimental/memory_resource.cpp",
1877"src/filesystem/directory_iterator.cpp",
1878"src/filesystem/int128_builtins.cpp",
1879"src/filesystem/operations.cpp",
1880"src/functional.cpp",
1881"src/future.cpp",
1882"src/hash.cpp",
1883"src/ios.cpp",
1884"src/iostream.cpp",
1885"src/locale.cpp",
1886"src/memory.cpp",
1887"src/mutex.cpp",
1888"src/mutex_destructor.cpp",
1889"src/new.cpp",
1890"src/optional.cpp",
1891"src/random.cpp",
1892"src/regex.cpp",
1893"src/shared_mutex.cpp",
1894"src/stdexcept.cpp",
1895"src/string.cpp",
1896"src/strstream.cpp",
1897"src/support/solaris/xlocale.cpp",
1898"src/support/win32/locale_win32.cpp",
1899"src/support/win32/support.cpp",
1900"src/support/win32/thread_win32.cpp",
1901"src/system_error.cpp",
1902"src/thread.cpp",
1903"src/typeinfo.cpp",
1904"src/utility.cpp",
1905"src/valarray.cpp",
1906"src/variant.cpp",
1907"src/vector.cpp",
1908};
18441909#endif
src/link.cpp+108
......@@ -1107,6 +1107,105 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node
11071107 return buf_ptr(&child_gen->bin_file_output_path);
11081108}
11091109
1110static const char *build_libcxxabi(CodeGen *parent, Stage2ProgressNode *progress_node) {
1111 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c++abi", progress_node);
1112 codegen_add_link_lib(child_gen, buf_create_from_str("c"));
1113
1114 ZigList<CFile *> c_source_files = {0};
1115
1116 const char *cxxabi_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "include",
1117 buf_ptr(parent->zig_lib_dir)));
1118 const char *cxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
1119 buf_ptr(parent->zig_lib_dir)));
1120
1121 for (size_t i = 0; i < array_length(ZIG_LIBCXXABI_FILES); i += 1) {
1122 const char *rel_src_path = ZIG_LIBCXXABI_FILES[i];
1123
1124 CFile *c_file = heap::c_allocator.create<CFile>();
1125 c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "%s",
1126 buf_ptr(parent->zig_lib_dir), rel_src_path));
1127
1128 c_file->args.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
1129 c_file->args.append("-D_LIBCPP_DISABLE_EXTERN_TEMPLATE");
1130 c_file->args.append("-D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS");
1131 c_file->args.append("-D_LIBCXXABI_BUILDING_LIBRARY");
1132
1133 c_file->args.append("-I");
1134 c_file->args.append(cxxabi_include_path);
1135
1136 c_file->args.append("-I");
1137 c_file->args.append(cxx_include_path);
1138
1139 c_file->args.append("-O3");
1140 c_file->args.append("-DNDEBUG");
1141 c_file->args.append("-fPIC");
1142 c_file->args.append("-nostdinc++");
1143 c_file->args.append("-fstrict-aliasing");
1144 c_file->args.append("-funwind-tables");
1145 c_file->args.append("-D_DEBUG");
1146 c_file->args.append("-UNDEBUG");
1147 c_file->args.append("-std=c++11");
1148
1149 c_source_files.append(c_file);
1150 }
1151
1152
1153 child_gen->c_source_files = c_source_files;
1154 codegen_build_and_link(child_gen);
1155 return buf_ptr(&child_gen->bin_file_output_path);
1156}
1157
1158static const char *build_libcxx(CodeGen *parent, Stage2ProgressNode *progress_node) {
1159 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c++", progress_node);
1160 codegen_add_link_lib(child_gen, buf_create_from_str("c"));
1161
1162 ZigList<CFile *> c_source_files = {0};
1163
1164 const char *cxxabi_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "include",
1165 buf_ptr(parent->zig_lib_dir)));
1166 const char *cxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
1167 buf_ptr(parent->zig_lib_dir)));
1168
1169 for (size_t i = 0; i < array_length(ZIG_LIBCXX_FILES); i += 1) {
1170 const char *rel_src_path = ZIG_LIBCXX_FILES[i];
1171
1172 Buf *src_path_buf = buf_create_from_str(rel_src_path);
1173 if (buf_starts_with_str(src_path_buf, "src/support/win32") && parent->zig_target->os != OsWindows) {
1174 continue;
1175 }
1176
1177 CFile *c_file = heap::c_allocator.create<CFile>();
1178 c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "%s",
1179 buf_ptr(parent->zig_lib_dir), rel_src_path));
1180
1181 c_file->args.append("-DNDEBUG");
1182 c_file->args.append("-D_LIBCPP_BUILDING_LIBRARY");
1183 c_file->args.append("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER");
1184 c_file->args.append("-DLIBCXX_BUILDING_LIBCXXABI");
1185
1186 c_file->args.append("-I");
1187 c_file->args.append(cxx_include_path);
1188
1189 c_file->args.append("-I");
1190 c_file->args.append(cxxabi_include_path);
1191
1192 c_file->args.append("-O3");
1193 c_file->args.append("-DNDEBUG");
1194 c_file->args.append("-fPIC");
1195 c_file->args.append("-nostdinc++");
1196 c_file->args.append("-fvisibility-inlines-hidden");
1197 c_file->args.append("-std=c++14");
1198 c_file->args.append("-Wno-user-defined-literals");
1199
1200 c_source_files.append(c_file);
1201 }
1202
1203
1204 child_gen->c_source_files = c_source_files;
1205 codegen_build_and_link(child_gen);
1206 return buf_ptr(&child_gen->bin_file_output_path);
1207}
1208
11101209static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) {
11111210 CFile *c_file = heap::c_allocator.create<CFile>();
11121211 c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s",
......@@ -1770,6 +1869,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
17701869 // libc is linked specially
17711870 continue;
17721871 }
1872 if (buf_eql_str(link_lib->name, "c++") || buf_eql_str(link_lib->name, "c++abi")) {
1873 // libc++ is linked specially
1874 continue;
1875 }
17731876 if (g->libc == nullptr && target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
17741877 // these libraries are always linked below when targeting glibc
17751878 continue;
......@@ -1785,6 +1888,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
17851888 lj->args.append(buf_ptr(arg));
17861889 }
17871890
1891 // libc++ dep
1892 if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
1893 lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
1894 lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
1895 }
17881896
17891897 // libc dep
17901898 if (g->libc_link_lib != nullptr && g->out_type != OutTypeObj) {
src/main.cpp+17-1
......@@ -412,6 +412,7 @@ static int main0(int argc, char **argv) {
412412 ZigList<const char *> framework_dirs = {0};
413413 ZigList<const char *> frameworks = {0};
414414 bool have_libc = false;
415 bool have_libcpp = false;
415416 const char *target_string = nullptr;
416417 bool rdynamic = false;
417418 const char *linker_script = nullptr;
......@@ -456,6 +457,7 @@ static int main0(int argc, char **argv) {
456457 const char *override_soname = nullptr;
457458 bool only_preprocess = false;
458459 bool ensure_libc_on_non_freestanding = false;
460 bool ensure_libcpp_on_non_freestanding = false;
459461
460462 ZigList<const char *> llvm_argv = {0};
461463 llvm_argv.append("zig (LLVM option parsing)");
......@@ -580,10 +582,11 @@ static int main0(int argc, char **argv) {
580582 return (term.how == TerminationIdClean) ? term.code : -1;
581583 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
582584 return stage2_fmt(argc, argv);
583 } else if (argc >= 2 && strcmp(argv[1], "cc") == 0) {
585 } else if (argc >= 2 && (strcmp(argv[1], "cc") == 0 || strcmp(argv[1], "c++") == 0)) {
584586 emit_h = false;
585587 strip = true;
586588 ensure_libc_on_non_freestanding = true;
589 ensure_libcpp_on_non_freestanding = (strcmp(argv[1], "c++") == 0);
587590
588591 bool c_arg = false;
589592 Stage2ClangArgIterator it;
......@@ -632,6 +635,8 @@ static int main0(int argc, char **argv) {
632635 case Stage2ClangArgL: // -l
633636 if (strcmp(it.only_arg, "c") == 0)
634637 have_libc = true;
638 if (strcmp(it.only_arg, "c++") == 0)
639 have_libcpp = true;
635640 link_libs.append(it.only_arg);
636641 break;
637642 case Stage2ClangArgIgnore:
......@@ -648,6 +653,9 @@ static int main0(int argc, char **argv) {
648653 case Stage2ClangArgNoStdLib:
649654 ensure_libc_on_non_freestanding = false;
650655 break;
656 case Stage2ClangArgNoStdLibCpp:
657 ensure_libcpp_on_non_freestanding = false;
658 break;
651659 case Stage2ClangArgShared:
652660 is_dynamic = true;
653661 is_shared_lib = true;
......@@ -916,6 +924,8 @@ static int main0(int argc, char **argv) {
916924 const char *l = &arg[2];
917925 if (strcmp(l, "c") == 0)
918926 have_libc = true;
927 if (strcmp(l, "c++") == 0)
928 have_libcpp = true;
919929 link_libs.append(l);
920930 } else if (arg[1] == 'I' && arg[2] != 0) {
921931 clang_argv.append("-I");
......@@ -1057,6 +1067,8 @@ static int main0(int argc, char **argv) {
10571067 } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) {
10581068 if (strcmp(argv[i], "c") == 0)
10591069 have_libc = true;
1070 if (strcmp(argv[i], "c++") == 0)
1071 have_libcpp = true;
10601072 link_libs.append(argv[i]);
10611073 } else if (strcmp(arg, "--forbid-library") == 0) {
10621074 forbidden_link_libs.append(argv[i]);
......@@ -1221,6 +1233,10 @@ static int main0(int argc, char **argv) {
12211233 have_libc = true;
12221234 link_libs.append("c");
12231235 }
1236 if (!have_libcpp && ensure_libcpp_on_non_freestanding && target.os != OsFreestanding) {
1237 have_libcpp = true;
1238 link_libs.append("c++");
1239 }
12241240
12251241 Buf zig_triple_buf = BUF_INIT;
12261242 target_triple_zig(&zig_triple_buf, &target);
src/stage2.h+1
......@@ -334,6 +334,7 @@ enum Stage2ClangArg {
334334 Stage2ClangArgPIC,
335335 Stage2ClangArgNoPIC,
336336 Stage2ClangArgNoStdLib,
337 Stage2ClangArgNoStdLibCpp,
337338 Stage2ClangArgShared,
338339 Stage2ClangArgRDynamic,
339340 Stage2ClangArgWL,
tools/update_clang_options.zig+4
......@@ -62,6 +62,10 @@ const known_options = [_]KnownOpt{
6262 .name = "no-standard-libraries",
6363 .ident = "nostdlib",
6464 },
65 .{
66 .name = "nostdlib++",
67 .ident = "nostdlib_cpp",
68 },
6569 .{
6670 .name = "shared",
6771 .ident = "shared",