diff --git a/CMakeLists.txt b/CMakeLists.txt index d384bc1b3..59655757d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -600,7 +600,6 @@ set(ZIG_STD_FILES "sort.zig" "special/bootstrap.zig" "special/bootstrap_lib.zig" - "special/build_file_template.zig" "special/build_runner.zig" "special/builtin.zig" "special/compiler_rt/aulldiv.zig" @@ -618,22 +617,26 @@ set(ZIG_STD_FILES "special/compiler_rt/fixunstfdi.zig" "special/compiler_rt/fixunstfsi.zig" "special/compiler_rt/fixunstfti.zig" + "special/compiler_rt/floattidf.zig" + "special/compiler_rt/floattisf.zig" + "special/compiler_rt/floattitf.zig" "special/compiler_rt/floatunditf.zig" "special/compiler_rt/floatunsitf.zig" "special/compiler_rt/floatuntidf.zig" "special/compiler_rt/floatuntisf.zig" "special/compiler_rt/floatuntitf.zig" - "special/compiler_rt/floattidf.zig" - "special/compiler_rt/floattisf.zig" - "special/compiler_rt/floattitf.zig" - "special/compiler_rt/muloti4.zig" "special/compiler_rt/index.zig" + "special/compiler_rt/muloti4.zig" "special/compiler_rt/truncXfYf2.zig" "special/compiler_rt/udivmod.zig" "special/compiler_rt/udivmoddi4.zig" "special/compiler_rt/udivmodti4.zig" "special/compiler_rt/udivti3.zig" "special/compiler_rt/umodti3.zig" + "special/init-exe/build.zig" + "special/init-exe/src/main.zig" + "special/init-lib/build.zig" + "special/init-lib/src/main.zig" "special/panic.zig" "special/test_runner.zig" "unicode.zig" @@ -796,6 +799,9 @@ if(MSVC) set(EXE_CFLAGS "${EXE_CFLAGS}") else() set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces") + if(MINGW) + set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format") + endif() endif() set(BLAKE_CFLAGS "-std=c99") diff --git a/build.zig b/build.zig index 0bb4808dc..bc9cd4c1c 100644 --- a/build.zig +++ b/build.zig @@ -112,6 +112,7 @@ pub fn build(b: *Builder) !void { test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); test_step.dependOn(tests.addBuildExampleTests(b, test_filter, modes)); + test_step.dependOn(tests.addCliTests(b, test_filter, modes)); test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); diff --git a/doc/langref.html.in b/doc/langref.html.in index f5b92873e..9bd11b823 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5877,7 +5877,7 @@ fn add(a: i32, b: i32) i32 { {#header_open|@OpaqueType#}
{#syntax#}@OpaqueType() type{#endsyntax#}
- Creates a new type with an unknown size and alignment. + Creates a new type with an unknown (but non-zero) size and alignment.
This is typically used for type safety when interacting with C code that does not expose struct details.
diff --git a/example/hello_world/hello_windows.zig b/example/hello_world/hello_windows.zig
index f55db2ede..8016c3c49 100644
--- a/example/hello_world/hello_windows.zig
+++ b/example/hello_world/hello_windows.zig
@@ -1,5 +1,7 @@
use @import("std").os.windows;
+extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) c_int;
+
export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT {
_ = MessageBoxA(null, c"hello", c"title", 0);
return 0;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index c9ae86539..328eda786 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1470,7 +1470,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdArray:
return type_allowed_in_extern(g, type_entry->data.array.child_type);
case ZigTypeIdFn:
- return type_entry->data.fn.fn_type_id.cc == CallingConventionC;
+ return type_entry->data.fn.fn_type_id.cc == CallingConventionC ||
+ type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall;
case ZigTypeIdPointer:
if (type_size(g, type_entry) == 0)
return false;
@@ -3992,9 +3993,10 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
return (ptr_type->data.pointer.explicit_alignment == 0) ?
get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
} else if (ptr_type->id == ZigTypeIdFn) {
- return (ptr_type->data.fn.fn_type_id.alignment == 0) ?
- LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->data.fn.raw_type_ref) :
- ptr_type->data.fn.fn_type_id.alignment;
+ // I tried making this use LLVMABIAlignmentOfType but it trips this assertion in LLVM:
+ // "Cannot getTypeInfo() on a type that is unsized!"
+ // when getting the alignment of `?extern fn() void`.
+ return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
} else if (ptr_type->id == ZigTypeIdPromise) {
return get_coro_frame_align_bytes(g);
} else {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index cad3694fe..91e7c8dde 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1662,6 +1662,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
if (actual_type->id == ZigTypeIdFloat) {
return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
} else if (actual_type->id == ZigTypeIdInt) {
+ if (wanted_bits == 0) {
+ if (!want_runtime_safety)
+ return nullptr;
+
+ LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
+ LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
+ LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_safety_crash(g, PanicMsgIdCastTruncatedData);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ return nullptr;
+ }
LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
if (!want_runtime_safety) {
return trunc_val;
diff --git a/src/compiler.cpp b/src/compiler.cpp
index dd02b541d..0d4dff5d5 100644
--- a/src/compiler.cpp
+++ b/src/compiler.cpp
@@ -5,6 +5,9 @@
static Buf saved_compiler_id = BUF_INIT;
static Buf saved_app_data_dir = BUF_INIT;
static Buf saved_stage1_path = BUF_INIT;
+static Buf saved_lib_dir = BUF_INIT;
+static Buf saved_special_dir = BUF_INIT;
+static Buf saved_std_dir = BUF_INIT;
Buf *get_stage1_cache_path() {
if (saved_stage1_path.list.length != 0) {
@@ -64,3 +67,101 @@ Error get_compiler_id(Buf **result) {
return ErrorNone;
}
+
+static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) {
+ Buf lib_buf = BUF_INIT;
+ buf_init_from_str(&lib_buf, "lib");
+
+ Buf zig_buf = BUF_INIT;
+ buf_init_from_str(&zig_buf, "zig");
+
+ Buf std_buf = BUF_INIT;
+ buf_init_from_str(&std_buf, "std");
+
+ Buf index_zig_buf = BUF_INIT;
+ buf_init_from_str(&index_zig_buf, "index.zig");
+
+ Buf test_lib_dir = BUF_INIT;
+ Buf test_zig_dir = BUF_INIT;
+ Buf test_std_dir = BUF_INIT;
+ Buf test_index_file = BUF_INIT;
+
+ os_path_join(test_path, &lib_buf, &test_lib_dir);
+ os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir);
+ os_path_join(&test_zig_dir, &std_buf, &test_std_dir);
+ os_path_join(&test_std_dir, &index_zig_buf, &test_index_file);
+
+ int err;
+ bool exists;
+ if ((err = os_file_exists(&test_index_file, &exists))) {
+ exists = false;
+ }
+ if (exists) {
+ buf_init_from_buf(out_zig_lib_dir, &test_zig_dir);
+ return true;
+ }
+ return false;
+}
+
+static int find_zig_lib_dir(Buf *out_path) {
+ int err;
+
+ Buf self_exe_path = BUF_INIT;
+ buf_resize(&self_exe_path, 0);
+ if (!(err = os_self_exe_path(&self_exe_path))) {
+ Buf *cur_path = &self_exe_path;
+
+ for (;;) {
+ Buf *test_dir = buf_alloc();
+ os_path_dirname(cur_path, test_dir);
+
+ if (buf_eql_buf(test_dir, cur_path)) {
+ break;
+ }
+
+ if (test_zig_install_prefix(test_dir, out_path)) {
+ return 0;
+ }
+
+ cur_path = test_dir;
+ }
+ }
+
+ return ErrorFileNotFound;
+}
+
+Buf *get_zig_lib_dir(void) {
+ if (saved_lib_dir.list.length != 0) {
+ return &saved_lib_dir;
+ }
+ buf_resize(&saved_lib_dir, 0);
+
+ int err;
+ if ((err = find_zig_lib_dir(&saved_lib_dir))) {
+ fprintf(stderr, "Unable to find zig lib directory\n");
+ exit(EXIT_FAILURE);
+ }
+ return &saved_lib_dir;
+}
+
+Buf *get_zig_std_dir() {
+ if (saved_std_dir.list.length != 0) {
+ return &saved_std_dir;
+ }
+ buf_resize(&saved_std_dir, 0);
+
+ os_path_join(get_zig_lib_dir(), buf_create_from_str("std"), &saved_std_dir);
+
+ return &saved_std_dir;
+}
+
+Buf *get_zig_special_dir() {
+ if (saved_special_dir.list.length != 0) {
+ return &saved_special_dir;
+ }
+ buf_resize(&saved_special_dir, 0);
+
+ os_path_join(get_zig_std_dir(), buf_sprintf("special"), &saved_special_dir);
+
+ return &saved_special_dir;
+}
diff --git a/src/compiler.hpp b/src/compiler.hpp
index b95e4ceda..ffdd1cefb 100644
--- a/src/compiler.hpp
+++ b/src/compiler.hpp
@@ -14,4 +14,8 @@
Buf *get_stage1_cache_path();
Error get_compiler_id(Buf **result);
+Buf *get_zig_lib_dir();
+Buf *get_zig_special_dir();
+Buf *get_zig_std_dir();
+
#endif
diff --git a/src/ir.cpp b/src/ir.cpp
index ce044aa0f..350459db2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -10015,21 +10015,25 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
if (value->id == IrInstructionIdLoadPtr) {
IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value;
- return load_ptr_inst->ptr;
- } else {
- IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope,
- source_instr->source_node, value, true, false);
- new_instruction->value.type = wanted_type;
-
- ZigType *child_type = wanted_type->data.pointer.child_type;
- if (type_has_bits(child_type)) {
- ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- assert(fn_entry);
- fn_entry->alloca_list.append(new_instruction);
- }
- ir_add_alloca(ira, new_instruction, child_type);
- return new_instruction;
+ ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type,
+ load_ptr_inst->ptr->value.type, source_instr->source_node, false);
+ if (const_cast_result.id == ConstCastResultIdInvalid)
+ return ira->codegen->invalid_instruction;
+ if (const_cast_result.id == ConstCastResultIdOk)
+ return load_ptr_inst->ptr;
}
+ IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, value, true, false);
+ new_instruction->value.type = wanted_type;
+
+ ZigType *child_type = wanted_type->data.pointer.child_type;
+ if (type_has_bits(child_type)) {
+ ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ assert(fn_entry);
+ fn_entry->alloca_list.append(new_instruction);
+ }
+ ir_add_alloca(ira, new_instruction, child_type);
+ return new_instruction;
}
static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
@@ -11057,7 +11061,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
- // enum to &const union which has the enum as the tag type
+ // enum to *const union which has the enum as the tag type
if (actual_type->id == ZigTypeIdEnum && wanted_type->id == ZigTypeIdPointer) {
ZigType *union_type = wanted_type->data.pointer.child_type;
if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
@@ -11187,6 +11191,13 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
}
}
}
+ // dereferencing a *u0 is comptime known to be 0
+ if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
+ source_instruction->source_node, child_type);
+ init_const_unsigned_negative(&result->value, child_type, 0, false);
+ return result;
+ }
// TODO if the instruction is a const ref instruction we can skip it
IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
source_instruction->source_node, ptr);
@@ -11521,7 +11532,13 @@ static bool optional_value_is_null(ConstExprValue *val) {
static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
Error err;
IrInstruction *op1 = bin_op_instruction->op1->other;
+ if (type_is_invalid(op1->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
IrInstruction *op2 = bin_op_instruction->op2->other;
+ if (type_is_invalid(op2->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
AstNode *source_node = bin_op_instruction->base.source_node;
IrBinOp op_id = bin_op_instruction->op_id;
@@ -11564,6 +11581,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
ir_link_new_instruction(is_non_null, &bin_op_instruction->base);
}
return ira->codegen->builtin_types.entry_bool;
+ } else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) {
+ ir_add_error_node(ira, source_node, buf_sprintf("comparison against null can only be done with optionals"));
+ return ira->codegen->builtin_types.entry_invalid;
}
if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) {
@@ -12063,6 +12083,12 @@ static ZigType *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_
ir_add_error(ira, &bin_op_instruction->base,
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
return ira->codegen->builtin_types.entry_invalid;
+ } else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value.data.x_bigint) == CmpEQ) {
+ IrInstruction *result = ir_build_cast(&ira->new_irb, bin_op_instruction->base.scope,
+ bin_op_instruction->base.source_node, op1->value.type, op1, CastOpNoop);
+ result->value.type = op1->value.type;
+ ir_link_new_instruction(result, &bin_op_instruction->base);
+ return result->value.type;
}
ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
@@ -18165,17 +18191,18 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
&source_dir_path,
rel_file_path,
};
- Buf file_path = os_path_resolve(resolve_paths, 2);
+ Buf *file_path = buf_alloc();
+ *file_path = os_path_resolve(resolve_paths, 2);
// load from file system into const expr
Buf *file_contents = buf_alloc();
int err;
- if ((err = file_fetch(ira->codegen, &file_path, file_contents))) {
+ if ((err = file_fetch(ira->codegen, file_path, file_contents))) {
if (err == ErrorFileNotFound) {
- ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
+ ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(file_path)));
return ira->codegen->builtin_types.entry_invalid;
} else {
- ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
+ ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err)));
return ira->codegen->builtin_types.entry_invalid;
}
}
@@ -18494,6 +18521,9 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
}
+ if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
+
ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
src_ptr_const, src_ptr_volatile, PtrLenUnknown,
src_ptr_align, 0, 0);
@@ -20174,11 +20204,19 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
instruction->base.source_node, nullptr, ptr);
casted_ptr->value.type = dest_type;
+ if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
+ ErrorMsg *msg = ir_add_error(ira, &instruction->base,
+ buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
+ buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
+ add_error_note(ira->codegen, msg, ptr->source_node,
+ buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name)));
+ add_error_note(ira->codegen, msg, dest_type_value->source_node,
+ buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
// Keep the bigger alignment, it can only help-
// unless the target is zero bits.
- if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
-
IrInstruction *result;
if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
@@ -20216,6 +20254,11 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
codegen->is_big_endian);
return;
+ case ZigTypeIdEnum:
+ bigint_write_twos_complement(&val->data.x_enum_tag, buf,
+ val->type->data.enumeration.tag_int_type->data.integral.bit_count,
+ codegen->is_big_endian);
+ return;
case ZigTypeIdFloat:
float_write_ieee597(val, buf, codegen->is_big_endian);
return;
@@ -20247,8 +20290,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
zig_panic("TODO buf_write_value_bytes error union");
case ZigTypeIdErrorSet:
zig_panic("TODO buf_write_value_bytes pure error type");
- case ZigTypeIdEnum:
- zig_panic("TODO buf_write_value_bytes enum type");
case ZigTypeIdFn:
zig_panic("TODO buf_write_value_bytes fn type");
case ZigTypeIdUnion:
diff --git a/src/main.cpp b/src/main.cpp
index bf6c14297..95fba8d59 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -25,6 +25,8 @@ static int usage(const char *arg0) {
" build-obj [source] create object from source or assembly\n"
" builtin show the source code of that @import(\"builtin\")\n"
" id print the base64-encoded compiler id\n"
+ " init-exe initialize a `zig build` application in the cwd\n"
+ " init-lib initialize a `zig build` library in the cwd\n"
" run [source] create executable and run immediately\n"
" translate-c [source] convert c code to zig code\n"
" targets list available compilation targets\n"
@@ -34,7 +36,7 @@ static int usage(const char *arg0) {
"Compile Options:\n"
" --assembly [source] add assembly file to build\n"
" --cache-dir [path] override the cache directory\n"
- " --cache [auto|off|on] build to the global cache and print output path to stdout\n"
+ " --cache [auto|off|on] build in global cache, print out paths to stdout\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
" -ftime-report print timing diagnostics\n"
@@ -42,7 +44,7 @@ static int usage(const char *arg0) {
" --name [name] override output name\n"
" --output [file] override destination path\n"
" --output-h [file] override generated header file path\n"
- " --pkg-begin [name] [path] make package available to import and push current pkg\n"
+ " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
" --pkg-end pop current pkg\n"
" --release-fast build with optimizations on and safety off\n"
" --release-safe build with optimizations on and safety on\n"
@@ -52,17 +54,16 @@ static int usage(const char *arg0) {
" --target-arch [name] specify target architecture\n"
" --target-environ [name] specify target environment\n"
" --target-os [name] specify target operating system\n"
- " --verbose-tokenize turn on compiler debug output for tokenization\n"
- " --verbose-ast turn on compiler debug output for parsing into an AST\n"
- " --verbose-link turn on compiler debug output for linking\n"
- " --verbose-ir turn on compiler debug output for Zig IR\n"
- " --verbose-llvm-ir turn on compiler debug output for LLVM IR\n"
- " --verbose-cimport turn on compiler debug output for C imports\n"
+ " --verbose-tokenize enable compiler debug output for tokenization\n"
+ " --verbose-ast enable compiler debug output for AST parsing\n"
+ " --verbose-link enable compiler debug output for linking\n"
+ " --verbose-ir enable compiler debug output for Zig IR\n"
+ " --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
+ " --verbose-cimport enable compiler debug output for C imports\n"
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
- " -mllvm [arg] additional arguments to forward to LLVM's option processing\n"
+ " -mllvm [arg] forward an arg to LLVM's option processing\n"
"Link Options:\n"
- " --ar-path [path] set the path to ar\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
@@ -142,78 +143,6 @@ static int print_target_list(FILE *f) {
return EXIT_SUCCESS;
}
-static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) {
- Buf lib_buf = BUF_INIT;
- buf_init_from_str(&lib_buf, "lib");
-
- Buf zig_buf = BUF_INIT;
- buf_init_from_str(&zig_buf, "zig");
-
- Buf std_buf = BUF_INIT;
- buf_init_from_str(&std_buf, "std");
-
- Buf index_zig_buf = BUF_INIT;
- buf_init_from_str(&index_zig_buf, "index.zig");
-
- Buf test_lib_dir = BUF_INIT;
- Buf test_zig_dir = BUF_INIT;
- Buf test_std_dir = BUF_INIT;
- Buf test_index_file = BUF_INIT;
-
- os_path_join(test_path, &lib_buf, &test_lib_dir);
- os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir);
- os_path_join(&test_zig_dir, &std_buf, &test_std_dir);
- os_path_join(&test_std_dir, &index_zig_buf, &test_index_file);
-
- int err;
- bool exists;
- if ((err = os_file_exists(&test_index_file, &exists))) {
- exists = false;
- }
- if (exists) {
- buf_init_from_buf(out_zig_lib_dir, &test_zig_dir);
- return true;
- }
- return false;
-}
-
-static int find_zig_lib_dir(Buf *out_path) {
- int err;
-
- Buf self_exe_path = BUF_INIT;
- buf_resize(&self_exe_path, 0);
- if (!(err = os_self_exe_path(&self_exe_path))) {
- Buf *cur_path = &self_exe_path;
-
- for (;;) {
- Buf *test_dir = buf_alloc();
- os_path_dirname(cur_path, test_dir);
-
- if (buf_eql_buf(test_dir, cur_path)) {
- break;
- }
-
- if (test_zig_install_prefix(test_dir, out_path)) {
- return 0;
- }
-
- cur_path = test_dir;
- }
- }
-
- return ErrorFileNotFound;
-}
-
-static Buf *resolve_zig_lib_dir(void) {
- int err;
- Buf *result = buf_alloc();
- if ((err = find_zig_lib_dir(result))) {
- fprintf(stderr, "Unable to find zig lib directory\n");
- exit(EXIT_FAILURE);
- }
- return result;
-}
-
enum Cmd {
CmdInvalid,
CmdBuild,
@@ -277,6 +206,9 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
}
int main(int argc, char **argv) {
+ char *arg0 = argv[0];
+ Error err;
+
if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
ZIG_CMAKE_BINARY_DIR,
@@ -290,8 +222,10 @@ int main(int argc, char **argv) {
return 0;
}
+ // Must be before all os.hpp function calls.
+ os_init();
+
if (argc == 2 && strcmp(argv[1], "id") == 0) {
- Error err;
Buf *compiler_id;
if ((err = get_compiler_id(&compiler_id))) {
fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err));
@@ -301,9 +235,97 @@ int main(int argc, char **argv) {
return EXIT_SUCCESS;
}
- os_init();
+ enum InitKind {
+ InitKindNone,
+ InitKindExe,
+ InitKindLib,
+ };
+ InitKind init_kind = InitKindNone;
+ if (argc >= 2) {
+ const char *init_cmd = argv[1];
+ if (strcmp(init_cmd, "init-exe") == 0) {
+ init_kind = InitKindExe;
+ } else if (strcmp(init_cmd, "init-lib") == 0) {
+ init_kind = InitKindLib;
+ }
+ if (init_kind != InitKindNone) {
+ if (argc >= 3) {
+ fprintf(stderr, "Unexpected extra argument: %s\n", argv[2]);
+ return usage(arg0);
+ }
+ Buf *cmd_template_path = buf_alloc();
+ os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);
+ Buf *build_zig_path = buf_alloc();
+ os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path);
+ Buf *src_dir_path = buf_alloc();
+ os_path_join(cmd_template_path, buf_create_from_str("src"), src_dir_path);
+ Buf *main_zig_path = buf_alloc();
+ os_path_join(src_dir_path, buf_create_from_str("main.zig"), main_zig_path);
+
+ Buf *cwd = buf_alloc();
+ if ((err = os_get_cwd(cwd))) {
+ fprintf(stderr, "Unable to get cwd: %s\n", err_str(err));
+ return EXIT_FAILURE;
+ }
+ Buf *cwd_basename = buf_alloc();
+ os_path_split(cwd, nullptr, cwd_basename);
+
+ Buf *build_zig_contents = buf_alloc();
+ if ((err = os_fetch_file_path(build_zig_path, build_zig_contents, false))) {
+ fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err));
+ return EXIT_FAILURE;
+ }
+ Buf *modified_build_zig_contents = buf_alloc();
+ for (size_t i = 0; i < buf_len(build_zig_contents); i += 1) {
+ char c = buf_ptr(build_zig_contents)[i];
+ if (c == '$') {
+ buf_append_buf(modified_build_zig_contents, cwd_basename);
+ } else {
+ buf_append_char(modified_build_zig_contents, c);
+ }
+ }
+
+ Buf *main_zig_contents = buf_alloc();
+ if ((err = os_fetch_file_path(main_zig_path, main_zig_contents, false))) {
+ fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err));
+ return EXIT_FAILURE;
+ }
+
+ Buf *out_build_zig_path = buf_create_from_str("build.zig");
+ Buf *out_src_dir_path = buf_create_from_str("src");
+ Buf *out_main_zig_path = buf_alloc();
+ os_path_join(out_src_dir_path, buf_create_from_str("main.zig"), out_main_zig_path);
+
+ bool already_exists;
+ if ((err = os_file_exists(out_build_zig_path, &already_exists))) {
+ fprintf(stderr, "Unable test existence of %s: %s\n", buf_ptr(out_build_zig_path), err_str(err));
+ return EXIT_FAILURE;
+ }
+ if (already_exists) {
+ fprintf(stderr, "This file would be overwritten: %s\n", buf_ptr(out_build_zig_path));
+ return EXIT_FAILURE;
+ }
+
+ if ((err = os_make_dir(out_src_dir_path))) {
+ fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err));
+ return EXIT_FAILURE;
+ }
+ os_write_file(out_build_zig_path, modified_build_zig_contents);
+ os_write_file(out_main_zig_path, main_zig_contents);
+ fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path));
+ fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path));
+ if (init_kind == InitKindExe) {
+ fprintf(stderr, "\nNext, try `zig build --help` or `zig build run`\n");
+ } else if (init_kind == InitKindLib) {
+ fprintf(stderr, "\nNext, try `zig build --help` or `zig build test`\n");
+ } else {
+ zig_unreachable();
+ }
+
+ return EXIT_SUCCESS;
+ }
+ }
- char *arg0 = argv[0];
Cmd cmd = CmdInvalid;
EmitFileType emit_file_type = EmitFileTypeBinary;
const char *in_file = nullptr;
@@ -333,7 +355,6 @@ int main(int argc, char **argv) {
ZigList