Search code examples
homebrewbundlerapple-m1pglibpq

pg gem install fails on M1 mac: "error: conflicting types for 'PQconnectdb'"


I'm installing the pg gem on mac osx 12.5 on an M1 macbook pro. Ruby bundler can't find libpq when running gem install pg:

current directory: /Users/me/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/pg-1.4.4/ext
/Users/me/.rbenv/versions/3.1.2/bin/ruby -I /Users/me/.rbenv/versions/3.1.2/lib/ruby/site_ruby/3.1.0 extconf.rb
Calling libpq with GVL unlocked
checking for pg_config... yes
Using config values from /opt/homebrew/opt/libpq/bin/pg_config
checking for whether -Wl,-rpath,/opt/homebrew/opt/libpq/lib is accepted as LDFLAGS... yes
Using libpq from /opt/homebrew/opt/libpq/lib
checking for libpq-fe.h... yes
checking for libpq/libpq-fs.h... yes
checking for pg_config_manual.h... yes
checking for PQconnectdb() in -lpq... no
checking for PQconnectdb() in -llibpq... no
checking for PQconnectdb() in -lms/libpq... no
Can't find the PostgreSQL client library (libpq)
*****************************************************************************

Unable to find PostgreSQL client library.

Please install libpq or postgresql client package like so:
  brew install libpq

or try again with:
  gem install pg -- --with-pg-config=/path/to/pg_config

or set library paths manually with:
  gem install pg -- --with-pg-include=/path/to/libpq-fe.h/ --with-pg-lib=/path/to/libpq.so/

...

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/me/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/extensions/x86_64-darwin-21/3.1.0/pg-1.4.4/mkmf.log

Here's what the mkmf.log shows:

conftest.c:16:13: error: conflicting types for 'PQconnectdb'
extern void PQconnectdb();
            ^
/opt/homebrew/include/postgresql@14/libpq-fe.h:285:16: note: previous declaration is here
extern PGconn *PQconnectdb(const char *conninfo);
               ^
conftest.c:17:27: error: too few arguments to function call, single argument 'conninfo' was not specified
int t(void) { PQconnectdb(); return 0; }
              ~~~~~~~~~~~ ^
/opt/homebrew/include/postgresql@14/libpq-fe.h:285:16: note: 'PQconnectdb' declared here
extern PGconn *PQconnectdb(const char *conninfo);

I've installed libpq using homebrew as suggested:

Warning: libpq 15.1 is already installed and up-to-date.

Interestingly, I also tried gem install pg -- --with-pg-include=/opt/homebrew/opt/libpq/include/libpq-fe.h/ but I couldn't find libpq.so poking around the homebrew install.

Any suggestions? Is it possible homebrew's installation of libpq leaves off a needed .so file? Is it suspect that the log file is under a x86_64-darwin-21 directory when I'm running on an M1 mac? Is error: conflicting types for 'PQconnectdb' a hint that I have an incompatible version of libpq with the pg gem?


Solution

  • The pg gem uses pg_config to configure itself. If the gem finds the wrong version of pg_config, it will misconfigure, resulting in the error you mentioned.

    On ARM Macs, Homebrew installs itself to a different location (/opt/homebrew) than it did on Intel Macs (/usr/local). However, if you used Apple's Migration Assistant, it's possible to end up with both Homebrew instances, which can confuse things when compiling gems.

    First, make sure your Ruby is arm64:

    $ ruby -v
    ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [arm64-darwin22]
    

    It should show arm64 there near the end.

    Next, see where pg_config is coming from:

    $ which pg_config
    /usr/local/bin/pg_config      <- Intel version
    /opt/homebrew/bin/pg_config   <- ARM version
    

    It'll show one of these two (or nothing). We're looking for the second line (ARM).

    If nothing, then postgresql is probably not installed (or not found).

    If it shows the first, then compilation is finding an Intel copy of pg_config. This was my case, after migrating from an Intel to ARM Mac.

    This confusion is partly made possible because pg_config comes from the postgresql package, not libpq. So, you'll need the arm64 version of postgresql installed too.

    If you install the unversioned (ie: latest) postgresql, this is hopefully all you need:

    $ brew install postgresql
    

    If you always install a specific version (as I do), then you'll also need to 'link' so that pg_config is properly made available.

    $ brew install postgresql@15
    $ brew link postgresql@15
    

    Using the link command is usually safe as long as this is the only version of postgresql you have installed (within the ARM copy of Homebrew).

    Hint 1: When upgrading versions of Postgres in the future, you may need to unlink the old before linking the new.

    Hint 2: If you have an Intel version of Postgres still running from the old copy of Homebrew, there is a possibility you'll have to migrate your data between the two or sort out some other conflict. That's out of scope here, so just a heads up.

    At this point you will hopefully see the proper pg_config:

    $ which pg_config
    /opt/homebrew/bin/pg_config   <- ARM version
    

    If not, also check your PATH as set by your shell. It's important that /opt/homebrew/bin is before /usr/local/bin.

    $ echo $PATH
    

    Fixing it depends on your choice of shell, so I'll skip that here.

    That should hopefully do it.

    Note that I didn't use --with-pg-config. While using that might allow skipping a step or two above, getting pg_config detecting properly also helps improve odds that other gems will compile properly in the future and not need ongoing workarounds.