Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions tomolt/libschrift/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.8)
project(schrift LANGUAGES C)

include(GNUInstallDirs)

add_library(schrift ${LIBSCHRIFT_SRC_DIR}/schrift.c)
set_target_properties(schrift PROPERTIES
PUBLIC_HEADER ${LIBSCHRIFT_SRC_DIR}/schrift.h
WINDOWS_EXPORT_ALL_SYMBOLS ON
C_EXTENSIONS OFF
C_STANDARD 99
)

find_library(LIBM m)
target_link_libraries(schrift PRIVATE $<$<BOOL:${LIBM}>:${LIBM}>)

install(
TARGETS schrift
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
109 changes: 109 additions & 0 deletions tomolt/libschrift/v0.10.1/libschrift_llar.gox
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import (
"os"
"path/filepath"
"runtime"
"slices"
)

const consumerSource = `#include <stdio.h>
#include <stdlib.h>

#include "schrift.h"

int main(void) {
printf("Schrift version: %s\n", sft_version());

return EXIT_SUCCESS;
}
`

id "tomolt/libschrift"

fromVer "v0.10.1"

defaults {
"shared": "OFF",
"fPIC": "ON",
}

filter => {
for name, values in target.options {
if name != "shared" && name != "fPIC" {
return false
}
for value in values {
if value != "ON" && value != "OFF" {
return false
}
}
}
return true
}

onBuild ctx => {
installDir := ctx.outputDir

cmakeLists := ctx.Proj.readFile("CMakeLists.txt")!
os.writeFile(filepath.join(ctx.SourceDir, "CMakeLists.txt"), cmakeLists, 0644)!

shared := slices.contains(target.options["shared"], "ON")
fPIC := slices.contains(target.options["fPIC"], "ON")
c := cmake.new(ctx.SourceDir, filepath.join(ctx.SourceDir, "_build"), installDir)
c.define "LIBSCHRIFT_SRC_DIR", ctx.SourceDir
c.define "CMAKE_INSTALL_LIBDIR", "lib"
c.defineBool "BUILD_SHARED_LIBS", shared
c.defineBool "CMAKE_POSITION_INDEPENDENT_CODE", fPIC
c.configure
c.build
c.install

licenseDir := filepath.join(installDir, "licenses")
os.mkdirAll(licenseDir, 0755)!
os.writeFile(filepath.join(licenseDir, "LICENSE"), os.readFile(filepath.join(ctx.SourceDir, "LICENSE"))!, 0644)!

osName := runtime.GOOS
osValues := target.require["os"]
if osValues.len > 0 {
osName = osValues[0]
}
metadata := "-I" + filepath.join(installDir, "include") + " -L" + filepath.join(installDir, "lib") + " -lschrift"
if osName == "linux" || osName == "freebsd" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -lm decision here is gated on osName == "linux" || "freebsd", while CMakeLists.txt:14-15 links libm whenever find_library(LIBM m) succeeds (any platform). These are two independent encodings of "does this platform need libm." For the default static build the consumer-side -lm is the load-bearing one (static archives don't record their deps), so on another Unix where libm exists but isn't in this list, the static library would build but consumers would fail to link. Deriving metadata from pkg-config (see the note at setMetadata) would keep these in sync automatically; otherwise consider aligning the two conditions and adding a comment on the intended platform contract.

metadata += " -lm"
}
ctx.setMetadata metadata

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metadata is hand-built rather than derived from an installed pkg-config file. formula-semantics.md states that for C/C++ library metadata you should install a valid .pc under lib/pkgconfig and set metadata from the full pkg-config lookup, treating hand-built -I/-L/-l fragments as a fallback (see how cglm documents its fallback at lines 74-89). Since this recipe injects its own CMakeLists.txt, it can configure_file-generate a schrift.pc and use the pkg-config helper for metadata — that keeps the consumer flags synchronized with the actual install and removes the duplicated OS/-lm logic. If a hand-built string is kept intentionally (upstream ships no pkg-config), add a one-line comment saying so, as the sibling recipe does.

}

onTest ctx => {
installDir := ctx.outputDir
testDir := filepath.join(ctx.SourceDir, "_llar_consumer")
os.mkdirAll(testDir, 0755)!

consumer := filepath.join(testDir, "consumer.c")
os.writeFile(consumer, []byte(consumerSource), 0644)!

osName := runtime.GOOS
osValues := target.require["os"]
if osValues.len > 0 {
osName = osValues[0]
}
args := []string{
"-I" + filepath.join(installDir, "include"),
consumer,
"-L" + filepath.join(installDir, "lib"),
"-lschrift",
}
if osName == "linux" || osName == "freebsd" {
args = append(args, "-lm")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onTest reconstructs -I/-L/-lschrift/-lm independently (mirroring the onBuild logic at lines 64-72) rather than consuming the published metadata / installed .pc. Per formula-semantics.md, a test that rebuilds the flags does not validate the published metadata — the test can pass while the advertised metadata is wrong, so a real consumer would still break with green CI. Prefer compiling the consumer with the same flags the Formula publishes (ideally via the pkg-config lookup).

binary := filepath.join(testDir, "consumer")
args = append(args, "-o", binary)
exec "cc", args...
lastErr!

if slices.contains(target.options["shared"], "ON") {
os.setenv("LD_LIBRARY_PATH", filepath.join(installDir, "lib"))!
os.setenv("DYLD_LIBRARY_PATH", filepath.join(installDir, "lib"))!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LD_LIBRARY_PATH/DYLD_LIBRARY_PATH are overwritten with only the install dir, dropping any pre-existing value. In this isolated test the risk is low, but if the environment already sets these (e.g. a toolchain lib dir) they'd be clobbered. Prefer prepending: installDir/lib + : + the existing value when one is present.

}
exec binary
lastErr!
}
4 changes: 4 additions & 0 deletions tomolt/libschrift/versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"path": "tomolt/libschrift",
"deps": {}
}
Loading