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.

Reply via email to