Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Fixup macports usr vs opt precedence #267

Closed
@rurban

Description

@rurban

This is a severe Configure bug, both in perl5 and cperl.
/usr/local/include vs /usr/local/lib and /opt/local vs /usr/local.

Test: egrep -- '-[IL]/.*/local/(include|lib)' config.sh
/opt/local vs /usr/local precedence needs to match.

Currently:

ccflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.11 -DNO_MATHOMS -march=corei7 -fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -I/opt/local/include -DPERL_USE_SAFE_PUTENV'

lddlflags=' -mmacosx-version-min=10.11 -bundle -undefined dynamic_lookup -L/opt/local/lib -L/usr/local/lib -L/opt/local/lib/libgcc -fstack-protector'

ldflags=' -mmacosx-version-min=10.11 -fstack-protector -L/opt/local/lib -L/usr/local/lib -L/opt/local/lib/libgcc'

It leads to wrong compile-time diagnostics with a run-time mismatch in a loaded dylib.
Probably also on other platforms.

Policies:

  • either prefer stable libs over customized ones: then -L/opt/local/lib over -L/usr/local/lib
  • or prefer customized libs (default).
    packagers could enforce the first policy for stability, ignoring updates or old cruft in /usr/local.

But the mismatch with inc is a bug.
Note that with -L/opt/local/lib the path to the dylib is enforced at compile-time, which leads to stable packaged-only dylibs, i.e. shared cpan XS libraries.
With -L/usr/local/lib preferred, which is in DYLD_FALLBACK_LIBRARY_PATH, the path is stripped, i.e.
the dylib is sensible to DYLD_LIBRARY_PATH overrides.

$ man dyld
DYLD_LIBRARY_PATH, DYLD_FALLBACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH

check:
otool -L blib/arch/auto/PATH/NAME.bundle

Makefile.PL recipe for your cpan module:

# fixup darwin macports usr vs opt precedence. /usr/local/include vs /usr/local/lib
my $ccflags = $Config{ccflags};
my $ldflags = $Config{ldflags};
my $lddlflags = $Config{lddlflags};
if ($lddlflags =~ m| -L/opt/local/lib| and $ccflags =~ m| -I/opt/local/include|) {
    # opt first?
    if ($lddlflags =~ m| -L/opt/local/lib.*-L/usr/local/lib|
        and $ccflags =~ m| -I/usr/local/include.*-I/opt/local/include|)
    {
        warn("Your perl has corrupt /opt/local vs /usr/local precedence!\n");
        warn("include prefers /usr/local, but lib /opt/local\n");
        warn("Fixing it up for you...\n");
        $lddlflags =~ s|(-L/opt/local/lib.*)(-L/usr/local/lib)|$2 $1|;
        if ($ldflags =~ m| -L/opt/local/lib.*-L/usr/local/lib|) {
            $ldflags =~ s|(-L/opt/local/lib.*)(-L/usr/local/lib)|$2 $1|;
        }
    }
}

my %WriteMakefileArgs = (
...
  'CCFLAGS'   => $ccflags,
  'LDFLAGS' => $ldflags,
  'LDDLFLAGS' => $lddlflags,

Cause:

locincpth vs loclibpth is correct:
locincpth='/usr/local/include /opt/local/include /usr/gnu/include /opt/gnu/include /usr/GNU/include /opt/GNU/include'
loclibpth='/usr/local/lib /opt/local/lib /usr/gnu/lib /opt/gnu/lib /usr/GNU/lib /opt/GNU/lib /opt/local/lib/libgcc'

the compiler settings incpth vs libpth are also correct:
$ grep '^...pth=' config.sh
incpth='/opt/local/lib/gcc6/gcc/x86_64-apple-darwin15/6.3.0/include /opt/local/include /opt/local/lib/gcc6/gcc/x86_64-apple-darwin15/6.3.0/include-fixed /usr/include'
libpth='/opt/local/lib /opt/local/lib/gcc6/gcc/x86_64-apple-darwin15/6.3.0/include-fixed /usr/lib /usr/local/lib /opt/local/lib/libgcc'

Only the merge logic for -I/usr/local/include is wrong.

But there are more errors in the hiding:
The libpth detection in Configure is lying. The paths in libpth are not actually searched, they are only constructed analog to incpth. e.g. macports gcc does not search -L/opt/local/lib

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions