[PATCH] Fix PCRE detection on OSX.

Ruslan Ermilov ru at nginx.com
Mon Dec 10 10:31:42 UTC 2012

On Mon, Dec 10, 2012 at 06:37:24AM +0400, Maxim Dounin wrote:
> The problem with Mac OS X is not with libpcre withou pcre.h, but with 
> broken toolchain which prefers headers from /usr/local/include but 
> libraries from /usr/lib by default.
> That is, header file from /usr/local/include was used, but library 
> from /usr/lib.  This is the clear incosistency in build toolchain 
> which will result in various build problems till fixed.

> Easy fix is to avoid using /usr/local/ till the problem is fixed.  
> Alternatively, one may try to provide appropriate compiler 
> arguments to fix the toolchain.  Another alternative would be to 
> switch to a different toolchain (e.g. MacPort's provided one).

Actually there are two problems.

The problem with broken toolchain isn't unique to OS X.  I've tried
it on at least Gentoo, CentOS, Debian, FreeBSD ports compilers, and
they all (mis)behave similar to OS X.

The problem with the broken toolchain is quite easy to fix, adding
"-isystem /usr/include" will result in /usr/include preferred over
/usr/local/lib (works on gcc, llvm-gcc and clang).  Depending on
the actual compiler used, the output might look like this:

: $ cc -isystem /usr/include -v -c test.c
: #include "..." search starts here:
: #include <...> search starts here:
:  /usr/include
:  /usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/include
:  /usr/local/include
:  /Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/include
:  /System/Library/Frameworks (framework directory)
:  /Library/Frameworks (framework directory)
: End of search list.

The second problem is missing /usr/include/pcre.h on OS X.

Fixing the first problem doesn't help to fix the second: the missing
/usr/include/pcre.h in OS X will still result in nginx (or any other
software using the default compiler and linker with default flags)
attempting to use /usr/local/include/pcre.h and /usr/lib/libpcre,
even if the compiler and linker are consistent and prefer

So I tent to repeat: avoid using /usr/local if at all possible.
(Or at least don't install libraries into /usr/local that also
exist in /usr/{include,lib}.)

A correct fix seems to be to exclude /usr/local/{include,lib} from
the default search paths (like FreeBSD does), but I'm not aware of
an easy way to do it.  And again, this is not unique to only OS X,
nor is nginx specific.

An alternative approach that prefers /usr/local/{include,lib} over
/usr/{include,lib} (as simple as -L/usr/local/lib) seems like an
overkill to me just to work around a misinstalled PCRE on OS X.

> I don't think nginx should try to do anything with it as it's 
> indeed not our problem.  But if we are going to, it probably 
> should be something better that just not searching for PCRE in 
> default compiler search paths, as it e.g. breaks compilation with 
> search paths explicitly configured by a user via ./configure 
> arguments.

Also note that the default feature test in auto/lib/pcre/conf
is not about "PCRE library in /usr/include", it's about the
"PCRE library in default locations", whatever it means, and
depends on the toolchain used.

Disabling the default feature test on OS X, as suggested, is bad
because while it adds a workaround for one of the possible setups,
it breaks the others.

Imagine there is a packaging system that installs stuff into
/my/prefix and ships with the toolchain that looks for headers
and libraries in /my/prefix/{include,lib}.  This system also
ships with the nginx port that configures nginx with the
--with-cc= argument to point to the compiler from the
toolchain (or sets up $PATH in environment accordingly).

A correct workaround should ensure that we don't try to use libpcre
from /usr/lib, because we know it's misinstalled, but shouldn't
otherwise pessimize other valid cases.  Since we don't know how
exactly the toolchain used is configured, we can merely delay the
default PCRE test on OS X:

Index: auto/lib/pcre/conf
--- auto/lib/pcre/conf	(revision 4948)
+++ auto/lib/pcre/conf	(working copy)
@@ -101,7 +101,17 @@
         ngx_feature_test="pcre *re;
                           re = pcre_compile(NULL, 0, NULL, 0, NULL);
                           if (re == NULL) return 1"
-        . auto/feature
+        if [ "$NGX_SYSTEM" = "Darwin" ]; then
+            # Apple provides libpcre in /usr/lib but no /usr/include/pcre.h.
+            # This may interfere with libpcre installed into /usr/local if
+            # system compiler is used.  To work around this, we delay the
+            # default test until after we tested /usr/local.
+            ngx_found=no
+        else
+            . auto/feature
+        fi
         if [ $ngx_found = no ]; then
@@ -119,6 +129,14 @@
             . auto/feature
+        if [ $ngx_found = no -a "$NGX_SYSTEM" = "Darwin" ]; then
+            ngx_feature="PCRE library"
+            ngx_feature_path=
+            ngx_feature_libs="-lpcre"
+            . auto/feature
+        fi
         if [ $ngx_found = no ]; then
             # RedHat RPM, Solaris package

More information about the nginx-devel mailing list