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
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.15)
project(tgc LANGUAGES C)

add_library(tgc ${TGC_SRC_DIR}/tgc.c)
set_property(TARGET tgc PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS TRUE)

include(GNUInstallDirs)
install(TARGETS tgc
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}

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.

GNUInstallDirs makes ${CMAKE_INSTALL_LIBDIR} resolve to lib64 on many 64-bit distros, but the formula hardcodes -L.../lib (see tgc_llar.gox:75, :94, :102-103). On those platforms the archive lands in lib64 and the consumer link/load fails. Pin the layout the way json-c does — c.define "CMAKE_INSTALL_LIBDIR", "lib" in onBuild — or install directly to lib/include here.

ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

install(FILES ${TGC_SRC_DIR}/tgc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
120 changes: 120 additions & 0 deletions orangeduck/tgc/05354008dc0de09e0a076647b8a678aaebfa58e6/tgc_llar.gox
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import (
"os"
"path/filepath"
"slices"
)

const consumerSource = `#include <tgc.h>
#include <string.h>

static tgc_t gc;

static void example_function() {
char *message = tgc_alloc(&gc, 64);
strcpy(message, "No More Memory Leaks!");

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.

Minor: this example uses strcpy but includes only <tgc.h>. It compiles today because tgc.h transitively includes <string.h>, so this is not a bug — but relying on a transitive include is fragile under stricter defaults. Adding #include <string.h> to consumerSource makes the example self-contained.

}

int main(int argc, char **argv) {
tgc_start(&gc, &argc);

example_function();

tgc_stop(&gc);

return 0;
}
`

id "orangeduck/tgc"

fromVer "05354008dc0de09e0a076647b8a678aaebfa58e6"

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("05354008dc0de09e0a076647b8a678aaebfa58e6/CMakeLists.txt")!
os.writeFile(filepath.join(ctx.SourceDir, "CMakeLists.txt"), cmakeLists, 0o644)!

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 "TGC_SRC_DIR", ctx.SourceDir
// Keep the installed library directory stable across platforms; GNUInstallDirs
// otherwise selects lib64 on some 64-bit systems.
c.define "CMAKE_INSTALL_LIBDIR", "lib"
c.defineBool "BUILD_SHARED_LIBS", shared
if !shared {
// The Conan recipe enables PIC for static builds only.
c.defineBool "CMAKE_POSITION_INDEPENDENT_CODE", fPIC
}
c.configure
c.build
c.install

licenseDir := filepath.join(installDir, "licenses")
os.mkdirAll(licenseDir, 0o755)!
os.writeFile(filepath.join(licenseDir, "LICENSE.md"), os.readFile(filepath.join(ctx.SourceDir, "LICENSE.md"))!, 0o644)!

// The upstream commit has no build files or pkg-config metadata, so this
// formula supplies the install recipe and a relocatable consumer interface.
pkgconfigDir := filepath.join(installDir, "lib", "pkgconfig")
os.mkdirAll(pkgconfigDir, 0o755)!
pc := `prefix=$${pcfiledir}/../..
includedir=$${prefix}/include
libdir=$${prefix}/lib

Name: tgc
Description: Tiny garbage collector for C
Version: 0.1.0
Cflags: -I$${includedir}
Libs: -L$${libdir} -ltgc
`
os.writeFile(filepath.join(pkgconfigDir, "tgc.pc"), []byte(pc), 0o644)!

pkgconfig.use installDir
ctx.setMetadata pkgconfig.lookup("tgc")!
}

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

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

binary := filepath.join(testDir, "consumer")

pkgconfig.use installDir
flags := pkgconfig.lookup("tgc")!.fields
args := []string{consumer}
args <- flags...
args <- "-o", binary
cc! args...

shared := slices.contains(target.options["shared"], "ON")
if shared {
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.

These overwrite any existing LD_LIBRARY_PATH/DYLD_LIBRARY_PATH rather than prepending. Benign in an isolated CI runner, but if the toolchain relies on a pre-existing value the shared-build consumer run could break — prefer prepending installDir/lib to the current value. (Also affected by the lib/lib64 issue above.)

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