aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-09-03 20:23:00 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-09-09 09:28:05 -0700
commit503ba7b27c6e8e248d271aec936623853cd8fcd1 (patch)
tree005438102ec6ba09cb9368397b9ff180f44790ad /src/main.cpp
parent749417a1f3060f0695bbfe72d929f06b0be42535 (diff)
downloadzig-503ba7b27c6e8e248d271aec936623853cd8fcd1.tar.gz
zig-503ba7b27c6e8e248d271aec936623853cd8fcd1.zip
start moving `zig cc` to stage2
* build.zig: repair the ability to link against llvm, clang, and lld * move the zig cc arg parsing logic to stage2 - the preprocessor flag is still TODO - the clang arg iterator code is improved to use slices instead of raw pointers because it no longer has to deal with an extern struct. * clean up error printing with a `fatal` function and use log API for messages rather than std.debug.print * add support for more CLI options to stage2 & update usage text - hooking up most of these new options is TODO * clean up the way libc and libc++ are detected via command line options. target information is used to determine if any of the libc candidate names are chosen. * add native library directory detection * implement the ability to invoke clang from stage2 * introduce a build_options.have_llvm so we can comptime branch on whether LLVM is linked in or not.
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp412
1 files changed, 5 insertions, 407 deletions
diff --git a/src/main.cpp b/src/main.cpp
index e2f6a82a12..af3bc4b2a1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -404,7 +404,6 @@ 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;
@@ -446,18 +445,8 @@ static int main0(int argc, char **argv) {
bool function_sections = false;
const char *mcpu = nullptr;
CodeModel code_model = CodeModelDefault;
- const char *override_soname = nullptr;
- bool only_pp_or_asm = false;
- bool ensure_libc_on_non_freestanding = false;
- bool ensure_libcpp_on_non_freestanding = false;
- bool disable_c_depfile = false;
bool want_native_include_dirs = false;
- Buf *linker_optimization = nullptr;
- OptionalBool linker_gc_sections = OptionalBoolNull;
- OptionalBool linker_allow_shlib_undefined = OptionalBoolNull;
OptionalBool linker_bind_global_refs_locally = OptionalBoolNull;
- bool linker_z_nodelete = false;
- bool linker_z_defs = false;
size_t stack_size_override = 0;
ZigList<const char *> llvm_argv = {0};
@@ -585,355 +574,10 @@ static int main0(int argc, char **argv) {
return stage2_fmt(argc, argv);
} else if (argc >= 2 && strcmp(argv[1], "env") == 0) {
return stage2_env(argc, argv);
- } 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);
- want_native_include_dirs = true;
-
- bool c_arg = false;
- Stage2ClangArgIterator it;
- stage2_clang_arg_iterator(&it, argc, argv);
- bool is_shared_lib = false;
- ZigList<Buf *> linker_args = {};
- while (it.has_next) {
- if ((err = stage2_clang_arg_next(&it))) {
- fprintf(stderr, "unable to parse command line parameters: %s\n", err_str(err));
- return EXIT_FAILURE;
- }
- switch (it.kind) {
- case Stage2ClangArgTarget: // example: -target riscv64-linux-unknown
- target_string = it.only_arg;
- break;
- case Stage2ClangArgO: // -o
- emit_bin_override_path = it.only_arg;
- enable_cache = CacheOptOn;
- break;
- case Stage2ClangArgC: // -c
- c_arg = true;
- break;
- case Stage2ClangArgOther:
- for (size_t i = 0; i < it.other_args_len; i += 1) {
- clang_argv.append(it.other_args_ptr[i]);
- }
- break;
- case Stage2ClangArgPositional: {
- FileExt file_ext = classify_file_ext(it.only_arg, strlen(it.only_arg));
- switch (file_ext) {
- case FileExtAsm:
- case FileExtC:
- case FileExtCpp:
- case FileExtLLVMIr:
- case FileExtLLVMBitCode:
- case FileExtHeader: {
- CFile *c_file = heap::c_allocator.create<CFile>();
- c_file->source_path = it.only_arg;
- c_source_files.append(c_file);
- break;
- }
- case FileExtUnknown:
- objects.append(it.only_arg);
- break;
- }
- break;
- }
- case Stage2ClangArgL: // -l
- if (strcmp(it.only_arg, "c") == 0) {
- have_libc = true;
- link_libs.append("c");
- } else if (strcmp(it.only_arg, "c++") == 0 ||
- strcmp(it.only_arg, "stdc++") == 0)
- {
- have_libcpp = true;
- link_libs.append("c++");
- } else {
- link_libs.append(it.only_arg);
- }
- break;
- case Stage2ClangArgIgnore:
- break;
- case Stage2ClangArgDriverPunt:
- // Never mind what we're doing, just pass the args directly. For example --help.
- return ZigClang_main(argc, argv);
- case Stage2ClangArgPIC:
- want_pic = WantPICEnabled;
- break;
- case Stage2ClangArgNoPIC:
- want_pic = WantPICDisabled;
- break;
- 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;
- break;
- case Stage2ClangArgRDynamic:
- rdynamic = true;
- break;
- case Stage2ClangArgWL: {
- const char *arg = it.only_arg;
- for (;;) {
- size_t pos = 0;
- while (arg[pos] != ',' && arg[pos] != 0) pos += 1;
- linker_args.append(buf_create_from_mem(arg, pos));
- if (arg[pos] == 0) break;
- arg += pos + 1;
- }
- break;
- }
- case Stage2ClangArgPreprocessOrAsm:
- // this handles both -E and -S
- only_pp_or_asm = true;
- for (size_t i = 0; i < it.other_args_len; i += 1) {
- clang_argv.append(it.other_args_ptr[i]);
- }
- break;
- case Stage2ClangArgOptimize:
- // alright what release mode do they want?
- if (strcmp(it.only_arg, "Os") == 0) {
- build_mode = BuildModeSmallRelease;
- } else if (strcmp(it.only_arg, "O2") == 0 ||
- strcmp(it.only_arg, "O3") == 0 ||
- strcmp(it.only_arg, "O4") == 0)
- {
- build_mode = BuildModeFastRelease;
- } else if (strcmp(it.only_arg, "Og") == 0 ||
- strcmp(it.only_arg, "O0") == 0)
- {
- build_mode = BuildModeDebug;
- } else {
- for (size_t i = 0; i < it.other_args_len; i += 1) {
- clang_argv.append(it.other_args_ptr[i]);
- }
- }
- break;
- case Stage2ClangArgDebug:
- strip = false;
- if (strcmp(it.only_arg, "-g") == 0) {
- // we handled with strip = false above
- } else {
- for (size_t i = 0; i < it.other_args_len; i += 1) {
- clang_argv.append(it.other_args_ptr[i]);
- }
- }
- break;
- case Stage2ClangArgSanitize:
- if (strcmp(it.only_arg, "undefined") == 0) {
- want_sanitize_c = WantCSanitizeEnabled;
- } else {
- for (size_t i = 0; i < it.other_args_len; i += 1) {
- clang_argv.append(it.other_args_ptr[i]);
- }
- }
- break;
- case Stage2ClangArgLinkerScript:
- linker_script = it.only_arg;
- break;
- case Stage2ClangArgVerboseCmds:
- verbose_cc = true;
- verbose_link = true;
- break;
- case Stage2ClangArgForLinker:
- linker_args.append(buf_create_from_str(it.only_arg));
- break;
- case Stage2ClangArgLinkerInputZ:
- linker_args.append(buf_create_from_str("-z"));
- linker_args.append(buf_create_from_str(it.only_arg));
- break;
- case Stage2ClangArgLibDir:
- lib_dirs.append(it.only_arg);
- break;
- case Stage2ClangArgMCpu:
- mcpu = it.only_arg;
- break;
- case Stage2ClangArgDepFile:
- disable_c_depfile = true;
- for (size_t i = 0; i < it.other_args_len; i += 1) {
- clang_argv.append(it.other_args_ptr[i]);
- }
- break;
- case Stage2ClangArgFrameworkDir:
- framework_dirs.append(it.only_arg);
- break;
- case Stage2ClangArgFramework:
- frameworks.append(it.only_arg);
- break;
- case Stage2ClangArgNoStdLibInc:
- want_native_include_dirs = false;
- break;
- }
- }
- // Parse linker args
- for (size_t i = 0; i < linker_args.length; i += 1) {
- Buf *arg = linker_args.at(i);
- if (buf_eql_str(arg, "-soname")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- Buf *soname_buf = linker_args.at(i);
- override_soname = buf_ptr(soname_buf);
- // use it as --name
- // example: libsoundio.so.2
- size_t prefix = 0;
- if (buf_starts_with_str(soname_buf, "lib")) {
- prefix = 3;
- }
- size_t end = buf_len(soname_buf);
- if (buf_ends_with_str(soname_buf, ".so")) {
- end -= 3;
- } else {
- bool found_digit = false;
- while (end > 0 && isdigit(buf_ptr(soname_buf)[end - 1])) {
- found_digit = true;
- end -= 1;
- }
- if (found_digit && end > 0 && buf_ptr(soname_buf)[end - 1] == '.') {
- end -= 1;
- } else {
- end = buf_len(soname_buf);
- }
- if (buf_ends_with_str(buf_slice(soname_buf, prefix, end), ".so")) {
- end -= 3;
- }
- }
- out_name = buf_ptr(buf_slice(soname_buf, prefix, end));
- } else if (buf_eql_str(arg, "-rpath")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- Buf *rpath = linker_args.at(i);
- rpath_list.append(buf_ptr(rpath));
- } else if (buf_eql_str(arg, "-I") ||
- buf_eql_str(arg, "--dynamic-linker") ||
- buf_eql_str(arg, "-dynamic-linker"))
- {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- dynamic_linker = buf_ptr(linker_args.at(i));
- } else if (buf_eql_str(arg, "-E") ||
- buf_eql_str(arg, "--export-dynamic") ||
- buf_eql_str(arg, "-export-dynamic"))
- {
- rdynamic = true;
- } else if (buf_eql_str(arg, "--version-script")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- version_script = linker_args.at(i);
- } else if (buf_starts_with_str(arg, "-O")) {
- linker_optimization = arg;
- } else if (buf_eql_str(arg, "--gc-sections")) {
- linker_gc_sections = OptionalBoolTrue;
- } else if (buf_eql_str(arg, "--no-gc-sections")) {
- linker_gc_sections = OptionalBoolFalse;
- } else if (buf_eql_str(arg, "--allow-shlib-undefined") ||
- buf_eql_str(arg, "-allow-shlib-undefined"))
- {
- linker_allow_shlib_undefined = OptionalBoolTrue;
- } else if (buf_eql_str(arg, "--no-allow-shlib-undefined") ||
- buf_eql_str(arg, "-no-allow-shlib-undefined"))
- {
- linker_allow_shlib_undefined = OptionalBoolFalse;
- } else if (buf_eql_str(arg, "-Bsymbolic")) {
- linker_bind_global_refs_locally = OptionalBoolTrue;
- } else if (buf_eql_str(arg, "-z")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- Buf *z_arg = linker_args.at(i);
- if (buf_eql_str(z_arg, "nodelete")) {
- linker_z_nodelete = true;
- } else if (buf_eql_str(z_arg, "defs")) {
- linker_z_defs = true;
- } else {
- fprintf(stderr, "warning: unsupported linker arg: -z %s\n", buf_ptr(z_arg));
- }
- } else if (buf_eql_str(arg, "--major-image-version")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- ver_major = atoi(buf_ptr(linker_args.at(i)));
- } else if (buf_eql_str(arg, "--minor-image-version")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- ver_minor = atoi(buf_ptr(linker_args.at(i)));
- } else if (buf_eql_str(arg, "--stack")) {
- i += 1;
- if (i >= linker_args.length) {
- fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
- return EXIT_FAILURE;
- }
- stack_size_override = atoi(buf_ptr(linker_args.at(i)));
- } else {
- fprintf(stderr, "warning: unsupported linker arg: %s\n", buf_ptr(arg));
- }
- }
-
- if (want_sanitize_c == WantCSanitizeEnabled && build_mode == BuildModeFastRelease) {
- build_mode = BuildModeSafeRelease;
- }
-
- if (only_pp_or_asm) {
- cmd = CmdBuild;
- out_type = OutTypeObj;
- emit_bin = false;
- // Transfer "objects" into c_source_files
- for (size_t i = 0; i < objects.length; i += 1) {
- CFile *c_file = heap::c_allocator.create<CFile>();
- c_file->source_path = objects.at(i);
- c_source_files.append(c_file);
- }
- for (size_t i = 0; i < c_source_files.length; i += 1) {
- Buf *src_path;
- if (emit_bin_override_path != nullptr) {
- src_path = buf_create_from_str(emit_bin_override_path);
- } else {
- src_path = buf_create_from_str(c_source_files.at(i)->source_path);
- }
- Buf basename = BUF_INIT;
- os_path_split(src_path, nullptr, &basename);
- c_source_files.at(i)->preprocessor_only_basename = buf_ptr(&basename);
- }
- } else if (!c_arg) {
- cmd = CmdBuild;
- if (is_shared_lib) {
- out_type = OutTypeLib;
- } else {
- out_type = OutTypeExe;
- }
- if (emit_bin_override_path == nullptr) {
- emit_bin_override_path = "a.out";
- enable_cache = CacheOptOn;
- }
- } else {
- cmd = CmdBuild;
- out_type = OutTypeObj;
- }
- if (c_source_files.length == 0 && objects.length == 0) {
- // For example `zig cc` and no args should print the "no input files" message.
- return ZigClang_main(argc, argv);
- }
+ } else if (argc >= 2 && strcmp(argv[1], "cc") == 0) {
+ return stage2_cc(argc, argv, false);
+ } else if (argc >= 2 && strcmp(argv[1], "c++") == 0) {
+ return stage2_cc(argc, argv, true);
} else for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
@@ -1038,7 +682,6 @@ static int main0(int argc, char **argv) {
have_libc = true;
link_libs.append("c");
} else if (strcmp(l, "c++") == 0 || strcmp(l, "stdc++") == 0) {
- have_libcpp = true;
link_libs.append("c++");
} else {
link_libs.append(l);
@@ -1185,7 +828,6 @@ static int main0(int argc, char **argv) {
have_libc = true;
link_libs.append("c");
} else if (strcmp(argv[i], "c++") == 0 || strcmp(argv[i], "stdc++") == 0) {
- have_libcpp = true;
link_libs.append("c++");
} else {
link_libs.append(argv[i]);
@@ -1351,15 +993,6 @@ static int main0(int argc, char **argv) {
return print_error_usage(arg0);
}
- if (!have_libc && ensure_libc_on_non_freestanding && target.os != OsFreestanding) {
- 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);
@@ -1616,20 +1249,10 @@ static int main0(int argc, char **argv) {
g->system_linker_hack = system_linker_hack;
g->function_sections = function_sections;
g->code_model = code_model;
- g->disable_c_depfile = disable_c_depfile;
- g->linker_optimization = linker_optimization;
- g->linker_gc_sections = linker_gc_sections;
- g->linker_allow_shlib_undefined = linker_allow_shlib_undefined;
g->linker_bind_global_refs_locally = linker_bind_global_refs_locally;
- g->linker_z_nodelete = linker_z_nodelete;
- g->linker_z_defs = linker_z_defs;
g->stack_size_override = stack_size_override;
- if (override_soname) {
- g->override_soname = buf_create_from_str(override_soname);
- }
-
for (size_t i = 0; i < lib_dirs.length; i += 1) {
codegen_add_lib_dir(g, lib_dirs.at(i));
}
@@ -1713,37 +1336,12 @@ static int main0(int argc, char **argv) {
buf_replace(g->output_dir, '/', '\\');
#endif
Buf *dest_path = buf_create_from_str(emit_bin_override_path);
- Buf *source_path;
- if (only_pp_or_asm) {
- source_path = buf_alloc();
- Buf *pp_only_basename = buf_create_from_str(
- c_source_files.at(0)->preprocessor_only_basename);
- os_path_join(g->output_dir, pp_only_basename, source_path);
-
- } else {
- source_path = &g->bin_file_output_path;
- }
+ Buf *source_path = &g->bin_file_output_path;
if ((err = os_update_file(source_path, dest_path))) {
fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(source_path),
buf_ptr(dest_path), err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
}
- } else if (only_pp_or_asm) {
-#if defined(ZIG_OS_WINDOWS)
- buf_replace(g->c_artifact_dir, '/', '\\');
-#endif
- // dump the preprocessed output to stdout
- for (size_t i = 0; i < c_source_files.length; i += 1) {
- Buf *source_path = buf_alloc();
- Buf *pp_only_basename = buf_create_from_str(
- c_source_files.at(i)->preprocessor_only_basename);
- os_path_join(g->c_artifact_dir, pp_only_basename, source_path);
- if ((err = os_dump_file(source_path, stdout))) {
- fprintf(stderr, "unable to read %s: %s\n", buf_ptr(source_path),
- err_str(err));
- return main_exit(root_progress_node, EXIT_FAILURE);
- }
- }
} else if (g->enable_cache) {
#if defined(ZIG_OS_WINDOWS)
buf_replace(&g->bin_file_output_path, '/', '\\');