in reply to Re: how to get Config values into a hash
in thread how to get Config values into a hash

Thx, Haukex, you've been instrumental in helping me to disambiguate Config situations in such nodes as Re^5: redacting from config hash and node Re^3: redacting from config hash. I hope this isn't a three strikes, you're out scenario, as I fanned on this one pretty hard. I was unaware that this Config was stamped when the user's perl install was made. It's been revealing for me to poke around in this space as a guy who knows some C. I wanted to see if I could read Config.pm, so typed

locate Config.pm >1.txt

I might have had 20 candidates with many interesting features on their own right, but I think I narrowed it down to 3 that look like the Config.pm that gets used.

diff /usr/lib/x86_64-linux-gnu/perl/5.26.1/Config.pm /usr/lib/x86_64-l +inux-gnu/perl-base/Config.pm >2.txt diff /usr/lib/x86_64-linux-gnu/perl/5.26.1/Config.pm /usr/lib/x86_64-l +inux-gnu/perl/cross-config-5.26.1/Config.pm >3.txt diff /usr/lib/x86_64-linux-gnu/perl-base/Config.pm /usr/lib/x86_64-lin +ux-gnu/perl/cross-config-5.26.1/Config.pm >5.txt

They weren't different from each other except for path. So I try to add functionality to a script to organize and probe these values. My next attempt fell apart when I tried to use Data::Dumper. What's more when I tried to work up the example from Data::Dumper, I couldn't get anywhere. I was able to cobble together a path for one of the Config.pm's using Path::Tiny and slurp it in. It's not horrendously long like some of this output, but to save the monastery's collective scrollfingers, I'll list the script and put abridged output between readmore tags:

$ cat 4.tk.pl #!/usr/bin/perl -w use 5.011; use utf8; use Config qw/%Config config_vars/; use lib "1.&#1087;&#1089;&#1099;/template_stuff"; use utils1 qw/print_hash/; my $archname = $Config{'archname'}; print "<$archname>\n"; say "---------------"; config_vars( "archname", "version", "libpath", "perl", "scriptdir", "s +itearchexp" ); say "---------------"; my $ref_Config = \%Config; print Dumper $ref_Config; # print() on unopened filehandle Dumper # print Dumper $Config; # Variable "$Config" is not imported print_hash($ref_Config); say "---------------"; use Path::Tiny; my ($archlibexp, $version) = ($Config{archlibexp},$Config{version}); my $arch_path = path($archlibexp)->parent; say "arch_path is $arch_path"; my $path_to_Config = path($arch_path,$version, "Config.pm"); my @lines = $path_to_Config->lines; say "lines are @lines"; say "---------------"; my $ref2_Config = \%Config::Config; print Dumper $ref2_Config; say "---------------"; use ExtUtils::MakeMaker::Config; say $Config{installbin}; say "---------------"; $Data::Dumper::Sortkeys = \&my_filter; my $foo = { map { (ord, "$_$_$_") } 'I'..'Q' }; say "foo is %$foo"; # print Dumper $foo; # print() on unopened filehandle Dumper print_hash($foo); my $bar = { %$foo }; my $baz = { reverse %$foo }; print Dumper [ $foo, $bar, $baz ]; sub my_filter { my ($hash) = @_; # return an array ref containing the hash keys to dump # in the order that you want them to be dumped return [ # Sort the keys of %$foo in reverse numeric order $hash eq $foo ? (sort {$b <=> $a} keys %$hash) : # Only dump the odd number keys of %$bar $hash eq $bar ? (grep {$_ % 2} keys %$hash) : # Sort keys in default order for all other hashes (sort keys %$hash) ]; } $
<x86_64-linux-gnu-thread-multi> --------------- archname='x86_64-linux-gnu-thread-multi'; version='5.26.1'; libpath='UNKNOWN'; perl='perl'; scriptdir='/usr/bin'; sitearchexp='/usr/local/lib/x86_64-linux-gnu/perl/5.26.1'; --------------- subroutine says this is your hash: key: Author, value: key: CONFIG, value: true ... key: zcat, value: key: zip, value: zip --------------- arch_path is /usr/lib/x86_64-linux-gnu/perl lines are # This file was created by configpm when Perl was built. Any + changes # made to this file will be lost the next time perl is built. # for a description of the variables, please have a look at the # Glossary file, as written in the Porting folder, or use the url: # http://perl5.git.perl.org/perl.git/blob/HEAD:/Porting/Glossary package Config; use strict; use warnings; use vars '%Config', '$VERSION'; $VERSION = "5.026001"; # Skip @Config::EXPORT because it only contains %Config, which we spe +cial # case below as it's not a function. @Config::EXPORT won't change in +the # lifetime of Perl 5. my %Export_Cache = (myconfig => 1, config_sh => 1, config_vars => 1, config_re => 1, compile_date => 1, local_patches => 1, bincompat_options => 1, non_bincompat_options => 1, header_files => 1); @Config::EXPORT = qw(%Config); @Config::EXPORT_OK = keys %Export_Cache; # Need to stub all the functions to make code such as print Config::c +onfig_sh # keep working sub bincompat_options; sub compile_date; sub config_re; sub config_sh; sub config_vars; sub header_files; sub local_patches; sub myconfig; sub non_bincompat_options; # Define our own import method to avoid pulling in the full Exporter: sub import { shift; @_ = @Config::EXPORT unless @_; my @funcs = grep $_ ne '%Config', @_; my $export_Config = @funcs < @_ ? 1 : 0; no strict 'refs'; my $callpkg = caller(0); foreach my $func (@funcs) { die qq{"$func" is not exported by the Config module\n} unless $Export_Cache{$func}; *{$callpkg.'::'.$func} = \&{$func}; } *{"$callpkg\::Config"} = \%Config if $export_Config; return; } die "$0: Perl lib version (5.26.1) doesn't match executable '$^X' ver +sion ($])" unless $^V; $^V eq 5.26.1 or die sprintf "%s: Perl lib version (5.26.1) doesn't match execu +table '$^X' version (%vd)", $0, $^V; sub FETCH { my($self, $key) = @_; # check for cached value (which may be undef so we use exists not + defined) return exists $self->{$key} ? $self->{$key} : $self->fetch_string +($key); } sub TIEHASH { bless $_[1], $_[0]; } sub DESTROY { } sub AUTOLOAD { require 'Config_heavy.pl'; goto \&launcher unless $Config::AUTOLOAD =~ /launcher$/; die "&Config::AUTOLOAD failed on $Config::AUTOLOAD"; } # tie returns the object, so the value returned to require will be tr +ue. tie %Config, 'Config', { archlibexp => '/usr/lib/x86_64-linux-gnu/perl/5.26', archname => 'x86_64-linux-gnu-thread-multi', cc => 'x86_64-linux-gnu-gcc', d_readlink => 'define', d_symlink => 'define', dlext => 'so', dlsrc => 'dl_dlopen.xs', dont_use_nlink => undef, exe_ext => '', inc_version_list => '5.26.0 5.26.0/x86_64-linux-gnu-thread-multi' +, intsize => '4', ldlibpthname => 'LD_LIBRARY_PATH', libpth => '/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/7/include +-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu / +lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib', osname => 'linux', osvers => '4.9.0', path_sep => ':', privlibexp => '/usr/share/perl/5.26', scriptdir => '/usr/bin', sitearchexp => '/usr/local/lib/x86_64-linux-gnu/perl/5.26.1', sitelibexp => '/usr/local/share/perl/5.26.1', so => 'so', useithreads => 'define', usevendorprefix => 'define', version => '5.26.1', }; --------------- --------------- /usr/bin --------------- foo is %HASH(0x55f2c54cf370) subroutine says this is your hash: key: 73, value: III key: 74, value: JJJ key: 75, value: KKK key: 76, value: LLL key: 77, value: MMM key: 78, value: NNN key: 79, value: OOO key: 80, value: PPP key: 81, value: QQQ

How did I lose my grip on Data::Dumper so as not to be able to even work up the example code?

With 1000's of values in this hash, would I find a variable that contained the path that I think is probable for being the one actually used when during use Config ();? Not really. Output then source:

arch_path is /usr/lib/x86_64-linux-gnu/perl --------------- archlib matched: /usr/lib/x86_64-linux-gnu/perl/5.26 archlibexp matched: /usr/lib/x86_64-linux-gnu/perl/5.26 config_arg13 matched: -Darchlib=/usr/lib/x86_64-linux-gnu/perl/5.26 config_arg16 matched: -Dvendorarch=/usr/lib/x86_64-linux-gnu/perl5/5.2 +6 ... installarchlib matched: /usr/lib/x86_64-linux-gnu/perl/5.26 installvendorarch matched: /usr/lib/x86_64-linux-gnu/perl5/5.26 vendorarch matched: /usr/lib/x86_64-linux-gnu/perl5/5.26 vendorarchexp matched: /usr/lib/x86_64-linux-gnu/perl5/5.26
#!/usr/bin/perl -w use 5.011; use utf8; use Config qw/%Config config_vars/; use lib "1.&#1087;&#1089;&#1099;/template_stuff"; use utils1 qw/print_hash/; use Path::Tiny; my ( $archlibexp, $version ) = ( $Config{archlibexp}, $Config{version} + ); my $arch_path = path($archlibexp)->parent; say "arch_path is $arch_path"; my $path_to_Config = path( $arch_path, $version, "Config.pm" ); my @lines = $path_to_Config->lines; # say "lines are @lines"; this works say "---------------"; for ( keys %Config ) { next if ($Config{$_} eq undef); if ( $Config{$_} =~ m%/usr/lib/x86_64-linux-gnu/perl% ) { say "$_ matched: $Config{$_}"; } }

My question here is how does perl decide which Config.pm it uses?

Thank you for your comments, haukex; I've been following your webperl development and have gotten good initial results that I'm building on.

Replies are listed 'Best First'.
Re^3: how to get Config values into a hash
by haukex (Archbishop) on Oct 19, 2018 at 12:07 UTC
    print Dumper $ref_Config; # print() on unopened filehandle Dumper

    Looks like you're missing use Data::Dumper; at the top of the script. The error message is a little confusing because Perl is trying to interpret that print as Indirect Object Syntax (print FILEHANDLE LIST).

    Other than that, looks like you've figured out @INC, and I already pointed out %INC, which will give you the location of the file that was actually loaded.

      print FILEHANDLE LIST

      Thx haukex for the precise explanation. I like to finish my threads with working code, for myself and presumably others who will search the net for why Data::Dumper doesn't work unless you 'use' it. They give a pretty good example here, and I wish that all modules would give example code snippets:

      $ ./1.dd.pl $VAR1 = [ { '81' => 'QQQ', '80' => 'PPP', '79' => 'OOO', '78' => 'NNN', '77' => 'MMM', '76' => 'LLL', '75' => 'KKK', '74' => 'JJJ', '73' => 'III' }, { '75' => 'KKK', '79' => 'OOO', '77' => 'MMM', '81' => 'QQQ', '73' => 'III' }, { 'III' => '73', 'JJJ' => '74', 'KKK' => '75', 'LLL' => '76', 'MMM' => '77', 'NNN' => '78', 'OOO' => '79', 'PPP' => '80', 'QQQ' => '81' } ]; $ cat 1.dd.pl #!/usr/bin/perl -w use 5.011; use Data::Dumper; $Data::Dumper::Sortkeys = \&my_filter; my $foo = { map { (ord, "$_$_$_") } 'I'..'Q' }; my $bar = { %$foo }; my $baz = { reverse %$foo }; print Dumper [ $foo, $bar, $baz ]; sub my_filter { my ($hash) = @_; # return an array ref containing the hash keys to dump # in the order that you want them to be dumped return [ # Sort the keys of %$foo in reverse numeric order $hash eq $foo ? (sort {$b <=> $a} keys %$hash) : # Only dump the odd number keys of %$bar $hash eq $bar ? (grep {$_ % 2} keys %$hash) : # Sort keys in default order for all other hashes (sort keys %$hash) ]; } $
Re^3: how to get Config values into a hash
by Aldebaran (Curate) on Oct 18, 2018 at 05:47 UTC
    My question here is how does perl decide which Config.pm it uses?

    I think I solved my own question here. When perl looks for Config.pm it starts at the top of @INC and keeps on going until it finds a match. I conjecture that it's guaranteed that there is one at the ultimate path with perl-base:

    $ ./2.cf.pl </usr/lib/x86_64-linux-gnu/perl/5.26> --------------- /home/bob/perl5/lib/perl5/x86_64-linux-gnu-thread-multi /home/bob/perl +5/lib/perl5 /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.26.1 /us +r/local/share/perl/5.26.1 /usr/lib/x86_64-linux-gnu/perl5/5.26 /usr/s +hare/perl5 /usr/lib/x86_64-linux-gnu/perl/5.26 /usr/share/perl/5.26 / +usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base path is /usr/lib/x86_64-linux-gnu/perl/5.26/Config.pm stat is File::stat=ARRAY(0x55f122748b70) $VAR1 = bless( [ 2054, 6591373, 33188, 1, 0, 0, 0, 3372, 1539824438, 1531923663, 1532749911, 4096, 8 ], 'File::stat' ); path is /usr/lib/x86_64-linux-gnu/perl-base/Config.pm stat is File::stat=ARRAY(0x55f122ad48c0) $VAR1 = bless( [ 2054, 6591655, 33188, 1, 0, 0, 0, 3373, 1539712704, 1531923663, 1532749916, 4096, 8 ], 'File::stat' ); $ cat 2.cf.pl #!/usr/bin/perl -w use 5.011; use utf8; use Config qw/%Config config_vars/; use Path::Tiny; use Data::Dumper; my $insarchname = $Config{'installarchlib'}; print "<$insarchname>\n"; say "---------------"; say "@INC"; foreach (@INC) { my $path1 = path( $_, "Config.pm" ); if ( -f $path1 ) { my $stat = $path1->stat; say "path is $path1"; say "stat is $stat"; say Dumper $stat; } } $