Last weekend tetragon and I had considerable discussion on #parrot about
this problem.  My diagnosis was that we should not be handling
command-line options at all in 'hints' files; they should be handled in
inter::progs.

The patch attached removes options handling from
config/init/hints/darwin.pm, adds a prompt for the flag about which Coke
was concerned in config/inter/progs.pm, and adds a file of tests for
config/init/hints/darwin.pm.

This was developed in the 'darwin_fix_hints' branch.  If you use 'patch'
to apply it to trunk, you'll probably get a bit of rejected material in
MANIFEST, but that doesn't affect the soundness of the rest of the
patch.  I will apply this to trunk in a few days if there is no objection.

Thank you very much.
kid51
Index: MANIFEST
===================================================================
--- MANIFEST    (.../trunk)     (revision 29926)
+++ MANIFEST    (.../branches/darwin_fix_hints) (revision 29963)
@@ -1,7 +1,7 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Fri Aug  1 22:58:18 2008 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Sat Aug  2 01:30:14 2008 UT
 #
 # See tools/dev/install_files.pl for documentation on the
 # format of this file.
@@ -3651,6 +3651,7 @@
 t/steps/init_defaults-01.t                                  []
 t/steps/init_headers-01.t                                   []
 t/steps/init_hints-01.t                                     []
+t/steps/init_hints-02.t                                     []
 t/steps/init_install-01.t                                   []
 t/steps/init_manifest-01.t                                  []
 t/steps/init_miniparrot-01.t                                []
Index: t/steps/init_hints-02.t
===================================================================
--- t/steps/init_hints-02.t     (.../trunk)     (revision 0)
+++ t/steps/init_hints-02.t     (.../branches/darwin_fix_hints) (revision 29963)
@@ -0,0 +1,278 @@
+#! perl
+# Copyright (C) 2007, The Perl Foundation.
+# $Id$
+# init_hints-02.t
+
+use strict;
+use warnings;
+use Data::Dumper;$Data::Dumper::Indent=1;
+use Test::More;
+plan( skip_all => 'Macports is Darwin only' ) unless $^O =~ /darwin/;
+plan( tests => 32 );
+use Carp;
+use Cwd;
+use File::Path ();
+use File::Spec::Functions qw/catfile/;
+use File::Temp qw(tempdir);
+use lib qw( lib t/configure/testlib );
+use_ok('config::init::defaults');
+use_ok('config::init::hints');
+use_ok('config::init::hints::darwin');
+use Parrot::Configure;
+use Parrot::Configure::Options qw( process_options );
+use Parrot::Configure::Test qw(
+    test_step_thru_runstep
+    test_step_constructor_and_description
+);
+use IO::CaptureOutput qw | capture |;
+
+my $args = process_options( {
+        argv => [],
+        mode => q{configure},
+} );
+
+my $conf = Parrot::Configure->new;
+test_step_thru_runstep( $conf, q{init::defaults}, $args );
+my $pkg = q{init::hints};
+$conf->add_steps($pkg);
+my $serialized = $conf->pcfreeze();
+$conf->options->set( %{$args} );
+my $step = test_step_constructor_and_description($conf);
+
+########### _precheck() ##########
+
+my ($flag, $stored, $verbose);
+$flag = 'ccflags';
+{
+    $stored = 'baz';
+    $verbose = 1;
+    my ($stdout, $stderr);
+    capture (
+        sub { init::hints::darwin::_precheck(
+            $flag, $stored, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    like($stdout, qr/Checking $flag/s,
+        "Got expected verbose output for _precheck()");
+    like($stdout, qr/Pre-check:\s+$stored/s,
+        "Got expected verbose output for _precheck()");
+}
+
+{
+    $stored = q{};
+    $verbose = 1;
+    my ($stdout, $stderr);
+    capture (
+        sub { init::hints::darwin::_precheck(
+            $flag, $stored, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    like($stdout, qr/Checking $flag/s,
+        "Got expected verbose output for _precheck()");
+    like($stdout, qr/Pre-check:\s+\(nil\)/s,
+        "Got expected verbose output for _precheck()");
+}
+
+{
+    $stored = 'baz';
+    $verbose = 0;
+    my ($stdout, $stderr);
+    capture (
+        sub { init::hints::darwin::_precheck(
+            $flag, $stored, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    ok(! $stdout, "As expected, got no verbose output");
+}
+
+########### _strip_arch_flags_engine() ##########
+
+my ($arches, $flagsref);
+$arches = $init::hints::darwin::defaults{architecture};
+$stored = q{foo -arch i386 -arch ppc bar -arch i386 baz};
+$flagsref  = {
+    map { $_ => '' }
+        @{ $init::hints::darwin::defaults{problem_flags} }
+};
+$flagsref = init::hints::darwin::_strip_arch_flags_engine(
+    $arches, $stored, $flagsref, 'ccflags'
+);
+$flagsref = init::hints::darwin::_strip_arch_flags_engine(
+    $arches, $stored, $flagsref, 'ldflags'
+);
+my $expected = qr/foo\sbar\sbaz/;
+like($flagsref->{ccflags}, $expected,
+    "-arch flags stripped appropriately from ccflags" );
+like($flagsref->{ldflags}, $expected,
+    "-arch flags stripped appropriately from ldflags" );
+
+########### _postcheck() ##########
+
+my $setting;
+$flag = 'ccflags';
+{
+    $setting = 'foo bar baz';
+    $verbose = 1;
+    my ($stdout, $stderr);
+    capture (
+        sub { init::hints::darwin::_postcheck($flagsref, $flag, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    like( $stdout,
+        qr/Post-check:\s+$setting/s,
+        "Got expected verbose output for _postcheck()"
+    );
+}
+
+{
+    $setting = 'foo bar baz';
+    $verbose = 0;
+    my ($stdout, $stderr);
+    capture (
+        sub { init::hints::darwin::_postcheck($flagsref, $flag, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    ok( ! $stdout, "As expected, got no verbose output");
+}
+
+$flagsref->{ccflags} = q{};
+$flag = 'ccflags';
+{
+    $verbose = 1;
+    my ($stdout, $stderr);
+    capture (
+        sub { init::hints::darwin::_postcheck($flagsref, $flag, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    like( $stdout,
+        qr/Post-check:\s+\(nil\)/s,
+        "Got expected verbose output for _postcheck()"
+    );
+}
+
+########### _strip_arch_flags() ##########
+
+my $ccflags_orig  = $conf->data->get( 'ccflags' );
+my $ldflags_orig  = $conf->data->get( 'ldflags' );
+
+$conf->data->set( ccflags =>
+    q{foo -arch i386 -arch ppc bar -arch i386 baz} );
+$conf->data->set( ldflags =>
+    q{foo -arch i386 -arch ppc bar -arch i386 baz -arch ppc samba} );
+$verbose = 0;
+$flagsref = init::hints::darwin::_strip_arch_flags($conf, $verbose);
+like( $flagsref->{ccflags}, qr/foo\sbar\sbaz/,
+    "-arch flags stripped appropriately for ccflags" );
+like( $flagsref->{ldflags}, qr/foo\sbar\sbaz\ssamba/,
+    "-arch flags stripped appropriately for ldflags" );
+
+$verbose = 1;
+{
+    my ($stdout, $stderr);
+    capture( sub { $flagsref =
+        init::hints::darwin::_strip_arch_flags($conf, $verbose); },
+        \$stdout,
+        \$stderr,
+    );
+    like( $flagsref->{ccflags}, qr/foo\sbar\sbaz/,
+        "-arch flags stripped appropriately for ccflags" );
+    like( $flagsref->{ldflags}, qr/foo\sbar\sbaz\ssamba/,
+        "-arch flags stripped appropriately for ldflags" );
+    like( $stdout,
+        qr/Stripping -arch flags due to Apple multi-architecture build 
problems/,
+        "Got expected verbose output from _strip_arch_flags()" );
+}
+
+$conf->data->set( ccflags => q{} );
+$conf->data->set( ldflags =>
+    q{foo -arch i386 -arch ppc bar -arch i386 baz -arch ppc samba} );
+$verbose = 0;
+$flagsref = init::hints::darwin::_strip_arch_flags($conf, $verbose);
+like( $flagsref->{ccflags}, qr/^$/,
+    "Got appropriate value when ccflags was empty" );
+like( $flagsref->{ldflags}, qr/foo\sbar\sbaz\ssamba/,
+    "-arch flags stripped appropriately for ldflags" );
+
+# re-set for next test
+$conf->data->set( ccflags => $ccflags_orig );
+$conf->data->set( ldflags => $ldflags_orig );
+
+########### _strip_ldl_as_needed() ##########
+
+my $libs_orig = $conf->data->get( 'libs' );
+my $uname_orig = $init::hints::darwin::defaults{uname};
+my $libs;
+
+$init::hints::darwin::defaults{uname} = '8.1.0';
+$libs = q{-ldlfoobar};
+$libs = init::hints::darwin::_strip_ldl_as_needed($libs);
+is($libs, q{foobar}, "'-ldl' stripped as expected");
+
+$init::hints::darwin::defaults{uname} = '6.1.0';
+$libs = q{-ldlfoobar};
+$libs = init::hints::darwin::_strip_ldl_as_needed($libs);
+is($libs, q{-ldlfoobar}, "'-ldl' not stripped, as expected");
+
+# re-set for next test
+$conf->data->set( ccflags => $ccflags_orig );
+$init::hints::darwin::defaults{uname} = $uname_orig;
+
+########### _set_deployment_environment()##########
+{
+    local %ENV = %ENV;
+    delete $ENV{'MACOSX_DEPLOYMENT_TARGET'};
+    my $sw_vers_orig = $init::hints::darwin::defaults{sw_vers};
+    $init::hints::darwin::defaults{sw_vers} = qq{99.88.77\n};
+    init::hints::darwin::_set_deployment_environment();
+    is( $ENV{'MACOSX_DEPLOYMENT_TARGET'}, q{99.88},
+        "Got expected environmental setting");
+
+    # re-set for next test
+    $init::hints::darwin::defaults{sw_vers} = $sw_vers_orig;
+
+    local $ENV{'MACOSX_DEPLOYMENT_TARGET'} = q{66.55};
+    init::hints::darwin::_set_deployment_environment();
+    is( $ENV{'MACOSX_DEPLOYMENT_TARGET'}, q{66.55},
+        "Got expected environmental setting");
+}
+
+pass("Completed all tests in $0");
+
+################### DOCUMENTATION ###################
+
+=head1 NAME
+
+init_hints-02.t - test init::hints::darwin
+
+=head1 SYNOPSIS
+
+    % prove t/steps/init_hints-02.t
+
+=head1 DESCRIPTION
+
+The files in this directory test functionality used by F<Configure.pl>.
+
+The tests in this file test init::hints::darwin.
+
+=head1 AUTHOR
+
+James E Keenan
+
+=head1 SEE ALSO
+
+config::init::hints, F<Configure.pl>.
+
+=cut
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:

Property changes on: t/steps/init_hints-02.t
___________________________________________________________________
Name: svn:eol-style
   + native
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Author Date Id Revision

Index: config/inter/progs.pm
===================================================================
--- config/inter/progs.pm       (.../trunk)     (revision 29926)
+++ config/inter/progs.pm       (.../branches/darwin_fix_hints) (revision 29963)
@@ -98,7 +98,8 @@
     $ld = prompt( "What program do you want to use to build shared 
libraries?", $ld ) if $ask;
     $conf->data->set( ld => $ld );
 
-    $ccflags = $conf->data->get('ccflags');
+    $ccflags = integrate( $conf->data->get('ccflags'),
+        $conf->options->get('ccflags') );
 
     # Remove some perl5-isms.
     $ccflags =~ s/-D((PERL|HAVE)_\w+\s*|USE_PERLIO)//g;
Index: config/init/hints/darwin.pm
===================================================================
--- config/init/hints/darwin.pm (.../trunk)     (revision 29926)
+++ config/init/hints/darwin.pm (.../branches/darwin_fix_hints) (revision 29963)
@@ -6,77 +6,44 @@
 use strict;
 use warnings;
 
+our %defaults = (
+    uname           => `uname -r`,
+    sw_vers         => `sw_vers -productVersion`,
+    problem_flags   => [ qw( ccflags ldflags ) ],
+    architectures   => [ qw( i386 ppc64 ppc x86_64 ) ],
+);
+
 sub runstep {
     my ( $self, $conf ) = @_;
 
     my $verbose = $conf->options->get('verbose');
 
-    # @flags is the list of options that have -arch flags added to them
+    # %flags is the list of options that have -arch flags added to them
     # implicitly through config/init/defaults.pm when using Apple's Perl
     # 5.8 build to run Configure.pl (it's a multi-architecture build).
     # This doesn't play nice with getting parrot to build on PPC systems
     # and causes all sorts of fun issues with lipo and friends.  So, it's
-    # time to remove all -arch flags set in $conf->data that haven't been
-    # requested by command-line options and force a single, native
-    # architecture to being the default build.
-    my @flags = qw(ccflags linkflags ldflags ld_share_flags ld_load_flags);
-    my @arches = qw(i386 ppc64 ppc x86_64);
+    # time to remove all -arch flags set in $conf->data and force a single, 
+    # native architecture to being the default build.
 
-    print "\nChecking for -arch flags not explicitly added:\n" if $verbose;
-    for my $flag (@flags) {
-        my $set_flags;
-        if ($flag =~ /^ld/) {
-            $set_flags = $conf->options->get('ldflags')||'';
-        }
-        else {
-            $set_flags = $conf->options->get($flag)||'';
-        }
-        my $stored = $conf->data->get($flag)||'';
+    my $flagsref = _strip_arch_flags($conf, $verbose);
 
-        print "Checking $flag...\n" if $verbose;
-        print "User-specified: ".($set_flags||'(nil)')."\n" if $verbose;
-        print "Pre-check: ".($stored||'(nil)')."\n" if $verbose;
-
-        for my $arch (@arches) {
-            if (!$set_flags || $set_flags !~ /(?:^|\W)-arch\s+$arch(?:\W|$)/) {
-                $stored =~ s/-arch\s+$arch//g;
-                $conf->data->set($flag => $stored);
-            }
-        }
-        print "Post-check: ".($conf->data->get($flag)||'(nil)')."\n" if 
$verbose;
-    }
     # And now, after possibly losing a few undesired compiler and linker
     # flags, on to the main Darwin config.
 
-    my ( $ccflags, $ldflags, $libs ) = $conf->data->get(qw(ccflags ldflags 
libs));
+    my $libs = _strip_ldl_as_needed( $conf->data->get( 'libs' ) );
 
-    my $OSVers = `uname -r`;
-    chomp $OSVers;
-    {
-        local $^W;
-        $OSVers =~ /(\d+)/;
-        if ( $1 >= 7 ) {
-            $libs =~ s/-ldl//;
-        }
-    }
+    _set_deployment_environment();
 
-    unless (exists $ENV{'MACOSX_DEPLOYMENT_TARGET'}) {
-        my $OSX_vers = `sw_vers -productVersion`;
-        chomp $OSX_vers;
-        # remove minor version
-        $OSX_vers =join '.', (split /[.]/, $OSX_vers)[0,1];
-        $ENV{'MACOSX_DEPLOYMENT_TARGET'} = $OSX_vers;
-    }
-
     my $lib_dir = $conf->data->get('build_dir') . "/blib/lib";
-    $ldflags .= " -L$lib_dir";
-    $ccflags .= " -pipe -fno-common -Wno-long-double ";
+    $flagsref->{ldflags} .= " -L$lib_dir";
+    $flagsref->{ccflags} .= " -pipe -fno-common -Wno-long-double ";
 
     $conf->data->set(
         darwin              => 1,
         osx_version         => $ENV{'MACOSX_DEPLOYMENT_TARGET'},
-        ccflags             => $ccflags,
-        ldflags             => $ldflags,
+        ccflags             => $flagsref->{ccflags},
+        ldflags             => $flagsref->{ldflags},
         ccwarn              => "-Wno-shadow",
         libs                => $libs,
         share_ext           => '.dylib',
@@ -89,8 +56,10 @@
         memalign            => 'some_memalign',
         has_dynamic_linking => 1,
 
-        # RT#43147 when built against a dynamic libparrot installable_parrot 
records
-        # the path to the blib version of the library
+        # RT 43147:  When built against a dynamic libparrot,
+        # installable_parrot records the path to the blib version 
+        # of the library.
+        
         parrot_is_shared       => 1,
         libparrot_shared       => 'libparrot.$(SOVERSION)$(SHARE_EXT)',
         libparrot_shared_alias => 'libparrot$(SHARE_EXT)',
@@ -103,6 +72,76 @@
     );
 }
 
+#################### INTERNAL SUBROUTINES ####################
+
+sub _precheck {
+    my ($flag, $stored, $verbose) = @_;
+    if ($verbose) {
+        print "Checking $flag...\n";
+        print "Pre-check: " . ($stored || '(nil)') . "\n";
+    }
+}
+
+sub _strip_arch_flags_engine {
+    my ($arches, $stored, $flagsref, $flag) = @_;
+    for my $arch ( @{ $defaults{architectures} } ) {
+        $stored =~ s/-arch\s+$arch//g;
+        $stored =~ s/\s+/ /g;
+        $flagsref->{$flag} = $stored;
+    }
+    return $flagsref;
+}
+
+sub _postcheck {
+    my ($flagsref, $flag, $verbose) = @_;
+    if ($verbose) {
+        print "Post-check: ", ( $flagsref->{$flag} or '(nil)' ), "\n";
+    }
+}
+
+sub _strip_arch_flags {
+    my ($conf, $verbose) = @_;
+    my $flagsref  = { map { $_ => '' } @{ $defaults{problem_flags} } };
+
+    print "\nStripping -arch flags due to Apple multi-architecture build 
problems:\n" if $verbose;
+    for my $flag ( keys %{ $flagsref } ) {
+        my $stored = $conf->data->get($flag) || '';
+
+        _precheck($flag, $stored, $verbose);
+
+        $flagsref = _strip_arch_flags_engine(
+            $defaults{architectures}, $stored, $flagsref, $flag
+        );
+
+        _postcheck($flagsref, $flag, $verbose);
+    }
+    return $flagsref;
+}
+
+sub _strip_ldl_as_needed {
+    my $libs = shift;
+    my $OSVers = $defaults{uname};
+    chomp $OSVers;
+    {
+        local $^W;
+        $OSVers =~ /(\d+)/;
+        if ( $1 >= 7 ) {
+            $libs =~ s/-ldl//;
+        }
+    }
+    return $libs;
+}
+
+sub _set_deployment_environment {
+    unless (defined $ENV{'MACOSX_DEPLOYMENT_TARGET'}) {
+        my $OSX_vers = $defaults{sw_vers};
+        chomp $OSX_vers;
+        # remove minor version
+        $OSX_vers =join '.', (split /[.]/, $OSX_vers)[0,1];
+        $ENV{'MACOSX_DEPLOYMENT_TARGET'} = $OSX_vers;
+    }
+}
+
 1;
 
 # Local Variables:

Reply via email to