mirror of
https://github.com/ziglang/zig.git
synced 2024-12-14 15:20:13 +00:00
build system: consolidate duplicate code and more
* add ability to add assembly files when building an exe, obj, or lib * add implicit cast from `[N]T` to `?[]const T` (closes #343) * remove link_exe and link_lib in favor of allowing build_exe and build_lib support no root zig source file
This commit is contained in:
parent
09bc4d6ba3
commit
7b0542d08b
@ -1296,6 +1296,7 @@ struct CodeGen {
|
|||||||
LLVMBuilderRef builder;
|
LLVMBuilderRef builder;
|
||||||
ZigLLVMDIBuilder *dbuilder;
|
ZigLLVMDIBuilder *dbuilder;
|
||||||
ZigLLVMDICompileUnit *compile_unit;
|
ZigLLVMDICompileUnit *compile_unit;
|
||||||
|
ZigLLVMDIFile *compile_unit_file;
|
||||||
|
|
||||||
ZigList<Buf *> link_libs; // non-libc link libs
|
ZigList<Buf *> link_libs; // non-libc link libs
|
||||||
// add -framework [name] args to linker
|
// add -framework [name] args to linker
|
||||||
@ -1468,6 +1469,7 @@ struct CodeGen {
|
|||||||
|
|
||||||
Buf global_asm;
|
Buf global_asm;
|
||||||
ZigList<Buf *> link_objects;
|
ZigList<Buf *> link_objects;
|
||||||
|
ZigList<Buf *> assembly_files;
|
||||||
|
|
||||||
ZigList<TypeTableEntry *> name_table_enums;
|
ZigList<TypeTableEntry *> name_table_enums;
|
||||||
|
|
||||||
|
@ -2851,9 +2851,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
|
|||||||
node->data.use.value = result;
|
node->data.use.value = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
|
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code) {
|
||||||
Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code)
|
|
||||||
{
|
|
||||||
if (g->verbose) {
|
if (g->verbose) {
|
||||||
fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(abs_full_path));
|
fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(abs_full_path));
|
||||||
fprintf(stderr, "----------------\n");
|
fprintf(stderr, "----------------\n");
|
||||||
@ -2894,7 +2892,10 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
|
|||||||
ast_print(stderr, import_entry->root, 0);
|
ast_print(stderr, import_entry->root, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: assert that src_basename has no '/' in it
|
Buf *src_dirname = buf_alloc();
|
||||||
|
Buf *src_basename = buf_alloc();
|
||||||
|
os_path_split(abs_full_path, src_dirname, src_basename);
|
||||||
|
|
||||||
import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
||||||
g->import_table.put(abs_full_path, import_entry);
|
g->import_table.put(abs_full_path, import_entry);
|
||||||
g->import_queue.append(import_entry);
|
g->import_queue.append(import_entry);
|
||||||
|
@ -40,8 +40,7 @@ void find_libc_lib_path(CodeGen *g);
|
|||||||
bool type_has_bits(TypeTableEntry *type_entry);
|
bool type_has_bits(TypeTableEntry *type_entry);
|
||||||
|
|
||||||
|
|
||||||
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
|
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
|
||||||
Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);
|
|
||||||
|
|
||||||
|
|
||||||
// TODO move these over, these used to be static
|
// TODO move these over, these used to be static
|
||||||
|
103
src/codegen.cpp
103
src/codegen.cpp
@ -55,7 +55,7 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
|
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {
|
||||||
CodeGen *g = allocate<CodeGen>(1);
|
CodeGen *g = allocate<CodeGen>(1);
|
||||||
|
|
||||||
codegen_add_time_event(g, "Initialize");
|
codegen_add_time_event(g, "Initialize");
|
||||||
@ -81,9 +81,17 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
|
|||||||
// reserve index 0 to indicate no error
|
// reserve index 0 to indicate no error
|
||||||
g->error_decls.append(nullptr);
|
g->error_decls.append(nullptr);
|
||||||
|
|
||||||
g->root_package = new_package(buf_ptr(root_source_dir), "");
|
if (root_src_path) {
|
||||||
g->std_package = new_package(ZIG_STD_DIR, "index.zig");
|
Buf *src_basename = buf_alloc();
|
||||||
g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
|
Buf *src_dir = buf_alloc();
|
||||||
|
os_path_split(root_src_path, src_dir, src_basename);
|
||||||
|
|
||||||
|
g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename));
|
||||||
|
g->std_package = new_package(ZIG_STD_DIR, "index.zig");
|
||||||
|
g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
|
||||||
|
} else {
|
||||||
|
g->root_package = new_package(".", "");
|
||||||
|
}
|
||||||
g->zig_std_dir = buf_create_from_str(ZIG_STD_DIR);
|
g->zig_std_dir = buf_create_from_str(ZIG_STD_DIR);
|
||||||
|
|
||||||
g->zig_std_special_dir = buf_alloc();
|
g->zig_std_special_dir = buf_alloc();
|
||||||
@ -757,7 +765,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
|
|||||||
|
|
||||||
static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) {
|
static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) {
|
||||||
LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
|
LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
|
||||||
LLVMBuildCall(g->builder, safety_crash_err_fn, &err_val, 1, "");
|
ZigLLVMBuildCall(g->builder, safety_crash_err_fn, &err_val, 1, LLVMFastCallConv, false, "");
|
||||||
LLVMBuildUnreachable(g->builder);
|
LLVMBuildUnreachable(g->builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3655,6 +3663,10 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void do_code_gen(CodeGen *g) {
|
static void do_code_gen(CodeGen *g) {
|
||||||
|
if (g->verbose) {
|
||||||
|
fprintf(stderr, "\nCode Generation:\n");
|
||||||
|
fprintf(stderr, "------------------\n");
|
||||||
|
}
|
||||||
assert(!g->errors.length);
|
assert(!g->errors.length);
|
||||||
|
|
||||||
codegen_add_time_event(g, "Code Generation");
|
codegen_add_time_event(g, "Code Generation");
|
||||||
@ -4602,8 +4614,9 @@ static void define_builtin_compile_vars(CodeGen *g) {
|
|||||||
add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false));
|
add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init(CodeGen *g, Buf *source_path) {
|
static void init(CodeGen *g) {
|
||||||
g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
|
assert(g->root_out_name);
|
||||||
|
g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
|
||||||
|
|
||||||
get_target_triple(&g->triple_str, &g->zig_target);
|
get_target_triple(&g->triple_str, &g->zig_target);
|
||||||
|
|
||||||
@ -4674,23 +4687,25 @@ static void init(CodeGen *g, Buf *source_path) {
|
|||||||
g->const_void_val.type = g->builtin_types.entry_void;
|
g->const_void_val.type = g->builtin_types.entry_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
|
void codegen_parseh(CodeGen *g, Buf *full_path) {
|
||||||
find_libc_include_path(g);
|
find_libc_include_path(g);
|
||||||
Buf *full_path = buf_alloc();
|
|
||||||
os_path_join(src_dirname, src_basename, full_path);
|
Buf *src_basename = buf_alloc();
|
||||||
|
Buf *src_dirname = buf_alloc();
|
||||||
|
os_path_split(full_path, src_dirname, src_basename);
|
||||||
|
|
||||||
ImportTableEntry *import = allocate<ImportTableEntry>(1);
|
ImportTableEntry *import = allocate<ImportTableEntry>(1);
|
||||||
import->source_code = source_code;
|
import->source_code = nullptr;
|
||||||
import->path = full_path;
|
import->path = full_path;
|
||||||
g->root_import = import;
|
g->root_import = import;
|
||||||
import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import);
|
import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import);
|
||||||
|
|
||||||
init(g, full_path);
|
init(g);
|
||||||
|
|
||||||
import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
||||||
|
|
||||||
ZigList<ErrorMsg *> errors = {0};
|
ZigList<ErrorMsg *> errors = {0};
|
||||||
int err = parse_h_buf(import, &errors, source_code, g, nullptr);
|
int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
|
fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -4719,7 +4734,7 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
|
|||||||
zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
|
zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
return add_source_file(g, package, abs_full_path, g->zig_std_special_dir, code_basename, import_code);
|
return add_source_file(g, package, abs_full_path, import_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
|
static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
|
||||||
@ -4736,23 +4751,27 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {
|
|||||||
return package;
|
return package;
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
|
static void gen_root_source(CodeGen *g) {
|
||||||
|
if (buf_len(&g->root_package->root_src_path) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
codegen_add_time_event(g, "Semantic Analysis");
|
codegen_add_time_event(g, "Semantic Analysis");
|
||||||
|
|
||||||
Buf source_path = BUF_INIT;
|
Buf *rel_full_path = buf_alloc();
|
||||||
os_path_join(src_dir, src_basename, &source_path);
|
os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, rel_full_path);
|
||||||
|
|
||||||
buf_init_from_buf(&g->root_package->root_src_path, src_basename);
|
|
||||||
|
|
||||||
init(g, &source_path);
|
|
||||||
|
|
||||||
Buf *abs_full_path = buf_alloc();
|
Buf *abs_full_path = buf_alloc();
|
||||||
int err;
|
int err;
|
||||||
if ((err = os_path_real(&source_path, abs_full_path))) {
|
if ((err = os_path_real(rel_full_path, abs_full_path))) {
|
||||||
zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));
|
zig_panic("unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
g->root_import = add_source_file(g, g->root_package, abs_full_path, src_dir, src_basename, source_code);
|
Buf *source_code = buf_alloc();
|
||||||
|
if ((err = os_fetch_file_path(rel_full_path, source_code))) {
|
||||||
|
zig_panic("unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
g->root_import = add_source_file(g, g->root_package, abs_full_path, source_code);
|
||||||
|
|
||||||
assert(g->root_out_name);
|
assert(g->root_out_name);
|
||||||
assert(g->out_type != OutTypeUnknown);
|
assert(g->out_type != OutTypeUnknown);
|
||||||
@ -4787,27 +4806,33 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g->verbose) {
|
|
||||||
fprintf(stderr, "\nCode Generation:\n");
|
|
||||||
fprintf(stderr, "------------------\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
do_code_gen(g);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen_add_root_assembly(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
|
void codegen_add_assembly(CodeGen *g, Buf *path) {
|
||||||
Buf source_path = BUF_INIT;
|
g->assembly_files.append(path);
|
||||||
os_path_join(src_dir, src_basename, &source_path);
|
}
|
||||||
|
|
||||||
init(g, &source_path);
|
static void gen_global_asm(CodeGen *g) {
|
||||||
|
Buf contents = BUF_INIT;
|
||||||
|
int err;
|
||||||
|
for (size_t i = 0; i < g->assembly_files.length; i += 1) {
|
||||||
|
Buf *asm_file = g->assembly_files.at(i);
|
||||||
|
if ((err = os_fetch_file_path(asm_file, &contents))) {
|
||||||
|
zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
|
||||||
|
}
|
||||||
|
if (g->zig_target.arch.arch == ZigLLVM_x86 || g->zig_target.arch.arch == ZigLLVM_x86_64) {
|
||||||
|
buf_append_str(&g->global_asm, ".intel_syntax noprefix\n");
|
||||||
|
}
|
||||||
|
buf_append_buf(&g->global_asm, &contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(g->root_out_name);
|
void codegen_build(CodeGen *g) {
|
||||||
assert(g->out_type != OutTypeUnknown);
|
assert(g->out_type != OutTypeUnknown);
|
||||||
|
init(g);
|
||||||
|
|
||||||
buf_init_from_str(&g->global_asm, ".intel_syntax noprefix\n");
|
gen_global_asm(g);
|
||||||
buf_append_buf(&g->global_asm, source_code);
|
gen_root_source(g);
|
||||||
|
|
||||||
do_code_gen(g);
|
do_code_gen(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);
|
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target);
|
||||||
|
|
||||||
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
|
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
|
||||||
void codegen_set_is_release(CodeGen *codegen, bool is_release);
|
void codegen_set_is_release(CodeGen *codegen, bool is_release);
|
||||||
@ -49,13 +49,13 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
|
|||||||
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
|
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
|
||||||
void codegen_add_time_event(CodeGen *g, const char *name);
|
void codegen_add_time_event(CodeGen *g, const char *name);
|
||||||
void codegen_print_timing_report(CodeGen *g, FILE *f);
|
void codegen_print_timing_report(CodeGen *g, FILE *f);
|
||||||
|
void codegen_build(CodeGen *g);
|
||||||
|
|
||||||
PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);
|
PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);
|
||||||
void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
|
void codegen_add_assembly(CodeGen *g, Buf *path);
|
||||||
void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
|
|
||||||
void codegen_add_object(CodeGen *g, Buf *object_path);
|
void codegen_add_object(CodeGen *g, Buf *object_path);
|
||||||
|
|
||||||
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);
|
void codegen_parseh(CodeGen *g, Buf *path);
|
||||||
void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
|
void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
|
||||||
|
|
||||||
void codegen_generate_h_file(CodeGen *g);
|
void codegen_generate_h_file(CodeGen *g);
|
||||||
|
41
src/ir.cpp
41
src/ir.cpp
@ -6043,6 +6043,21 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implicit [N]T to ?[]const N
|
||||||
|
if (expected_type->id == TypeTableEntryIdMaybe &&
|
||||||
|
is_slice(expected_type->data.maybe.child_type) &&
|
||||||
|
actual_type->id == TypeTableEntryIdArray)
|
||||||
|
{
|
||||||
|
TypeTableEntry *ptr_type =
|
||||||
|
expected_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||||
|
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||||
|
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
|
||||||
|
types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
|
||||||
|
{
|
||||||
|
return ImplicitCastMatchResultYes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implicit number literal to typed number
|
// implicit number literal to typed number
|
||||||
// implicit number literal to &const integer
|
// implicit number literal to &const integer
|
||||||
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
|
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
|
||||||
@ -7093,6 +7108,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// explicit cast from [N]T to ?[]const N
|
||||||
|
if (wanted_type->id == TypeTableEntryIdMaybe &&
|
||||||
|
is_slice(wanted_type->data.maybe.child_type) &&
|
||||||
|
actual_type->id == TypeTableEntryIdArray)
|
||||||
|
{
|
||||||
|
TypeTableEntry *ptr_type =
|
||||||
|
wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||||
|
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||||
|
if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
|
||||||
|
types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
|
||||||
|
{
|
||||||
|
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
|
||||||
|
if (type_is_invalid(cast1->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
|
||||||
|
if (type_is_invalid(cast2->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
return cast2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// explicit cast from []T to []u8 or []u8 to []T
|
// explicit cast from []T to []u8 or []u8 to []T
|
||||||
if (is_slice(wanted_type) && is_slice(actual_type) &&
|
if (is_slice(wanted_type) && is_slice(actual_type) &&
|
||||||
(is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||
|
(is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||
|
||||||
@ -10880,8 +10918,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi
|
|||||||
return ira->codegen->builtin_types.entry_invalid;
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportTableEntry *target_import = add_source_file(ira->codegen, target_package,
|
ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code);
|
||||||
abs_full_path, search_dir, import_target_path, import_code);
|
|
||||||
|
|
||||||
scan_decls(ira->codegen, target_import->decls_scope, target_import->root);
|
scan_decls(ira->codegen, target_import->decls_scope, target_import->root);
|
||||||
|
|
||||||
|
14
src/link.cpp
14
src/link.cpp
@ -33,9 +33,11 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
|
|||||||
|
|
||||||
static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
||||||
Buf *source_basename = buf_sprintf("%s.zig", oname);
|
Buf *source_basename = buf_sprintf("%s.zig", oname);
|
||||||
|
Buf *full_path = buf_alloc();
|
||||||
|
os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
|
||||||
|
|
||||||
ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
|
ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
|
||||||
CodeGen *child_gen = codegen_create(parent_gen->zig_std_special_dir, child_target);
|
CodeGen *child_gen = codegen_create(full_path, child_target);
|
||||||
child_gen->link_libc = parent_gen->link_libc;
|
child_gen->link_libc = parent_gen->link_libc;
|
||||||
|
|
||||||
child_gen->link_libs.resize(parent_gen->link_libs.length);
|
child_gen->link_libs.resize(parent_gen->link_libs.length);
|
||||||
@ -60,15 +62,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
|||||||
codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
|
codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
|
||||||
codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
|
codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
|
||||||
|
|
||||||
Buf *full_path = buf_alloc();
|
codegen_build(child_gen);
|
||||||
os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
|
|
||||||
|
|
||||||
Buf source_code = BUF_INIT;
|
|
||||||
if (os_fetch_file_path(full_path, &source_code)) {
|
|
||||||
zig_panic("unable to fetch file: %s\n", buf_ptr(full_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
codegen_add_root_code(child_gen, parent_gen->zig_std_special_dir, source_basename, &source_code);
|
|
||||||
const char *o_ext = target_o_file_ext(&child_gen->zig_target);
|
const char *o_ext = target_o_file_ext(&child_gen->zig_target);
|
||||||
Buf *o_out = buf_sprintf("%s%s", oname, o_ext);
|
Buf *o_out = buf_sprintf("%s%s", oname, o_ext);
|
||||||
codegen_link(child_gen, buf_ptr(o_out));
|
codegen_link(child_gen, buf_ptr(o_out));
|
||||||
|
185
src/main.cpp
185
src/main.cpp
@ -19,29 +19,19 @@
|
|||||||
static int usage(const char *arg0) {
|
static int usage(const char *arg0) {
|
||||||
fprintf(stderr, "Usage: %s [command] [options]\n"
|
fprintf(stderr, "Usage: %s [command] [options]\n"
|
||||||
"Commands:\n"
|
"Commands:\n"
|
||||||
" asm [source] create object from assembly\n"
|
|
||||||
" build build project from build.zig\n"
|
" build build project from build.zig\n"
|
||||||
" build_exe [source] create executable from source\n"
|
" build_exe [source] create executable from source or object files\n"
|
||||||
" build_lib [source] create library from source\n"
|
" build_lib [source] create library from source or object files\n"
|
||||||
" build_obj [source] create object from source\n"
|
" build_obj [source] create object from source or assembly\n"
|
||||||
" link_exe [objects] create executable from objects\n"
|
|
||||||
" link_lib [objects] create library from objects\n"
|
|
||||||
" parseh [source] convert a c header file to zig extern declarations\n"
|
" parseh [source] convert a c header file to zig extern declarations\n"
|
||||||
" targets list available compilation targets\n"
|
" targets list available compilation targets\n"
|
||||||
" test [source] create and run a test build\n"
|
" test [source] create and run a test build\n"
|
||||||
" version print version number and exit\n"
|
" version print version number and exit\n"
|
||||||
"Options:\n"
|
"Compile Options:\n"
|
||||||
" --ar-path [path] set the path to ar\n"
|
" --assembly [source] add assembly file to build\n"
|
||||||
" --color [auto|off|on] enable or disable colored error messages\n"
|
" --color [auto|off|on] enable or disable colored error messages\n"
|
||||||
" --dynamic-linker [path] set the path to ld.so\n"
|
" --enable-timing-info print timing diagnostics\n"
|
||||||
" --each-lib-rpath add rpath for each used dynamic library\n"
|
|
||||||
" --ld-path [path] set the path to the linker\n"
|
|
||||||
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
|
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
|
||||||
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
|
|
||||||
" --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
|
|
||||||
" --library [lib] link against lib\n"
|
|
||||||
" --library-path [dir] add a directory to the library search path\n"
|
|
||||||
" --linker-script [path] use a custom linker script\n"
|
|
||||||
" --name [name] override output name\n"
|
" --name [name] override output name\n"
|
||||||
" --output [file] override destination path\n"
|
" --output [file] override destination path\n"
|
||||||
" --release build with optimizations on and debug protection off\n"
|
" --release build with optimizations on and debug protection off\n"
|
||||||
@ -52,26 +42,34 @@ static int usage(const char *arg0) {
|
|||||||
" --target-os [name] specify target operating system\n"
|
" --target-os [name] specify target operating system\n"
|
||||||
" --verbose turn on compiler debug output\n"
|
" --verbose turn on compiler debug output\n"
|
||||||
" --zig-std-dir [path] directory where zig standard library resides\n"
|
" --zig-std-dir [path] directory where zig standard library resides\n"
|
||||||
" -L[dir] alias for --library-path\n"
|
|
||||||
" -dirafter [dir] same as -isystem but do it last\n"
|
" -dirafter [dir] same as -isystem but do it last\n"
|
||||||
" -framework [name] (darwin only) link against framework\n"
|
|
||||||
" -isystem [dir] add additional search path for other .h files\n"
|
" -isystem [dir] add additional search path for other .h files\n"
|
||||||
" -mconsole (windows only) --subsystem console to the linker\n"
|
"Link Options:\n"
|
||||||
" -mios-version-min [ver] (darwin only) set iOS deployment target\n"
|
" --ar-path [path] set the path to ar\n"
|
||||||
" -mlinker-version [ver] (darwin only) override linker version\n"
|
" --dynamic-linker [path] set the path to ld.so\n"
|
||||||
" -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"
|
" --each-lib-rpath add rpath for each used dynamic library\n"
|
||||||
" -municode (windows only) link with unicode\n"
|
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
|
||||||
" -mwindows (windows only) --subsystem windows to the linker\n"
|
" --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
|
||||||
|
" --library [lib] link against lib\n"
|
||||||
|
" --library-path [dir] add a directory to the library search path\n"
|
||||||
|
" --linker-script [path] use a custom linker script\n"
|
||||||
|
" --object [obj] add object file to build\n"
|
||||||
|
" -L[dir] alias for --library-path\n"
|
||||||
" -rdynamic add all symbols to the dynamic symbol table\n"
|
" -rdynamic add all symbols to the dynamic symbol table\n"
|
||||||
" -rpath [path] add directory to the runtime library search path\n"
|
" -rpath [path] add directory to the runtime library search path\n"
|
||||||
" --enable-timing-info print timing diagnostics\n"
|
" -mconsole (windows) --subsystem console to the linker\n"
|
||||||
|
" -mwindows (windows) --subsystem windows to the linker\n"
|
||||||
|
" -municode (windows) link with unicode\n"
|
||||||
|
" -framework [name] (darwin) link against framework\n"
|
||||||
|
" -mios-version-min [ver] (darwin) set iOS deployment target\n"
|
||||||
|
" -mlinker-version [ver] (darwin) override linker version\n"
|
||||||
|
" -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
|
||||||
|
" --ver-major [ver] dynamic library semver major version\n"
|
||||||
|
" --ver-minor [ver] dynamic library semver minor version\n"
|
||||||
|
" --ver-patch [ver] dynamic library semver patch version\n"
|
||||||
"Test Options:\n"
|
"Test Options:\n"
|
||||||
" --test-filter [text] skip tests that do not match filter\n"
|
" --test-filter [text] skip tests that do not match filter\n"
|
||||||
" --test-name-prefix [text] add prefix to all tests\n"
|
" --test-name-prefix [text] add prefix to all tests\n"
|
||||||
"Dynamic Library Options:\n"
|
|
||||||
" --ver-major [ver] semver major version\n"
|
|
||||||
" --ver-minor [ver] semver minor version\n"
|
|
||||||
" --ver-patch [ver] semver patch version\n"
|
|
||||||
, arg0);
|
, arg0);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -117,8 +115,6 @@ enum Cmd {
|
|||||||
CmdVersion,
|
CmdVersion,
|
||||||
CmdParseH,
|
CmdParseH,
|
||||||
CmdTargets,
|
CmdTargets,
|
||||||
CmdAsm,
|
|
||||||
CmdLink,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
@ -159,6 +155,7 @@ int main(int argc, char **argv) {
|
|||||||
ZigList<const char *> rpath_list = {0};
|
ZigList<const char *> rpath_list = {0};
|
||||||
bool each_lib_rpath = false;
|
bool each_lib_rpath = false;
|
||||||
ZigList<const char *> objects = {0};
|
ZigList<const char *> objects = {0};
|
||||||
|
ZigList<const char *> asm_files = {0};
|
||||||
const char *test_filter = nullptr;
|
const char *test_filter = nullptr;
|
||||||
const char *test_name_prefix = nullptr;
|
const char *test_name_prefix = nullptr;
|
||||||
size_t ver_major = 0;
|
size_t ver_major = 0;
|
||||||
@ -197,16 +194,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodeGen *g = codegen_create(build_runner_path, nullptr);
|
||||||
Buf root_source_dir = BUF_INIT;
|
|
||||||
Buf root_source_code = BUF_INIT;
|
|
||||||
Buf root_source_name = BUF_INIT;
|
|
||||||
os_path_split(build_runner_path, &root_source_dir, &root_source_name);
|
|
||||||
if ((err = os_fetch_file_path(build_runner_path, &root_source_code))) {
|
|
||||||
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(build_runner_path), err_str(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
CodeGen *g = codegen_create(&root_source_dir, nullptr);
|
|
||||||
codegen_set_out_name(g, buf_create_from_str("build"));
|
codegen_set_out_name(g, buf_create_from_str("build"));
|
||||||
codegen_set_out_type(g, OutTypeExe);
|
codegen_set_out_type(g, OutTypeExe);
|
||||||
codegen_set_verbose(g, verbose);
|
codegen_set_verbose(g, verbose);
|
||||||
@ -256,7 +244,7 @@ int main(int argc, char **argv) {
|
|||||||
PackageTableEntry *build_pkg = new_package(buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename));
|
PackageTableEntry *build_pkg = new_package(buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename));
|
||||||
build_pkg->package_table.put(buf_create_from_str("std"), g->std_package);
|
build_pkg->package_table.put(buf_create_from_str("std"), g->std_package);
|
||||||
g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
|
g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
|
||||||
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
|
codegen_build(g);
|
||||||
codegen_link(g, "build");
|
codegen_link(g, "build");
|
||||||
|
|
||||||
Termination term;
|
Termination term;
|
||||||
@ -339,6 +327,10 @@ int main(int argc, char **argv) {
|
|||||||
lib_dirs.append(argv[i]);
|
lib_dirs.append(argv[i]);
|
||||||
} else if (strcmp(arg, "--library") == 0) {
|
} else if (strcmp(arg, "--library") == 0) {
|
||||||
link_libs.append(argv[i]);
|
link_libs.append(argv[i]);
|
||||||
|
} else if (strcmp(arg, "--object") == 0) {
|
||||||
|
objects.append(argv[i]);
|
||||||
|
} else if (strcmp(arg, "--assembly") == 0) {
|
||||||
|
asm_files.append(argv[i]);
|
||||||
} else if (strcmp(arg, "--target-arch") == 0) {
|
} else if (strcmp(arg, "--target-arch") == 0) {
|
||||||
target_arch = argv[i];
|
target_arch = argv[i];
|
||||||
} else if (strcmp(arg, "--target-os") == 0) {
|
} else if (strcmp(arg, "--target-os") == 0) {
|
||||||
@ -382,12 +374,6 @@ int main(int argc, char **argv) {
|
|||||||
} else if (strcmp(arg, "build_lib") == 0) {
|
} else if (strcmp(arg, "build_lib") == 0) {
|
||||||
cmd = CmdBuild;
|
cmd = CmdBuild;
|
||||||
out_type = OutTypeLib;
|
out_type = OutTypeLib;
|
||||||
} else if (strcmp(arg, "link_lib") == 0) {
|
|
||||||
cmd = CmdLink;
|
|
||||||
out_type = OutTypeLib;
|
|
||||||
} else if (strcmp(arg, "link_exe") == 0) {
|
|
||||||
cmd = CmdLink;
|
|
||||||
out_type = OutTypeExe;
|
|
||||||
} else if (strcmp(arg, "version") == 0) {
|
} else if (strcmp(arg, "version") == 0) {
|
||||||
cmd = CmdVersion;
|
cmd = CmdVersion;
|
||||||
} else if (strcmp(arg, "parseh") == 0) {
|
} else if (strcmp(arg, "parseh") == 0) {
|
||||||
@ -396,8 +382,6 @@ int main(int argc, char **argv) {
|
|||||||
cmd = CmdTest;
|
cmd = CmdTest;
|
||||||
} else if (strcmp(arg, "targets") == 0) {
|
} else if (strcmp(arg, "targets") == 0) {
|
||||||
cmd = CmdTargets;
|
cmd = CmdTargets;
|
||||||
} else if (strcmp(arg, "asm") == 0) {
|
|
||||||
cmd = CmdAsm;
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unrecognized command: %s\n", arg);
|
fprintf(stderr, "Unrecognized command: %s\n", arg);
|
||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
@ -407,16 +391,12 @@ int main(int argc, char **argv) {
|
|||||||
case CmdBuild:
|
case CmdBuild:
|
||||||
case CmdParseH:
|
case CmdParseH:
|
||||||
case CmdTest:
|
case CmdTest:
|
||||||
case CmdAsm:
|
|
||||||
if (!in_file) {
|
if (!in_file) {
|
||||||
in_file = arg;
|
in_file = arg;
|
||||||
} else {
|
} else {
|
||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CmdLink:
|
|
||||||
objects.append(arg);
|
|
||||||
break;
|
|
||||||
case CmdVersion:
|
case CmdVersion:
|
||||||
case CmdTargets:
|
case CmdTargets:
|
||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
@ -430,25 +410,19 @@ int main(int argc, char **argv) {
|
|||||||
case CmdBuild:
|
case CmdBuild:
|
||||||
case CmdParseH:
|
case CmdParseH:
|
||||||
case CmdTest:
|
case CmdTest:
|
||||||
case CmdAsm:
|
|
||||||
case CmdLink:
|
|
||||||
{
|
{
|
||||||
bool one_source_input = (cmd == CmdBuild || cmd == CmdParseH || cmd == CmdTest || cmd == CmdAsm);
|
if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
|
||||||
if (one_source_input) {
|
fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
|
||||||
if (!in_file) {
|
return usage(arg0);
|
||||||
fprintf(stderr, "Expected source file argument.\n");
|
} else if ((cmd == CmdParseH || cmd == CmdTest) && !in_file) {
|
||||||
return usage(arg0);
|
fprintf(stderr, "Expected source file argument.\n");
|
||||||
}
|
return usage(arg0);
|
||||||
} else if (cmd == CmdLink) {
|
} else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
|
||||||
if (objects.length == 0) {
|
fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
|
||||||
fprintf(stderr, "Expected one or more object arguments.\n");
|
return usage(arg0);
|
||||||
return usage(arg0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
zig_unreachable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert((cmd != CmdBuild && cmd != CmdLink) || out_type != OutTypeUnknown);
|
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
|
||||||
|
|
||||||
init_all_targets();
|
init_all_targets();
|
||||||
|
|
||||||
@ -479,45 +453,22 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_name = (cmd == CmdBuild || cmd == CmdAsm || cmd == CmdLink || cmd == CmdParseH);
|
bool need_name = (cmd == CmdBuild || cmd == CmdParseH);
|
||||||
|
|
||||||
Buf in_file_buf = BUF_INIT;
|
Buf *in_file_buf = nullptr;
|
||||||
|
|
||||||
Buf root_source_dir = BUF_INIT;
|
|
||||||
Buf root_source_code = BUF_INIT;
|
|
||||||
Buf root_source_name = BUF_INIT;
|
|
||||||
|
|
||||||
Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :
|
Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :
|
||||||
(out_name == nullptr) ? nullptr : buf_create_from_str(out_name);
|
(out_name == nullptr) ? nullptr : buf_create_from_str(out_name);
|
||||||
|
|
||||||
if (one_source_input) {
|
if (in_file) {
|
||||||
buf_init_from_str(&in_file_buf, in_file);
|
in_file_buf = buf_create_from_str(in_file);
|
||||||
|
|
||||||
if (buf_eql_str(&in_file_buf, "-")) {
|
if (need_name && buf_out_name == nullptr) {
|
||||||
os_get_cwd(&root_source_dir);
|
Buf basename = BUF_INIT;
|
||||||
if ((err = os_fetch_file(stdin, &root_source_code))) {
|
os_path_split(in_file_buf, nullptr, &basename);
|
||||||
fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
|
buf_out_name = buf_alloc();
|
||||||
return 1;
|
os_path_extname(&basename, buf_out_name, nullptr);
|
||||||
}
|
|
||||||
buf_init_from_str(&root_source_name, "");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
|
|
||||||
if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) {
|
|
||||||
fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_name && buf_out_name == nullptr) {
|
|
||||||
buf_out_name = buf_alloc();
|
|
||||||
Buf ext_name = BUF_INIT;
|
|
||||||
os_path_extname(&root_source_name, buf_out_name, &ext_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (cmd == CmdLink) {
|
|
||||||
os_get_cwd(&root_source_dir);
|
|
||||||
} else {
|
|
||||||
zig_unreachable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_name && buf_out_name == nullptr) {
|
if (need_name && buf_out_name == nullptr) {
|
||||||
@ -525,7 +476,10 @@ int main(int argc, char **argv) {
|
|||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGen *g = codegen_create(&root_source_dir, target);
|
Buf *zig_root_source_file = (cmd == CmdParseH) ? nullptr : in_file_buf;
|
||||||
|
|
||||||
|
CodeGen *g = codegen_create(zig_root_source_file, target);
|
||||||
|
codegen_set_out_name(g, buf_out_name);
|
||||||
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
|
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
|
||||||
codegen_set_is_release(g, is_release_build);
|
codegen_set_is_release(g, is_release_build);
|
||||||
codegen_set_is_test(g, cmd == CmdTest);
|
codegen_set_is_test(g, cmd == CmdTest);
|
||||||
@ -536,14 +490,11 @@ int main(int argc, char **argv) {
|
|||||||
codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
|
codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
|
||||||
codegen_set_strip(g, strip);
|
codegen_set_strip(g, strip);
|
||||||
codegen_set_is_static(g, is_static);
|
codegen_set_is_static(g, is_static);
|
||||||
if (cmd == CmdAsm) {
|
if (out_type != OutTypeUnknown) {
|
||||||
codegen_set_out_type(g, OutTypeObj);
|
|
||||||
} else if (out_type != OutTypeUnknown) {
|
|
||||||
codegen_set_out_type(g, out_type);
|
codegen_set_out_type(g, out_type);
|
||||||
} else if (cmd == CmdTest) {
|
} else if (cmd == CmdTest) {
|
||||||
codegen_set_out_type(g, OutTypeExe);
|
codegen_set_out_type(g, OutTypeExe);
|
||||||
}
|
}
|
||||||
codegen_set_out_name(g, buf_out_name);
|
|
||||||
if (libc_lib_dir)
|
if (libc_lib_dir)
|
||||||
codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
|
codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
|
||||||
if (libc_static_lib_dir)
|
if (libc_static_lib_dir)
|
||||||
@ -598,33 +549,25 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == CmdBuild) {
|
if (cmd == CmdBuild) {
|
||||||
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
|
|
||||||
codegen_link(g, out_file);
|
|
||||||
if (timing_info)
|
|
||||||
codegen_print_timing_report(g, stderr);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
} else if (cmd == CmdLink) {
|
|
||||||
for (size_t i = 0; i < objects.length; i += 1) {
|
for (size_t i = 0; i < objects.length; i += 1) {
|
||||||
codegen_add_object(g, buf_create_from_str(objects.at(i)));
|
codegen_add_object(g, buf_create_from_str(objects.at(i)));
|
||||||
}
|
}
|
||||||
codegen_link(g, out_file);
|
for (size_t i = 0; i < asm_files.length; i += 1) {
|
||||||
if (timing_info)
|
codegen_add_assembly(g, buf_create_from_str(asm_files.at(i)));
|
||||||
codegen_print_timing_report(g, stderr);
|
}
|
||||||
return EXIT_SUCCESS;
|
codegen_build(g);
|
||||||
} else if (cmd == CmdAsm) {
|
|
||||||
codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code);
|
|
||||||
codegen_link(g, out_file);
|
codegen_link(g, out_file);
|
||||||
if (timing_info)
|
if (timing_info)
|
||||||
codegen_print_timing_report(g, stderr);
|
codegen_print_timing_report(g, stderr);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} else if (cmd == CmdParseH) {
|
} else if (cmd == CmdParseH) {
|
||||||
codegen_parseh(g, &root_source_dir, &root_source_name, &root_source_code);
|
codegen_parseh(g, in_file_buf);
|
||||||
ast_render_decls(g, stdout, 4, g->root_import);
|
ast_render_decls(g, stdout, 4, g->root_import);
|
||||||
if (timing_info)
|
if (timing_info)
|
||||||
codegen_print_timing_report(g, stderr);
|
codegen_print_timing_report(g, stderr);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} else if (cmd == CmdTest) {
|
} else if (cmd == CmdTest) {
|
||||||
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
|
codegen_build(g);
|
||||||
codegen_link(g, "./test");
|
codegen_link(g, "./test");
|
||||||
ZigList<const char *> args = {0};
|
ZigList<const char *> args = {0};
|
||||||
Termination term;
|
Termination term;
|
||||||
|
20
src/os.cpp
20
src/os.cpp
@ -146,24 +146,28 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
|
|||||||
|
|
||||||
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {
|
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {
|
||||||
if (buf_len(full_path) == 0) {
|
if (buf_len(full_path) == 0) {
|
||||||
buf_init_from_str(out_basename, "");
|
if (out_basename) buf_init_from_str(out_basename, "");
|
||||||
buf_init_from_str(out_extname, "");
|
if (out_extname) buf_init_from_str(out_extname, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t i = buf_len(full_path) - 1;
|
size_t i = buf_len(full_path) - 1;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (buf_ptr(full_path)[i] == '.') {
|
if (buf_ptr(full_path)[i] == '.') {
|
||||||
buf_resize(out_basename, 0);
|
if (out_basename) {
|
||||||
buf_append_mem(out_basename, buf_ptr(full_path), i);
|
buf_resize(out_basename, 0);
|
||||||
|
buf_append_mem(out_basename, buf_ptr(full_path), i);
|
||||||
|
}
|
||||||
|
|
||||||
buf_resize(out_extname, 0);
|
if (out_extname) {
|
||||||
buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);
|
buf_resize(out_extname, 0);
|
||||||
|
buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
buf_init_from_buf(out_basename, full_path);
|
if (out_basename) buf_init_from_buf(out_basename, full_path);
|
||||||
buf_init_from_str(out_extname, "");
|
if (out_extname) buf_init_from_str(out_extname, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i -= 1;
|
i -= 1;
|
||||||
|
607
std/build.zig
607
std/build.zig
@ -120,28 +120,22 @@ pub const Builder = struct {
|
|||||||
self.lib_dir = %%os.path.join(self.allocator, self.prefix, "lib");
|
self.lib_dir = %%os.path.join(self.allocator, self.prefix, "lib");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addExecutable(self: &Builder, name: []const u8, root_src: []const u8) -> &LibOrExeStep {
|
pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
||||||
const exe = %%self.allocator.create(LibOrExeStep);
|
return LibExeObjStep.createExecutable(self, name, root_src);
|
||||||
*exe = LibOrExeStep.initExecutable(self, name, root_src);
|
|
||||||
return exe;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &ObjectStep {
|
pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep {
|
||||||
const obj_step = %%self.allocator.create(ObjectStep);
|
return LibExeObjStep.createObject(self, name, root_src);
|
||||||
*obj_step = ObjectStep.init(self, name, root_src);
|
|
||||||
return obj_step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: []const u8, ver: &const Version) -> &LibOrExeStep {
|
pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8,
|
||||||
const lib_step = %%self.allocator.create(LibOrExeStep);
|
ver: &const Version) -> &LibExeObjStep
|
||||||
*lib_step = LibOrExeStep.initSharedLibrary(self, name, root_src, ver);
|
{
|
||||||
return lib_step;
|
return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: []const u8) -> &LibOrExeStep {
|
pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
||||||
const lib_step = %%self.allocator.create(LibOrExeStep);
|
return LibExeObjStep.createStaticLibrary(self, name, root_src);
|
||||||
*lib_step = LibOrExeStep.initStaticLibrary(self, name, root_src);
|
|
||||||
return lib_step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep {
|
pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep {
|
||||||
@ -150,28 +144,10 @@ pub const Builder = struct {
|
|||||||
return test_step;
|
return test_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &AsmStep {
|
pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep {
|
||||||
const asm_step = %%self.allocator.create(AsmStep);
|
const obj_step = LibExeObjStep.createObject(self, name, null);
|
||||||
*asm_step = AsmStep.init(self, name, src);
|
obj_step.addAssemblyFile(src);
|
||||||
return asm_step;
|
return obj_step;
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addLinkExecutable(self: &Builder, name: []const u8) -> &LinkStep {
|
|
||||||
const exe = %%self.allocator.create(LinkStep);
|
|
||||||
*exe = LinkStep.initExecutable(self, name);
|
|
||||||
return exe;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addLinkStaticLibrary(self: &Builder, name: []const u8) -> &LinkStep {
|
|
||||||
const exe = %%self.allocator.create(LinkStep);
|
|
||||||
*exe = LinkStep.initStaticLibrary(self, name);
|
|
||||||
return exe;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addLinkSharedLibrary(self: &Builder, name: []const u8, ver: &const Version) -> &LinkStep {
|
|
||||||
const exe = %%self.allocator.create(LinkStep);
|
|
||||||
*exe = LinkStep.initSharedLibrary(self, name, ver);
|
|
||||||
return exe;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &CLibrary {
|
pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &CLibrary {
|
||||||
@ -635,10 +611,10 @@ const LinkerScript = enum {
|
|||||||
Path: []const u8,
|
Path: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LibOrExeStep = struct {
|
pub const LibExeObjStep = struct {
|
||||||
step: Step,
|
step: Step,
|
||||||
builder: &Builder,
|
builder: &Builder,
|
||||||
root_src: []const u8,
|
root_src: ?[]const u8,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
target: Target,
|
target: Target,
|
||||||
linker_script: LinkerScript,
|
linker_script: LinkerScript,
|
||||||
@ -652,30 +628,45 @@ pub const LibOrExeStep = struct {
|
|||||||
out_filename: []const u8,
|
out_filename: []const u8,
|
||||||
out_filename_major_only: []const u8,
|
out_filename_major_only: []const u8,
|
||||||
out_filename_name_only: []const u8,
|
out_filename_name_only: []const u8,
|
||||||
|
object_files: List([]const u8),
|
||||||
|
assembly_files: List([]const u8),
|
||||||
|
|
||||||
const Kind = enum {
|
const Kind = enum {
|
||||||
Exe,
|
Exe,
|
||||||
Lib,
|
Lib,
|
||||||
|
Obj,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn initExecutable(builder: &Builder, name: []const u8, root_src: []const u8) -> LibOrExeStep {
|
pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8,
|
||||||
return initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
|
ver: &const Version) -> &LibExeObjStep
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initSharedLibrary(builder: &Builder, name: []const u8, root_src: []const u8,
|
|
||||||
ver: &const Version) -> LibOrExeStep
|
|
||||||
{
|
{
|
||||||
return initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
|
const self = %%builder.allocator.create(LibExeObjStep);
|
||||||
|
*self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initStaticLibrary(builder: &Builder, name: []const u8, root_src: []const u8) -> LibOrExeStep {
|
pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
||||||
return initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
|
const self = %%builder.allocator.create(LibExeObjStep);
|
||||||
|
*self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initExtraArgs(builder: &Builder, name: []const u8, root_src: []const u8, kind: Kind,
|
pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep {
|
||||||
static: bool, ver: &const Version) -> LibOrExeStep
|
const self = %%builder.allocator.create(LibExeObjStep);
|
||||||
|
*self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
|
||||||
|
const self = %%builder.allocator.create(LibExeObjStep);
|
||||||
|
*self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind,
|
||||||
|
static: bool, ver: &const Version) -> LibExeObjStep
|
||||||
{
|
{
|
||||||
var self = LibOrExeStep {
|
var self = LibExeObjStep {
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.verbose = false,
|
.verbose = false,
|
||||||
.release = false,
|
.release = false,
|
||||||
@ -692,13 +683,18 @@ pub const LibOrExeStep = struct {
|
|||||||
.out_filename = undefined,
|
.out_filename = undefined,
|
||||||
.out_filename_major_only = undefined,
|
.out_filename_major_only = undefined,
|
||||||
.out_filename_name_only = undefined,
|
.out_filename_name_only = undefined,
|
||||||
|
.object_files = List([]const u8).init(builder.allocator),
|
||||||
|
.assembly_files = List([]const u8).init(builder.allocator),
|
||||||
};
|
};
|
||||||
self.computeOutFileNames();
|
self.computeOutFileNames();
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn computeOutFileNames(self: &LibOrExeStep) {
|
fn computeOutFileNames(self: &LibExeObjStep) {
|
||||||
switch (self.kind) {
|
switch (self.kind) {
|
||||||
|
Kind.Obj => {
|
||||||
|
self.out_filename = self.builder.fmt("{}{}", self.name, self.target.oFileExt());
|
||||||
|
},
|
||||||
Kind.Exe => {
|
Kind.Exe => {
|
||||||
self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());
|
self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());
|
||||||
},
|
},
|
||||||
@ -715,7 +711,7 @@ pub const LibOrExeStep = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTarget(self: &LibOrExeStep, target_arch: Arch, target_os: Os, target_environ: Environ) {
|
pub fn setTarget(self: &LibExeObjStep, target_arch: Arch, target_os: Os, target_environ: Environ) {
|
||||||
self.target = Target.Cross {
|
self.target = Target.Cross {
|
||||||
CrossTarget {
|
CrossTarget {
|
||||||
.arch = target_arch,
|
.arch = target_arch,
|
||||||
@ -723,47 +719,93 @@ pub const LibOrExeStep = struct {
|
|||||||
.environ = target_environ,
|
.environ = target_environ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
self.computeOutFileNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LibOrExeStep keeps a reference to script for its lifetime or until this function
|
/// LibExeObjStep keeps a reference to script for its lifetime or until this function
|
||||||
/// is called again.
|
/// is called again.
|
||||||
pub fn setLinkerScriptContents(self: &LibOrExeStep, script: []const u8) {
|
pub fn setLinkerScriptContents(self: &LibExeObjStep, script: []const u8) {
|
||||||
self.linker_script = LinkerScript.Embed { script };
|
self.linker_script = LinkerScript.Embed { script };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setLinkerScriptPath(self: &LibOrExeStep, path: []const u8) {
|
pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) {
|
||||||
self.linker_script = LinkerScript.Path { path };
|
self.linker_script = LinkerScript.Path { path };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkSystemLibrary(self: &LibOrExeStep, name: []const u8) {
|
pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) {
|
||||||
%%self.link_libs.put(name);
|
%%self.link_libs.put(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setVerbose(self: &LibOrExeStep, value: bool) {
|
pub fn setVerbose(self: &LibExeObjStep, value: bool) {
|
||||||
self.verbose = value;
|
self.verbose = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setRelease(self: &LibOrExeStep, value: bool) {
|
pub fn setRelease(self: &LibExeObjStep, value: bool) {
|
||||||
self.release = value;
|
self.release = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setOutputPath(self: &LibOrExeStep, value: []const u8) {
|
pub fn setOutputPath(self: &LibExeObjStep, value: []const u8) {
|
||||||
self.output_path = value;
|
self.output_path = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) {
|
||||||
|
%%self.assembly_files.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) {
|
||||||
|
assert(self.kind != Kind.Obj);
|
||||||
|
|
||||||
|
%%self.object_files.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) {
|
||||||
|
assert(obj.kind == Kind.Obj);
|
||||||
|
assert(self.kind != Kind.Obj);
|
||||||
|
|
||||||
|
self.step.dependOn(&obj.step);
|
||||||
|
|
||||||
|
const path_to_obj = test (obj.output_path) |explicit_out_path| {
|
||||||
|
explicit_out_path
|
||||||
|
} else {
|
||||||
|
// TODO make it so we always know where this will be
|
||||||
|
%%os.path.join(self.builder.allocator, self.builder.out_dir,
|
||||||
|
self.builder.fmt("{}{}", obj.name, obj.target.oFileExt()))
|
||||||
|
};
|
||||||
|
%%self.object_files.append(path_to_obj);
|
||||||
|
}
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
fn make(step: &Step) -> %void {
|
||||||
const self = @fieldParentPtr(LibOrExeStep, "step", step);
|
const self = @fieldParentPtr(LibExeObjStep, "step", step);
|
||||||
const builder = self.builder;
|
const builder = self.builder;
|
||||||
|
|
||||||
|
if (self.root_src == null and self.object_files.len == 0 and self.assembly_files.len == 0) {
|
||||||
|
%%io.stderr.printf("{}: linker needs 1 or more objects to link\n", step.name);
|
||||||
|
return error.NeedAnObject;
|
||||||
|
}
|
||||||
|
|
||||||
var zig_args = List([]const u8).init(builder.allocator);
|
var zig_args = List([]const u8).init(builder.allocator);
|
||||||
defer zig_args.deinit();
|
defer zig_args.deinit();
|
||||||
|
|
||||||
const cmd = switch (self.kind) {
|
const cmd = switch (self.kind) {
|
||||||
Kind.Lib => "build_lib",
|
Kind.Lib => "build_lib",
|
||||||
Kind.Exe => "build_exe",
|
Kind.Exe => "build_exe",
|
||||||
|
Kind.Obj => "build_obj",
|
||||||
};
|
};
|
||||||
%%zig_args.append(cmd);
|
%%zig_args.append(cmd);
|
||||||
%%zig_args.append(builder.pathFromRoot(self.root_src));
|
|
||||||
|
test (self.root_src) |root_src| {
|
||||||
|
%%zig_args.append(builder.pathFromRoot(root_src));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (self.object_files.toSliceConst()) |object_file| {
|
||||||
|
%%zig_args.append("--object");
|
||||||
|
%%zig_args.append(builder.pathFromRoot(object_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (self.assembly_files.toSliceConst()) |asm_file| {
|
||||||
|
%%zig_args.append("--assembly");
|
||||||
|
%%zig_args.append(builder.pathFromRoot(asm_file));
|
||||||
|
}
|
||||||
|
|
||||||
if (self.verbose) {
|
if (self.verbose) {
|
||||||
%%zig_args.append("--verbose");
|
%%zig_args.append("--verbose");
|
||||||
@ -856,437 +898,6 @@ pub const LibOrExeStep = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ObjectStep = struct {
|
|
||||||
step: Step,
|
|
||||||
builder: &Builder,
|
|
||||||
root_src: []const u8,
|
|
||||||
name: []const u8,
|
|
||||||
target: Target,
|
|
||||||
verbose: bool,
|
|
||||||
release: bool,
|
|
||||||
output_path: ?[]const u8,
|
|
||||||
|
|
||||||
pub fn init(builder: &Builder, name: []const u8, root_src: []const u8) -> ObjectStep {
|
|
||||||
ObjectStep {
|
|
||||||
.builder = builder,
|
|
||||||
.verbose = false,
|
|
||||||
.release = false,
|
|
||||||
.root_src = root_src,
|
|
||||||
.name = name,
|
|
||||||
.target = Target.Native,
|
|
||||||
.step = Step.init(name, builder.allocator, make),
|
|
||||||
.output_path = null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setTarget(self: &ObjectStep, target_arch: Arch, target_os: Os, target_environ: Environ) {
|
|
||||||
self.target = Target.Cross {
|
|
||||||
CrossTarget {
|
|
||||||
.arch = target_arch,
|
|
||||||
.os = target_os,
|
|
||||||
.environ = target_environ,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setVerbose(self: &ObjectStep, value: bool) {
|
|
||||||
self.verbose = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setRelease(self: &ObjectStep, value: bool) {
|
|
||||||
self.release = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setOutputPath(self: &ObjectStep, value: []const u8) {
|
|
||||||
self.output_path = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
|
||||||
const self = @fieldParentPtr(ObjectStep, "step", step);
|
|
||||||
const builder = self.builder;
|
|
||||||
|
|
||||||
var zig_args = List([]const u8).init(builder.allocator);
|
|
||||||
defer zig_args.deinit();
|
|
||||||
|
|
||||||
%%zig_args.append("build_obj");
|
|
||||||
%%zig_args.append(builder.pathFromRoot(self.root_src));
|
|
||||||
|
|
||||||
if (self.verbose) {
|
|
||||||
%%zig_args.append("--verbose");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.release) {
|
|
||||||
%%zig_args.append("--release");
|
|
||||||
}
|
|
||||||
|
|
||||||
test (self.output_path) |output_path| {
|
|
||||||
%%zig_args.append("--output");
|
|
||||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
%%zig_args.append("--name");
|
|
||||||
%%zig_args.append(self.name);
|
|
||||||
|
|
||||||
switch (self.target) {
|
|
||||||
Target.Native => {},
|
|
||||||
Target.Cross => |cross_target| {
|
|
||||||
%%zig_args.append("--target-arch");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.arch));
|
|
||||||
|
|
||||||
%%zig_args.append("--target-os");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.os));
|
|
||||||
|
|
||||||
%%zig_args.append("--target-environ");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.environ));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for (builder.include_paths.toSliceConst()) |include_path| {
|
|
||||||
%%zig_args.append("-isystem");
|
|
||||||
%%zig_args.append(include_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (builder.rpaths.toSliceConst()) |rpath| {
|
|
||||||
%%zig_args.append("-rpath");
|
|
||||||
%%zig_args.append(rpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (builder.lib_paths.toSliceConst()) |lib_path| {
|
|
||||||
%%zig_args.append("--library-path");
|
|
||||||
%%zig_args.append(lib_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
%%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const AsmStep = struct {
|
|
||||||
step: Step,
|
|
||||||
builder: &Builder,
|
|
||||||
name: []const u8,
|
|
||||||
target: Target,
|
|
||||||
verbose: bool,
|
|
||||||
release: bool,
|
|
||||||
output_path: ?[]const u8,
|
|
||||||
src_path: []const u8,
|
|
||||||
|
|
||||||
pub fn init(builder: &Builder, name: []const u8, src_path: []const u8) -> AsmStep {
|
|
||||||
var self = AsmStep {
|
|
||||||
.step = Step.init(name, builder.allocator, make),
|
|
||||||
.builder = builder,
|
|
||||||
.name = name,
|
|
||||||
.target = Target.Native,
|
|
||||||
.verbose = false,
|
|
||||||
.release = false,
|
|
||||||
.output_path = null,
|
|
||||||
.src_path = src_path,
|
|
||||||
};
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setTarget(self: &AsmStep, target_arch: Arch, target_os: Os, target_environ: Environ) {
|
|
||||||
self.target = Target.Cross {
|
|
||||||
CrossTarget {
|
|
||||||
.arch = target_arch,
|
|
||||||
.os = target_os,
|
|
||||||
.environ = target_environ,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setVerbose(self: &AsmStep, value: bool) {
|
|
||||||
self.verbose = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setRelease(self: &AsmStep, value: bool) {
|
|
||||||
self.release = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setOutputPath(self: &AsmStep, value: []const u8) {
|
|
||||||
self.output_path = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
|
||||||
const self = @fieldParentPtr(AsmStep, "step", step);
|
|
||||||
const builder = self.builder;
|
|
||||||
|
|
||||||
var zig_args = List([]const u8).init(builder.allocator);
|
|
||||||
defer zig_args.deinit();
|
|
||||||
|
|
||||||
%%zig_args.append("asm");
|
|
||||||
%%zig_args.append(builder.pathFromRoot(self.src_path));
|
|
||||||
|
|
||||||
if (self.verbose) {
|
|
||||||
%%zig_args.append("--verbose");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.release) {
|
|
||||||
%%zig_args.append("--release");
|
|
||||||
}
|
|
||||||
|
|
||||||
test (self.output_path) |output_path| {
|
|
||||||
%%zig_args.append("--output");
|
|
||||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
%%zig_args.append("--name");
|
|
||||||
%%zig_args.append(self.name);
|
|
||||||
|
|
||||||
switch (self.target) {
|
|
||||||
Target.Native => {},
|
|
||||||
Target.Cross => |cross_target| {
|
|
||||||
%%zig_args.append("--target-arch");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.arch));
|
|
||||||
|
|
||||||
%%zig_args.append("--target-os");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.os));
|
|
||||||
|
|
||||||
%%zig_args.append("--target-environ");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.environ));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
%%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const LinkStep = struct {
|
|
||||||
step: Step,
|
|
||||||
builder: &Builder,
|
|
||||||
name: []const u8,
|
|
||||||
target: Target,
|
|
||||||
linker_script: LinkerScript,
|
|
||||||
link_libs: BufSet,
|
|
||||||
verbose: bool,
|
|
||||||
release: bool,
|
|
||||||
output_path: ?[]const u8,
|
|
||||||
object_files: List([]const u8),
|
|
||||||
static: bool,
|
|
||||||
out_filename: []const u8,
|
|
||||||
out_type: OutType,
|
|
||||||
version: Version,
|
|
||||||
major_only_filename: []const u8,
|
|
||||||
name_only_filename: []const u8,
|
|
||||||
|
|
||||||
const OutType = enum {
|
|
||||||
Exe,
|
|
||||||
Lib,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn initExecutable(builder: &Builder, name: []const u8) -> LinkStep {
|
|
||||||
return init(builder, name, OutType.Exe, builder.version(0, 0, 0), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) -> LinkStep {
|
|
||||||
return init(builder, name, OutType.Lib, version, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initStaticLibrary(builder: &Builder, name: []const u8) -> LinkStep {
|
|
||||||
return init(builder, name, OutType.Lib, builder.version(0, 0, 0), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(builder: &Builder, name: []const u8, out_type: OutType, version: &const Version, static: bool) -> LinkStep {
|
|
||||||
var self = LinkStep {
|
|
||||||
.builder = builder,
|
|
||||||
.verbose = false,
|
|
||||||
.release = false,
|
|
||||||
.name = name,
|
|
||||||
.target = Target.Native,
|
|
||||||
.linker_script = LinkerScript.None,
|
|
||||||
.link_libs = BufSet.init(builder.allocator),
|
|
||||||
.step = Step.init(name, builder.allocator, make),
|
|
||||||
.output_path = null,
|
|
||||||
.object_files = List([]const u8).init(builder.allocator),
|
|
||||||
.out_type = out_type,
|
|
||||||
.version = *version,
|
|
||||||
.static = static,
|
|
||||||
.out_filename = undefined,
|
|
||||||
.major_only_filename = undefined,
|
|
||||||
.name_only_filename = undefined,
|
|
||||||
};
|
|
||||||
self.computeOutFileName();
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn computeOutFileName(self: &LinkStep) {
|
|
||||||
switch (self.out_type) {
|
|
||||||
OutType.Exe => {
|
|
||||||
self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());
|
|
||||||
},
|
|
||||||
OutType.Lib => {
|
|
||||||
if (self.static) {
|
|
||||||
self.out_filename = self.builder.fmt("lib{}.a", self.name);
|
|
||||||
} else {
|
|
||||||
self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}",
|
|
||||||
self.name, self.version.major, self.version.minor, self.version.patch);
|
|
||||||
self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);
|
|
||||||
self.name_only_filename = self.builder.fmt("lib{}.so", self.name);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addObjectFile(self: &LinkStep, file: []const u8) {
|
|
||||||
%%self.object_files.append(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addObject(self: &LinkStep, obj: &ObjectStep) {
|
|
||||||
self.step.dependOn(&obj.step);
|
|
||||||
|
|
||||||
const path_to_obj = test (obj.output_path) |explicit_out_path| {
|
|
||||||
explicit_out_path
|
|
||||||
} else {
|
|
||||||
// TODO make it so we always know where this will be
|
|
||||||
%%os.path.join(self.builder.allocator, self.builder.out_dir,
|
|
||||||
self.builder.fmt("{}{}", obj.name, obj.target.oFileExt()))
|
|
||||||
};
|
|
||||||
%%self.object_files.append(path_to_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addAssembly(self: &LinkStep, assembly: &AsmStep) {
|
|
||||||
self.step.dependOn(&assembly.step);
|
|
||||||
|
|
||||||
const path_to_obj = test (assembly.output_path) |explicit_out_path| {
|
|
||||||
explicit_out_path
|
|
||||||
} else {
|
|
||||||
// TODO make it so we always know where this will be
|
|
||||||
%%os.path.join(self.builder.allocator, self.builder.out_dir,
|
|
||||||
self.builder.fmt("{}{}", assembly.name, assembly.target.oFileExt()))
|
|
||||||
};
|
|
||||||
%%self.object_files.append(path_to_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setTarget(self: &LinkStep, target_arch: Arch, target_os: Os, target_environ: Environ) {
|
|
||||||
self.target = Target.Cross {
|
|
||||||
CrossTarget {
|
|
||||||
.arch = target_arch,
|
|
||||||
.os = target_os,
|
|
||||||
.environ = target_environ,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.computeOutFileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// LinkStep keeps a reference to script for its lifetime or until this function
|
|
||||||
/// is called again.
|
|
||||||
pub fn setLinkerScriptContents(self: &LinkStep, script: []const u8) {
|
|
||||||
self.linker_script = LinkerScript.Embed { script };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setLinkerScriptPath(self: &LinkStep, path: []const u8) {
|
|
||||||
self.linker_script = LinkerScript.Path { path };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn linkSystemLibrary(self: &LinkStep, name: []const u8) {
|
|
||||||
%%self.link_libs.put(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setVerbose(self: &LinkStep, value: bool) {
|
|
||||||
self.verbose = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setRelease(self: &LinkStep, value: bool) {
|
|
||||||
self.release = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setOutputPath(self: &LinkStep, value: []const u8) {
|
|
||||||
self.output_path = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make(step: &Step) -> %void {
|
|
||||||
const self = @fieldParentPtr(LinkStep, "step", step);
|
|
||||||
const builder = self.builder;
|
|
||||||
|
|
||||||
if (self.object_files.len == 0) {
|
|
||||||
%%io.stderr.printf("{}: linker needs 1 or more objects to link\n", step.name);
|
|
||||||
return error.NeedAnObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
var zig_args = List([]const u8).init(builder.allocator);
|
|
||||||
defer zig_args.deinit();
|
|
||||||
|
|
||||||
const cmd = switch (self.out_type) {
|
|
||||||
OutType.Exe => "link_exe",
|
|
||||||
OutType.Lib => "link_lib",
|
|
||||||
};
|
|
||||||
%%zig_args.append(cmd);
|
|
||||||
|
|
||||||
for (self.object_files.toSliceConst()) |object_file| {
|
|
||||||
%%zig_args.append(builder.pathFromRoot(object_file));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.verbose) {
|
|
||||||
%%zig_args.append("--verbose");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.release) {
|
|
||||||
%%zig_args.append("--release");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.static) {
|
|
||||||
%%zig_args.append("--static");
|
|
||||||
}
|
|
||||||
|
|
||||||
test (self.output_path) |output_path| {
|
|
||||||
%%zig_args.append("--output");
|
|
||||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
%%zig_args.append("--name");
|
|
||||||
%%zig_args.append(self.name);
|
|
||||||
|
|
||||||
switch (self.target) {
|
|
||||||
Target.Native => {},
|
|
||||||
Target.Cross => |cross_target| {
|
|
||||||
%%zig_args.append("--target-arch");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.arch));
|
|
||||||
|
|
||||||
%%zig_args.append("--target-os");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.os));
|
|
||||||
|
|
||||||
%%zig_args.append("--target-environ");
|
|
||||||
%%zig_args.append(@enumTagName(cross_target.environ));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (self.linker_script) {
|
|
||||||
LinkerScript.None => {},
|
|
||||||
LinkerScript.Embed => |script| {
|
|
||||||
const tmp_file_name = "linker.ld.tmp"; // TODO issue #298
|
|
||||||
io.writeFile(tmp_file_name, script, builder.allocator)
|
|
||||||
%% |err| debug.panic("unable to write linker script: {}\n", @errorName(err));
|
|
||||||
%%zig_args.append("--linker-script");
|
|
||||||
%%zig_args.append(tmp_file_name);
|
|
||||||
},
|
|
||||||
LinkerScript.Path => |path| {
|
|
||||||
%%zig_args.append("--linker-script");
|
|
||||||
%%zig_args.append(path);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var it = self.link_libs.iterator();
|
|
||||||
while (true) {
|
|
||||||
const entry = it.next() ?? break;
|
|
||||||
%%zig_args.append("--library");
|
|
||||||
%%zig_args.append(entry.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (builder.rpaths.toSliceConst()) |rpath| {
|
|
||||||
%%zig_args.append("-rpath");
|
|
||||||
%%zig_args.append(rpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (builder.lib_paths.toSliceConst()) |lib_path| {
|
|
||||||
%%zig_args.append("--library-path");
|
|
||||||
%%zig_args.append(lib_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
%%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const TestStep = struct {
|
pub const TestStep = struct {
|
||||||
step: Step,
|
step: Step,
|
||||||
builder: &Builder,
|
builder: &Builder,
|
||||||
@ -1592,15 +1203,17 @@ pub const CExecutable = struct {
|
|||||||
%%self.full_path_libs.append(clib.out_filename);
|
%%self.full_path_libs.append(clib.out_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkLibrary(self: &CExecutable, lib: &LibOrExeStep) {
|
pub fn linkLibrary(self: &CExecutable, lib: &LibExeObjStep) {
|
||||||
assert(lib.kind == LibOrExeStep.Kind.Lib);
|
assert(lib.kind == LibExeObjStep.Kind.Lib);
|
||||||
self.step.dependOn(&lib.step);
|
self.step.dependOn(&lib.step);
|
||||||
%%self.full_path_libs.append(lib.out_filename);
|
%%self.full_path_libs.append(lib.out_filename);
|
||||||
// TODO should be some kind of isolated directory that only has this header in it
|
// TODO should be some kind of isolated directory that only has this header in it
|
||||||
%%self.include_dirs.append(self.builder.out_dir);
|
%%self.include_dirs.append(self.builder.out_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addObject(self: &CExecutable, obj: &ObjectStep) {
|
pub fn addObject(self: &CExecutable, obj: &LibExeObjStep) {
|
||||||
|
assert(obj.kind == LibExeObjStep.Kind.Obj);
|
||||||
|
|
||||||
self.step.dependOn(&obj.step);
|
self.step.dependOn(&obj.step);
|
||||||
|
|
||||||
// TODO make it so we always know where this will be
|
// TODO make it so we always know where this will be
|
||||||
|
@ -90,7 +90,11 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
|
|||||||
// at compile time. I'll call it issue #313
|
// at compile time. I'll call it issue #313
|
||||||
const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";
|
const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";
|
||||||
|
|
||||||
const compile_unit = findCompileUnit(st, return_address) ?? return error.MissingDebugInfo;
|
const compile_unit = findCompileUnit(st, return_address) ?? {
|
||||||
|
%return out_stream.print(DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n\n\n", return_address);
|
||||||
|
%return out_stream.flush();
|
||||||
|
continue;
|
||||||
|
};
|
||||||
const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name);
|
const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name);
|
||||||
try (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| {
|
try (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| {
|
||||||
defer line_info.deinit();
|
defer line_info.deinit();
|
||||||
|
@ -150,3 +150,12 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 {
|
|||||||
|
|
||||||
return slice[0...1];
|
return slice[0...1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "implicitly cast from [N]T to ?[]const T" {
|
||||||
|
assert(mem.eql(u8, ??castToMaybeSlice(), "hi"));
|
||||||
|
comptime assert(mem.eql(u8, ??castToMaybeSlice(), "hi"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn castToMaybeSlice() -> ?[]const u8 {
|
||||||
|
return "hi";
|
||||||
|
}
|
||||||
|
@ -355,18 +355,16 @@ pub const CompareOutputContext = struct {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assembly = b.addAssemble("test", root_src);
|
const exe = b.addExecutable("test", null);
|
||||||
|
exe.addAssemblyFile(root_src);
|
||||||
|
exe.setOutputPath(exe_path);
|
||||||
|
|
||||||
for (case.sources.toSliceConst()) |src_file| {
|
for (case.sources.toSliceConst()) |src_file| {
|
||||||
const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);
|
const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);
|
||||||
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
|
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
|
||||||
assembly.step.dependOn(&write_src.step);
|
exe.step.dependOn(&write_src.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
const exe = b.addLinkExecutable("test");
|
|
||||||
exe.addAssembly(assembly);
|
|
||||||
exe.setOutputPath(exe_path);
|
|
||||||
|
|
||||||
const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name,
|
const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name,
|
||||||
case.expected_output);
|
case.expected_output);
|
||||||
run_and_cmp_output.step.dependOn(&exe.step);
|
run_and_cmp_output.step.dependOn(&exe.step);
|
||||||
|
Loading…
Reference in New Issue
Block a user