Compare commits
2 Commits
13e6bd5689
...
c292c51c44
Author | SHA1 | Date | |
---|---|---|---|
c292c51c44 | |||
25a3169b85 |
31
.github/workflows/zig-build.yaml
vendored
Normal file
31
.github/workflows/zig-build.yaml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
name: Generic zig build
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
- '!zig-develop*'
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: elerch/setup-zig@v3
|
||||||
|
with:
|
||||||
|
version: 0.12.0
|
||||||
|
- uses: Hanaasagi/zig-action-cache@v1.1.5
|
||||||
|
- name: Install fontconfig
|
||||||
|
run: apt update && apt install libfontconfig1 && ln -s /usr/lib/x86_64-linux-gnu/libfontconfig.so.1 /usr/local/lib/libfontconfig.so
|
||||||
|
- name: Build project
|
||||||
|
run: zig build --summary all
|
||||||
|
- name: Run tests
|
||||||
|
run: zig build test --summary all
|
||||||
|
- name: Notify
|
||||||
|
uses: elerch/action-notify-ntfy@v2.github
|
||||||
|
if: env.GITEA_ACTIONS == 'true'
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.NTFY_HOST }}
|
||||||
|
topic: ${{ secrets.NTFY_TOPIC }}
|
||||||
|
status: ${{ job.status }}
|
||||||
|
user: ${{ secrets.NTFY_USER }}
|
||||||
|
password: ${{ secrets.NTFY_PASSWORD }}
|
|
@ -6,7 +6,7 @@ RUN apt-get update \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
xz-utils \
|
xz-utils \
|
||||||
&& curl https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz | tar -C /usr/local/ -xJ \
|
&& curl https://ziglang.org/download/0.12.0/zig-linux-x86_64-0.12.0.tar.xz | tar -C /usr/local/ -xJ \
|
||||||
&& apt-get -y remove curl xz-utils \
|
&& apt-get -y remove curl xz-utils \
|
||||||
&& ln -s /usr/local/zig*/zig /usr/local/bin \
|
&& ln -s /usr/local/zig*/zig /usr/local/bin \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
|
@ -19,8 +19,9 @@ Building
|
||||||
|
|
||||||
This is not fully `zig build` friendly, since it links to system libraries.
|
This is not fully `zig build` friendly, since it links to system libraries.
|
||||||
Specifically, you need to have [fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/)
|
Specifically, you need to have [fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/)
|
||||||
and dependencies installed. I initially went down that rabbit hole, but it's
|
and dependencies installed. The include files are pulled from fontconfig 2.14.1,
|
||||||
kind of a mess that I don't need for what is really a personal project.
|
which is the version in debian bullseye, but he system library still needs to
|
||||||
|
linked.
|
||||||
|
|
||||||
To help with the build, a Dockerfile exists in this repository that can be used
|
To help with the build, a Dockerfile exists in this repository that can be used
|
||||||
to create a docker image with the appropriate zig version and system libraries.
|
to create a docker image with the appropriate zig version and system libraries.
|
||||||
|
|
17
build.zig
17
build.zig
|
@ -24,7 +24,9 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
configure(exe);
|
const fontconfig = b.dependency("fontconfig", .{});
|
||||||
|
|
||||||
|
configure(b, fontconfig, exe);
|
||||||
|
|
||||||
// This declares intent for the executable to be installed into the
|
// This declares intent for the executable to be installed into the
|
||||||
// standard location when the user invokes the "install" step (the default
|
// standard location when the user invokes the "install" step (the default
|
||||||
|
@ -62,7 +64,7 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
configure(unit_tests);
|
configure(b, fontconfig, unit_tests);
|
||||||
|
|
||||||
const run_unit_tests = b.addRunArtifact(unit_tests);
|
const run_unit_tests = b.addRunArtifact(unit_tests);
|
||||||
|
|
||||||
|
@ -73,14 +75,17 @@ pub fn build(b: *std.Build) void {
|
||||||
test_step.dependOn(&run_unit_tests.step);
|
test_step.dependOn(&run_unit_tests.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure(object: anytype) void {
|
fn configure(b: *std.Build, fontconfig: *std.Build.Dependency, object: anytype) void {
|
||||||
// object.linkage = .static;
|
// object.linkage = .static;
|
||||||
object.linkLibC();
|
object.linkLibC();
|
||||||
|
|
||||||
// Fontconfig must be installed. Docker can also be used (see Dockerfile)
|
// Fontconfig must be installed. Docker can also be used (see Dockerfile)
|
||||||
object.addSystemIncludePath("/usr/include");
|
object.addSystemIncludePath(fontconfig.path(""));
|
||||||
object.linkSystemLibrary("fontconfig");
|
object.linkSystemLibrary("fontconfig");
|
||||||
// object.linkSystemLibrary("expat"); // fontconfig dependency - needed for static builds
|
// object.linkSystemLibrary("expat"); // fontconfig dependency - needed for static builds
|
||||||
object.addLibraryPath("/usr/lib");
|
object.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
|
||||||
object.addCSourceFile("src/fontconfig.c", &[_][]const u8{"-std=c99"});
|
object.addCSourceFile(.{
|
||||||
|
.file = b.path("src/fontconfig.c"),
|
||||||
|
.flags = &[_][]const u8{"-std=c99"},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
36
build.zig.zon
Normal file
36
build.zig.zon
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
.{
|
||||||
|
.name = "fontfinder",
|
||||||
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
|
.version = "0.0.0",
|
||||||
|
|
||||||
|
// This field is optional.
|
||||||
|
// This is currently advisory only; Zig does not yet do anything
|
||||||
|
// with this value.
|
||||||
|
//.minimum_zig_version = "0.11.0",
|
||||||
|
|
||||||
|
// This field is optional.
|
||||||
|
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
||||||
|
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
||||||
|
// Once all dependencies are fetched, `zig build` no longer requires
|
||||||
|
// internet connectivity.
|
||||||
|
.dependencies = .{
|
||||||
|
.fontconfig = .{
|
||||||
|
.url = "https://gitlab.freedesktop.org/fontconfig/fontconfig/-/archive/2.14.1/fontconfig-2.14.1.tar.gz",
|
||||||
|
.hash = "1220a54d89babad491b562dad3f2c73414c95ea2f46a4e7206f1e36be4632654458e",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.paths = .{
|
||||||
|
// This makes *all* files, recursively, included in this package. It is generally
|
||||||
|
// better to explicitly list the files and directories instead, to insure that
|
||||||
|
// fetching from tarballs, file system paths, and version control all result
|
||||||
|
// in the same contents hash.
|
||||||
|
"",
|
||||||
|
// For example...
|
||||||
|
//"build.zig",
|
||||||
|
//"build.zig.zon",
|
||||||
|
//"src",
|
||||||
|
//"LICENSE",
|
||||||
|
//"README.md",
|
||||||
|
},
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ pub const FontList = struct {
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub fn initCapacity(allocator: std.mem.Allocator, num: usize, pattern: *c.FcPattern, fontset: *c.FcFontSet) std.mem.Allocator.Error!Self {
|
pub fn initCapacity(allocator: std.mem.Allocator, num: usize, pattern: *c.FcPattern, fontset: *c.FcFontSet) std.mem.Allocator.Error!Self {
|
||||||
var al = try std.ArrayList(Font).initCapacity(allocator, num);
|
const al = try std.ArrayList(Font).initCapacity(allocator, num);
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.list = al,
|
.list = al,
|
||||||
|
@ -192,7 +192,7 @@ pub const FontQuery = struct {
|
||||||
var rc = std.ArrayList(RangeFont).init(self.allocator);
|
var rc = std.ArrayList(RangeFont).init(self.allocator);
|
||||||
defer rc.deinit();
|
defer rc.deinit();
|
||||||
|
|
||||||
var previously_supported = blk: {
|
const previously_supported = blk: {
|
||||||
if (!exclude_previous) break :blk null;
|
if (!exclude_previous) break :blk null;
|
||||||
var al = try std.ArrayList(bool).initCapacity(self.allocator, ending_codepoint - starting_codepoint);
|
var al = try std.ArrayList(bool).initCapacity(self.allocator, ending_codepoint - starting_codepoint);
|
||||||
defer al.deinit();
|
defer al.deinit();
|
||||||
|
@ -267,7 +267,7 @@ test "Get fonts" {
|
||||||
var fl = try fq.fontList(":regular:normal:spacing=100:slant=0");
|
var fl = try fq.fontList(":regular:normal:spacing=100:slant=0");
|
||||||
defer fl.deinit();
|
defer fl.deinit();
|
||||||
try std.testing.expect(fl.list.items.len > 0);
|
try std.testing.expect(fl.list.items.len > 0);
|
||||||
var matched = blk: {
|
const matched = blk: {
|
||||||
for (fl.list.items) |item| {
|
for (fl.list.items) |item| {
|
||||||
log.debug("full_name: '{s}'", .{item.full_name});
|
log.debug("full_name: '{s}'", .{item.full_name});
|
||||||
if (std.mem.eql(u8, "DejaVu Sans Mono", item.full_name))
|
if (std.mem.eql(u8, "DejaVu Sans Mono", item.full_name))
|
||||||
|
|
14
src/main.zig
14
src/main.zig
|
@ -52,7 +52,7 @@ pub fn main() !u8 {
|
||||||
if (options.list_fonts) {
|
if (options.list_fonts) {
|
||||||
var fq = fontconfig.FontQuery.init(allocator);
|
var fq = fontconfig.FontQuery.init(allocator);
|
||||||
defer fq.deinit();
|
defer fq.deinit();
|
||||||
var fl = try fq.fontList(options.pattern);
|
const fl = try fq.fontList(options.pattern);
|
||||||
var longest_family_name = @as(usize, 0);
|
var longest_family_name = @as(usize, 0);
|
||||||
var longest_style_name = @as(usize, 0);
|
var longest_style_name = @as(usize, 0);
|
||||||
for (fl.list.items) |f| {
|
for (fl.list.items) |f| {
|
||||||
|
@ -81,7 +81,7 @@ pub fn main() !u8 {
|
||||||
var si = std.mem.splitScalar(u8, fo, ',');
|
var si = std.mem.splitScalar(u8, fo, ',');
|
||||||
var fq = fontconfig.FontQuery.init(allocator);
|
var fq = fontconfig.FontQuery.init(allocator);
|
||||||
defer fq.deinit();
|
defer fq.deinit();
|
||||||
var fl = try fq.fontList(options.pattern);
|
const fl = try fq.fontList(options.pattern);
|
||||||
// This messes with data after, and we don't need to deinit anyway
|
// This messes with data after, and we don't need to deinit anyway
|
||||||
// defer fl.deinit();
|
// defer fl.deinit();
|
||||||
var al = try std.ArrayList(fontconfig.Font).initCapacity(allocator, std.mem.count(u8, fo, ",") + 2);
|
var al = try std.ArrayList(fontconfig.Font).initCapacity(allocator, std.mem.count(u8, fo, ",") + 2);
|
||||||
|
@ -184,7 +184,7 @@ fn outputRange(
|
||||||
) !void {
|
) !void {
|
||||||
var fq = fontconfig.FontQuery.init(allocator);
|
var fq = fontconfig.FontQuery.init(allocator);
|
||||||
defer fq.deinit();
|
defer fq.deinit();
|
||||||
var range_fonts = try fq.fontsForRange(starting_codepoint, ending_codepoint, fonts, exclude_previous); // do we want hard limits around this?
|
const range_fonts = try fq.fontsForRange(starting_codepoint, ending_codepoint, fonts, exclude_previous); // do we want hard limits around this?
|
||||||
defer allocator.free(range_fonts);
|
defer allocator.free(range_fonts);
|
||||||
|
|
||||||
std.log.debug("Got {d} range fonts back from query", .{range_fonts.len});
|
std.log.debug("Got {d} range fonts back from query", .{range_fonts.len});
|
||||||
|
@ -323,7 +323,7 @@ test "command line parses with long name no equals" {
|
||||||
try std.testing.expectEqualStrings("Latin-1", options.groups.?);
|
try std.testing.expectEqualStrings("Latin-1", options.groups.?);
|
||||||
}
|
}
|
||||||
test "command line parses with long name equals" {
|
test "command line parses with long name equals" {
|
||||||
var log_level = std.testing.log_level;
|
const log_level = std.testing.log_level;
|
||||||
defer std.testing.log_level = log_level;
|
defer std.testing.log_level = log_level;
|
||||||
// std.testing.log_level = .debug;
|
// std.testing.log_level = .debug;
|
||||||
var it = try std.process.ArgIteratorGeneral(.{}).init(std.testing.allocator, "--groups=Latin-1");
|
var it = try std.process.ArgIteratorGeneral(.{}).init(std.testing.allocator, "--groups=Latin-1");
|
||||||
|
@ -339,7 +339,7 @@ test "Get ranges" {
|
||||||
var fl = try fq.fontList(":regular:normal:spacing=100:slant=0");
|
var fl = try fq.fontList(":regular:normal:spacing=100:slant=0");
|
||||||
defer fl.deinit();
|
defer fl.deinit();
|
||||||
try std.testing.expect(fl.list.items.len > 0);
|
try std.testing.expect(fl.list.items.len > 0);
|
||||||
var matched = blk: {
|
const matched = blk: {
|
||||||
for (fl.list.items) |item| {
|
for (fl.list.items) |item| {
|
||||||
std.log.debug("full_name: '{s}'", .{item.full_name});
|
std.log.debug("full_name: '{s}'", .{item.full_name});
|
||||||
if (std.mem.eql(u8, "DejaVu Sans Mono", item.full_name))
|
if (std.mem.eql(u8, "DejaVu Sans Mono", item.full_name))
|
||||||
|
@ -352,7 +352,7 @@ test "Get ranges" {
|
||||||
var al = std.ArrayList(u8).init(std.testing.allocator);
|
var al = std.ArrayList(u8).init(std.testing.allocator);
|
||||||
defer al.deinit();
|
defer al.deinit();
|
||||||
const range_name = "Basic Latin";
|
const range_name = "Basic Latin";
|
||||||
var matched_range = try blk: {
|
const matched_range = try blk: {
|
||||||
var unicode_ranges = unicode.all_ranges();
|
var unicode_ranges = unicode.all_ranges();
|
||||||
while (unicode_ranges.next()) |range| {
|
while (unicode_ranges.next()) |range| {
|
||||||
var it = std.mem.splitScalar(u8, range_name, ',');
|
var it = std.mem.splitScalar(u8, range_name, ',');
|
||||||
|
@ -364,7 +364,7 @@ test "Get ranges" {
|
||||||
}
|
}
|
||||||
break :blk error.RangeNotFound;
|
break :blk error.RangeNotFound;
|
||||||
};
|
};
|
||||||
var log_level = std.testing.log_level;
|
const log_level = std.testing.log_level;
|
||||||
std.testing.log_level = .debug;
|
std.testing.log_level = .debug;
|
||||||
defer std.testing.log_level = log_level;
|
defer std.testing.log_level = log_level;
|
||||||
try outputRange(
|
try outputRange(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user