aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-03-21 15:29:52 -0400
committerAndrew Kelley <andrew@ziglang.org>2020-03-21 15:40:49 -0400
commit0eee98edc1e505486a9ec51a331d3aa322fce9ee (patch)
treedfdc8a69b1c1f3d2ebf89f4a09f81c1d1942866e /src/main.cpp
parenta4eaeee72011a2f7866a18420812178991feaf8d (diff)
downloadzig-0eee98edc1e505486a9ec51a331d3aa322fce9ee.tar.gz
zig-0eee98edc1e505486a9ec51a331d3aa322fce9ee.zip
zig cc improvements
* The generated options data file is sorted now in a way that makes sure longer prefixes are first. This prevents collisions with some parameters. * Add support for `-fPIC`, `-fno-PIC`, `-nostdlib`, `-shared`, `-rdynamic`, `-Wl,-soname`, `-Wl,-rpath` * Better support for `-o`. * Disable generating h files * Shared library support. * Better positional argument support.
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp149
1 files changed, 140 insertions, 9 deletions
diff --git a/src/main.cpp b/src/main.cpp
index f850b0bc47..0bb6868f1a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -430,6 +430,7 @@ static int main0(int argc, char **argv) {
bool enable_dump_analysis = false;
bool enable_doc_generation = false;
bool emit_bin = true;
+ const char *emit_bin_override_path = nullptr;
bool emit_asm = false;
bool emit_llvm_ir = false;
bool emit_h = false;
@@ -451,6 +452,7 @@ static int main0(int argc, char **argv) {
bool function_sections = false;
const char *mcpu = nullptr;
CodeModel code_model = CodeModelDefault;
+ const char *override_soname = nullptr;
ZigList<const char *> llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
@@ -576,10 +578,14 @@ static int main0(int argc, char **argv) {
} else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
return stage2_fmt(argc, argv);
} else if (argc >= 2 && strcmp(argv[1], "cc") == 0) {
- const char *o_arg = nullptr;
+ emit_h = false;
+
bool c_arg = false;
Stage2ClangArgIterator it;
stage2_clang_arg_iterator(&it, argc, argv);
+ bool nostdlib = false;
+ 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));
@@ -590,7 +596,8 @@ static int main0(int argc, char **argv) {
target_string = it.only_arg;
break;
case Stage2ClangArgO: // -o
- o_arg = it.only_arg;
+ emit_bin_override_path = it.only_arg;
+ enable_cache = CacheOptOn;
break;
case Stage2ClangArgC: // -c
c_arg = true;
@@ -601,9 +608,17 @@ static int main0(int argc, char **argv) {
}
break;
case Stage2ClangArgPositional: {
- CFile *c_file = heap::c_allocator.create<CFile>();
- c_file->source_path = it.only_arg;
- c_source_files.append(c_file);
+ Buf *arg_buf = buf_create_from_str(it.only_arg);
+ if (buf_ends_with_str(arg_buf, ".c") ||
+ buf_ends_with_str(arg_buf, ".cpp") ||
+ buf_ends_with_str(arg_buf, ".s"))
+ {
+ CFile *c_file = heap::c_allocator.create<CFile>();
+ c_file->source_path = it.only_arg;
+ c_source_files.append(c_file);
+ } else {
+ objects.append(it.only_arg);
+ }
break;
}
case Stage2ClangArgL: // -l
@@ -611,18 +626,111 @@ static int main0(int argc, char **argv) {
have_libc = true;
link_libs.append(it.only_arg);
break;
+ case Stage2ClangArgIgnore:
+ break;
+ case Stage2ClangArgPassthrough:
+ // 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:
+ nostdlib = true;
+ 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;
+ }
+ }
+ }
+ // 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 {
+ fprintf(stderr, "warning: unsupported linker arg: %s\n", buf_ptr(arg));
}
}
+
+ if (!nostdlib && !have_libc) {
+ have_libc = true;
+ link_libs.append("c");
+ }
if (!c_arg) {
cmd = CmdBuild;
- out_type = OutTypeExe;
- if (o_arg == nullptr) {
- zig_panic("TODO set out name to a.out");
+ if (is_shared_lib) {
+ out_type = OutTypeLib;
+ } else {
+ out_type = OutTypeExe;
+ }
+ if (emit_bin_override_path == nullptr) {
+ emit_bin_override_path = "a.out";
}
} 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 for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
@@ -1184,6 +1292,18 @@ static int main0(int argc, char **argv) {
buf_out_name = buf_alloc();
os_path_extname(&basename, buf_out_name, nullptr);
}
+ if (need_name && buf_out_name == nullptr && objects.length == 1) {
+ Buf basename = BUF_INIT;
+ os_path_split(buf_create_from_str(objects.at(0)), nullptr, &basename);
+ buf_out_name = buf_alloc();
+ os_path_extname(&basename, buf_out_name, nullptr);
+ }
+ if (need_name && buf_out_name == nullptr && emit_bin_override_path != nullptr) {
+ Buf basename = BUF_INIT;
+ os_path_split(buf_create_from_str(emit_bin_override_path), nullptr, &basename);
+ buf_out_name = buf_alloc();
+ os_path_extname(&basename, buf_out_name, nullptr);
+ }
if (need_name && buf_out_name == nullptr) {
fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
@@ -1259,6 +1379,10 @@ static int main0(int argc, char **argv) {
g->function_sections = function_sections;
g->code_model = code_model;
+ 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));
}
@@ -1337,7 +1461,14 @@ static int main0(int argc, char **argv) {
os_spawn_process(args, &term);
return term.code;
} else if (cmd == CmdBuild) {
- if (g->enable_cache) {
+ if (emit_bin_override_path != nullptr) {
+ Buf *dest_path = buf_create_from_str(emit_bin_override_path);
+ if ((err = os_update_file(&g->bin_file_output_path, dest_path))) {
+ fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path),
+ buf_ptr(dest_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, '/', '\\');
buf_replace(g->output_dir, '/', '\\');