Building a C library with opam

Hello :slightly_smiling_face:

I want to build a c library (specifically libspng) with opam and statically link it into one of my ocaml projects.

I have a few questions about how to do this in the best way.
My opam file currently looks like this:

opam-version: "2.0"
synopsis: "Simple, modern libpng alternative"
description: """
  libspng (simple png) is a C library for reading and writing Portable Network Graphics (PNG) format files
  with a focus on security and ease of use.
  The goal is to provide a fast PNG library with a simpler API than libpng.
maintainer: ["Torben Ewert <>"]
author: [""]
license: "BSD-2-Clause"
homepage: ""
bug-reports: ""
dev-repo: "git+"

depends: [
  "conf-zlib" {build}
  "conf-cmake" {build}

build-env: [
  [CFLAGS = "-O3 -fPIC"]
build: [
    "-DCMAKE_MAKE_PROGRAM=make" {os-family = "windows"}
    "-GUnix Makefiles" {os-family = "windows"}
    "-DCMAKE_HOST_WIN32=true" {os-family = "windows"}
  [make "-j%{jobs}%"]
install: [make "install"]

url {
	src: ""
	checksum: ["md5=7d9159a1e08d7dd258ac146537236b67"]


  1. Do I need the source files from libspng or does opam unpack the archive provided in the url field?
    Without the sources present it always fails with The source directory "..." does not appear to contain CMakeLists.txt.. So I guess I need the source files. But what is the url field for then?

  2. Is %{prefix}% the correct install prefix?
    When installing the package into my ocaml project, the files are moved directly into the local switch folder (_opam/lib/libspng_static.a, …). That is unlike all other packages, which have a subfolder inside lib. So I would think that _opam/lib/libspng/libspng_static.a would be better?

  3. Should I even do a make install or would it be better to provide a libspng.install file which moves the built files?

  4. When building on windows (cygwin) the prefix variable gets evaluated to D:\a\foo\bar\_opam which is interpreted as a relative path. So the files get installed into the wrong location.
    I “fixed” that by moving the build steps into a file and wrapping the prefix with cygpath if in a cygwin environment.
    Is this behaviour a bug in opam? I would expect, that the prefix (and all other opam vars) are already pointing to the correct cygwin directories when building on windows.

  5. Should I update the environment variables (ex. PKG_CONFIG_PATH) with the setenv field?

Thank you in advance for your help! I am still pretty new to opam and am maybe a bit confused about some things :smile:

- Torben

  1. Opam unpacks the archive. No idea why the file CMakeLists.txt is not there.

  2. %{prefix}% should be fine. When you talk about other packages, I assume you mean OCaml libraries. The fact that subdirectories are used is an OCaml/Findlib convention; it does not apply to C libraries.

  3. Only bother with an .install file if make install does not work properly.

  4. No idea.

  5. You do not need to update PKG_CONFIG_PATH. The package conf-pkg-config already makes this environment variable point to %{lib}%/pkgconfig. So, assuming that make install properly populated this directory, that should be sufficient. (That is also assuming that any Opam package built on top of your packaged library depends on conf-pkg-config {build}.)

1 Like

Thank you for your answer!

1: I will investigate the missing sources issue a bit further then. Should the unpacked archive be visible inside some switch folder?

2: Yes I am talking about ocaml libraries. I was just wondering if that is how it is supposed to look :smile:

5: Should I depend on conf-pkg-config then?

Yes, the unpacked archive is somewhere under .opam/yourswitch/.opam-switch/build. You might need to pass the option --keep-build-dir to opam install.

As for conf-pkg-config, the Opam package for your C library should depend on it only if the C library uses the pkgconfig command during its build (e.g., to locate Zlib).

1 Like