1 package ExtUtils::CBuilder::Base;
11 $VERSION = eval $VERSION;
15 my $self = bless {@_}, $class;
17 $self->{properties}{perl} = $class->find_perl_interpreter
18 or warn "Warning: Can't locate your perl binary";
20 while (my ($k,$v) = each %Config) {
21 $self->{config}{$k} = $v unless exists $self->{config}{$k};
26 sub find_perl_interpreter {
28 File::Spec->file_name_is_absolute($perl = $^X)
29 or -f ($perl = $Config::Config{perlpath})
36 my %files = map {$_, 1} @_;
40 my ($self, $filename) = @_;
42 # File name, minus the suffix
43 (my $file_base = $filename) =~ s/\.[^.]+$//;
44 return "$file_base$self->{config}{obj_ext}";
47 sub arg_include_dirs {
49 return map {"-I$_"} @_;
52 sub arg_nolink { '-c' }
55 my ($self, $file) = @_;
59 sub arg_share_object_file {
60 my ($self, $file) = @_;
61 return ($self->split_like_shell($self->{config}{lddlflags}), '-o', $file);
65 my ($self, $file) = @_;
70 my ($self, %args) = @_;
71 die "Missing 'source' argument to compile()" unless defined $args{source};
73 my $cf = $self->{config}; # For convenience
75 $args{object_file} ||= $self->object_file($args{source});
77 my @include_dirs = $self->arg_include_dirs
78 (@{$args{include_dirs} || []},
81 my @extra_compiler_flags = $self->split_like_shell($args{extra_compiler_flags});
82 my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
83 my @ccflags = $self->split_like_shell($cf->{ccflags});
84 my @optimize = $self->split_like_shell($cf->{optimize});
85 my @flags = (@include_dirs, @cccdlflags, @extra_compiler_flags,
88 $self->arg_object_file($args{object_file}),
91 my @cc = $self->split_like_shell($cf->{cc});
93 $self->do_system(@cc, @flags, $args{source})
94 or die "error building $args{object_file} from '$args{source}'";
96 return $args{object_file};
101 return $self->{have_compiler} if defined $self->{have_compiler};
103 my $tmpfile = File::Spec->catfile(File::Spec->tmpdir, 'compilet.c');
106 open FH, "> $tmpfile" or die "Can't create $tmpfile: $!";
107 print FH "int boot_compilet() { return 1; }\n";
111 my ($obj_file, @lib_files);
113 $obj_file = $self->compile(source => $tmpfile);
114 @lib_files = $self->link(objects => $obj_file, module_name => 'compilet');
117 my $result = $self->{have_compiler} = $@ ? 0 : 1;
119 foreach (grep defined, $tmpfile, $obj_file, @lib_files) {
126 my ($self, $dl_file) = @_;
127 $dl_file =~ s/\.[^.]+$//;
129 return "$dl_file.$self->{config}{dlext}";
134 my ($self, $dl_file) = @_;
135 $dl_file =~ s/\.[^.]+$//;
137 return "$dl_file$self->{config}{_exe}";
140 sub need_prelink { 0 }
143 my ($self, %args) = @_;
145 ($args{dl_file} = $args{dl_name}) =~ s/.*::// unless $args{dl_file};
147 require ExtUtils::Mksymlists;
148 ExtUtils::Mksymlists::Mksymlists( # dl. abbrev for dynamic library
149 DL_VARS => $args{dl_vars} || [],
150 DL_FUNCS => $args{dl_funcs} || {},
151 FUNCLIST => $args{dl_func_list} || [],
152 IMPORTS => $args{dl_imports} || {},
153 NAME => $args{dl_name},
154 DLBASE => $args{dl_base},
155 FILE => $args{dl_file},
158 # Mksymlists will create one of these files
159 return grep -e, map "$args{dl_file}.$_", qw(ext def opt);
163 my ($self, %args) = @_;
164 return $self->_do_link('lib_file', lddl => 1, %args);
167 sub link_executable {
168 my ($self, %args) = @_;
169 return $self->_do_link('exe_file', lddl => 0, %args);
173 my ($self, $type, %args) = @_;
175 my $cf = $self->{config}; # For convenience
177 my $objects = delete $args{objects};
178 $objects = [$objects] unless ref $objects;
179 my $out = $args{$type} || $self->$type($objects->[0]);
183 $self->prelink(%args,
184 dl_name => $args{module_name}) if $self->need_prelink;
186 my @linker_flags = $self->split_like_shell($args{extra_linker_flags});
187 my @output = $args{lddl} ? $self->arg_share_object_file($out) : $self->arg_exec_file($out);
188 my @shrp = $self->split_like_shell($cf->{shrpenv});
189 my @ld = $self->split_like_shell($cf->{ld});
190 $self->do_system(@shrp, @ld, @output, @$objects, @linker_flags)
191 or die "error building $out from @$objects";
193 return wantarray ? ($out, @temp_files) : $out;
198 my ($self, @cmd) = @_;
199 print "@cmd\n" if !$self->{quiet};
200 return !system(@cmd);
203 sub split_like_shell {
204 my ($self, $string) = @_;
206 return () unless defined($string);
207 return @$string if UNIVERSAL::isa($string, 'ARRAY');
208 $string =~ s/^\s+|\s+$//g;
209 return () unless length($string);
211 return Text::ParseWords::shellwords($string);
214 # if building perl, perl's main source directory
216 # N.B. makemaker actually searches regardless of PERL_CORE, but
217 # only squawks at not finding it if PERL_CORE is set
219 if ($ENV{PERL_CORE}) {
220 my $Updir = File::Spec->updir;
222 foreach $dir ($Updir,
223 File::Spec->catdir($Updir,$Updir),
224 File::Spec->catdir($Updir,$Updir,$Updir),
225 File::Spec->catdir($Updir,$Updir,$Updir,$Updir),
226 File::Spec->catdir($Updir,$Updir,$Updir,$Updir,$Updir))
229 -f File::Spec->catfile($dir,"config_h.SH")
231 -f File::Spec->catfile($dir,"perl.h")
233 -f File::Spec->catfile($dir,"lib","Exporter.pm")
239 warn "PERL_CORE is set but I can't find your perl source!\n";
245 # directory of perl's include files
249 $self->perl_src() || File::Spec->catdir($self->{config}{archlibexp},"CORE");