|
1 | 1 | const std = @import("std"); |
2 | | -const metap = @import("metaplus").@"meta+"; |
3 | 2 |
|
4 | | -pub const Sdk = @import("src/phantom/sdk.zig"); |
| 3 | +const WaylandScanner = @import("zig-wayland").Scanner; |
5 | 4 |
|
6 | | -pub const DisplayBackendType = metap.enums.fields.mix(metap.enums.fromDecls(@import("src/phantom/display/backends.zig")), Sdk.TypeFor(.displays)); |
7 | | -pub const FontBackendType = metap.enums.fields.mix(metap.enums.fromDecls(@import("src/phantom/fonts/backends.zig")), Sdk.TypeFor(.fonts)); |
8 | | -pub const PlatformBackendType = metap.enums.fields.mix(metap.enums.fromDecls(@import("src/phantom/platform/backends.zig")), Sdk.TypeFor(.platforms)); |
9 | | -pub const SceneBackendType = metap.enums.fields.mix(metap.enums.fromDecls(@import("src/phantom/scene/backends.zig")), Sdk.TypeFor(.scenes)); |
10 | | -pub const ImageFormatType = metap.enums.fields.mix(metap.enums.fromDecls(@import("src/phantom/painting/image/formats.zig")), Sdk.TypeFor(.imageFormats)); |
11 | | - |
12 | | -fn addSourceFiles( |
13 | | - b: *std.Build, |
14 | | - fileOverrides: *std.StringHashMap([]const u8), |
15 | | - rootSource: *[]const u8, |
16 | | - phantomSource: *std.Build.Step.WriteFile, |
17 | | - rootPath: []const u8, |
18 | | -) !void { |
19 | | - var depSourceRoot = try std.fs.openDirAbsolute(b.pathJoin(&.{ rootPath, "phantom" }), .{ .iterate = true }); |
20 | | - defer depSourceRoot.close(); |
21 | | - |
22 | | - var walker = try depSourceRoot.walk(b.allocator); |
23 | | - defer walker.deinit(); |
24 | | - |
25 | | - while (try walker.next()) |entry| { |
26 | | - if (entry.kind == .directory) continue; |
27 | | - |
28 | | - const entryPath = b.pathJoin(&.{ rootPath, "phantom", entry.path }); |
29 | | - var entrySource = try Sdk.readAll(b.allocator, entryPath); |
30 | | - errdefer b.allocator.free(entrySource); |
31 | | - |
32 | | - const entrypointRel = try std.fs.path.relative(b.allocator, std.fs.path.dirname(entryPath).?, b.pathJoin(&.{ rootPath, "phantom.zig" })); |
33 | | - defer b.allocator.free(entrypointRel); |
34 | | - |
35 | | - const entrySourceOrig = entrySource; |
36 | | - entrySource = try std.mem.replaceOwned(u8, b.allocator, entrySourceOrig, "@import(\"phantom\")", b.fmt("@import(\"{s}\")", .{entrypointRel})); |
37 | | - b.allocator.free(entrySourceOrig); |
38 | | - |
39 | | - if (fileOverrides.getPtr(entry.path)) |sourceptr| { |
40 | | - const fullSource = try Sdk.updateSource(b.allocator, sourceptr.*, entrySource); |
41 | | - errdefer b.allocator.free(fullSource); |
42 | | - |
43 | | - b.allocator.free(sourceptr.*); |
44 | | - sourceptr.* = fullSource; |
45 | | - } else { |
46 | | - const origPath = b.pathFromRoot(b.pathJoin(&.{ "src/phantom", entry.path })); |
47 | | - if (Sdk.readAll(b.allocator, origPath) catch null) |origSource| { |
48 | | - defer b.allocator.free(origSource); |
49 | | - |
50 | | - const fullSource = try Sdk.updateSource(b.allocator, origSource, entrySource); |
51 | | - errdefer b.allocator.free(fullSource); |
52 | | - |
53 | | - try fileOverrides.put(try b.allocator.dupe(u8, entry.path), fullSource); |
54 | | - b.allocator.free(entrySource); |
55 | | - } else { |
56 | | - _ = phantomSource.add(b.pathJoin(&.{ "phantom", entry.path }), entrySource); |
57 | | - } |
58 | | - } |
59 | | - } |
60 | | - |
61 | | - const src = try Sdk.readAll(b.allocator, b.pathJoin(&.{ rootPath, "phantom.zig" })); |
62 | | - defer b.allocator.free(src); |
| 5 | +pub fn build(b: *std.Build) void { |
| 6 | + const target = b.standardTargetOptions(.{}); |
| 7 | + const optimize = b.standardOptimizeOption(.{}); |
| 8 | + const linkage = b.option(std.builtin.LinkMode, "linkage", "Whether to link as a static or dynamic binary"); |
63 | 9 |
|
64 | | - const fullSource = try Sdk.updateSource(b.allocator, rootSource.*, src); |
65 | | - errdefer b.allocator.free(fullSource); |
| 10 | + const fsys_default = linkage == .dynamic and switch (target.result.os.tag) { |
| 11 | + .linux, .windows, .macos => true, |
| 12 | + else => false, |
| 13 | + }; |
66 | 14 |
|
67 | | - b.allocator.free(rootSource.*); |
68 | | - rootSource.* = fullSource; |
69 | | -} |
| 15 | + const fsys_cairo = b.systemIntegrationOption("cairo", .{ |
| 16 | + .default = fsys_default, |
| 17 | + }); |
70 | 18 |
|
71 | | -pub fn build(b: *std.Build) !void { |
72 | | - const target = b.standardTargetOptions(.{}); |
73 | | - const optimize = b.standardOptimizeOption(.{}); |
74 | | - const no_docs = b.option(bool, "no-docs", "skip installing documentation") orelse false; |
75 | | - const no_importer = b.option(bool, "no-importer", "disables the import system (not recommended)") orelse false; |
76 | | - const display_backend = b.option(DisplayBackendType, "display-backend", "The display backend to use for the example") orelse .headless; |
77 | | - const platform_backend = b.option(PlatformBackendType, "platform-backend", "The display backend to use for the example") orelse .std; |
78 | | - const scene_backend = b.option(SceneBackendType, "scene-backend", "The scene backend to use for the example") orelse .headless; |
| 19 | + const fsys_wayland = b.systemIntegrationOption("wayland", .{ |
| 20 | + .default = fsys_default, |
| 21 | + }); |
79 | 22 |
|
80 | | - const vizops = b.dependency("vizops", .{ |
| 23 | + const zigimg = b.dependency("zigimg", .{ |
81 | 24 | .target = target, |
82 | 25 | .optimize = optimize, |
83 | 26 | }); |
84 | 27 |
|
85 | | - const metaplus = b.dependency("metaplus", .{ |
| 28 | + const z2d = b.dependency("z2d", .{ |
86 | 29 | .target = target, |
87 | 30 | .optimize = optimize, |
88 | 31 | }); |
89 | 32 |
|
90 | | - const anyplus = b.dependency("any+", .{ |
| 33 | + const module = b.addModule("phantom", .{ |
| 34 | + .root_source_file = b.path("src/phantom.zig"), |
91 | 35 | .target = target, |
92 | 36 | .optimize = optimize, |
| 37 | + .imports = &.{ |
| 38 | + .{ |
| 39 | + .name = "zigimg", |
| 40 | + .module = zigimg.module("zigimg"), |
| 41 | + }, |
| 42 | + .{ |
| 43 | + .name = "z2d", |
| 44 | + .module = z2d.module("z2d"), |
| 45 | + }, |
| 46 | + }, |
93 | 47 | }); |
94 | 48 |
|
95 | | - const phantomOptions = b.addOptions(); |
96 | | - phantomOptions.addOption(bool, "no_importer", no_importer); |
97 | | - |
98 | | - var phantomDeps = std.ArrayList(std.Build.Module.Import).init(b.allocator); |
99 | | - errdefer phantomDeps.deinit(); |
100 | | - |
101 | | - try phantomDeps.append(.{ |
102 | | - .name = "vizops", |
103 | | - .module = vizops.module("vizops"), |
104 | | - }); |
105 | | - |
106 | | - try phantomDeps.append(.{ |
107 | | - .name = "meta+", |
108 | | - .module = metaplus.module("meta+"), |
109 | | - }); |
110 | | - |
111 | | - try phantomDeps.append(.{ |
112 | | - .name = "any+", |
113 | | - .module = anyplus.module("any+"), |
114 | | - }); |
115 | | - |
116 | | - try phantomDeps.append(.{ |
117 | | - .name = "phantom.options", |
118 | | - .module = phantomOptions.createModule(), |
119 | | - }); |
120 | | - |
121 | | - const phantomSource = b.addWriteFiles(); |
122 | | - |
123 | | - var fileOverrides = std.StringHashMap([]const u8).init(b.allocator); |
124 | | - defer fileOverrides.deinit(); |
125 | | - |
126 | | - var rootSource = try Sdk.readAll(b.allocator, b.pathFromRoot("src/phantom.zig")); |
127 | | - defer b.allocator.free(rootSource); |
| 49 | + const options = b.addOptions(); |
| 50 | + options.addOption(bool, "cairo", fsys_cairo); |
| 51 | + options.addOption(bool, "wayland", fsys_wayland); |
128 | 52 |
|
129 | | - if (!no_importer) { |
130 | | - inline for (Sdk.availableDepenencies) |dep| { |
131 | | - const pkg = @field(@import("root").dependencies.packages, dep[1]); |
132 | | - const pkgdep = b.dependencyInner(dep[0], pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, .{ |
133 | | - .target = target, |
134 | | - .optimize = optimize, |
135 | | - .@"no-importer" = true, |
136 | | - }); |
137 | | - |
138 | | - const depSourceRootPath = b.pathJoin(&.{ pkg.build_root, "src" }); |
139 | | - try addSourceFiles(b, &fileOverrides, &rootSource, phantomSource, depSourceRootPath); |
140 | | - |
141 | | - var iter = pkgdep.module(dep[0]).import_table.iterator(); |
142 | | - while (iter.next()) |entry| { |
143 | | - var alreadyExists = false; |
144 | | - for (phantomDeps.items) |i| { |
145 | | - if (std.mem.eql(u8, i.name, entry.key_ptr.*)) { |
146 | | - alreadyExists = true; |
147 | | - break; |
148 | | - } |
149 | | - } |
| 53 | + if (fsys_cairo) { |
| 54 | + module.linkSystemLibrary("cairo", .{ |
| 55 | + .needed = true, |
| 56 | + .preferred_link_mode = linkage orelse .dynamic, |
| 57 | + }); |
150 | 58 |
|
151 | | - if (!alreadyExists or !std.mem.eql(u8, entry.key_ptr.*, "phantom")) { |
152 | | - try phantomDeps.append(.{ |
153 | | - .name = entry.key_ptr.*, |
154 | | - .module = entry.value_ptr.*, |
155 | | - }); |
156 | | - } |
157 | | - } |
158 | | - } |
| 59 | + module.link_libc = true; |
159 | 60 | } |
160 | 61 |
|
161 | | - if (b.option([]const u8, "import-module", "inject a module to be imported")) |importModuleString| { |
162 | | - const modulePathLen = std.mem.indexOf(u8, importModuleString, ":") orelse importModuleString.len; |
163 | | - const modulePath = importModuleString[0..modulePathLen]; |
| 62 | + if (fsys_wayland) { |
| 63 | + const scanner = WaylandScanner.create(b, .{}); |
164 | 64 |
|
165 | | - try addSourceFiles(b, &fileOverrides, &rootSource, phantomSource, modulePath); |
| 65 | + scanner.generate("wl_compositor", 1); |
| 66 | + scanner.generate("wl_output", 1); |
| 67 | + scanner.generate("wl_shm", 1); |
166 | 68 |
|
167 | | - if (modulePathLen < importModuleString.len) { |
168 | | - const imports = try Sdk.ModuleImport.decode(b.allocator, importModuleString[(modulePathLen + 1)..]); |
169 | | - defer imports.deinit(); |
| 69 | + const wayland = b.createModule(.{ .root_source_file = scanner.result }); |
170 | 70 |
|
171 | | - for (imports.value) |dep| { |
172 | | - var alreadyExists = false; |
173 | | - for (phantomDeps.items) |i| { |
174 | | - if (std.mem.eql(u8, i.name, dep.name)) { |
175 | | - alreadyExists = true; |
176 | | - break; |
177 | | - } |
| 71 | + module.addImport("wayland", wayland); |
178 | 72 |
|
179 | | - if (!alreadyExists or !std.mem.eql(u8, dep.name, "phantom")) { |
180 | | - try phantomDeps.append(.{ |
181 | | - .name = dep.name, |
182 | | - .module = try dep.createModule(b, target, optimize), |
183 | | - }); |
184 | | - } |
185 | | - } |
186 | | - } |
187 | | - } |
188 | | - } |
189 | | - |
190 | | - var phantomSourceRoot = try std.fs.openDirAbsolute(b.pathFromRoot("src/phantom"), .{ .iterate = true }); |
191 | | - defer phantomSourceRoot.close(); |
192 | | - |
193 | | - var walker = try phantomSourceRoot.walk(b.allocator); |
194 | | - defer walker.deinit(); |
195 | | - |
196 | | - while (try walker.next()) |entry| { |
197 | | - if (entry.kind == .directory) continue; |
| 73 | + module.linkSystemLibrary("wayland-client", .{ |
| 74 | + .needed = true, |
| 75 | + .preferred_link_mode = linkage orelse .dynamic, |
| 76 | + }); |
198 | 77 |
|
199 | | - const entryPath = b.pathJoin(&.{ "phantom", entry.path }); |
| 78 | + module.linkSystemLibrary("wayland-server", .{ |
| 79 | + .needed = true, |
| 80 | + .preferred_link_mode = linkage orelse .dynamic, |
| 81 | + }); |
200 | 82 |
|
201 | | - if (fileOverrides.get(entry.path)) |source| { |
202 | | - _ = phantomSource.add(entryPath, source); |
203 | | - } else { |
204 | | - _ = phantomSource.addCopyFile(.{ |
205 | | - .path = b.pathFromRoot(b.pathJoin(&.{ "src/phantom", entry.path })), |
206 | | - }, entryPath); |
207 | | - } |
| 83 | + module.link_libc = true; |
208 | 84 | } |
209 | 85 |
|
210 | | - const phantom = b.addModule("phantom", .{ |
211 | | - .root_source_file = phantomSource.add("phantom.zig", rootSource), |
212 | | - .imports = phantomDeps.items, |
213 | | - }); |
214 | | - |
215 | | - const step_test = b.step("test", "Run all unit tests"); |
| 86 | + module.addOptions("options", options); |
216 | 87 |
|
217 | | - const unit_tests = b.addTest(.{ |
218 | | - .root_source_file = phantom.root_source_file.?, |
219 | | - .target = target, |
220 | | - .optimize = optimize, |
| 88 | + const autodoc_test = b.addObject(.{ |
| 89 | + .name = "phantom", |
| 90 | + .root_module = module, |
221 | 91 | }); |
222 | 92 |
|
223 | | - for (phantomDeps.items) |dep| { |
224 | | - unit_tests.root_module.addImport(dep.name, dep.module); |
225 | | - } |
226 | | - |
227 | | - const run_unit_tests = b.addRunArtifact(unit_tests); |
228 | | - step_test.dependOn(&run_unit_tests.step); |
229 | | - b.installArtifact(unit_tests); |
230 | | - |
231 | | - const exe_options = b.addOptions(); |
232 | | - exe_options.addOption(DisplayBackendType, "display_backend", display_backend); |
233 | | - exe_options.addOption(PlatformBackendType, "platform_backend", platform_backend); |
234 | | - exe_options.addOption(SceneBackendType, "scene_backend", scene_backend); |
235 | | - |
236 | | - const sdk = try Sdk.get(b, platform_backend, phantom); |
237 | | - defer sdk.deinit(); |
238 | | - |
239 | | - const pkg_example = sdk.addPackage(.{ |
240 | | - .id = "dev.phantomui.example", |
241 | | - .name = "example", |
242 | | - .root_module = .{ |
243 | | - .root_source_file = .{ |
244 | | - .path = b.pathFromRoot("src/example.zig"), |
245 | | - }, |
246 | | - .target = target, |
247 | | - .optimize = optimize, |
248 | | - }, |
249 | | - .kind = .application, |
250 | | - .version = .{ |
251 | | - .major = 0, |
252 | | - .minor = 1, |
253 | | - .patch = 0, |
254 | | - }, |
| 93 | + const install_docs = b.addInstallDirectory(.{ |
| 94 | + .source_dir = autodoc_test.getEmittedDocs(), |
| 95 | + .install_dir = .prefix, |
| 96 | + .install_subdir = "doc/phantom", |
255 | 97 | }); |
256 | 98 |
|
257 | | - pkg_example.root_module.addImport("vizops", vizops.module("vizops")); |
258 | | - pkg_example.root_module.addImport("options", exe_options.createModule()); |
| 99 | + b.getInstallStep().dependOn(&install_docs.step); |
259 | 100 |
|
260 | | - sdk.installPackage(pkg_example); |
| 101 | + const step_test = b.step("test", "Run unit tests"); |
261 | 102 |
|
262 | | - if (!no_docs) { |
263 | | - const docs = b.addInstallDirectory(.{ |
264 | | - .source_dir = unit_tests.getEmittedDocs(), |
265 | | - .install_dir = .prefix, |
266 | | - .install_subdir = "docs", |
267 | | - }); |
| 103 | + const test_exe = b.addTest(.{ |
| 104 | + .target = target, |
| 105 | + .optimize = optimize, |
| 106 | + .root_module = module, |
| 107 | + }); |
268 | 108 |
|
269 | | - b.getInstallStep().dependOn(&docs.step); |
270 | | - } |
| 109 | + const test_run = b.addRunArtifact(test_exe); |
| 110 | + step_test.dependOn(&test_run.step); |
271 | 111 | } |
0 commit comments