如何让 perl Makefile.PL 在编译 XS 模块时使用给定的 C 编译器?
How to make perl Makefile.PL use a given C compiler when compiling an XS module?
我正在尝试构建 Acme::Damn using a pre-compiled perl
downloaded with conda, see this 问题以获取详细信息。用于构建 perl
的 cc
由以下给出:
$ perl -V | grep cc=./
cc='/tmp/build/80754af9/perl_1527832170752/_build_env/bin/x86_64-conda_cos6-linux-gnu-gcc'
我的机器上不存在,因此 make
失败:
$ 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
我可以安装用于使用 conda 构建 perl 的相同编译器:
$ 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
如何让 perl Makefile.PL
在生成 Makefile
时将其用作编译器位置?我试过了:
CC=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc perl Makefile.PL
但这不起作用。
Makefile.PL
采用参数,而不是环境变量。
perl Makefile.PL CC=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc
修复 Config.pm
以指向正确的位置。
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 )"
这会导致 perl -V:cc
显示更新后的路径。
cc
也在 Config_heavy.pl
中定义。因此,您可能还需要以下内容:
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 )"
通过查看 Config_heavy.pl
,我可以看到比 cc
更多的配置变量可能也需要更新,包括 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
, 和 xlibpth
.
根据@ikegami的回答,我写了下面的Perl脚本来修改Config.pm
和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";
}
在 conda 环境中 运行 以上脚本之后,我可以编译模块:
$ 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
我正在尝试构建 Acme::Damn using a pre-compiled perl
downloaded with conda, see this 问题以获取详细信息。用于构建 perl
的 cc
由以下给出:
$ perl -V | grep cc=./
cc='/tmp/build/80754af9/perl_1527832170752/_build_env/bin/x86_64-conda_cos6-linux-gnu-gcc'
我的机器上不存在,因此 make
失败:
$ 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
我可以安装用于使用 conda 构建 perl 的相同编译器:
$ 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
如何让 perl Makefile.PL
在生成 Makefile
时将其用作编译器位置?我试过了:
CC=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc perl Makefile.PL
但这不起作用。
Makefile.PL
采用参数,而不是环境变量。
perl Makefile.PL CC=/home/hakon/anaconda3/envs/perl_test/bin/x86_64-conda_cos6-linux-gnu-gcc
修复 Config.pm
以指向正确的位置。
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 )"
这会导致 perl -V:cc
显示更新后的路径。
cc
也在 Config_heavy.pl
中定义。因此,您可能还需要以下内容:
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 )"
通过查看 Config_heavy.pl
,我可以看到比 cc
更多的配置变量可能也需要更新,包括 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
, 和 xlibpth
.
根据@ikegami的回答,我写了下面的Perl脚本来修改Config.pm
和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";
}
在 conda 环境中 运行 以上脚本之后,我可以编译模块:
$ 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