Skip to content

Commit

Permalink
Address review comments
Browse files Browse the repository at this point in the history
- support building shared library
- use defineCMacro() instead of direct flag manipulation
- 80 line length
- remove NO_PROC_FOR_LIBRARIES
- add TODO entries
- add install_headers option
  • Loading branch information
plajjan committed Dec 18, 2023
1 parent e9531b4 commit d9a4d4c
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 122 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/zig-build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# This workflow uses Zig and its excellent cross-compilation support to test
# compiling for multiple platforms. No tests are actually run since it would
# require emulation. We should add a test for the native platform though.
# require emulation.
# TODO: add test for native platform
# TODO: move from nightly to zig 0.12 once it is released
name: zig build

on: [push, pull_request]
Expand Down
288 changes: 167 additions & 121 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,178 +18,224 @@ pub fn build(b: *std.build.Builder) void {
if (t.isWasm()) { // matches both emscripten and wasi
default_enable_threads = false;
}
const enable_threads = b.option(bool, "enable_threads", "Support threads") orelse default_enable_threads;
const enable_parallel_mark = b.option(bool, "enable_parallel_mark", "Parallelize marking and free list construction") orelse true;
const enable_thread_local_alloc = b.option(bool, "enable_thread_local_alloc", "Turn on thread-local allocation optimization") orelse true;
const enable_gcj_support = b.option(bool, "enable_gcj_support", "Support for gcj") orelse true;
const enable_java_finalization = b.option(bool, "enable_java_finalization", "Support for java finalization") orelse true;
const enable_atomic_uncollectable = b.option(bool, "enable_atomic_uncollectable", "Support for atomic uncollectible allocation") orelse true;
const enable_redirect_malloc = b.option(bool, "enable_redirect_malloc", "Redirect malloc and friend to GC routines") orelse false;
const enable_disclaim = b.option(bool, "enable_disclaim", "Support alternative finalization interface") orelse true;
const enable_large_config = b.option(bool, "enable_large_config", "Optimize for large heap or root set") orelse true;
const enable_mmap = b.option(bool, "enable_mmap", "Use mmap instead of sbrk to expand the heap") orelse true;
const enable_munmap = b.option(bool, "enable_munmap", "Return page to the OS if empty for N collections") orelse true;

const lib = b.addStaticLibrary(.{
const enable_cplusplus = b.option(
bool, "enable_cplusplus", "C++ support") orelse false;
const build_shared_libs = b.option(
bool, "build_shared_libs",
"Build shared lib (or static when disabled)") orelse true;
const enable_threads = b.option(
bool, "enable_threads",
"Support threads") orelse default_enable_threads;
const enable_parallel_mark = b.option(
bool, "enable_parallel_mark",
"Parallelize marking and free list construction") orelse true;
const enable_thread_local_alloc = b.option(
bool, "enable_thread_local_alloc",
"Turn on thread-local allocation optimization") orelse true;
const enable_gcj_support = b.option(
bool, "enable_gcj_support", "Support for gcj") orelse true;
const enable_java_finalization = b.option(
bool, "enable_java_finalization",
"Support for java finalization") orelse true;
const enable_atomic_uncollectable = b.option(
bool, "enable_atomic_uncollectable",
"Support for atomic uncollectible allocation") orelse true;
const enable_redirect_malloc = b.option(
bool, "enable_redirect_malloc",
"Redirect malloc and friend to GC routines") orelse false;
const enable_disclaim = b.option(
bool, "enable_disclaim",
"Support alternative finalization interface") orelse true;
const enable_large_config = b.option(
bool, "enable_large_config",
"Optimize for large heap or root set") orelse true;
const enable_mmap = b.option(
bool, "enable_mmap",
"Use mmap instead of sbrk to expand the heap") orelse true;
const enable_munmap = b.option(
bool, "enable_munmap",
"Return page to the OS if empty for N collections") orelse true;
const install_headers = b.option(
bool, "install_headers",
"Install header and pkg-config metadata files") orelse true;

var lib = b.addStaticLibrary(.{
.name = "gc",
.target = target,
.optimize = optimize,
});
if (build_shared_libs) {
lib = b.addSharedLibrary(.{
.name = "gc",
.target = target,
.optimize = optimize,
});
}

var source_files = std.ArrayList([]const u8).init(b.allocator);
defer source_files.deinit();
var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit();

source_files.appendSlice(&.{
"alloc.c",
"reclaim.c",
"allchblk.c",
"misc.c",
"mach_dep.c",
"os_dep.c",
"mark_rts.c",
"headers.c",
"mark.c",
"obj_map.c",
"blacklst.c",
"finalize.c",
"new_hblk.c",
"dbg_mlc.c",
"malloc.c",
"dyn_load.c",
"typd_mlc.c",
"ptr_chck.c",
"mallocx.c",
}) catch unreachable;

if (t.abi.isMusl()) {
std.log.debug("Musl detected", .{});
flags.appendSlice(&.{"-DNO_GETCONTEXT"}) catch unreachable;
lib.defineCMacro("NO_GETCONTEXT", "1");
}

// Always enabled
lib.defineCMacro("ALL_INTERIOR_POINTERS", "1");
lib.defineCMacro("NO_EXECUTE_PERMISSION", "1");
// Zig comes with clang that supports atomics so we can hardcode this
lib.defineCMacro("GC_BUILTIN_ATOMIC", "1");
// TODO: Should this be configurable?
lib.defineCMacro("NO_PROC_FOR_LIBRARIES", "1");
flags.appendSlice(&.{
"-fno-sanitize=undefined",
// Always enabled
"-DALL_INTERIOR_POINTERS",
"-DNO_EXECUTE_PERMISSION",
// Zig comes with clang that supports atomics so we can hardcode this
"-DGC_BUILTIN_ATOMIC",
// TODO: Should this be configurable?
"-DNO_PROC_FOR_LIBRARIES",
}) catch unreachable;

if (enable_threads) {
flags.appendSlice(&.{"-DGC_THREADS"}) catch unreachable;
if (enable_parallel_mark)
flags.appendSlice(&.{"-DPARALLEL_MARK"}) catch unreachable;
lib.defineCMacro("GC_THREADS", "1");
lib.defineCMacro("_REENTRANT", "1");
if (enable_parallel_mark) {
lib.defineCMacro("PARALLEL_MARK", "1");
}
if (enable_thread_local_alloc) {
lib.addCSourceFiles(.{
.files = &.{
"specific.c",
"thread_local_alloc.c",
},
.flags = flags.items,
});
lib.defineCMacro("THREAD_LOCAL_ALLOC", "1");
source_files.appendSlice(&.{
"specific.c",
"thread_local_alloc.c",
}) catch unreachable;
}
if (t.os.tag == .windows) {
lib.addCSourceFiles(.{
.files = &.{"win32_threads.c"},
.flags = flags.items,
});
source_files.appendSlice(&.{
"win32_threads.c"
}) catch unreachable;
} else {
lib.addCSourceFiles(.{
.files = &.{
"gc_dlopen.c",
"pthread_start.c",
"pthread_support.c"
},
.flags = flags.items,
});
source_files.appendSlice(&.{
"gc_dlopen.c",
"pthread_start.c",
"pthread_support.c"
}) catch unreachable;
if (t.os.tag == .macos) {
lib.addCSourceFiles(.{
.files = &.{"darwin_stop_world.c"},
.flags = flags.items,
});
source_files.appendSlice(&.{
"darwin_stop_world.c"
}) catch unreachable;
} else {
lib.addCSourceFiles(.{
.files = &.{"pthread_stop_world.c"},
.flags = flags.items,
});
source_files.appendSlice(&.{
"pthread_stop_world.c"
}) catch unreachable;
}
}
}

if (enable_gcj_support) {
flags.appendSlice(&.{"-DGC_GCJ_SUPPORT"}) catch unreachable;
lib.addCSourceFiles(.{
.files = &.{"gcj_mlc.c"},
.flags = flags.items,
});
lib.defineCMacro("GC_GCJ_SUPPORT", "1");
source_files.appendSlice(&.{
"gcj_mlc.c"
}) catch unreachable;
}

if (enable_disclaim) {
flags.appendSlice(&.{"-DENABLE_DISCLAIM"}) catch unreachable;
lib.addCSourceFiles(.{
.files = &.{"fnlz_mlc.c"},
.flags = flags.items,
});
lib.defineCMacro("ENABLE_DISCLAIM", "1");
source_files.appendSlice(&.{
"fnlz_mlc.c"
}) catch unreachable;
}

if (enable_java_finalization)
flags.appendSlice(&.{"-DJAVA_FINALIZATION"}) catch unreachable;
if (enable_java_finalization) {
lib.defineCMacro("JAVA_FINALIZATION", "1");
}

if (enable_atomic_uncollectable)
flags.appendSlice(&.{"-DGC_ATOMIC_UNCOLLECTABLE"}) catch unreachable;
if (enable_atomic_uncollectable) {
lib.defineCMacro("GC_ATOMIC_UNCOLLECTABLE", "1");
}

if (enable_redirect_malloc) {
flags.appendSlice(&.{
"-DREDIRECT_MALLOC=GC_malloc",
"-DIGNORE_FREE",
}) catch unreachable;
lib.defineCMacro("REDIRECT_MALLOC=GC_malloc", "1");
lib.defineCMacro("IGNORE_FREE", "1");
if (t.os.tag == .windows) {
flags.appendSlice(&.{"-DREDIRECT_MALLOC_IN_HEADER"}) catch unreachable;
lib.defineCMacro("REDIRECT_MALLOC_IN_HEADER", "1");
} else {
flags.appendSlice(&.{"-DGC_USE_DLOPEN_WRAP"}) catch unreachable;
lib.defineCMacro("GC_USE_DLOPEN_WRAP", "1");
}
}

if (enable_munmap) {
flags.appendSlice(&.{"-DUSE_MMAP"}) catch unreachable;
flags.appendSlice(&.{"-DUSE_MUNMAP"}) catch unreachable;
lib.defineCMacro("USE_MMAP", "1");
lib.defineCMacro("USE_MUNMAP", "1");
} else if (enable_mmap) {
flags.appendSlice(&.{"-DUSE_MMAP"}) catch unreachable;
lib.defineCMacro("USE_MMAP", "1");
}

if (enable_large_config)
flags.appendSlice(&.{"-DLARGE_CONFIG"}) catch unreachable;

const source_files = [_][]const u8{
"alloc.c",
"reclaim.c",
"allchblk.c",
"misc.c",
"mach_dep.c",
"os_dep.c",
"mark_rts.c",
"headers.c",
"mark.c",
"obj_map.c",
"blacklst.c",
"finalize.c",
"new_hblk.c",
"dbg_mlc.c",
"malloc.c",
"dyn_load.c",
"typd_mlc.c",
"ptr_chck.c",
"mallocx.c",
};
if (enable_large_config) {
lib.defineCMacro("LARGE_CONFIG", "1");
}

if (build_shared_libs) {
source_files.clearAndFree();
source_files.appendSlice(&.{
"extra/gc.c"
}) catch unreachable;
if (enable_threads and !(target.isDarwin() or target.isWindows())) {
source_files.appendSlice(&.{
"pthread_start.c"
}) catch unreachable;
}
}
lib.addCSourceFiles(.{
.files = &source_files,
.files = source_files.items,
.flags = flags.items,
});
lib.addIncludePath(.{ .path = "include" });
lib.linkLibC();
lib.installHeader("include/gc.h", "gc.h");
lib.installHeader("include/gc/cord.h", "gc/cord.h");
lib.installHeader("include/gc/cord_pos.h", "gc/cord_pos.h");
lib.installHeader("include/gc/ec.h", "gc/ec.h");
lib.installHeader("include/gc/gc_backptr.h", "gc/gc_backptr.h");
lib.installHeader("include/gc/gc_config_macros.h", "gc/gc_config_macros.h");
lib.installHeader("include/gc/gc_disclaim.h", "gc/gc_disclaim.h");
lib.installHeader("include/gc/gc_gcj.h", "gc/gc_gcj.h");
lib.installHeader("include/gc/gc.h", "gc/gc.h");
lib.installHeader("include/gc/gc_inline.h", "gc/gc_inline.h");
lib.installHeader("include/gc/gc_mark.h", "gc/gc_mark.h");
lib.installHeader("include/gc/gc_pthread_redirects.h", "gc/gc_pthread_redirects.h");
lib.installHeader("include/gc/gc_tiny_fl.h", "gc/gc_tiny_fl.h");
lib.installHeader("include/gc/gc_typed.h", "gc/gc_typed.h");
lib.installHeader("include/gc/gc_version.h", "gc/gc_version.h");
lib.installHeader("include/gc/javaxfc.h", "gc/javaxfc.h");
lib.installHeader("include/gc/leak_detector.h", "gc/leak_detector.h");

// TODO: for C++
//lib.installHeader("include/gc/gc_allocator.h", "gc/gc_allocator.h");
//lib.installHeader("include/gc/gc_cpp.h", "gc/gc_cpp.h");
if (install_headers) {
lib.installHeader("include/gc.h", "gc.h");
lib.installHeader("include/gc/cord.h", "gc/cord.h");
lib.installHeader("include/gc/cord_pos.h", "gc/cord_pos.h");
lib.installHeader("include/gc/ec.h", "gc/ec.h");
lib.installHeader("include/gc/gc_backptr.h", "gc/gc_backptr.h");
lib.installHeader("include/gc/gc_config_macros.h",
"gc/gc_config_macros.h");
lib.installHeader("include/gc/gc_disclaim.h", "gc/gc_disclaim.h");
lib.installHeader("include/gc/gc_gcj.h", "gc/gc_gcj.h");
lib.installHeader("include/gc/gc.h", "gc/gc.h");
lib.installHeader("include/gc/gc_inline.h", "gc/gc_inline.h");
lib.installHeader("include/gc/gc_mark.h", "gc/gc_mark.h");
lib.installHeader("include/gc/gc_pthread_redirects.h",
"gc/gc_pthread_redirects.h");
lib.installHeader("include/gc/gc_tiny_fl.h", "gc/gc_tiny_fl.h");
lib.installHeader("include/gc/gc_typed.h", "gc/gc_typed.h");
lib.installHeader("include/gc/gc_version.h", "gc/gc_version.h");
lib.installHeader("include/gc/javaxfc.h", "gc/javaxfc.h");
lib.installHeader("include/gc/leak_detector.h", "gc/leak_detector.h");

if (enable_cplusplus) {
lib.installHeader("include/gc/gc_allocator.h", "gc/gc_allocator.h");
lib.installHeader("include/gc/gc_cpp.h", "gc/gc_cpp.h");
}
}

b.installArtifact(lib);

}

0 comments on commit d9a4d4c

Please sign in to comment.