Cross-platform bugs: - ncomplib.c: fseek was called as fseek(f, whence, offset) instead of fseek(f, offset, whence). Seeks only worked correctly when offset happened to numerically equal a valid whence constant. - neonucleus.c: nn_realloc passed memory pointer instead of ctx to nn_alloc in the NULL and sentinel paths. Any call with memory=NULL dereferences NULL as a context struct and crashes. Confirmed by test_realloc.c which crashes before fix and passes after. - neonucleus.h: NN_TiB was defined as (1024 * NN_TiB), referencing itself. Fixed to ((size_t)1024 * NN_GiB). - luaarch.c: unicode functions were registered on the component Lua table instead of the unicode table. Wrong stack index variable was used in all five lua_setfield calls. - neonucleus.c: NN_ATOMIC_NONE versions of nn_incRef/nn_decRef took 1 argument but were called with 2 everywhere. Added the missing size_t n parameter. Windows build: - neonucleus.c: NN_LOCK_CREATE in NN_THREAD_WINDOWS was missing a return statement, falling through into NN_LOCK_DESTROY and immediately closing the freshly created mutex handle. - ncomplib.c: Added Windows implementations for opendir, readdir, closedir, stat, mkdir and directory removal using FindFirstFileA, FindNextFileA, _stat, _mkdir and _rmdir. - main.c: Fall back to USERNAME env var when USER is not set. - neonucleus.h: Added NN_VLA macro. Expands to a plain VLA on GCC/Clang, uses _alloca on MSVC. Applied in luaarch.c and neonucleus.c where VLAs were used. - neonucleus.h: Added NN_INIT macro. Expands to a compound literal cast on GCC/Clang, expands to nothing on MSVC which does not support compound literals as constant initializers at file scope. Applied to all global struct initializers in neonucleus.c. - neonucleus.c: Auto-define NN_ATOMIC_NONE on MSVC in C mode since MSVC does not provide stdatomic.h outside of C++ mode.
218 lines
6.8 KiB
Zig
218 lines
6.8 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
|
|
const LibBuildOpts = struct {
|
|
target: std.Build.ResolvedTarget,
|
|
optimize: std.builtin.OptimizeMode,
|
|
baremetal: bool,
|
|
bit32: bool,
|
|
};
|
|
|
|
fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module {
|
|
const dataMod = b.createModule(.{
|
|
.target = opts.target,
|
|
.optimize = opts.optimize,
|
|
.strip = if (opts.optimize == .Debug) false else true,
|
|
.unwind_tables = if (opts.optimize == .Debug) null else .none,
|
|
.pic = true,
|
|
.sanitize_c = .full,
|
|
});
|
|
|
|
const strict = opts.optimize != .Debug;
|
|
|
|
dataMod.addCSourceFiles(.{
|
|
.files = &[_][]const u8{
|
|
"src/neonucleus.c",
|
|
"src/ncomplib.c",
|
|
},
|
|
.flags = &.{
|
|
if (opts.baremetal) "-DNN_BAREMETAL" else "",
|
|
if (opts.bit32) "-DNN_BIT32" else "",
|
|
if (strict) "-Wall" else "",
|
|
if (strict) "-Werror" else "",
|
|
"-std=gnu23",
|
|
"-Wno-keyword-macro", // cuz bools
|
|
"-fPIE",
|
|
},
|
|
});
|
|
|
|
if (!opts.baremetal) {
|
|
dataMod.link_libc = true; // we need a libc
|
|
}
|
|
|
|
dataMod.addIncludePath(b.path("src"));
|
|
|
|
return dataMod;
|
|
}
|
|
|
|
const LuaVersion = enum {
|
|
lua52,
|
|
lua53,
|
|
lua54,
|
|
};
|
|
|
|
fn compileRaylib(b: *std.Build, os: std.Target.Os.Tag, c: *std.Build.Step.Compile) void {
|
|
// TODO: find out how to send our target to this build cmd
|
|
const raylib = b.addSystemCommand(&.{ "zig", "build" });
|
|
raylib.setCwd(b.path("foreign/raylib/"));
|
|
raylib.stdio = .inherit;
|
|
|
|
c.step.dependOn(&raylib.step);
|
|
c.addIncludePath(b.path("foreign/raylib/zig-out/include/"));
|
|
c.addLibraryPath(b.path("foreign/raylib/zig-out/lib/"));
|
|
c.linkSystemLibrary("raylib");
|
|
if (os == .windows) {
|
|
c.linkSystemLibrary("WinMM");
|
|
c.linkSystemLibrary("GDI32"); // <---
|
|
c.linkSystemLibrary("User32"); // ^ Windows can't just rely on GDI
|
|
c.linkSystemLibrary("Shell32");
|
|
c.linkSystemLibrary("OpenGL32");
|
|
}
|
|
}
|
|
|
|
// For the test architecture, we specify the target Lua version we so desire.
|
|
// This can be checked for with Lua's _VERSION
|
|
|
|
fn compileTheRightLua(b: *std.Build, target: std.Build.ResolvedTarget, version: LuaVersion) !*std.Build.Step.Compile {
|
|
const alloc = b.allocator;
|
|
const dirName = @tagName(version);
|
|
|
|
// its a static library because COFF is a pile of shit
|
|
const c = b.addLibrary(.{
|
|
.name = "lua",
|
|
.root_module = b.addModule("luamod", .{
|
|
.link_libc = true,
|
|
.optimize = .ReleaseFast,
|
|
.target = target,
|
|
}),
|
|
.linkage = .static,
|
|
});
|
|
|
|
const rootPath = try std.mem.join(alloc, std.fs.path.sep_str, &.{ "foreign", dirName });
|
|
|
|
// get all the .c files
|
|
var files = try std.ArrayList([]const u8).initCapacity(b.allocator, 0);
|
|
errdefer files.deinit(b.allocator);
|
|
|
|
var dir = try std.fs.cwd().openDir(rootPath, std.fs.Dir.OpenOptions{ .iterate = true });
|
|
defer dir.close();
|
|
|
|
var iter = dir.iterate();
|
|
|
|
while (try iter.next()) |e| {
|
|
if (std.mem.startsWith(u8, e.name, "l") and std.mem.endsWith(u8, e.name, ".c") and !std.mem.eql(u8, e.name, "lua.c")) {
|
|
const name = try alloc.dupe(u8, e.name);
|
|
try files.append(b.allocator, name);
|
|
}
|
|
}
|
|
|
|
c.addCSourceFiles(.{
|
|
.root = b.path(rootPath),
|
|
.files = files.items,
|
|
});
|
|
|
|
return c;
|
|
}
|
|
|
|
fn includeTheRightLua(b: *std.Build, c: *std.Build.Step.Compile, version: LuaVersion) !void {
|
|
const alloc = b.allocator;
|
|
const dirName = @tagName(version);
|
|
|
|
const rootPath = try std.mem.join(alloc, std.fs.path.sep_str, &.{ "foreign", dirName });
|
|
|
|
c.addIncludePath(b.path(rootPath));
|
|
}
|
|
|
|
pub fn build(b: *std.Build) !void {
|
|
const target = b.standardTargetOptions(.{});
|
|
|
|
const os = target.result.os.tag;
|
|
|
|
const optimize = b.standardOptimizeOption(.{});
|
|
|
|
const opts = LibBuildOpts{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
.baremetal = b.option(bool, "baremetal", "Compiles without libc integration") orelse false,
|
|
.bit32 = target.result.ptrBitWidth() == 32,
|
|
};
|
|
|
|
const noEmu = b.option(bool, "noEmu", "Disable compiling the emulator (fixes some build system quirks)") orelse false;
|
|
|
|
const includeFiles = b.addInstallHeaderFile(b.path("src/neonucleus.h"), "neonucleus.h");
|
|
|
|
const engineMod = addEngineSources(b, opts);
|
|
|
|
const engineStatic = b.addLibrary(.{
|
|
.name = "neonucleus",
|
|
.root_module = engineMod,
|
|
.linkage = .static,
|
|
});
|
|
|
|
const engineShared = b.addLibrary(.{
|
|
.name = if (os == .windows) "neonucleusdll" else "neonucleus",
|
|
.root_module = engineMod,
|
|
.linkage = .dynamic,
|
|
});
|
|
|
|
const engineStep = b.step("engine", "Builds the engine as a static library");
|
|
engineStep.dependOn(&engineStatic.step);
|
|
engineStep.dependOn(&includeFiles.step);
|
|
engineStep.dependOn(&b.addInstallArtifact(engineStatic, .{}).step);
|
|
|
|
const sharedStep = b.step("shared", "Builds the engine as a shared library");
|
|
sharedStep.dependOn(&engineShared.step);
|
|
sharedStep.dependOn(&includeFiles.step);
|
|
sharedStep.dependOn(&b.addInstallArtifact(engineShared, .{}).step);
|
|
|
|
if (!noEmu) {
|
|
const emulator = b.addExecutable(.{
|
|
.name = "neonucleus",
|
|
.root_module = b.addModule("emulator", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
}),
|
|
});
|
|
emulator.linkLibC();
|
|
|
|
const sysraylib_flag = b.option(bool, "sysraylib", "Use the system raylib instead of compiling raylib") orelse false;
|
|
if (sysraylib_flag) {
|
|
emulator.linkSystemLibrary("raylib");
|
|
} else {
|
|
compileRaylib(b, os, emulator);
|
|
}
|
|
|
|
const luaVer = b.option(LuaVersion, "lua", "The version of Lua to use.") orelse LuaVersion.lua53;
|
|
emulator.addCSourceFiles(.{
|
|
.files = &.{
|
|
"src/luaarch.c",
|
|
"src/main.c",
|
|
},
|
|
.flags = &.{
|
|
if (opts.baremetal) "-DNN_BAREMETAL" else "",
|
|
if (opts.bit32) "-DNN_BIT32" else "",
|
|
},
|
|
});
|
|
const l = try compileTheRightLua(b, target, luaVer);
|
|
try includeTheRightLua(b, emulator, luaVer);
|
|
|
|
// forces us to link in everything too
|
|
emulator.linkLibrary(l);
|
|
emulator.linkLibrary(engineStatic);
|
|
|
|
const emulatorStep = b.step("emulator", "Builds the emulator");
|
|
emulatorStep.dependOn(&emulator.step);
|
|
emulatorStep.dependOn(&b.addInstallArtifact(emulator, .{}).step);
|
|
|
|
var run_cmd = b.addRunArtifact(emulator);
|
|
|
|
if (b.args) |args| {
|
|
run_cmd.addArgs(args);
|
|
}
|
|
|
|
const run_step = b.step("run", "Run the emulator");
|
|
run_step.dependOn(emulatorStep);
|
|
run_step.dependOn(&run_cmd.step);
|
|
}
|
|
}
|