How to make perl Makefile.PL use a given C compiler when compiling an XS module?

旧时模样 提交于 2021-01-28 04:15:38

问题


I am trying to build Acme::Damn using a pre-compiled perl downloaded with conda, see this question for details. The cc that was used to build perl with is given by:

$ perl -V | grep cc=./
    cc='/tmp/build/80754af9/perl_1527832170752/_build_env/bin/x86_64-conda_cos6-linux-gnu-gcc'

which does not exist on my machine, and make thus fails:

$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Warning: prerequisite Test::Exception 0 not found.
Generating a Unix-style Makefile
Writing Makefile for Acme::Damn
Writing MYMETA.yml and MYMETA.json
$ make
cp Damn.pm blib/lib/Acme/Damn.pm
Running Mkbootstrap for Damn ()
chmod 644 "Damn.bs"
"/home/hakon/anaconda3/envs/perl_test/bin/perl" -MExtUtils::Command::MM -e 'cp_nonempty' -- Damn.bs blib/arch/auto/Acme/Damn/Damn.bs 644
"/home/hakon/anaconda3/envs/perl_test/bin/perl" "/home/hakon/anaconda3/envs/perl_test/lib/5.26.2/ExtUtils/xsubpp"  -typemap '/home/hakon/anaconda3/envs/perl_test/lib/5.26.2/ExtUtils/typemap'  Damn.xs > Damn.xsc
mv Damn.xsc Damn.c
/tmp/build/80754af9/perl_1527832170752/_build_env/bin/x86_64-conda_cos6-linux-gnu-gcc -c  -I. -D_REENTRANT -D_GNU_SOURCE --sysroot=/tmp/build/80754af9/perl_1527832170752/_build_env/x86_64-conda_cos6-linux-gnu/sysroot -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O2   -DVERSION=\"0.08\" -DXS_VERSION=\"0.08\" -fPIC --sysroot=/tmp/build/80754af9/perl_1527832170752/_build_env/x86_64-conda_cos6-linux-gnu/sysroot "-I/home/hakon/anaconda3/envs/perl_test/lib/5.26.2/x86_64-linux-thread-multi/CORE"   Damn.c
/bin/sh: 1: /tmp/build/80754af9/perl_1527832170752/_build_env/bin/x86_64-conda_cos6-linux-gnu-gcc: not found
make: *** [Makefile:337: Damn.o] Error 127

I can install the same compiler that was used to build perl with conda:

$ conda install -c anaconda gcc_linux-64
$ which  x86_64-conda_cos6-linux-gnu-gcc
/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc

How can I make perl Makefile.PL use this as the compiler location when generating the Makefile ? I tried:

CC=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc perl Makefile.PL

but this does not work.


回答1:


Fix Config.pm to point to the right location.

perl -i~ -spe's{^\s*cc\s*=>\s*\x27\K[^\x27]*}{$cc}' \
   -- -cc=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc \
   -- "$( perldoc -lm Config )"

That causes perl -V:cc to show the updated path.

cc is also defined in Config_heavy.pl, though. So you might also need the following:

perl -i~ -spe's{^cc=\x27\K[^\x27]*}{$cc}' \
   -- -cc=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc \
   -- "$( perldoc -lm Config_heavy.pl )"



回答2:


Makefile.PL takes arguments, not environment variables.

perl Makefile.PL CC=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc



回答3:


By looking at Config_heavy.pl, I can see a lot more config variables than cc that probably needs to be updated also, including cccdlflags, ccflags, config_arg10, config_arg8, config_args, cppflags, cpprun, cppstdin, glibpth, incpth, ld, lddlflags, libpth, libsdirs, libsfound, libspath, locincpth, loclibpth, strings, sysroot, timeincl, usrinc, and xlibpth.

Based on the answer of @ikegami, I wrote the following Perl script to modify both Config.pm and Config_heavy.pl:

use feature qw(say);
use strict;
use warnings;
use Config;
{
    my $compiler_name = 'x86_64-conda_cos6-linux-gnu-gcc';
    my $cc = $Config{cc};
    my ($old_prefix) = $cc =~ m{^(.*?)/bin/$compiler_name};
    die "Unexpected: Could not find old sysroot prefix." if !defined $old_prefix;
    my $new_prefix = $ENV{CONDA_PREFIX};
    die "Unexpected: Could find new sysroot prefix." if !defined $new_prefix;
    say "Old prefix: $old_prefix";
    say "New prefix: $new_prefix";
    fix_config_file($old_prefix, $new_prefix, 'Config.pm');
    fix_config_file($old_prefix, $new_prefix, 'Config_heavy.pl');
}

sub fix_config_file {
    my ($old_prefix, $new_prefix, $fn) = @_;

    my $path = qx/perldoc -lm $fn/;
    chomp $path;
    system 'perl', '-i~', '-pe', "s{\Q$old_prefix\E}{$new_prefix}g", $path;
    say "Updated: $path";
}

After running the above script from within the conda environment, I could compile the module:

$ perl Makefile.PL 
Warning: prerequisite Test::Exception 0 not found.
Generating a Unix-style Makefile
Writing Makefile for Acme::Damn
Writing MYMETA.yml and MYMETA.json

$ make
Skip blib/lib/Acme/Damn.pm (unchanged)
Running Mkbootstrap for Damn ()
chmod 644 "Damn.bs"
"/home/hakon/anaconda3/envs/perl_test/bin/perl" -MExtUtils::Command::MM -e 'cp_nonempty' -- Damn.bs blib/arch/auto/Acme/Damn/Damn.bs 644
/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc -c  -I. -D_REENTRANT -D_GNU_SOURCE --sysroot=/home/hakon/anaconda3/envs/perl_test/x86_64-conda_cos6-linux-gnu/sysroot -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O2   -DVERSION=\"0.08\" -DXS_VERSION=\"0.08\" -fPIC --sysroot=/home/hakon/anaconda3/envs/perl_test/x86_64-conda_cos6-linux-gnu/sysroot "-I/home/hakon/anaconda3/envs/perl_test/lib/5.26.2/x86_64-linux-thread-multi/CORE"   Damn.c
rm -f blib/arch/auto/Acme/Damn/Damn.so
/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc  -shared -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,-rpath,/home/hakon/anaconda3/envs/perl_test/lib -L/home/hakon/anaconda3/envs/perl_test/lib --sysroot /home/hakon/anaconda3/envs/perl_test/x86_64-conda_cos6-linux-gnu/sysroot -fstack-protector-strong Damn.o  -o blib/arch/auto/Acme/Damn/Damn.so  \
      \
  
chmod 755 blib/arch/auto/Acme/Damn/Damn.so
Manifying 1 pod document


来源:https://stackoverflow.com/questions/65728942/how-to-make-perl-makefile-pl-use-a-given-c-compiler-when-compiling-an-xs-module

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!