9b6c09c32 Merge pull request #5049 from wwderw/master 0b125a5fd Update Makefile 0b7dda8ab Merge pull request #5050 from katanya04/master 3d93b3026 Update font load message 78a06990c Merge pull request #5041 from PanicTitan/master 82b80a699 Review formatting, avoid variable 71b302846 Review formatting, avoid variable 8823aba9d Update rprand.h 6b9a685ba Merge pull request #5048 from veins1/patch-4 14582a9f0 Merge pull request #5047 from RomainPlmg/#5009-fix-colorreplace-alpha 093e5200d Update Makefile 0405de794 Fix for music stopping too early d03ac97ef GetMusicTimePlayed fix for music shorter than buffer size 34af70866 [rtextures] Fix ImageColorReplace() alpha issue #5009 e00c5eb8b Merge pull request #5043 from vinnyhorgan/master cbea2ff50 Merge pull request #5046 from maiconpintoabreu/updatestream-music 3320a2c83 Fix to prevent UpdateMusicStream to run without music playing e7c043529 Merge pull request #5044 from backspaceoverload/fix-HalfToFloat 44ebf3238 Fix HalfToFloat Mantissa hex value 901afadbf fix warning log macro in rlgl f34e24068 Merge pull request #5042 from Sir-Irk/ImageDrawLineEx_fix fce3102f1 Remove excess comments 9f03d7c42 fixing comments 0c69c43c3 fix ImageDrawLineEx to be able to draw even numbered thicknesses 9e908e4a7 Update core_custom_frame_control.c to work properly on web 20a07a65d Merge pull request #5037 from garrisonhh/fix-gaussian-blur 8dbacafbe fix overflow in cast for ImageBlurGaussian 55a567471 Merge pull request #5036 from sleeptightAnsiC/update_glfw_mappings_h 930890555 [glfw] update mappings.h using GenerateMappings.cmake defbeee1a Merge pull request #5020 from Emil2010/master d972582bc Merge pull request #5025 from zedeckj/master 595756498 Merge pull request #5026 from jonathandw743/sdlfix eaea8e0b0 Merge pull request #5033 from wwderw/master 8ef51850b Update raudio.c a92f67bf3 Merge pull request #5031 from AmityWilder/safety-comments 205b6a092 Merge branch 'raysan5:master' into safety-comments 9f6d37ecb Update raylib_api.* by CI d4f09984a Add safety notes to 'Update_' functions 79c29cbe2 fixed compile error for PLATFORM sdl e91a3697f Fixed typo 910f4083e update dr_libs 7f8dfc6c6 Merge pull request #5018 from maiconpintoabreu/fix-zig-wasm-win-mac f1600a0c7 Fix issue on zig build emscripten run if the user has not installed emsdk 46f01e315 Merge pull request #5013 from maiconpintoabreu/zig-examples 2e74133a6 Merge pull request #5014 from fosskers/colin/cl-binding 7f32b9a96 Merge pull request #5015 from Sir-Irk/gltf_model_fix 8cf932c82 Merge pull request #5016 from Sir-Irk/fix_pbr_example_tangents ed509193d remving w multiply on the tangent itself f86295732 fixing shader tangents to be vec4 bee524e5e fixing offset for processing tangents for gltf loading eef1bac3e fix misspelling 0cae8890b Remove -fno-stack-protector as it is not needed and add requestFullscreen on exported methods 1db006b08 docs: mention another Common Lisp binding 8f50436dc Fix comments 6e9c3acaa Add run examples using zig and emscripten for web bdda18656 Merge pull request #5011 from maiconpintoabreu/update-emsdk-fix-touch d659037fb Update emsdk version for zig build to fix the issue with the EM_BOOL c35e13647 Merge branch 'master' of https://github.com/raysan5/raylib 44f670899 REVIEWED: Avoid `rtext` dependency on `rcore_desktop_sdl` #4959 e09dcf611 Merge pull request #5006 from ElDigoXD/patch-1 6266d0f41 Fix typo on config.h b67737608 Delete shader in case compilation fails 1abac023b Update rcore.c 8b0230f5b Merge pull request #5002 from mlorenc227/master 518ad8b01 Fix ScanDirectoryFilesRecursively 4bc8d3761 Merge pull request #4999 from danilwhale/raylib-cs.bleedingedge 43bad2612 docs: add Raylib-cs.BleedingEdge to the bindings fd4375a74 Merge pull request #4992 from M374LX/rgfw-update 17a618758 Merge pull request #4995 from Not-Nik/zig-raygui-options abf255fbe Merge pull request #4993 from Marcos-cat/master 106bcf460 add uiua bindings to the list 96c898852 Update RGFW 3e336e447 Reviewed warning 59bcf680a Code gardening... 8a3a8ee8e Update shapes_digital_clock.c 533c12c38 Small security tweaks 5f497d068 REVIEWED: `shapes_digital_clock` example cb369f8df Merge pull request #4985 from hmz-rhl/master 3f228f459 [examples] : adding new fancy clock 8d319b100 Merge pull request #4983 from M374LX/miniaudio-update d218db9ee Merge pull request #4982 from LainLayer/rgfw-timeout 59338c2c2 Update raylib_api.* by CI 714de02a8 Merge pull request #4980 from williewillus/pr4980 c81097505 Merge pull request #4981 from garrisonhh/add-build-zig-zon-license 53faf7ae7 Merge pull request #4977 from jestarray/patch-2 bb5b5434a Update miniaudio to v0.11.22 51958d6e2 changed `RGFW_window_eventWait` timeout to -1 b52a9f8a0 Add LICENSE to build.zig.zon 19ae6f2c2 [rshapes] Fix incorrect parameter names in DrawRectangleGradientEx 58a6846c8 Update raylib_api.* by CI 296e3af47 add const qualifier to ImageDrawTriangleFan and ImageDrawTriangleStrip arguments 924c87db3 Merge pull request #4976 from M374LX/rgfw-update-dev 6eeaf1dd5 Update RGFW to 1.7.5-dev c1bb53738 Merge pull request #4974 from M374LX/rgfw-escape-fix 9bf4388a4 Merge pull request #4965 from M374LX/rgfw-update 3414d96ea Update raylib_api.* by CI 20c0c92bd Merge pull request #4963 from meowstr/master bc2b2864e RGFW: fix Escape always closing the window b26f6d34b Allow passing options to raygui in build.zig b9c2ecc44 Merge pull request #4969 from M374LX/update-comments 8f2ecfba4 Update raylib_api.* by CI 341817261 Update comments 015db1641 Merge pull request #4964 from M374LX/axes-comment a9525bfbc Update RGFW to 1.7 16f398b46 Update comment (gamepad axes) 6d5aedbd3 Add DrawEllipseV and DrawEllipseLinesV 913c23648 REVIEWED: `MAX_GAMEPAD_AXES` 341bfb22c REVIEWED: `MAX_GAMEPAD_AXEX` for consistency #4960 2afae1b3e Merge pull request #4962 from M374LX/rgfw-rctrl f9fa63366 Merge pull request #4958 from M374LX/unused-var c0cf57f8f RGFW backend: add missing Right Control key 299f5350a Remove unused variable 2d952d8e9 Update raylib_api.* by CI d7148f5f9 REDESIGNED: Base64 encoding/decoding functions 5ddd13b77 REVIEWED: Hexadecimal formatting to be consistent 8d9c1cecb Update raylib_api.* by CI afb52b19a WARNING: REDESIGNED: `EncodeDataBase64()`, NULL terminated string returned 21f0fe2a7 Removed some spaces e3b9dbe75 Merge pull request #4947 from padmadevd/master b6daa48a9 Update rcore_android.c a1d57e83f Merge pull request #4948 from parzivail/bug/meshnormals 21e711b13 Fix typo in mesh animNormals 5da2d1011 Update rcore_android.c 2be18e2c5 Merge pull request #4944 from Pivok7/master 0ffc8c517 Pbr example fix 8c99a508c REVIEWED: `WindowSizeCallback()`, GLFW a51d33444 Merge branch 'master' of https://github.com/raysan5/raylib 9d4c31533 Update rtext.c 15a0cf89b Merge pull request #4936 from lumenkeyes/master ba3121914 Merge pull request #4937 from Bigfoot71/fix-gen-tangents 5076d5743 Merge pull request #4938 from JeffM2501/const_save_callback 4a1e9931a Update raylib_api.* by CI aa684a33d make save file callback match const correctness of calling function d135eef46 fix and improve `GenMeshTangents` 6f11e27bb fix typo dea6a2477 build.zig fix: link EGL for Android 63b988ade Update raylib_api.* by CI f7d03efb4 REVIEWED: `DecodeDataBase64()`, follow convention: 3083f0cd4 REVIEWED: `SaveFileText()`, const input text 693c9c292 Formatting tweaks 4ac31f7cd Merge pull request #4928 from JeffM2501/unload_default_font ebaa922f6 Properly clean up the default font on unload, it may be reused if the window is created again 7e0727836 Update rprand.h 1402e830b Merge pull request #4926 from karl-zylinski/draw-sphere-normals 6fad12db7 Merge pull request #4927 from lumenkeyes/master 35de7b26a catch error in build.zig eae3fd83d properly detect if abi is android c4b9c0e03 properly generate android triple in build.zig a15548fb5 Add normals to DrawSphereEx 3d6e24af4 Merge pull request #4906 from Bigfoot71/fix-clip 512b1bed4 Merge pull request #4925 from JeffM2501/animated_meshes_GL11 e07e3354a Merge branch 'animated_meshes_GL11' of github.com:JeffM2501/raylib into animated_meshes_GL11 ee2ab11cc Use the animated verts and normals in GL 1.1 if they exist 95c96b345 Use the animated verts and normals in GL 1.1 if they exist 31d63d08e Merge pull request #4922 from Bigfoot71/review-file-dir-2 a7ad2d196 Merge pull request #4918 from JeffM2501/default_font_image_leaks 3d292a6c3 Merge pull request #4923 from JeffM2501/gltf_bone_fix e53a43b7b Assign meshes without bone weights to the bone they are attached to so they animate. 38aec920b makes `path` static in `ScanDirectoryFilesRecursively` 03988d2ce added a NULL check in `UnloadDirectoryFiles` c08714438 Merge branch 'raysan5:master' into fix-clip 82c87d1f6 Merge pull request #4920 from MrScautHD/patch-1 8533d284c Update BINDINGS.md 94c5de33a Make the default font loadable before InitWindow, for use with the image API. Make the default font loader early out if we have already loaded parts of it, so we don't leak memory 461c9c9d9 review tabs a7333a9da review near/far git-subtree-dir: libs/raylib git-subtree-split: 9b6c09c32f7283e849918aef220ec4fa629af8d2
715 lines
31 KiB
Zig
715 lines
31 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
|
|
/// Minimum supported version of Zig
|
|
const min_ver = "0.13.0";
|
|
|
|
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
|
const emccOutputFile = "index.html";
|
|
|
|
comptime {
|
|
const order = std.SemanticVersion.order;
|
|
const parse = std.SemanticVersion.parse;
|
|
if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt)
|
|
@compileError("Raylib requires zig version " ++ min_ver);
|
|
}
|
|
|
|
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
|
|
switch (platform) {
|
|
.glfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_GLFW", ""),
|
|
.rgfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_RGFW", ""),
|
|
.sdl => raylib.root_module.addCMacro("PLATFORM_DESKTOP_SDL", ""),
|
|
.android => raylib.root_module.addCMacro("PLATFORM_ANDROID", ""),
|
|
else => {},
|
|
}
|
|
}
|
|
|
|
fn createEmsdkStep(b: *std.Build, emsdk: *std.Build.Dependency) *std.Build.Step.Run {
|
|
if (builtin.os.tag == .windows) {
|
|
return b.addSystemCommand(&.{emsdk.path("emsdk.bat").getPath(b)});
|
|
} else {
|
|
return b.addSystemCommand(&.{emsdk.path("emsdk").getPath(b)});
|
|
}
|
|
}
|
|
|
|
fn emSdkSetupStep(b: *std.Build, emsdk: *std.Build.Dependency) !?*std.Build.Step.Run {
|
|
const dot_emsc_path = emsdk.path(".emscripten").getPath(b);
|
|
const dot_emsc_exists = !std.meta.isError(std.fs.accessAbsolute(dot_emsc_path, .{}));
|
|
|
|
if (!dot_emsc_exists) {
|
|
const emsdk_install = createEmsdkStep(b, emsdk);
|
|
emsdk_install.addArgs(&.{ "install", "latest" });
|
|
const emsdk_activate = createEmsdkStep(b, emsdk);
|
|
emsdk_activate.addArgs(&.{ "activate", "latest" });
|
|
emsdk_activate.step.dependOn(&emsdk_install.step);
|
|
return emsdk_activate;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Adapted from Not-Nik/raylib-zig
|
|
fn emscriptenRunStep(b: *std.Build, emsdk: *std.Build.Dependency, examplePath: []const u8) !*std.Build.Step.Run {
|
|
const dot_emsc_path = emsdk.path("upstream/emscripten/cache/sysroot/include").getPath(b);
|
|
// If compiling on windows , use emrun.bat.
|
|
const emrunExe = switch (builtin.os.tag) {
|
|
.windows => "emrun.bat",
|
|
else => "emrun",
|
|
};
|
|
var emrun_run_arg = try b.allocator.alloc(u8, dot_emsc_path.len + emrunExe.len + 1);
|
|
defer b.allocator.free(emrun_run_arg);
|
|
|
|
if (b.sysroot == null) {
|
|
emrun_run_arg = try std.fmt.bufPrint(emrun_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ emsdk.path("upstream/emscripten").getPath(b), emrunExe });
|
|
} else {
|
|
emrun_run_arg = try std.fmt.bufPrint(emrun_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ dot_emsc_path, emrunExe });
|
|
}
|
|
const run_cmd = b.addSystemCommand(&.{ emrun_run_arg, examplePath });
|
|
return run_cmd;
|
|
}
|
|
|
|
/// A list of all flags from `src/config.h` that one may override
|
|
const config_h_flags = outer: {
|
|
// Set this value higher if compile errors happen as `src/config.h` gets larger
|
|
@setEvalBranchQuota(1 << 20);
|
|
|
|
const config_h = @embedFile("src/config.h");
|
|
var flags: [std.mem.count(u8, config_h, "\n") + 1][]const u8 = undefined;
|
|
|
|
var i = 0;
|
|
var lines = std.mem.tokenizeScalar(u8, config_h, '\n');
|
|
while (lines.next()) |line| {
|
|
if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue;
|
|
if (std.mem.containsAtLeast(u8, line, 1, "MODULE")) continue;
|
|
if (std.mem.startsWith(u8, line, "//")) continue;
|
|
if (std.mem.startsWith(u8, line, "#if")) continue;
|
|
|
|
var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
|
|
flag = flag["#define ".len - 1 ..]; // Remove #define
|
|
flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
|
|
flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
|
|
flag = "-D" ++ flag; // Prepend with -D
|
|
|
|
flags[i] = flag;
|
|
i += 1;
|
|
}
|
|
|
|
// Uncomment this to check what flags normally get passed
|
|
//@compileLog(flags[0..i].*);
|
|
break :outer flags[0..i].*;
|
|
};
|
|
|
|
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
|
|
var raylib_flags_arr = std.ArrayList([]const u8).init(b.allocator);
|
|
defer raylib_flags_arr.deinit();
|
|
|
|
try raylib_flags_arr.appendSlice(&[_][]const u8{
|
|
"-std=gnu99",
|
|
"-D_GNU_SOURCE",
|
|
"-DGL_SILENCE_DEPRECATION=199309L",
|
|
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674
|
|
});
|
|
|
|
if (options.shared) {
|
|
try raylib_flags_arr.appendSlice(&[_][]const u8{
|
|
"-fPIC",
|
|
"-DBUILD_LIBTYPE_SHARED",
|
|
});
|
|
}
|
|
|
|
// Sets a flag indiciating the use of a custom `config.h`
|
|
try raylib_flags_arr.append("-DEXTERNAL_CONFIG_FLAGS");
|
|
if (options.config.len > 0) {
|
|
// Splits a space-separated list of config flags into multiple flags
|
|
//
|
|
// Note: This means certain flags like `-x c++` won't be processed properly.
|
|
// `-xc++` or similar should be used when possible
|
|
var config_iter = std.mem.tokenizeScalar(u8, options.config, ' ');
|
|
|
|
// Apply config flags supplied by the user
|
|
while (config_iter.next()) |config_flag|
|
|
try raylib_flags_arr.append(config_flag);
|
|
|
|
// Apply all relevant configs from `src/config.h` *except* the user-specified ones
|
|
//
|
|
// Note: Currently using a suboptimal `O(m*n)` time algorithm where:
|
|
// `m` corresponds roughly to the number of lines in `src/config.h`
|
|
// `n` corresponds to the number of user-specified flags
|
|
outer: for (config_h_flags) |flag| {
|
|
// If a user already specified the flag, skip it
|
|
config_iter.reset();
|
|
while (config_iter.next()) |config_flag| {
|
|
// For a user-specified flag to match, it must share the same prefix and have the
|
|
// same length or be followed by an equals sign
|
|
if (!std.mem.startsWith(u8, config_flag, flag)) continue;
|
|
if (config_flag.len == flag.len or config_flag[flag.len] == '=') continue :outer;
|
|
}
|
|
|
|
// Otherwise, append default value from config.h to compile flags
|
|
try raylib_flags_arr.append(flag);
|
|
}
|
|
} else {
|
|
// Set default config if no custome config got set
|
|
try raylib_flags_arr.appendSlice(&config_h_flags);
|
|
}
|
|
|
|
const raylib = if (options.shared)
|
|
b.addSharedLibrary(.{
|
|
.name = "raylib",
|
|
.target = target,
|
|
.optimize = optimize,
|
|
})
|
|
else
|
|
b.addStaticLibrary(.{
|
|
.name = "raylib",
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
raylib.linkLibC();
|
|
|
|
// No GLFW required on PLATFORM_DRM
|
|
if (options.platform != .drm) {
|
|
raylib.addIncludePath(b.path("src/external/glfw/include"));
|
|
}
|
|
|
|
var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2);
|
|
c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" });
|
|
|
|
if (options.rshapes) {
|
|
try c_source_files.append("src/rshapes.c");
|
|
try raylib_flags_arr.append("-DSUPPORT_MODULE_RSHAPES");
|
|
}
|
|
if (options.rtextures) {
|
|
try c_source_files.append("src/rtextures.c");
|
|
try raylib_flags_arr.append("-DSUPPORT_MODULE_RTEXTURES");
|
|
}
|
|
if (options.rtext) {
|
|
try c_source_files.append("src/rtext.c");
|
|
try raylib_flags_arr.append("-DSUPPORT_MODULE_RTEXT");
|
|
}
|
|
if (options.rmodels) {
|
|
try c_source_files.append("src/rmodels.c");
|
|
try raylib_flags_arr.append("-DSUPPORT_MODULE_RMODELS");
|
|
}
|
|
if (options.raudio) {
|
|
try c_source_files.append("src/raudio.c");
|
|
try raylib_flags_arr.append("-DSUPPORT_MODULE_RAUDIO");
|
|
}
|
|
|
|
if (options.opengl_version != .auto) {
|
|
raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), "");
|
|
}
|
|
|
|
raylib.addIncludePath(b.path("src/platforms"));
|
|
switch (target.result.os.tag) {
|
|
.windows => {
|
|
switch (options.platform) {
|
|
.glfw => try c_source_files.append("src/rglfw.c"),
|
|
.rgfw, .sdl, .drm, .android => {},
|
|
}
|
|
|
|
raylib.linkSystemLibrary("winmm");
|
|
raylib.linkSystemLibrary("gdi32");
|
|
raylib.linkSystemLibrary("opengl32");
|
|
|
|
setDesktopPlatform(raylib, options.platform);
|
|
},
|
|
.linux => {
|
|
if (options.platform == .drm) {
|
|
if (options.opengl_version == .auto) {
|
|
raylib.linkSystemLibrary("GLESv2");
|
|
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
|
}
|
|
|
|
raylib.linkSystemLibrary("EGL");
|
|
raylib.linkSystemLibrary("gbm");
|
|
raylib.linkSystemLibrary2("libdrm", .{ .use_pkg_config = .force });
|
|
|
|
raylib.root_module.addCMacro("PLATFORM_DRM", "");
|
|
raylib.root_module.addCMacro("EGL_NO_X11", "");
|
|
raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
|
|
} else if (target.result.abi.isAndroid()) {
|
|
|
|
//these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems
|
|
const hostTuple = switch (builtin.target.os.tag) {
|
|
.linux => "linux-x86_64",
|
|
.windows => "windows-x86_64",
|
|
.macos => "darwin-x86_64",
|
|
else => @panic("unsupported host OS"),
|
|
};
|
|
|
|
const androidTriple = switch (target.result.cpu.arch) {
|
|
.x86 => "i686-linux-android",
|
|
.x86_64 => "x86_64-linux-android",
|
|
.arm => "arm-linux-androideabi",
|
|
.aarch64 => "aarch64-linux-android",
|
|
.riscv64 => "riscv64-linux-android",
|
|
else => error.InvalidAndroidTarget,
|
|
} catch @panic("invalid android target!");
|
|
const androidNdkPathString: []const u8 = options.android_ndk;
|
|
if (androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set");
|
|
const androidApiLevel: []const u8 = options.android_api_version;
|
|
|
|
const androidSysroot = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/toolchains/llvm/prebuilt/", hostTuple, "/sysroot" });
|
|
const androidLibPath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/lib/", androidTriple });
|
|
const androidApiSpecificPath = try std.fs.path.join(b.allocator, &.{ androidLibPath, androidApiLevel });
|
|
const androidIncludePath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/include" });
|
|
const androidArchIncludePath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, androidTriple });
|
|
const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" });
|
|
const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" });
|
|
|
|
raylib.addLibraryPath(.{ .cwd_relative = androidLibPath });
|
|
raylib.root_module.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath });
|
|
raylib.addSystemIncludePath(.{ .cwd_relative = androidIncludePath });
|
|
raylib.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath });
|
|
raylib.addSystemIncludePath(.{ .cwd_relative = androidAsmPath });
|
|
raylib.addSystemIncludePath(.{ .cwd_relative = androidGluePath });
|
|
|
|
var libcData = std.ArrayList(u8).init(b.allocator);
|
|
const writer = libcData.writer();
|
|
try (std.zig.LibCInstallation{
|
|
.include_dir = androidIncludePath,
|
|
.sys_include_dir = androidIncludePath,
|
|
.crt_dir = androidApiSpecificPath,
|
|
}).render(writer);
|
|
const libcFile = b.addWriteFiles().add("android-libc.txt", try libcData.toOwnedSlice());
|
|
raylib.setLibCFile(libcFile);
|
|
|
|
if (options.opengl_version == .auto) {
|
|
raylib.root_module.linkSystemLibrary("GLESv2", .{});
|
|
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
|
}
|
|
raylib.root_module.linkSystemLibrary("EGL", .{});
|
|
|
|
setDesktopPlatform(raylib, .android);
|
|
} else {
|
|
try c_source_files.append("src/rglfw.c");
|
|
|
|
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
|
raylib.root_module.addCMacro("_GLFW_X11", "");
|
|
raylib.linkSystemLibrary("GLX");
|
|
raylib.linkSystemLibrary("X11");
|
|
raylib.linkSystemLibrary("Xcursor");
|
|
raylib.linkSystemLibrary("Xext");
|
|
raylib.linkSystemLibrary("Xfixes");
|
|
raylib.linkSystemLibrary("Xi");
|
|
raylib.linkSystemLibrary("Xinerama");
|
|
raylib.linkSystemLibrary("Xrandr");
|
|
raylib.linkSystemLibrary("Xrender");
|
|
}
|
|
|
|
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
|
|
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
|
|
std.log.err(
|
|
\\ `wayland-scanner` may not be installed on the system.
|
|
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
|
|
, .{});
|
|
@panic("`wayland-scanner` not found");
|
|
};
|
|
raylib.root_module.addCMacro("_GLFW_WAYLAND", "");
|
|
raylib.linkSystemLibrary("EGL");
|
|
raylib.linkSystemLibrary("wayland-client");
|
|
raylib.linkSystemLibrary("xkbcommon");
|
|
waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
|
|
waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
|
|
waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
|
|
waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
|
|
waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
|
|
waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
|
|
waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
|
|
waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
|
|
waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
|
|
}
|
|
setDesktopPlatform(raylib, options.platform);
|
|
}
|
|
},
|
|
.freebsd, .openbsd, .netbsd, .dragonfly => {
|
|
try c_source_files.append("rglfw.c");
|
|
raylib.linkSystemLibrary("GL");
|
|
raylib.linkSystemLibrary("rt");
|
|
raylib.linkSystemLibrary("dl");
|
|
raylib.linkSystemLibrary("m");
|
|
raylib.linkSystemLibrary("X11");
|
|
raylib.linkSystemLibrary("Xrandr");
|
|
raylib.linkSystemLibrary("Xinerama");
|
|
raylib.linkSystemLibrary("Xi");
|
|
raylib.linkSystemLibrary("Xxf86vm");
|
|
raylib.linkSystemLibrary("Xcursor");
|
|
|
|
setDesktopPlatform(raylib, options.platform);
|
|
},
|
|
.macos => {
|
|
// Include xcode_frameworks for cross compilation
|
|
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
|
|
raylib.addSystemFrameworkPath(dep.path("Frameworks"));
|
|
raylib.addSystemIncludePath(dep.path("include"));
|
|
raylib.addLibraryPath(dep.path("lib"));
|
|
}
|
|
|
|
// On macos rglfw.c include Objective-C files.
|
|
try raylib_flags_arr.append("-ObjC");
|
|
raylib.root_module.addCSourceFile(.{
|
|
.file = b.path("src/rglfw.c"),
|
|
.flags = raylib_flags_arr.items,
|
|
});
|
|
_ = raylib_flags_arr.pop();
|
|
raylib.linkFramework("Foundation");
|
|
raylib.linkFramework("CoreServices");
|
|
raylib.linkFramework("CoreGraphics");
|
|
raylib.linkFramework("AppKit");
|
|
raylib.linkFramework("IOKit");
|
|
|
|
setDesktopPlatform(raylib, options.platform);
|
|
},
|
|
.emscripten => {
|
|
if (b.lazyDependency("emsdk", .{})) |dep| {
|
|
if (try emSdkSetupStep(b, dep)) |emSdkStep| {
|
|
raylib.step.dependOn(&emSdkStep.step);
|
|
}
|
|
|
|
raylib.addIncludePath(dep.path("upstream/emscripten/cache/sysroot/include"));
|
|
}
|
|
|
|
raylib.root_module.addCMacro("PLATFORM_WEB", "");
|
|
if (options.opengl_version == .auto) {
|
|
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
|
}
|
|
},
|
|
else => {
|
|
@panic("Unsupported OS");
|
|
},
|
|
}
|
|
|
|
raylib.root_module.addCSourceFiles(.{
|
|
.files = c_source_files.items,
|
|
.flags = raylib_flags_arr.items,
|
|
});
|
|
|
|
return raylib;
|
|
}
|
|
|
|
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency, options: Options) void {
|
|
const raylib_dep = b.dependencyFromBuildZig(@This(), options);
|
|
var gen_step = b.addWriteFiles();
|
|
raylib.step.dependOn(&gen_step.step);
|
|
|
|
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
|
|
raylib.addCSourceFile(.{ .file = raygui_c_path });
|
|
raylib.addIncludePath(raygui_dep.path("src"));
|
|
raylib.addIncludePath(raylib_dep.path("src"));
|
|
|
|
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
|
|
}
|
|
|
|
pub const Options = struct {
|
|
raudio: bool = true,
|
|
rmodels: bool = true,
|
|
rshapes: bool = true,
|
|
rtext: bool = true,
|
|
rtextures: bool = true,
|
|
platform: PlatformBackend = .glfw,
|
|
shared: bool = false,
|
|
linux_display_backend: LinuxDisplayBackend = .Both,
|
|
opengl_version: OpenglVersion = .auto,
|
|
android_ndk: []const u8 = "",
|
|
android_api_version: []const u8 = "35",
|
|
/// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
|
|
config: []const u8 = &.{},
|
|
|
|
const defaults = Options{};
|
|
|
|
pub fn getOptions(b: *std.Build) Options {
|
|
return .{
|
|
.platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform,
|
|
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
|
|
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
|
|
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
|
|
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
|
|
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
|
|
.shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared,
|
|
.linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
|
|
.opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
|
|
.config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{},
|
|
.android_ndk = b.option([]const u8, "android_ndk", "specify path to android ndk") orelse std.process.getEnvVarOwned(b.allocator, "ANDROID_NDK_HOME") catch "",
|
|
.android_api_version = b.option([]const u8, "android_api_version", "specify target android API level") orelse defaults.android_api_version,
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const OpenglVersion = enum {
|
|
auto,
|
|
gl_1_1,
|
|
gl_2_1,
|
|
gl_3_3,
|
|
gl_4_3,
|
|
gles_2,
|
|
gles_3,
|
|
|
|
pub fn toCMacroStr(self: @This()) []const u8 {
|
|
switch (self) {
|
|
.auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"),
|
|
.gl_1_1 => return "GRAPHICS_API_OPENGL_11",
|
|
.gl_2_1 => return "GRAPHICS_API_OPENGL_21",
|
|
.gl_3_3 => return "GRAPHICS_API_OPENGL_33",
|
|
.gl_4_3 => return "GRAPHICS_API_OPENGL_43",
|
|
.gles_2 => return "GRAPHICS_API_OPENGL_ES2",
|
|
.gles_3 => return "GRAPHICS_API_OPENGL_ES3",
|
|
}
|
|
}
|
|
};
|
|
|
|
pub const LinuxDisplayBackend = enum {
|
|
X11,
|
|
Wayland,
|
|
Both,
|
|
};
|
|
|
|
pub const PlatformBackend = enum {
|
|
glfw,
|
|
rgfw,
|
|
sdl,
|
|
drm,
|
|
android,
|
|
};
|
|
|
|
pub fn build(b: *std.Build) !void {
|
|
// Standard target options allows the person running `zig build` to choose
|
|
// what target to build for. Here we do not override the defaults, which
|
|
// means any target is allowed, and the default is native. Other options
|
|
// for restricting supported target set are available.
|
|
const target = b.standardTargetOptions(.{});
|
|
// Standard optimization options allow the person running `zig build` to select
|
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
|
const optimize = b.standardOptimizeOption(.{});
|
|
|
|
const lib = try compileRaylib(b, target, optimize, Options.getOptions(b));
|
|
|
|
lib.installHeader(b.path("src/raylib.h"), "raylib.h");
|
|
lib.installHeader(b.path("src/rcamera.h"), "rcamera.h");
|
|
lib.installHeader(b.path("src/raymath.h"), "raymath.h");
|
|
lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");
|
|
|
|
b.installArtifact(lib);
|
|
|
|
const examples = b.step("examples", "Build/Install all examples");
|
|
examples.dependOn(try addExamples("audio", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("core", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("models", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("others", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("shaders", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("shapes", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("text", b, target, optimize, lib));
|
|
examples.dependOn(try addExamples("textures", b, target, optimize, lib));
|
|
}
|
|
|
|
fn waylandGenerate(
|
|
b: *std.Build,
|
|
raylib: *std.Build.Step.Compile,
|
|
comptime protocol: []const u8,
|
|
comptime basename: []const u8,
|
|
) void {
|
|
const waylandDir = "src/external/glfw/deps/wayland";
|
|
const protocolDir = b.pathJoin(&.{ waylandDir, protocol });
|
|
const clientHeader = basename ++ ".h";
|
|
const privateCode = basename ++ "-code.h";
|
|
|
|
const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
|
|
client_step.addFileArg(b.path(protocolDir));
|
|
raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
|
|
|
|
const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
|
|
private_step.addFileArg(b.path(protocolDir));
|
|
raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname());
|
|
|
|
raylib.step.dependOn(&client_step.step);
|
|
raylib.step.dependOn(&private_step.step);
|
|
}
|
|
|
|
fn addExamples(
|
|
comptime module: []const u8,
|
|
b: *std.Build,
|
|
target: std.Build.ResolvedTarget,
|
|
optimize: std.builtin.OptimizeMode,
|
|
raylib: *std.Build.Step.Compile,
|
|
) !*std.Build.Step {
|
|
const all = b.step(module, "All " ++ module ++ " examples");
|
|
const module_subpath = b.pathJoin(&.{ "examples", module });
|
|
const module_resources = b.pathJoin(&.{ module_subpath, "resources@resources" });
|
|
var dir = try std.fs.cwd().openDir(b.pathFromRoot(module_subpath), .{ .iterate = true });
|
|
defer if (comptime builtin.zig_version.minor >= 12) dir.close();
|
|
|
|
var iter = dir.iterate();
|
|
while (try iter.next()) |entry| {
|
|
if (entry.kind != .file) continue;
|
|
const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue;
|
|
const name = entry.name[0..extension_idx];
|
|
const path = b.pathJoin(&.{ module_subpath, entry.name });
|
|
|
|
// zig's mingw headers do not include pthread.h
|
|
if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue;
|
|
|
|
if (target.result.os.tag == .emscripten) {
|
|
const exe_lib = b.addStaticLibrary(.{
|
|
.name = name,
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
exe_lib.addCSourceFile(.{
|
|
.file = b.path(path),
|
|
.flags = &.{},
|
|
});
|
|
exe_lib.linkLibC();
|
|
|
|
if (std.mem.eql(u8, name, "rlgl_standalone")) {
|
|
//TODO: Make rlgl_standalone example work
|
|
continue;
|
|
}
|
|
if (std.mem.eql(u8, name, "raylib_opengl_interop")) {
|
|
//TODO: Make raylib_opengl_interop example work
|
|
continue;
|
|
}
|
|
|
|
exe_lib.linkLibrary(raylib);
|
|
|
|
// Include emscripten for cross compilation
|
|
if (b.lazyDependency("emsdk", .{})) |emsdk_dep| {
|
|
if (try emSdkSetupStep(b, emsdk_dep)) |emSdkStep| {
|
|
exe_lib.step.dependOn(&emSdkStep.step);
|
|
}
|
|
|
|
exe_lib.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
|
|
|
|
// Create the output directory because emcc can't do it.
|
|
const emccOutputDirExample = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str });
|
|
const mkdir_command = switch (builtin.os.tag) {
|
|
.windows => b.addSystemCommand(&.{ "cmd.exe", "/c", "if", "not", "exist", emccOutputDirExample, "mkdir", emccOutputDirExample }),
|
|
else => b.addSystemCommand(&.{ "mkdir", "-p", emccOutputDirExample }),
|
|
};
|
|
|
|
const emcc_exe = switch (builtin.os.tag) {
|
|
.windows => "emcc.bat",
|
|
else => "emcc",
|
|
};
|
|
|
|
const emcc_exe_path = b.pathJoin(&.{ emsdk_dep.path("upstream/emscripten").getPath(b), emcc_exe });
|
|
const emcc_command = b.addSystemCommand(&[_][]const u8{emcc_exe_path});
|
|
emcc_command.step.dependOn(&mkdir_command.step);
|
|
const emccOutputDirExampleWithFile = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str, emccOutputFile });
|
|
emcc_command.addArgs(&[_][]const u8{
|
|
"-o",
|
|
emccOutputDirExampleWithFile,
|
|
"-sFULL-ES3=1",
|
|
"-sUSE_GLFW=3",
|
|
"-sSTACK_OVERFLOW_CHECK=1",
|
|
"-sEXPORTED_RUNTIME_METHODS=['requestFullscreen']",
|
|
"-sASYNCIFY",
|
|
"-O0",
|
|
"--emrun",
|
|
"--preload-file",
|
|
module_resources,
|
|
"--shell-file",
|
|
b.path("src/shell.html").getPath(b),
|
|
});
|
|
|
|
const link_items: []const *std.Build.Step.Compile = &.{
|
|
raylib,
|
|
exe_lib,
|
|
};
|
|
for (link_items) |item| {
|
|
emcc_command.addFileArg(item.getEmittedBin());
|
|
emcc_command.step.dependOn(&item.step);
|
|
}
|
|
|
|
const run_step = try emscriptenRunStep(b, emsdk_dep, emccOutputDirExampleWithFile);
|
|
run_step.step.dependOn(&emcc_command.step);
|
|
run_step.addArg("--no_browser");
|
|
const run_option = b.step(name, name);
|
|
|
|
run_option.dependOn(&run_step.step);
|
|
|
|
all.dependOn(&emcc_command.step);
|
|
}
|
|
} else {
|
|
const exe = b.addExecutable(.{
|
|
.name = name,
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
exe.addCSourceFile(.{ .file = b.path(path), .flags = &.{} });
|
|
exe.linkLibC();
|
|
|
|
// special examples that test using these external dependencies directly
|
|
// alongside raylib
|
|
if (std.mem.eql(u8, name, "rlgl_standalone")) {
|
|
exe.addIncludePath(b.path("src"));
|
|
exe.addIncludePath(b.path("src/external/glfw/include"));
|
|
if (!hasCSource(raylib.root_module, "rglfw.c")) {
|
|
exe.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = &.{} });
|
|
}
|
|
}
|
|
if (std.mem.eql(u8, name, "raylib_opengl_interop")) {
|
|
exe.addIncludePath(b.path("src/external"));
|
|
}
|
|
|
|
exe.linkLibrary(raylib);
|
|
|
|
switch (target.result.os.tag) {
|
|
.windows => {
|
|
exe.linkSystemLibrary("winmm");
|
|
exe.linkSystemLibrary("gdi32");
|
|
exe.linkSystemLibrary("opengl32");
|
|
|
|
exe.root_module.addCMacro("PLATFORM_DESKTOP", "");
|
|
},
|
|
.linux => {
|
|
exe.linkSystemLibrary("GL");
|
|
exe.linkSystemLibrary("rt");
|
|
exe.linkSystemLibrary("dl");
|
|
exe.linkSystemLibrary("m");
|
|
exe.linkSystemLibrary("X11");
|
|
|
|
exe.root_module.addCMacro("PLATFORM_DESKTOP", "");
|
|
},
|
|
.macos => {
|
|
exe.linkFramework("Foundation");
|
|
exe.linkFramework("Cocoa");
|
|
exe.linkFramework("OpenGL");
|
|
exe.linkFramework("CoreAudio");
|
|
exe.linkFramework("CoreVideo");
|
|
exe.linkFramework("IOKit");
|
|
|
|
exe.root_module.addCMacro("PLATFORM_DESKTOP", "");
|
|
},
|
|
else => {
|
|
@panic("Unsupported OS");
|
|
},
|
|
}
|
|
|
|
const install_cmd = b.addInstallArtifact(exe, .{});
|
|
|
|
const run_cmd = b.addRunArtifact(exe);
|
|
run_cmd.cwd = b.path(module_subpath);
|
|
run_cmd.step.dependOn(&install_cmd.step);
|
|
|
|
const run_step = b.step(name, name);
|
|
run_step.dependOn(&run_cmd.step);
|
|
|
|
all.dependOn(&install_cmd.step);
|
|
}
|
|
}
|
|
return all;
|
|
}
|
|
|
|
fn hasCSource(module: *std.Build.Module, name: []const u8) bool {
|
|
for (module.link_objects.items) |o| switch (o) {
|
|
.c_source_file => |c| if (switch (c.file) {
|
|
.src_path => |s| std.ascii.endsWithIgnoreCase(s.sub_path, name),
|
|
.generated, .cwd_relative, .dependency => false,
|
|
}) return true,
|
|
.c_source_files => |s| for (s.files) |c| if (std.ascii.endsWithIgnoreCase(c, name)) return true,
|
|
else => {},
|
|
};
|
|
return false;
|
|
}
|