|
1 | 1 | const std = @import("std");
|
| 2 | +const builtin = @import("builtin"); |
| 3 | + |
| 4 | +const cfiles_exts = [_][]const u8{ ".c", ".cpp", ".cxx", ".c++", ".cc" }; |
| 5 | +const extension_name = "godot-llama-cpp"; |
2 | 6 |
|
3 | 7 | pub fn build(b: *std.Build) !void {
|
4 | 8 | const target = b.standardTargetOptions(.{});
|
5 | 9 | const optimize = b.standardOptimizeOption(.{});
|
| 10 | + const zig_triple = try target.result.zigTriple(b.allocator); |
6 | 11 |
|
7 |
| - const extension = b.addSharedLibrary(.{ .name = "godot-llama-cpp", .target = target, .optimize = optimize }); |
8 |
| - extension.addIncludePath(.{ .path = "src" }); |
9 |
| - // extension.addIncludePath(.{ .path = "llama.cpp" }); |
10 |
| - // extension.addIncludePath(.{ .path = "llama.cpp/common" }); |
11 |
| - extension.addIncludePath(.{ .path = "godot-cpp/include/" }); |
12 |
| - extension.addIncludePath(.{ .path = "godot-cpp/gdextension/" }); |
13 |
| - extension.addIncludePath(.{ .path = "godot-cpp/gen/include/" }); |
14 |
| - extension.addObjectFile(.{ .path = "godot-cpp/zig-out/lib/libgodot.lib" }); |
| 12 | + var objs = std.ArrayList(*std.Build.Step.Compile).init(b.allocator); |
| 13 | + |
| 14 | + // godot-cpp |
| 15 | + const lib_godot = b.addStaticLibrary(.{ |
| 16 | + .name = "godot-cpp", |
| 17 | + .target = target, |
| 18 | + .optimize = optimize, |
| 19 | + }); |
| 20 | + b.build_root.handle.access("godot_cpp/gen", .{}) catch |e| { |
| 21 | + switch (e) { |
| 22 | + error.FileNotFound => { |
| 23 | + const binds_run = b.addSystemCommand(&.{ "python", "binding_generator.py", "godot_cpp/gdextension/extension_api.json", "godot_cpp" }); |
| 24 | + lib_godot.step.dependOn(&binds_run.step); |
| 25 | + }, |
| 26 | + else => { |
| 27 | + return; |
| 28 | + }, |
| 29 | + } |
| 30 | + }; |
| 31 | + lib_godot.linkLibCpp(); |
| 32 | + lib_godot.addIncludePath(.{ .path = "godot_cpp/gdextension/" }); |
| 33 | + lib_godot.addIncludePath(.{ .path = "godot_cpp/include/" }); |
| 34 | + lib_godot.addIncludePath(.{ .path = "godot_cpp/gen/include" }); |
| 35 | + const lib_godot_sources = try findFilesRecursive(b, "godot_cpp/src", &cfiles_exts); |
| 36 | + const lib_godot_gen_sources = try findFilesRecursive(b, "godot_cpp/gen/src", &cfiles_exts); |
| 37 | + lib_godot.addCSourceFiles(.{ .files = lib_godot_gen_sources, .flags = &.{ "-std=c++17", "-fno-exceptions" } }); |
| 38 | + lib_godot.addCSourceFiles(.{ .files = lib_godot_sources, .flags = &.{ "-std=c++17", "-fno-exceptions" } }); |
| 39 | + // try objs.append(lib_godot); |
| 40 | + |
| 41 | + // llama.cpp |
| 42 | + const commit_hash = try std.ChildProcess.run(.{ .allocator = b.allocator, .argv = &.{ "git", "rev-parse", "HEAD" }, .cwd = b.pathFromRoot("llama.cpp") }); |
| 43 | + const zig_version = builtin.zig_version_string; |
| 44 | + try b.build_root.handle.writeFile2(.{ .sub_path = "llama.cpp/common/build-info.cpp", .data = b.fmt( |
| 45 | + \\int LLAMA_BUILD_NUMBER = {}; |
| 46 | + \\char const *LLAMA_COMMIT = "{s}"; |
| 47 | + \\char const *LLAMA_COMPILER = "Zig {s}"; |
| 48 | + \\char const *LLAMA_BUILD_TARGET = "{s}"; |
| 49 | + \\ |
| 50 | + , .{ 0, commit_hash.stdout[0 .. commit_hash.stdout.len - 1], zig_version, zig_triple }) }); |
| 51 | + |
| 52 | + var flags = std.ArrayList([]const u8).init(b.allocator); |
| 53 | + if (target.result.abi != .msvc) try flags.append("-D_GNU_SOURCE"); |
| 54 | + if (target.result.os.tag == .macos) try flags.appendSlice(&.{ "-D_DARWIN_C_SOURCE", "-DGGML_USE_METAL", "-DGGML_USE_ACCELERATE", "-DACCELERATE_USE_LAPACK", "-DACCELERATE_LAPACK_ILP64" }) else try flags.append("-DGGML_USE_VULKAN"); |
| 55 | + try flags.append("-D_XOPEN_SOURCE=600"); |
15 | 56 |
|
| 57 | + var cflags = std.ArrayList([]const u8).init(b.allocator); |
| 58 | + try cflags.append("-std=c11"); |
| 59 | + try cflags.appendSlice(flags.items); |
| 60 | + var cxxflags = std.ArrayList([]const u8).init(b.allocator); |
| 61 | + try cxxflags.append("-std=c++11"); |
| 62 | + try cxxflags.appendSlice(flags.items); |
| 63 | + |
| 64 | + const include_paths = [_][]const u8{ "llama.cpp", "llama.cpp/common" }; |
| 65 | + const llama = buildObj(.{ |
| 66 | + .b = b, |
| 67 | + .name = "llama", |
| 68 | + .target = target, |
| 69 | + .optimize = optimize, |
| 70 | + .sources = &.{"llama.cpp/llama.cpp"}, |
| 71 | + .include_paths = &include_paths, |
| 72 | + .link_lib_cpp = true, |
| 73 | + .link_lib_c = false, |
| 74 | + .flags = cxxflags.items, |
| 75 | + }); |
| 76 | + const ggml = buildObj(.{ |
| 77 | + .b = b, |
| 78 | + .name = "ggml", |
| 79 | + .target = target, |
| 80 | + .optimize = optimize, |
| 81 | + .sources = &.{"llama.cpp/ggml.c"}, |
| 82 | + .include_paths = &include_paths, |
| 83 | + .link_lib_c = true, |
| 84 | + .link_lib_cpp = false, |
| 85 | + .flags = cflags.items, |
| 86 | + }); |
| 87 | + const common = buildObj(.{ |
| 88 | + .b = b, |
| 89 | + .name = "common", |
| 90 | + .target = target, |
| 91 | + .optimize = optimize, |
| 92 | + .sources = &.{"llama.cpp/common/common.cpp"}, |
| 93 | + .include_paths = &include_paths, |
| 94 | + .link_lib_cpp = true, |
| 95 | + .link_lib_c = false, |
| 96 | + .flags = cxxflags.items, |
| 97 | + }); |
| 98 | + const console = buildObj(.{ |
| 99 | + .b = b, |
| 100 | + .name = "console", |
| 101 | + .target = target, |
| 102 | + .optimize = optimize, |
| 103 | + .sources = &.{"llama.cpp/common/console.cpp"}, |
| 104 | + .include_paths = &include_paths, |
| 105 | + .link_lib_cpp = true, |
| 106 | + .link_lib_c = false, |
| 107 | + .flags = cxxflags.items, |
| 108 | + }); |
| 109 | + const sampling = buildObj(.{ |
| 110 | + .b = b, |
| 111 | + .name = "sampling", |
| 112 | + .target = target, |
| 113 | + .optimize = optimize, |
| 114 | + .sources = &.{"llama.cpp/common/sampling.cpp"}, |
| 115 | + .include_paths = &include_paths, |
| 116 | + .link_lib_cpp = true, |
| 117 | + .link_lib_c = false, |
| 118 | + .flags = cxxflags.items, |
| 119 | + }); |
| 120 | + const grammar_parser = buildObj(.{ |
| 121 | + .b = b, |
| 122 | + .name = "grammar_parser", |
| 123 | + .target = target, |
| 124 | + .optimize = optimize, |
| 125 | + .sources = &.{"llama.cpp/common/grammar-parser.cpp"}, |
| 126 | + .include_paths = &include_paths, |
| 127 | + .link_lib_cpp = true, |
| 128 | + .link_lib_c = false, |
| 129 | + .flags = cxxflags.items, |
| 130 | + }); |
| 131 | + const build_info = buildObj(.{ |
| 132 | + .b = b, |
| 133 | + .name = "build_info", |
| 134 | + .target = target, |
| 135 | + .optimize = optimize, |
| 136 | + .sources = &.{"llama.cpp/common/build-info.cpp"}, |
| 137 | + .include_paths = &include_paths, |
| 138 | + .link_lib_cpp = true, |
| 139 | + .link_lib_c = false, |
| 140 | + .flags = cxxflags.items, |
| 141 | + }); |
| 142 | + const ggml_alloc = buildObj(.{ |
| 143 | + .b = b, |
| 144 | + .name = "ggml_alloc", |
| 145 | + .target = target, |
| 146 | + .optimize = optimize, |
| 147 | + .sources = &.{"llama.cpp/ggml-alloc.c"}, |
| 148 | + .include_paths = &include_paths, |
| 149 | + .link_lib_c = true, |
| 150 | + .link_lib_cpp = false, |
| 151 | + .flags = cflags.items, |
| 152 | + }); |
| 153 | + const ggml_backend = buildObj(.{ |
| 154 | + .b = b, |
| 155 | + .name = "ggml_backend", |
| 156 | + .target = target, |
| 157 | + .optimize = optimize, |
| 158 | + .sources = &.{"llama.cpp/ggml-backend.c"}, |
| 159 | + .include_paths = &include_paths, |
| 160 | + .link_lib_c = true, |
| 161 | + .link_lib_cpp = false, |
| 162 | + .flags = cflags.items, |
| 163 | + }); |
| 164 | + const ggml_quants = buildObj(.{ |
| 165 | + .b = b, |
| 166 | + .name = "ggml_quants", |
| 167 | + .target = target, |
| 168 | + .optimize = optimize, |
| 169 | + .sources = &.{"llama.cpp/ggml-quants.c"}, |
| 170 | + .include_paths = &include_paths, |
| 171 | + .link_lib_c = true, |
| 172 | + .link_lib_cpp = false, |
| 173 | + .flags = cflags.items, |
| 174 | + }); |
| 175 | + try objs.appendSlice(&.{ llama, ggml, common, console, sampling, grammar_parser, build_info, ggml_alloc, ggml_backend, ggml_quants }); |
| 176 | + |
| 177 | + if (target.result.os.tag == .macos) { |
| 178 | + const ggml_metal = buildObj(.{ |
| 179 | + .b = b, |
| 180 | + .name = "ggml_metal", |
| 181 | + .target = target, |
| 182 | + .optimize = optimize, |
| 183 | + .sources = &.{"llama.cpp/ggml-metal.m"}, |
| 184 | + .include_paths = &include_paths, |
| 185 | + .link_lib_c = true, |
| 186 | + .link_lib_cpp = false, |
| 187 | + .flags = cflags.items, |
| 188 | + }); |
| 189 | + try objs.append(ggml_metal); |
| 190 | + } else { |
| 191 | + const ggml_vulkan = buildObj(.{ |
| 192 | + .b = b, |
| 193 | + .name = "ggml_vulkan", |
| 194 | + .target = target, |
| 195 | + .optimize = optimize, |
| 196 | + .sources = &.{"llama.cpp/ggml-vulkan.cpp"}, |
| 197 | + .include_paths = &include_paths, |
| 198 | + .link_lib_cpp = true, |
| 199 | + .link_lib_c = false, |
| 200 | + .flags = cxxflags.items, |
| 201 | + }); |
| 202 | + try objs.append(ggml_vulkan); |
| 203 | + } |
| 204 | + |
| 205 | + const extension = b.addSharedLibrary(.{ .name = b.fmt("{s}-{s}", .{ extension_name, zig_triple }), .target = target, .optimize = optimize }); |
| 206 | + const sources = try findFilesRecursive(b, "src", &cfiles_exts); |
| 207 | + extension.addCSourceFiles(.{ .files = sources, .flags = &.{ "-std=c++17", "-fno-exceptions" } }); |
| 208 | + extension.addIncludePath(.{ .path = "src" }); |
| 209 | + extension.addIncludePath(.{ .path = "godot_cpp/include/" }); |
| 210 | + extension.addIncludePath(.{ .path = "godot_cpp/gdextension/" }); |
| 211 | + extension.addIncludePath(.{ .path = "godot_cpp/gen/include/" }); |
| 212 | + extension.addIncludePath(.{ .path = "llama.cpp" }); |
| 213 | + extension.addIncludePath(.{ .path = "llama.cpp/common" }); |
| 214 | + for (objs.items) |obj| { |
| 215 | + extension.addObject(obj); |
| 216 | + } |
16 | 217 | extension.linkLibC();
|
17 | 218 | extension.linkLibCpp();
|
| 219 | + if (target.result.os.tag == .macos) { |
| 220 | + extension.linkFramework("Metal"); |
| 221 | + extension.linkFramework("MetalKit"); |
| 222 | + extension.linkFramework("Foundation"); |
| 223 | + extension.linkFramework("Accelerate"); |
| 224 | + } else { |
| 225 | + extension.linkSystemLibrary("vulkan"); |
| 226 | + } |
| 227 | + extension.linkLibrary(lib_godot); |
18 | 228 |
|
19 |
| - const sources = try findFilesRecursive(b, "src", &.{ ".c", ".cpp", ".cxx", ".c++", ".cc" }); |
20 |
| - extension.addCSourceFiles(.{ .files = sources, .flags = &.{ "-std=c++17", "-fno-exceptions" } }); |
| 229 | + b.installArtifact(extension); |
| 230 | +} |
21 | 231 |
|
22 |
| - // const llama_libs = try findFilesRecursive(b, "llama.cpp/zig-out/lib", &.{".lib"}); |
23 |
| - // for (llama_libs) |lib| { |
24 |
| - // extension.addObjectFile(.{ .path = lib }); |
25 |
| - // } |
| 232 | +const BuildObjectParams = struct { |
| 233 | + b: *std.Build, |
| 234 | + name: []const u8, |
| 235 | + target: std.Build.ResolvedTarget, |
| 236 | + optimize: std.builtin.OptimizeMode, |
| 237 | + sources: []const []const u8, |
| 238 | + include_paths: []const []const u8, |
| 239 | + link_lib_c: bool, |
| 240 | + link_lib_cpp: bool, |
| 241 | + flags: []const []const u8, |
| 242 | +}; |
26 | 243 |
|
27 |
| - b.installArtifact(extension); |
| 244 | +fn buildObj(params: BuildObjectParams) *std.Build.Step.Compile { |
| 245 | + const obj = params.b.addObject(.{ |
| 246 | + .name = params.name, |
| 247 | + .target = params.target, |
| 248 | + .optimize = params.optimize, |
| 249 | + }); |
| 250 | + for (params.include_paths) |path| { |
| 251 | + obj.addIncludePath(.{ .path = path }); |
| 252 | + } |
| 253 | + if (params.link_lib_c) { |
| 254 | + obj.linkLibC(); |
| 255 | + } |
| 256 | + if (params.link_lib_cpp) { |
| 257 | + obj.linkLibCpp(); |
| 258 | + } |
| 259 | + obj.addCSourceFiles(.{ .files = params.sources, .flags = params.flags }); |
| 260 | + return obj; |
28 | 261 | }
|
29 | 262 |
|
30 | 263 | fn findFilesRecursive(b: *std.Build, dir_name: []const u8, exts: []const []const u8) ![][]const u8 {
|
31 | 264 | var sources = std.ArrayList([]const u8).init(b.allocator);
|
32 | 265 |
|
33 |
| - var dir = try std.fs.cwd().openDir(dir_name, .{ .iterate = true }); |
| 266 | + var dir = try b.build_root.handle.openDir(dir_name, .{ .iterate = true }); |
34 | 267 | var walker = try dir.walk(b.allocator);
|
35 | 268 | defer walker.deinit();
|
36 | 269 | while (try walker.next()) |entry| {
|
|
0 commit comments