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: