From 8accd2806042d3c326dbd239101fd7f03975fc6e Mon Sep 17 00:00:00 2001 From: abap34 Date: Fri, 29 May 2026 17:45:17 +0900 Subject: [PATCH 1/2] Simplify PDF backend dependencies Declare the native PDF backend dependency set through local pkg-config metadata and link it with forced pkg-config resolution. Drop the rsvg-convert command path now that SVG assets are drawn through librsvg in the renderer. Co-authored-by: Codex --- .github/workflows/publish-render-image.yml | 1 - .github/workflows/render-smoke.yml | 1 - build.zig | 25 ++++++++++------------ release/docker/render/Dockerfile | 2 +- release/tools/pre-release-check.sh | 1 - src/main.zig | 1 - src/render/{pdf_native_c.c => pdf/pdf.c} | 2 +- src/render/{pdf_native_c.h => pdf/pdf.h} | 4 ++-- src/render/pdf/ss-pdf.pc | 6 ++++++ src/render/pdf_native.zig | 16 +------------- 10 files changed, 22 insertions(+), 37 deletions(-) rename src/render/{pdf_native_c.c => pdf/pdf.c} (99%) rename src/render/{pdf_native_c.h => pdf/pdf.h} (97%) create mode 100644 src/render/pdf/ss-pdf.pc diff --git a/.github/workflows/publish-render-image.yml b/.github/workflows/publish-render-image.yml index 859595e..b28568c 100644 --- a/.github/workflows/publish-render-image.yml +++ b/.github/workflows/publish-render-image.yml @@ -45,7 +45,6 @@ jobs: git \ imagemagick \ libcairo2-dev \ - librsvg2-bin \ librsvg2-dev \ libpango1.0-dev \ pkg-config \ diff --git a/.github/workflows/render-smoke.yml b/.github/workflows/render-smoke.yml index 045dc15..b0868f1 100644 --- a/.github/workflows/render-smoke.yml +++ b/.github/workflows/render-smoke.yml @@ -59,7 +59,6 @@ jobs: git \ imagemagick \ libcairo2-dev \ - librsvg2-bin \ librsvg2-dev \ libpango1.0-dev \ pkg-config \ diff --git a/build.zig b/build.zig index 92891ed..6fe5ea8 100644 --- a/build.zig +++ b/build.zig @@ -15,6 +15,12 @@ pub fn build(b: *std.Build) void { b.build_root.handle.access(b.graph.io, md4c_src ++ "/md4c.c", .{}) catch @panic("MD4C sources are missing; run `scripts/setup-md4c.sh` before `zig build`."); const md4c_include = b.path(md4c_src); + const pdf_pkg_config_path = b.path("src/render/pdf").getPath(b); + const pkg_config_path = if (b.graph.environ_map.get("PKG_CONFIG_PATH")) |path| + b.fmt("{s}{c}{s}", .{ pdf_pkg_config_path, std.fs.path.delimiter, path }) + else + pdf_pkg_config_path; + b.graph.environ_map.put("PKG_CONFIG_PATH", pkg_config_path) catch @panic("OOM"); const utils_mod = b.createModule(.{ .root_source_file = b.path("src/utils/root.zig"), @@ -292,20 +298,11 @@ pub fn build(b: *std.Build) void { } fn addNativePdfBackend(b: *std.Build, module: *std.Build.Module) void { - module.addIncludePath(b.path("src/render")); - addLinuxPangoIncludePaths(module); - module.addCSourceFile(.{ .file = b.path("src/render/pdf_native_c.c") }); - module.linkSystemLibrary("librsvg-2.0", .{ .use_pkg_config = .force }); - module.linkSystemLibrary("pangocairo-1.0", .{ .use_pkg_config = .no }); - module.linkSystemLibrary("pango-1.0", .{ .use_pkg_config = .no }); -} - -fn addLinuxPangoIncludePaths(module: *std.Build.Module) void { - module.addSystemIncludePath(.{ .cwd_relative = "/usr/include/pango-1.0" }); - module.addSystemIncludePath(.{ .cwd_relative = "/usr/include/harfbuzz" }); - module.addSystemIncludePath(.{ .cwd_relative = "/usr/include/fribidi" }); - module.addSystemIncludePath(.{ .cwd_relative = "/usr/include/libthai" }); - module.addSystemIncludePath(.{ .cwd_relative = "/usr/include/libdatrie" }); + module.addIncludePath(b.path("src/render/pdf")); + module.addCSourceFile(.{ + .file = b.path("src/render/pdf/pdf.c"), + }); + module.linkSystemLibrary("ss-pdf", .{ .use_pkg_config = .force }); } fn readReleaseVersion(b: *std.Build) ![]const u8 { diff --git a/release/docker/render/Dockerfile b/release/docker/render/Dockerfile index 71cc281..68da79a 100644 --- a/release/docker/render/Dockerfile +++ b/release/docker/render/Dockerfile @@ -64,7 +64,7 @@ RUN set -eu; \ libcairo2 \ libpango-1.0-0 \ libpangocairo-1.0-0 \ - librsvg2-bin \ + librsvg2-2 \ poppler-utils \ qpdf \ texlive-full; \ diff --git a/release/tools/pre-release-check.sh b/release/tools/pre-release-check.sh index 48c90d8..ee74da1 100755 --- a/release/tools/pre-release-check.sh +++ b/release/tools/pre-release-check.sh @@ -155,7 +155,6 @@ require_command npm require_command pkg-config require_command qpdf require_command pdftoppm -require_command rsvg-convert require_command pdflatex require_command ruby if [[ "$skip_docker" != true ]]; then diff --git a/src/main.zig b/src/main.zig index 4138803..7d2ffb7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -359,7 +359,6 @@ const DoctorTool = struct { const doctor_tools = [_]DoctorTool{ .{ .name = "qpdf", .purpose = "PDF assembly and normalization", .required = true }, .{ .name = "magick", .purpose = "raster image conversion and resizing" }, - .{ .name = "rsvg-convert", .purpose = "SVG asset conversion" }, .{ .name = "pdftocairo", .purpose = "PDF/vector asset conversion" }, .{ .name = "pdflatex", .purpose = "LaTeX math rendering" }, }; diff --git a/src/render/pdf_native_c.c b/src/render/pdf/pdf.c similarity index 99% rename from src/render/pdf_native_c.c rename to src/render/pdf/pdf.c index 05a45e0..bfb9809 100644 --- a/src/render/pdf_native_c.c +++ b/src/render/pdf/pdf.c @@ -1,4 +1,4 @@ -#include "pdf_native_c.h" +#include "pdf.h" #include #include diff --git a/src/render/pdf_native_c.h b/src/render/pdf/pdf.h similarity index 97% rename from src/render/pdf_native_c.h rename to src/render/pdf/pdf.h index 57f13e1..97c0e1c 100644 --- a/src/render/pdf_native_c.h +++ b/src/render/pdf/pdf.h @@ -1,5 +1,5 @@ -#ifndef SS_PDF_NATIVE_C_H -#define SS_PDF_NATIVE_C_H +#ifndef SS_PDF_H +#define SS_PDF_H #ifdef __cplusplus extern "C" { diff --git a/src/render/pdf/ss-pdf.pc b/src/render/pdf/ss-pdf.pc new file mode 100644 index 0000000..68473db --- /dev/null +++ b/src/render/pdf/ss-pdf.pc @@ -0,0 +1,6 @@ +Name: ss-pdf +Description: ss native PDF backend dependencies +Version: 0 +Requires: librsvg-2.0 pangocairo +Libs: +Cflags: diff --git a/src/render/pdf_native.zig b/src/render/pdf_native.zig index f9f27bf..8ea0f1d 100644 --- a/src/render/pdf_native.zig +++ b/src/render/pdf_native.zig @@ -5,7 +5,7 @@ const declarations = @import("../language/declarations.zig"); const semantic_env = @import("../language/env.zig"); const c = @cImport({ - @cInclude("pdf_native_c.h"); + @cInclude("pdf.h"); }); const Allocator = std.mem.Allocator; @@ -2651,7 +2651,6 @@ fn resolveAssetPath(ctx: *DrawContext, rel_path: []const u8) ![]const u8 { } fn rasterToSizedPng(ctx: *DrawContext, source: []const u8, target_width: f32, target_height: f32) ![]const u8 { - if (std.ascii.eqlIgnoreCase(std.fs.path.extension(source), ".svg")) return svgToPng(ctx, source); if (std.ascii.eqlIgnoreCase(std.fs.path.extension(source), ".png")) { var source_width: f64 = 0; var source_height: f64 = 0; @@ -2684,19 +2683,6 @@ fn rasterToSizedPng(ctx: *DrawContext, source: []const u8, target_width: f32, ta return out; } -fn svgToPng(ctx: *DrawContext, source: []const u8) ![]const u8 { - const out = try cachedAssetPath(ctx, "svg", source, "png"); - errdefer ctx.allocator.free(out); - if (try cachedPngAvailable(ctx, out)) return out; - const tmp = try tempCachePath(ctx, out, "png"); - defer ctx.allocator.free(tmp); - errdefer deleteFileIfExists(ctx, tmp); - try runChecked(ctx, &.{ "rsvg-convert", "-f", "png", "-o", tmp, source }, .inherit); - try validatePng(tmp); - try publishCacheFile(ctx, tmp, out); - return out; -} - fn pdfToSvg(ctx: *DrawContext, source: []const u8) ![]const u8 { const out = try cachedAssetPath(ctx, "pdf", source, "svg"); errdefer ctx.allocator.free(out); From 3230aab5d673a4c1c690b0b757a982f424f91888 Mon Sep 17 00:00:00 2001 From: abap34 Date: Fri, 29 May 2026 18:26:02 +0900 Subject: [PATCH 2/2] Refactor build.zig Organize module creation and test registration helpers so the build file stays focused on build graph structure. Co-authored-by: Codex --- build.zig | 441 +++++++++++++++++++++++++----------------------------- 1 file changed, 205 insertions(+), 236 deletions(-) diff --git a/build.zig b/build.zig index 6fe5ea8..522916b 100644 --- a/build.zig +++ b/build.zig @@ -1,8 +1,30 @@ const std = @import("std"); +const Module = std.Build.Module; +const Step = std.Build.Step; +const Import = Module.Import; + +const BuildContext = struct { + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, +}; + +const ProjectModules = struct { + utils: *Module, + model: *Module, + language_type: *Module, + ast: *Module, + stdlib_assets: *Module, + project: *Module, + core: *Module, +}; + pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const ctx = BuildContext{ .b = b, .target = target, .optimize = optimize }; + const release_version = readReleaseVersion(b) catch @panic("release/VERSION must contain the release version."); const default_version = b.fmt("{s}-dev", .{release_version}); const version = b.option([]const u8, "version", "Version string reported by `ss --version`") orelse default_version; @@ -14,86 +36,10 @@ pub fn build(b: *std.Build) void { const md4c_src = "third_party/md4c/src"; b.build_root.handle.access(b.graph.io, md4c_src ++ "/md4c.c", .{}) catch @panic("MD4C sources are missing; run `scripts/setup-md4c.sh` before `zig build`."); - const md4c_include = b.path(md4c_src); - const pdf_pkg_config_path = b.path("src/render/pdf").getPath(b); - const pkg_config_path = if (b.graph.environ_map.get("PKG_CONFIG_PATH")) |path| - b.fmt("{s}{c}{s}", .{ pdf_pkg_config_path, std.fs.path.delimiter, path }) - else - pdf_pkg_config_path; - b.graph.environ_map.put("PKG_CONFIG_PATH", pkg_config_path) catch @panic("OOM"); - - const utils_mod = b.createModule(.{ - .root_source_file = b.path("src/utils/root.zig"), - .target = target, - .optimize = optimize, - }); - - const model_mod = b.createModule(.{ - .root_source_file = b.path("src/core/model.zig"), - .target = target, - .optimize = optimize, - }); - - const language_type_mod = b.createModule(.{ - .root_source_file = b.path("src/language/type.zig"), - .target = target, - .optimize = optimize, - }); - language_type_mod.addImport("model", model_mod); - - const ast_mod = b.createModule(.{ - .root_source_file = b.path("src/ast.zig"), - .target = target, - .optimize = optimize, - }); - ast_mod.addImport("model", model_mod); - ast_mod.addImport("language_type", language_type_mod); - - const stdlib_assets_mod = b.createModule(.{ - .root_source_file = b.path("stdlib/embed.zig"), - .target = target, - .optimize = optimize, - }); - - const project_mod = b.createModule(.{ - .root_source_file = b.path("src/project.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - project_mod.addImport("utils", utils_mod); - - const core_mod = b.createModule(.{ - .root_source_file = b.path("src/core.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - core_mod.addImport("utils", utils_mod); - core_mod.addImport("ast", ast_mod); - core_mod.addImport("model", model_mod); - core_mod.addImport("language_type", language_type_mod); - core_mod.addIncludePath(md4c_include); - core_mod.addCSourceFiles(.{ - .root = b.path(md4c_src), - .files = &.{"md4c.c"}, - }); - - const exe_mod = b.createModule(.{ - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - exe_mod.addImport("core", core_mod); - exe_mod.addImport("utils", utils_mod); - exe_mod.addImport("ast", ast_mod); - exe_mod.addImport("model", model_mod); - exe_mod.addImport("language_type", language_type_mod); - exe_mod.addImport("stdlib_assets", stdlib_assets_mod); - exe_mod.addOptions("build_options", build_options); - addNativePdfBackend(b, exe_mod); + addPdfPkgConfigPath(b); + const modules = createProjectModules(ctx, md4c_src, b.path(md4c_src)); + const exe_mod = createCliModule(ctx, modules, build_options); const exe = b.addExecutable(.{ .name = "ss", .root_module = exe_mod, @@ -106,165 +52,190 @@ pub fn build(b: *std.Build) void { const run_step = b.step("run", "Run the ss CLI"); run_step.dependOn(&run_cmd.step); - const core_tests = b.addTest(.{ - .root_module = core_mod, - }); + addTestStep(ctx, modules, build_options, exe); +} - const parser_tests_mod = b.createModule(.{ - .root_source_file = b.path("src/syntax.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - parser_tests_mod.addImport("core", core_mod); - parser_tests_mod.addImport("utils", utils_mod); - parser_tests_mod.addImport("ast", ast_mod); - parser_tests_mod.addImport("model", model_mod); - parser_tests_mod.addImport("language_type", language_type_mod); - parser_tests_mod.addImport("stdlib_assets", stdlib_assets_mod); - const parser_tests = b.addTest(.{ - .root_module = parser_tests_mod, +fn createProjectModules(ctx: BuildContext, md4c_src: []const u8, md4c_include: std.Build.LazyPath) ProjectModules { + const utils_mod = createModule(ctx, "src/utils/root.zig", &.{}, null); + const model_mod = createModule(ctx, "src/core/model.zig", &.{}, null); + const language_type_mod = createModule(ctx, "src/language/type.zig", &.{ + import("model", model_mod), + }, null); + const ast_mod = createModule(ctx, "src/ast.zig", &.{ + import("model", model_mod), + import("language_type", language_type_mod), + }, null); + const stdlib_assets_mod = createModule(ctx, "stdlib/embed.zig", &.{}, null); + const project_mod = createModule(ctx, "src/project.zig", &.{ + import("utils", utils_mod), + }, true); + const core_mod = createModule(ctx, "src/core.zig", &.{ + import("utils", utils_mod), + import("ast", ast_mod), + import("model", model_mod), + import("language_type", language_type_mod), + }, true); + core_mod.addIncludePath(md4c_include); + core_mod.addCSourceFiles(.{ + .root = ctx.b.path(md4c_src), + .files = &.{"md4c.c"}, }); - const main_tests_mod = b.createModule(.{ - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - main_tests_mod.addImport("core", core_mod); - main_tests_mod.addImport("utils", utils_mod); - main_tests_mod.addImport("ast", ast_mod); - main_tests_mod.addImport("model", model_mod); - main_tests_mod.addImport("language_type", language_type_mod); - main_tests_mod.addImport("stdlib_assets", stdlib_assets_mod); - main_tests_mod.addOptions("build_options", build_options); - addNativePdfBackend(b, main_tests_mod); - const main_tests = b.addTest(.{ - .root_module = main_tests_mod, - }); + return .{ + .utils = utils_mod, + .model = model_mod, + .language_type = language_type_mod, + .ast = ast_mod, + .stdlib_assets = stdlib_assets_mod, + .project = project_mod, + .core = core_mod, + }; +} - const syntax_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/syntax_spec_tests.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - syntax_spec_tests_mod.addImport("core", core_mod); - syntax_spec_tests_mod.addImport("utils", utils_mod); - syntax_spec_tests_mod.addImport("ast", ast_mod); - syntax_spec_tests_mod.addImport("model", model_mod); - syntax_spec_tests_mod.addImport("language_type", language_type_mod); - syntax_spec_tests_mod.addImport("syntax", parser_tests_mod); - const syntax_spec_tests = b.addTest(.{ - .root_module = syntax_spec_tests_mod, - }); +fn createCliModule(ctx: BuildContext, modules: ProjectModules, build_options: *Step.Options) *Module { + const module = createCommonModule(ctx, "src/main.zig", modules, true); + module.addOptions("build_options", build_options); + addNativePdfBackend(ctx.b, module); + return module; +} - const language_type_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/language_type_spec_tests.zig"), - .target = target, - .optimize = optimize, - }); - language_type_spec_tests_mod.addImport("model", model_mod); - language_type_spec_tests_mod.addImport("language_type", language_type_mod); - const language_type_spec_tests = b.addTest(.{ - .root_module = language_type_spec_tests_mod, - }); +fn addTestStep( + ctx: BuildContext, + modules: ProjectModules, + build_options: *Step.Options, + exe: *Step.Compile, +) void { + const b = ctx.b; + const test_step = b.step("test", "Run ss test targets"); - const language_registry_mod = b.createModule(.{ - .root_source_file = b.path("src/language/registry.zig"), - .target = target, - .optimize = optimize, - }); - language_registry_mod.addImport("core", core_mod); - language_registry_mod.addImport("language_type", language_type_mod); + addTestModule(b, test_step, modules.core); - const language_registry_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/language_registry_spec_tests.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - language_registry_spec_tests_mod.addImport("core", core_mod); - language_registry_spec_tests_mod.addImport("model", model_mod); - language_registry_spec_tests_mod.addImport("language_type", language_type_mod); - language_registry_spec_tests_mod.addImport("registry", language_registry_mod); - const language_registry_spec_tests = b.addTest(.{ - .root_module = language_registry_spec_tests_mod, - }); + const syntax_mod = createCommonTestModule(ctx, test_step, "src/syntax.zig", modules, true); + const main_tests_mod = createCliModule(ctx, modules, build_options); + addTestModule(b, test_step, main_tests_mod); + addModuleTest(ctx, test_step, "tests/syntax_spec_tests.zig", &.{ + import("core", modules.core), + import("utils", modules.utils), + import("ast", modules.ast), + import("model", modules.model), + import("language_type", modules.language_type), + import("syntax", syntax_mod), + }, true); + addModuleTest(ctx, test_step, "tests/language_type_spec_tests.zig", &.{ + import("model", modules.model), + import("language_type", modules.language_type), + }, null); - const core_ir_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/core_ir_spec_tests.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - core_ir_spec_tests_mod.addImport("core", core_mod); - core_ir_spec_tests_mod.addImport("utils", utils_mod); - core_ir_spec_tests_mod.addImport("ast", ast_mod); - core_ir_spec_tests_mod.addImport("model", model_mod); - core_ir_spec_tests_mod.addImport("language_type", language_type_mod); - const core_ir_spec_tests = b.addTest(.{ - .root_module = core_ir_spec_tests_mod, - }); + const registry_mod = createModule(ctx, "src/language/registry.zig", &.{ + import("core", modules.core), + import("language_type", modules.language_type), + }, null); + addModuleTest(ctx, test_step, "tests/language_registry_spec_tests.zig", &.{ + import("core", modules.core), + import("model", modules.model), + import("language_type", modules.language_type), + import("registry", registry_mod), + }, true); + addModuleTest(ctx, test_step, "tests/core_ir_spec_tests.zig", &.{ + import("core", modules.core), + import("utils", modules.utils), + import("ast", modules.ast), + import("model", modules.model), + import("language_type", modules.language_type), + }, true); + addModuleTest(ctx, test_step, "tests/layout_graph_spec_tests.zig", &.{ + import("core", modules.core), + import("utils", modules.utils), + import("ast", modules.ast), + import("model", modules.model), + import("language_type", modules.language_type), + }, true); + addModuleTest(ctx, test_step, "tests/project_spec_tests.zig", &.{ + import("project", modules.project), + }, null); - const layout_graph_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/layout_graph_spec_tests.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - layout_graph_spec_tests_mod.addImport("core", core_mod); - layout_graph_spec_tests_mod.addImport("utils", utils_mod); - layout_graph_spec_tests_mod.addImport("ast", ast_mod); - layout_graph_spec_tests_mod.addImport("model", model_mod); - layout_graph_spec_tests_mod.addImport("language_type", language_type_mod); - const layout_graph_spec_tests = b.addTest(.{ - .root_module = layout_graph_spec_tests_mod, - }); + const compiler_mod = createCommonModule(ctx, "src/compiler.zig", modules, true); + const compiler_semantics_support_mod = createModule(ctx, "tests/compiler_semantics_spec_support.zig", &.{ + import("utils", modules.utils), + import("compiler", compiler_mod), + }, true); + addModuleTest(ctx, test_step, "tests/compiler_semantics_spec_tests.zig", &.{ + import("compiler_semantics", compiler_semantics_support_mod), + }, true); - const project_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/project_spec_tests.zig"), - .target = target, - .optimize = optimize, - }); - project_spec_tests_mod.addImport("project", project_mod); - const project_spec_tests = b.addTest(.{ - .root_module = project_spec_tests_mod, - }); + addSmokeChecks(b, test_step, exe); +} - const compiler_semantics_support_mod = b.createModule(.{ - .root_source_file = b.path("tests/compiler_semantics_spec_support.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - const compiler_mod = b.createModule(.{ - .root_source_file = b.path("src/compiler.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, +fn createModule( + ctx: BuildContext, + root_source_file: []const u8, + imports: []const Import, + link_libc: ?bool, +) *Module { + return ctx.b.createModule(.{ + .root_source_file = ctx.b.path(root_source_file), + .target = ctx.target, + .optimize = ctx.optimize, + .imports = imports, + .link_libc = link_libc, }); - compiler_mod.addImport("core", core_mod); - compiler_mod.addImport("utils", utils_mod); - compiler_mod.addImport("ast", ast_mod); - compiler_mod.addImport("model", model_mod); - compiler_mod.addImport("language_type", language_type_mod); - compiler_mod.addImport("stdlib_assets", stdlib_assets_mod); - compiler_semantics_support_mod.addImport("utils", utils_mod); - compiler_semantics_support_mod.addImport("compiler", compiler_mod); +} - const compiler_semantics_spec_tests_mod = b.createModule(.{ - .root_source_file = b.path("tests/compiler_semantics_spec_tests.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - compiler_semantics_spec_tests_mod.addImport("compiler_semantics", compiler_semantics_support_mod); - const compiler_semantics_spec_tests = b.addTest(.{ - .root_module = compiler_semantics_spec_tests_mod, - }); +fn createCommonModule(ctx: BuildContext, root_source_file: []const u8, modules: ProjectModules, link_libc: ?bool) *Module { + return createModule(ctx, root_source_file, &.{ + import("core", modules.core), + import("utils", modules.utils), + import("ast", modules.ast), + import("model", modules.model), + import("language_type", modules.language_type), + import("stdlib_assets", modules.stdlib_assets), + }, link_libc); +} + +fn import(name: []const u8, module: *Module) Import { + return .{ .name = name, .module = module }; +} + +fn addModuleTest( + ctx: BuildContext, + test_step: *Step, + root_source_file: []const u8, + imports: []const Import, + link_libc: ?bool, +) void { + _ = createTestModule(ctx, test_step, root_source_file, imports, link_libc); +} + +fn createCommonTestModule( + ctx: BuildContext, + test_step: *Step, + root_source_file: []const u8, + modules: ProjectModules, + link_libc: ?bool, +) *Module { + const test_mod = createCommonModule(ctx, root_source_file, modules, link_libc); + addTestModule(ctx.b, test_step, test_mod); + return test_mod; +} + +fn createTestModule( + ctx: BuildContext, + test_step: *Step, + root_source_file: []const u8, + imports: []const Import, + link_libc: ?bool, +) *Module { + const test_mod = createModule(ctx, root_source_file, imports, link_libc); + addTestModule(ctx.b, test_step, test_mod); + return test_mod; +} + +fn addTestModule(b: *std.Build, test_step: *Step, module: *Module) void { + const test_artifact = b.addTest(.{ .root_module = module }); + test_step.dependOn(&b.addRunArtifact(test_artifact).step); +} +fn addSmokeChecks(b: *std.Build, test_step: *Step, exe: *Step.Compile) void { const smoke_check_files = [_][]const u8{ "stdlib/core/classes.ss", "stdlib/core/components.ss", @@ -279,17 +250,6 @@ pub fn build(b: *std.Build) void { "stdlib/themes/pop.ss", }; - const test_step = b.step("test", "Run ss test targets"); - test_step.dependOn(&b.addRunArtifact(core_tests).step); - test_step.dependOn(&b.addRunArtifact(parser_tests).step); - test_step.dependOn(&b.addRunArtifact(main_tests).step); - test_step.dependOn(&b.addRunArtifact(syntax_spec_tests).step); - test_step.dependOn(&b.addRunArtifact(language_type_spec_tests).step); - test_step.dependOn(&b.addRunArtifact(language_registry_spec_tests).step); - test_step.dependOn(&b.addRunArtifact(core_ir_spec_tests).step); - test_step.dependOn(&b.addRunArtifact(layout_graph_spec_tests).step); - test_step.dependOn(&b.addRunArtifact(project_spec_tests).step); - test_step.dependOn(&b.addRunArtifact(compiler_semantics_spec_tests).step); for (smoke_check_files) |path| { const smoke_check = b.addRunArtifact(exe); smoke_check.addArgs(&.{ "check", path }); @@ -297,7 +257,16 @@ pub fn build(b: *std.Build) void { } } -fn addNativePdfBackend(b: *std.Build, module: *std.Build.Module) void { +fn addPdfPkgConfigPath(b: *std.Build) void { + const pdf_pkg_config_path = b.path("src/render/pdf").getPath(b); + const pkg_config_path = if (b.graph.environ_map.get("PKG_CONFIG_PATH")) |path| + b.fmt("{s}{c}{s}", .{ pdf_pkg_config_path, std.fs.path.delimiter, path }) + else + pdf_pkg_config_path; + b.graph.environ_map.put("PKG_CONFIG_PATH", pkg_config_path) catch @panic("OOM"); +} + +fn addNativePdfBackend(b: *std.Build, module: *Module) void { module.addIncludePath(b.path("src/render/pdf")); module.addCSourceFile(.{ .file = b.path("src/render/pdf/pdf.c"),