feat(pkgconfig): create pkg-config metadata - #181
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
FennoAI Review — x/pcfile
Solid, well-tested addition. New layers validation cleanly (required fields, single-line constraints, relative-path enforcement), WriteTo correctly mirrors the stdlib io.WriterTo idiom, and the tests are thorough — encoding shapes, validation errors, shell-quoting, short-write/error propagation, and a real pkg-config integration test.
One correctness/hardening item is worth deciding on before merge (the ${...} escaping gap in fragment values), plus a couple of minor notes below and inline.
Windows/backslash paths (minor): the traversal guard at x/pcfile/pcfile.go:69-70 uses the slash-only path package (path.IsAbs/path.Clean), so backslash forms (..\..\outside, C:\..., \\server\share) are not rejected. Given .pc consumers here are POSIX this is low risk, but the check is incomplete relative to its stated intent ("must stay relative to the package root"). Consider also rejecting values containing \ or a drive-letter pattern.
Docs (minor): New's "relocatable" claim (x/pcfile/pcfile.go:32) holds only when the .pc file is installed exactly two levels below the package root, since prefix=${pcfiledir}/../.. is hard-coded. Worth documenting that placement assumption. WriteTo's doc could also note the io.ErrShortWrite synthesis and the panic-on-invalid-count behavior.
Nothing here is blocking.
| cflags = append(cflags, "-I${prefix}/"+shellquote.Join(dir)) | ||
| } | ||
| for _, define := range spec.Defines { | ||
| cflags = append(cflags, "-D"+shellquote.Join(define)) |
There was a problem hiding this comment.
${...} escaping is not applied to Libs/Cflags fragments.
escapeLiteral (${ → $${) protects the header fields (Name/Description/Version/URL), but the libs/cflags fragments built here (lines 100–114) are emitted verbatim through shellquote.Join without it. pkg-config performs ${var} substitution over the whole Libs:/Cflags: value, so a fragment value containing a literal ${...} can inject an unintended variable reference.
shellquote.Join only neutralizes this for values with no whitespace: $ { } are in its specialChars, so foo${bar} becomes foo\$\{bar\} (safe). But a value containing a space, tab, or leading ~ switches shellquote to single-quote mode and emits the ${...} verbatim — e.g. Defines: ["FOO ${pc_sysrootdir}"] produces -D'FOO ${pc_sysrootdir}', and pkg-config expands ${pc_sysrootdir} before shell-tokenization (single quotes don't suppress it). TestNewQuotesFragmentValues already exercises this single-quote path.
If any of Defines/Libraries/Frameworks/*Dirs can originate from package-supplied metadata, this is an attacker-influenced boundary. Suggest applying escapeLiteral to fragment values as well (consistently with the shellquote round-trip), or rejecting fragment values that contain ${.
This PR extends the auto-imported
x/pkgconfigpackage so LLAR Formulas can create.pcmetadata as well as query it.The implementation includes:
Spec,File, andFile.WriteTowith relocatable defaults forprefix,exec_prefix,libdir, andincludedir.requires = [...]input asRequireswhile keeping each package'sLibsandCflagsseparate from dependency flags.pc.libs.private/sharedandpc.cflags.private/shared, and implementString()so XGo interpolation such as${pc.libs}returns the public fragment text automatically.Name,Description, andVersion, preserve other supplied values verbatim, and keep dependency and fragment ordering stable.x/pcfileAPI, regenerate the ixgo export withv1.1.6, and cover encoding, writer behavior, recursive lookup, property chains, and automatic string conversion.This keeps pkg-config creation and querying under one Formula-facing API and removes repeated handwritten
.pcstructure. Closes #180.