mattn / mattn/moonbit-postgres

Build fails on macOS: libpq-fe.h not found due to hardcoded include path

Open
#1 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
MoonBit
Stars
8
Forks
2
Avg merge
1m
Merged PRs (30d)
3

Description

## Summary

Building on macOS fails because `moon.pkg.json` hardcodes `-I/usr/include/postgresql` in `stub-cc-flags`. This path only exists on Debian/Ubuntu (via `libpq-dev`). On macOS, `libpq-fe.h` is located elsewhere depending on the installation method.

## Environment

- macOS (Apple Silicon, macOS 15)
- PostgreSQL installed via Homebrew (`brew install libpq`)
- mattn/postgres v0.10.4
- MoonBit moon 0.1.20260209 (b129ae2 2026-02-09)

## Error

```
$ moon test --target native
failed: /usr/bin/cc -o ... -I/usr/include/postgresql ...
.mooncakes/mattn/postgres/postgres_c.c:2:10: fatal error: 'libpq-fe.h' file not found
2 | #include
| ^~~~~~~~~~~~
1 error generated.
```

## Cause

In `moon.pkg.json`:

```json
"link": {
"native": {
"cc-link-flags": "-lpq",
"stub-cc-flags": "-I/usr/include/postgresql",
"stub-cc-link-flags": "-lpq"
}
}
```

The path `/usr/include/postgresql` is Linux-specific (Debian/Ubuntu with `libpq-dev`). On macOS, the header location varies by installation method:

| Installation | Header path | Lib path |
|---|---|---|
| Homebrew (Apple Silicon) | `/opt/homebrew/opt/libpq/include` | `/opt/homebrew/opt/libpq/lib` |
| Homebrew (Intel) | `/usr/local/opt/libpq/include` | `/usr/local/opt/libpq/lib` |
| Postgres.app | `/Applications/Postgres.app/Contents/Versions/16/include` | `/Applications/Postgres.app/Contents/Versions/16/lib` |

Additionally, the linker flags (`-lpq` only) are missing the `-L` path, so linking also fails on macOS even after the header issue is resolved.

## What we tried and what fixed it

**Step 1**: `moon test --target native` fails out of the box on macOS.

The actual `cc` invocation emitted by `moon` (visible in the error output):
```
/usr/bin/cc -o .../.mooncakes/mattn/postgres/postgres_c.o \
-I/Users/.../.moon/include \
-g -c -fwrapv -fno-strict-aliasing -Wno-unused-value -fPIC \
-DMOONBIT_USE_SHARED_RUNTIME \
.mooncakes/mattn/postgres/postgres_c.c \
-I/usr/include/postgresql
```
`-I/usr/include/postgresql` is the only include path for `libpq-fe.h`, and it does not exist on macOS.

**Step 2**: Installed `brew install libpq`.

Homebrew installs headers to `/opt/homebrew/opt/libpq/include/libpq-fe.h` (confirmed with `find`). However, passing `CPPFLAGS="-I/opt/homebrew/opt/libpq/include"` to `moon test` had no effect in our test — `moon` appears to construct the `cc` command directly from `stub-cc-flags` in `moon.pkg.json`, without picking up `CPPFLAGS`.

**Step 3a (workaround — env vars)**: Setting `C_INCLUDE_PATH` and `LIBRARY_PATH` before running `moon test` works and is not overwritten by `moon install`:

```
$ C_INCLUDE_PATH="/opt/homebrew/include/postgresql@14" \
LIBRARY_PATH="/opt/homebrew/lib/postgresql@14" \
moon test --target native
Total tests: 264, passed: 264, failed: 0.
```

This was confirmed both when building the library source directly and when using it as a `.mooncakes/` dependency from another project.

**Step 3b (workaround — edit .mooncakes)**: Manually editing `.mooncakes/mattn/postgres/moon.pkg.json` also works:

```diff
"link": {
"native": {
- "cc-link-flags": "-lpq",
- "stub-cc-flags": "-I/usr/include/postgresql",
- "stub-cc-link-flags": "-lpq"
+ "cc-link-flags": "-L/opt/homebrew/opt/libpq/lib -lpq",
+ "stub-cc-flags": "-I/opt/homebrew/opt/libpq/include",
+ "stub-cc-link-flags": "-L/opt/homebrew/opt/libpq/lib -lpq"
}
}
```

This is fragile because `moon install` overwrites the change.

## Suggested Fix Direction

The immediate problem is the hardcoded `stub-cc-flags` in `moon.pkg.json`. The cleanest cross-platform solution would be to use `pg_config --includedir` / `pg_config --libdir` to detect paths at build time.

The package already has `build.js` (declared via `--moonbit-unstable-prebuild`), which currently outputs:
```javascript
const config = {
link_configs: [{ package: "mattn/postgres", link_libs: ["pq"] }]
};
console.log(JSON.stringify(config));
```

However, it's unclear whether the prebuild script output format supports setting compiler include paths (`-I` flags) — the current API appears to only expose `link_libs` and possibly `link_search_paths` for the linker. If the prebuild API does not support `stub-cc-flags` substitution, this would need to be a MoonBit-level feature request.

**Alternatively**, if MoonBit supports variable expansion in `moon.pkg.json` (e.g. `${build.INCLUDE_DIR}`), the fix could look like:

```javascript
// build.js
const { execSync } = require('child_process');
let includeDir = '/usr/include/postgresql';
let libDir = '/usr/lib';
try {
includeDir = execSync('pg_config --includedir').toString().trim();
libDir = execSync('pg_config --libdir').toString().trim();
} catch (e) {}
console.log(JSON.stringify({ vars: { PQ_INCLUDE: includeDir, PQ_LIB: libDir } }));
```

```json
// moon.pkg.json (if ${build.VAR} substitution is supported)
"stub-cc-flags": "-I${build.PQ_INCLUDE}",
"cc-link-flags": "-L${build.PQ_LIB} -lpq"
```

We're not sure whether this variable substitution syntax is currently supported — would appreciate guidance on the intended approach.

**Note on `pg_config` availability**: `pg_config` is included with full PostgreSQL installations (e.g. `brew install postgresql`, Postgres.app). With `brew install libpq` (headers only), it's available at `/opt/homebrew/opt/libpq/bin/pg_config` but not on `PATH` by default since it's keg-only. A fallback to platform-specific default paths would be needed.

Note: The README already correctly lists `brew install postgresql` for macOS — the issue is only in the build configuration.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with moon.pkg.json and build.js, then run moon test --target native on macOS with Homebrew libpq to reproduce the missing header and linker path failures. Check whether the prebuild output supports compiler include paths, linker search paths, or variable substitution, and consult the MoonBit build configuration documentation. Done means native tests pass on the documented macOS setup without editing .mooncakes files.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, javascript, postgresql
Domain
build-system, databases
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.