# Building a C library with opam

**URL:** <https://discuss.ocaml.org/t/building-a-c-library-with-opam/11069>\
**Category:** Learning\
**Tags:** opam\
**Created:** [December 29, 2022, 1:39pm UTC](https://discuss.ocaml.org/t/building-a-c-library-with-opam/11069 "2022-12-29T13:39:53Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![eWert-Online](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ewert-online/32/4130_2.png) [@eWert-Online](https://discuss.ocaml.org/u/eWert-Online)\
**Post date:** [December 29, 2022, 1:39pm UTC](https://discuss.ocaml.org/t/building-a-c-library-with-opam/11069/1 "2022-12-29T13:39:53Z")

</div>

Hello 🙂

I want to build a c library (specifically [libspng](https://github.com/randy408/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:

```auto
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 <torben@ewert-online.com>"]
author: ["randy408@protonmail.com"]
license: "BSD-2-Clause"
homepage: "https://libspng.org/"
bug-reports: "https://github.com/.../issues"
dev-repo: "git+https://github.com/randy408/libspng"

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

build-env: [
  [CFLAGS = "-O3 -fPIC"]
]
build: [
  [
    "%{conf-cmake:cmd}%"
    "-DCMAKE_MAKE_PROGRAM=make" {os-family = "windows"}
    "-GUnix Makefiles" {os-family = "windows"}
    "-DCMAKE_HOST_WIN32=true" {os-family = "windows"}
    "-DCMAKE_BUILD_TYPE=RELEASE"
    "-DCMAKE_INSTALL_PREFIX=%{prefix}%"
  ]
  [make "-j%{jobs}%"]
]
install: [make "install"]

url {
	src: "https://github.com/randy408/libspng/archive/refs/tags/v0.7.3.tar.gz"
	checksum: ["md5=7d9159a1e08d7dd258ac146537236b67"]
}

```

**Questions:**

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 `build.sh` 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 😄

- Torben

---

<div class="post-metadata">

**Author:** ![silene](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/silene/32/2707_2.png) [@silene](https://discuss.ocaml.org/u/silene)\
**Post date:** [December 29, 2022, 7:27pm UTC](https://discuss.ocaml.org/t/building-a-c-library-with-opam/11069/2 "2022-12-29T19:27:02Z")

</div>

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}`.)

---

<div class="post-metadata">

**Author:** ![eWert-Online](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ewert-online/32/4130_2.png) [@eWert-Online](https://discuss.ocaml.org/u/eWert-Online)\
**Post date:** [December 29, 2022, 8:32pm UTC](https://discuss.ocaml.org/t/building-a-c-library-with-opam/11069/3 "2022-12-29T20:32:08Z")

</div>

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 😄

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

---

<div class="post-metadata">

**Author:** ![silene](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/silene/32/2707_2.png) [@silene](https://discuss.ocaml.org/u/silene)\
**Post date:** [December 30, 2022, 7:30am UTC](https://discuss.ocaml.org/t/building-a-c-library-with-opam/11069/4 "2022-12-30T07:30:52Z")

</div>

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).
