Hi! We've been discussing adding pkg-config support here at the Gosling 2024 chicken meetup. Here is a proposal.
Using pkg-config can simplify adding foreign dependencies to eggs. Ideally, a single pkg-config identifier is sufficient to supply the chicken compiler with all the flags necessary to compile an egg which uses a foreign-dependency. The aim is to eliminate the need for custom-build scripts like [this]( https://bugs.call-cc.org/browser/project/release/5/svn-client/trunk/build-svn-client ). However, here are some of the downsides: (1) `pkg-config` may not be present on the build machine. We probably do not wish to have this as a hard dependency. However, it may be reasonable to depend on it to automatically build certain eggs with foreign dependencies. We try to adressed this below. (2) One concern is that the `pkg-config` identifiers may differ on different systems. If this turns out to be a problem in practice, I don't know if there is a clean solution for this. As far as I know, thre are two `pkg-config` implementations: pkg-config and pkgconf, the latter being a rewrite. The good news is that both provide a `pkg-config` executable which appear to be compatible. Taking the zstd egg as an example, here's a proposal of the new structure: ``` ((synopsis "ZStandard bindings") (author "Kristian Lein-Mathisen") (category data) (license "BSD") (dependencies) (test-dependencies test) (components (extension zstd-loq-level (source "zstd-module.scm") (source-dependencies "zstd.scm") ;;(csc-options "-L" "-lzstd") ;; <-- must be removed (would introduce duplicates) (foreign-dependencies (pkg-config libzstd))) (extension zstd-nicer-api (source "zstd-nicer-api.scm")) (program "zcompress"))) ``` So in practice, (csc-options "-L" "-lzstd") turns into (foreign-dependencies (pkg-config libzstd)) Some remarks: - `foreign-dependencies` can now provide native library resolution using `pkg-config` - `foreign-dependencies` can appear inside components and instead of top-level - `foreign-dependencies` is still allowed top-level for compatibility but is still ignored (and should be deprecated?) - `foreign-dependencies` can contain a `(pkg-config pkg …)` specification - `foreign-dependencies` can be extended in the future to support other specifications, e.g. `(nixos nixpackage …)` - `pkg` is passed to `pkg-config --libs --cflags $pkg` unless overridden - the output of `pkg-config --libs $pgk` can be overridden with environment variables (even if `pkg-config` is present) - if `pkg-config` isn't present, we can provide an informative error say which environment-variable to set - note: we assume `pkg` identifiers are representable as environment variables (should be ok, they are already filenames) Here's an imaginary implementation: ```scheme (define (resolve-pkg-config pkg) (let* ((var (conc "CHICKEN_INSTALL_PKG_CONFIG_" pkg)) (libs (get-environment-variable var))) (if libs libs (if (which "pkg-config") (shell "pkg-config" "--libs" "--cflags" pkg) (error (conc "pkg-config not found. install it, or set the environment variable " var " to reflect the required CSC_OPTIONS.\n" "for example: export \"" var "=-L -l" (remove-suffix pkg "lib") "\"")))))) ``` So, for example: ``` # defaults work as expected $ pkg-config --libs libzstd -lzstd $ chicken-install zstd csc ... -lzstd ... $ ldd zstd.so libzstd.so.1 => ... ... $ apt remove pkg-config $ chicken-install zstd error: pkg-config not found. install it, or set the environment variable CHICKEN_INSTALL_PKG_CONFIG_zstd. for example export "CHICKEN_INSTALL_PKG_CONFIG_zstd=-L -lzstd" # using pkg-config foreign-dependencies without pkg-config $ env CHICKEN_INSTALL_PKG_CONFIG_libzstd="-L -lzstd" chicken-install zstd ... $ ldd zstd.so libzstd.so.1 => ... # even with pkg-config installed, it can be useful to override foreign dependencies: $ env "CHICKEN_INSTALL_PKG_CONFIG_zstd=-L -l/tmp/libzstd1.1.so" chicken-install zstd ... $ ldd zstd.so libzstd1.1.so => /tmp/libzstd1.1.so ``` Cheers, K.
