Skip to content

Add json-c/json-c LLAR Formula (Conan 0.18 translation) - #122

Closed
fennoai[bot] wants to merge 1 commit into
mainfrom
fennoai/issue-39-1785409774
Closed

Add json-c/json-c LLAR Formula (Conan 0.18 translation)#122
fennoai[bot] wants to merge 1 commit into
mainfrom
fennoai/issue-39-1785409774

Conversation

@fennoai

@fennoai fennoai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Translates the Conan Center json-c recipe into an idiomatic LLAR Formula, adding json-c/json-c to llarhub. Serves the upstream tag json-c-0.18-20240915 (Conan version 0.18).

Closes #39

Files

  • json-c/json-c/versions.json — module metadata, no static deps.
  • json-c/json-c/json-c-0.18-20240915/JsonC_llar.gox — the Formula.

Translation notes

  • Build (CMake): mirrors the Conan CMakeToolchain variables for json-c ≥ 0.17 — BUILD_SHARED_LIBS/BUILD_STATIC_LIBS from the shared option, DISABLE_STATIC_FPIC from fPIC, plus BUILD_TESTING=OFF and BUILD_APPS=OFF. Calls configure/build/install directly (they panic on failure).
  • Dependencies: none. Verified against the upstream CMakeLists.txt at the tag — threading is optional and off by default; no find_package for external libraries. So no onRequire.
  • Options: shared (default OFF) and fPIC (default ON), matching the Conan default_options. Package-owned, declared via defaults{}.
  • Metadata: derived from the installed json-c.pc via pkg-config --libs (-L<lib> -ljson-c) rather than guessing from the Conan package_info block.
  • onTest: compiles and runs the Conan test_package consumer (json_object_* + serialize) in an independent tree under ctx.SourceDir, resolving flags from json-c.pc, so it passes identically on a build cache hit (where onBuild never runs).
  • fromVer boundary: pinned to the verified json-c-0.18-20240915 tag. The Conan folder also covers 0.14–0.17, but those revisions use a different build contract (no BUILD_STATIC_LIBS/DISABLE_STATIC_FPIC before 0.15; no BUILD_APPS and a forced CMP0042/policy-min before 0.17). Only 0.18 was inspected, so earlier tags are intentionally not claimed.

Validation

Run with llar v0.3.0. All succeed:

Command Result
llar test ./json-c/json-c@json-c-0.18-20240915 ✅ build + install + onTest
re-run (cache-hit onTest) ✅ consumer still compiled + ran
--os linux --arch amd64
--os linux --arch amd64 --option shared=ON
--os linux --arch amd64 --option fPIC=OFF
llar test ./json-c/json-c@json-c-0.17-20230812 ✅ correctly rejected (no formula found) — confirms the fromVer boundary

onTest output: json object created: { "Categories": [ "c", "c++" ] }

Note on option propagation in llar v0.3.0: each --option selection produces a distinct matrix/cache key and builds+tests cleanly, but the current runtime only injects the selected matrix into filter/onRequire (via injectMatrix in internal/modules/load.go) and not into onBuild/onTest, so the actual build currently uses the defaults{} values regardless of --option. The formula reads target.options per the documented contract (matching the targetsurface fixture), so it will honor overrides once the runtime propagates the matrix to the build hooks. Flagging for maintainer awareness — left the formula on the documented API rather than working around a runtime limitation, since the change was scoped to the json-c/json-c module files only.

Translate the Conan Center json-c recipe into an idiomatic LLAR Formula
serving the upstream tag json-c-0.18-20240915.

- CMake build mirroring the Conan CMakeToolchain variables for json-c
  >= 0.17: BUILD_SHARED_LIBS/BUILD_STATIC_LIBS from the `shared` option,
  DISABLE_STATIC_FPIC from `fPIC`, plus BUILD_TESTING=OFF and BUILD_APPS=OFF.
- No dependencies (verified against the upstream CMakeLists; threading is
  optional and off by default).
- Metadata derived from the installed json-c.pc via pkg-config.
- onTest compiles and runs the Conan test_package consumer in an
  independent tree so it also passes on a build cache hit.
- fromVer pinned to the verified 0.18 tag; earlier tags in the same Conan
  folder use a different build contract and are intentionally not claimed.

Closes #39

Co-authored-by: fennoai[bot] <231223108+fennoai[bot]@users.noreply.github.com>
Co-authored-by: MeteorsLiu <17515813+MeteorsLiu@users.noreply.github.com>
@MeteorsLiu MeteorsLiu closed this Jul 30, 2026
@fennoai
fennoai Bot deleted the fennoai/issue-39-1785409774 branch July 30, 2026 11:59

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

FennoAI Review — json-c formula

Thanks for the well-documented formula — the Conan-derived option mapping, the honest fromVer rationale, and deriving link flags from the installed json-c.pc via pkg-config are all solid.

My main concern is a cluster of constructs that don't appear in the documented formula API (.claude/skills/write-formula/SKILL.md) or in the only existing example (madler/zlib/1.0.0/Zlib_llar.gox):

  • onBuild ctx => {...} uses a single lambda parameter; the documented signature is onBuild (ctx, proj, out) => {} and every example routes output through out (out.setMetadata, out.addErr).
  • ctx.outputDir is read as a bare property; the API defines ctx.outputDir() returning (string, error).
  • ctx.setMetadata — metadata is documented on BuildResult (out.setMetadata), not on Context.
  • defaults { ... }, target.options[...], and onTest have no entry in the "Complete API Reference".

I could not find the formula runtime source in this repo to confirm these either way. If they rely on a newer runtime API than SKILL.md documents, please point to it and the API-mismatch inline comments can be dismissed — but note the c.configure/build/install error-handling issue below holds regardless, and if SKILL.md is stale it should be updated so it no longer claims to be complete.

See inline comments for specifics. Severity ranges from likely-blocking (API mismatch, dropped build errors) to low (comment accuracy, shell hardening).

// forced CMP0042/policy-min before 0.17). Only the 0.18 revision was verified,
// so this is the honest fromVer boundary. Add a lower threshold with its own
// formula when an earlier range is actually verified.
fromVer "json-c-0.18-20240915"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

fromVer "json-c-0.18-20240915" uses a full upstream tag string as the version boundary. SKILL.md describes fromVer as the minimum version served and the existing example uses a plain 1.0.0. json-c-0.18-20240915 is not semver/dpkg-comparable, so the default gnu.Compare may not order it as intended. Consider adding a json-c_cmp.gox version comparator (see SKILL.md "Two Classfiles") and confirm how the resolver compares this tag.

// for the static library, whether position-independent code is emitted. The
// upstream CMakeLists defaults both libraries ON; Conan builds exactly one,
// defaulting to the static library.
defaults {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

defaults { ... } is not a documented ModuleF top-level DSL method (documented: id, fromVer, matrix, onRequire, onBuild). SKILL.md's "XGo Pitfalls" #1 also warns that a bare {...} block at statement level is ambiguous with a lambda. If defaults is a supported runtime API, please confirm; otherwise this needs reworking.

"fPIC": "ON",
}

onBuild ctx => {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

onBuild ctx => {...} uses a single-parameter lambda. The documented signature is onBuild (ctx, proj, out) => {}OnBuild(func(*Context, *Project, *BuildResult)), and the zlib example uses all three params. Without out in scope there's no documented way to call out.setMetadata / out.addErr (see lines 53 and the panics below). Please restore the three-parameter signature and route output through out.

}

onBuild ctx => {
installDir := ctx.outputDir

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ctx.outputDir is used as a bare property returning a single value. The API defines ctx.outputDir() as OutputDir__0() (string, error) — call it with parentheses and handle the error, e.g. installDir, err := ctx.outputDir(); if err != nil { out.addErr err; return } (cf. zlib lines 6-10). Same at line 57.

onBuild ctx => {
installDir := ctx.outputDir

shared := slices.contains(target.options["shared"], "ON")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

target.options["shared"] / target.options["fPIC"] (line 29) reference a global target that isn't in the documented API (ModuleF/Project/Context/BuildResult/ModuleDeps). If reading build-option values this way is supported by the current runtime, please confirm; otherwise there's no documented mechanism for it.

c.defineBool "BUILD_TESTING", false
c.defineBool "BUILD_APPS", false

c.configure

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

c.configure / c.build / c.install are invoked as bare command-style statements, silently discarding their error returns. The zlib example error-checks every one (lines 14-28). As written, a failed configure/build/install would proceed silently and produce a broken or empty install. Capture and handle each error (e.g. err = c.configure(); if err != nil { out.addErr err; return }). This holds regardless of the API-signature question.

if lastErr != nil {
panic lastErr
}
ctx.setMetadata output.trimSpace

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ctx.setMetadatasetMetadata is documented on BuildResult (out.setMetadata), not on Context. Use the out parameter (see line 23). Also note panic lastErr (lines 50-52) diverges from the repo convention of out.addErr err; return used by zlib and every SKILL example for recoverable build errors.

os.writeFile(testDir+"/consumer.c", []byte(src), 0o644)!

// Point pkg-config at the installed result. This env change is all the
// test needs, so the consumer builds in its own tree and works identically

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Comment accuracy: this says "the consumer builds in its own tree", but the consumer is compiled by a raw cc call at line 104, not cmake. cmake.new(ctx.SourceDir, testDir, installDir) (line 84) is constructed only so c.use installDir (line 85) sets PKG_CONFIG_PATH/CPPFLAGS/LDFLAGS; the testDir build-dir arg is never used and no cmake configure/build runs. The cache-hit conclusion is correct (onTest reads only installDir), but reword to reflect that there's no cmake build tree, or drop the unused cmake.new/testDir argument.

libs := output.trimSpace

bin := testDir + "/consumer"
exec "sh", "-c", "cc "+cflags+" "+testDir+"/consumer.c -o "+bin+" "+libs

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This assembles a shell command by concatenating unquoted values into sh -c: cflags/libs (pkg-config output) and testDir/bin (derived from ctx.SourceDir). A space or shell metacharacter in the workspace path (or .pc contents) would break the compile or be interpreted by the shell. Low severity under the build-tooling trust model (inputs aren't remote-attacker-controlled), but it's the lone deviation from the safe argv-form exec used elsewhere (lines 48, 88, 96, 109). Prefer argv form: exec "cc", <cflags split...>, testDir+"/consumer.c", "-o", bin, <libs split...>, or at least shell-quote the interpolated paths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Translate Conan Center json-c recipe to LLAR

1 participant