Commit | Line | Data |
7b6a53a1 |
1 | #!/usr/bin/env perl |
8fde61e3 |
2 | # |
7b6a53a1 |
3 | # Build.pm |
4 | # |
5 | # Copyright (C) 2005 David J. Goehrig <dgoehrig@cpan.org> |
6 | # |
7 | # ------------------------------------------------------------------------------ |
8 | # |
9 | # This library is free software; you can redistribute it and/or |
10 | # modify it under the terms of the GNU Lesser General Public |
11 | # License as published by the Free Software Foundation; either |
12 | # version 2.1 of the License, or (at your option) any later version. |
13 | # |
14 | # This library is distributed in the hope that it will be useful, |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | # Lesser General Public License for more details. |
18 | # |
19 | # You should have received a copy of the GNU Lesser General Public |
20 | # License along with this library; if not, write to the Free Software |
21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | # |
23 | # ------------------------------------------------------------------------------ |
24 | # |
25 | # Please feel free to send questions, suggestions or improvements to: |
26 | # |
27 | # David J. Goehrig |
28 | # dgoehrig@cpan.org |
8fde61e3 |
29 | # |
30 | |
31 | package SDL::Build; |
32 | |
33 | use strict; |
084b921f |
34 | use warnings; |
35 | use Carp; |
8fde61e3 |
36 | use base 'Module::Build'; |
37 | |
38 | use File::Spec; |
39 | use Data::Dumper; |
40 | use Config; |
41 | |
42 | # Module::Build doesn't seem to have a way to use separate flags for separate |
43 | # XS files, so here's the override that makes separate files build correctly: |
44 | sub process_xs |
45 | { |
46 | my ($self, $file) = @_; |
8fde61e3 |
47 | my $properties = $self->{properties}; |
e00a4871 |
48 | |
8fde61e3 |
49 | my $file_args = $self->notes( 'file_flags' )->{$file}; |
7b6a53a1 |
50 | |
8fde61e3 |
51 | my @old_values = @$properties{ keys %$file_args }; |
52 | @$properties{ keys %$file_args } = values %$file_args; |
8fde61e3 |
53 | $self->SUPER::process_xs( $file ); |
54 | @$properties{ keys %$file_args } = @old_values; |
7b6a53a1 |
55 | |
8fde61e3 |
56 | } |
57 | |
58 | # every platform has slightly different library and header paths |
59 | sub get_arch |
60 | { |
61 | my ($self, $os) = @_; |
62 | my $modpath = File::Spec->catfile( |
63 | 'SDL', 'Build', ucfirst( $os ) . '.pm' ); |
64 | my $module = 'SDL::Build::' . ucfirst( $os ); |
65 | |
084b921f |
66 | require $modpath or croak "No module for $os platform\n"; |
8fde61e3 |
67 | |
68 | return $module; |
69 | } |
70 | |
71 | # which headers are installed? |
72 | sub find_subsystems |
73 | { |
74 | my ($self, $subsystems, $libraries) = @_; |
75 | my %includes_libs = $self->fetch_includes(); |
76 | my %enabled; |
77 | |
78 | while ( my ($name, $subsystem) = each %$subsystems ) |
79 | { |
80 | for my $library (@{ $subsystem->{libraries} }) |
81 | { |
82 | my $lib = $libraries->{$library} |
084b921f |
83 | or croak "Unknown library '$library' for '$name'\n"; |
8fde61e3 |
84 | |
85 | my ($inc_dir, $link_dir) = |
86 | $self->find_header( $lib->{header}, \%includes_libs ); |
87 | $enabled{$name}{ $library } = $inc_dir ? [ $inc_dir, $link_dir ] |
88 | : 0; |
89 | } |
90 | } |
91 | |
92 | return \%enabled; |
93 | } |
94 | |
95 | # set the define flags for the libraries we have |
96 | sub build_defines |
97 | { |
98 | my ($self, $libraries, $build_systems) = @_; |
99 | |
100 | my %defines; |
101 | |
102 | while (my ($subsystem, $buildable) = each %$build_systems) |
103 | { |
104 | for my $build (grep { $buildable->{ $_ } } keys %$buildable) |
105 | { |
106 | push @{ $defines{ $subsystem } }, "-D$libraries->{$build}{define}"; |
107 | } |
108 | } |
109 | |
110 | return \%defines; |
111 | } |
112 | |
113 | # set the include paths for the libraries we have |
114 | sub build_includes |
115 | { |
116 | my ($self, $libraries, $build_systems) = @_; |
117 | |
118 | my %includes; |
119 | |
120 | while (my ($subsystem, $buildable) = each %$build_systems) |
121 | { |
122 | my %sub_include; |
123 | for my $build (grep { $buildable->{ $_ } } keys %$buildable) |
124 | { |
125 | $sub_include{ $buildable->{ $build }[0] }++; |
126 | } |
127 | |
128 | $includes{ $subsystem } = [ map { "-I$_" } keys %sub_include ]; |
129 | } |
130 | |
131 | return \%includes; |
132 | } |
133 | |
134 | # set the linker paths and flags for the libraries we have |
135 | sub build_links |
136 | { |
137 | my ($self, $libraries, $build_systems) = @_; |
138 | |
139 | my %links; |
140 | |
141 | while (my ($subsystem, $buildable) = each %$build_systems) |
142 | { |
143 | my %sub_links; |
144 | for my $build (grep { $buildable->{ $_ } } keys %$buildable) |
145 | { |
146 | $sub_links{ $buildable->{ $build }[1] }++; |
147 | push @{ $links{ $subsystem }{libs} }, "-l$build"; |
148 | } |
149 | |
150 | $links{ $subsystem }{paths} = [ map { "-L$_" } keys %sub_links ]; |
151 | } |
152 | |
153 | return \%links; |
154 | } |
155 | |
156 | # save this all in a format process_xs() can understand |
157 | sub set_flags |
158 | { |
159 | my ($self, $subsystems, $build, $defines, $includes, $links, |
160 | $sdl_compile, $sdl_link) = @_; |
161 | |
162 | my %file_flags; |
163 | |
164 | while (my ($subsystem, $buildable) = each %$build) |
165 | { |
166 | my $sub_file = $subsystems->{$subsystem}{file}{to}; |
167 | my $sub_includes = join(' ', @{ $includes->{$subsystem} } ); |
168 | |
169 | $file_flags{ $sub_file } = |
170 | { |
171 | extra_compiler_flags => |
172 | [ |
173 | @{ $includes->{$subsystem} }, |
174 | split(' ',$sdl_compile), |
175 | @{ $defines->{$subsystem} }, |
7b6a53a1 |
176 | ( defined $Config{usethreads} ? ('-DUSE_THREADS', '-fPIC') : ('-fPIC' )), |
8fde61e3 |
177 | ], |
178 | extra_linker_flags => |
179 | [ |
180 | @{ $links->{$subsystem}{paths} }, |
181 | split(' ',$sdl_link), |
182 | @{ $links->{$subsystem}{libs} }, |
183 | ], |
184 | }, |
185 | } |
186 | |
187 | $self->notes( 'file_flags' => \%file_flags ); |
188 | } |
189 | |
190 | # look for a header somewhere on the system |
191 | sub find_header |
192 | { |
193 | my ($self, $header, $includes) = @_; |
194 | |
195 | for my $inc_dir (keys %$includes) |
196 | { |
197 | next unless -e File::Spec->catfile( $inc_dir, $header ); |
198 | return ($inc_dir, $includes->{$inc_dir}); |
199 | } |
200 | } |
201 | |
202 | sub write_sdl_config |
203 | { |
204 | my ($self, $config) = @_; |
205 | my $path = File::Spec->catfile(qw( lib SDL Config.pm )); |
206 | my $dd = Data::Dumper->new( [ $config ], [ 'sdl_config' ] ); |
207 | my $hash = $dd->Dump(); |
208 | (my $text = <<' END_HEADER' . $hash . <<' END_FOOTER'); |
209 | package SDL::Config; |
210 | |
211 | my $sdl_config; |
212 | END_HEADER |
213 | |
214 | sub has |
215 | { |
216 | my ($class, $define) = @_; |
217 | scalar grep { $$sdl_config{$_}{$define} } keys %$sdl_config; |
218 | } |
219 | |
220 | 1; |
221 | END_FOOTER |
222 | |
223 | $text =~ s/^\t//gm; |
224 | |
084b921f |
225 | open my $file, '>', $path or croak "Cannot write to '$path': $!\n"; |
8fde61e3 |
226 | print $file $text; |
227 | } |
228 | |
7b6a53a1 |
229 | # Subclass Darwin to build Objective-C addons |
230 | |
231 | sub filter_support { |
232 | my $self = shift; |
233 | print STDERR "[SDL::Build] generic filter\n"; |
234 | return (); |
235 | } |
236 | |
237 | sub process_support_files { |
238 | my $self = shift; |
239 | my $p = $self->{properties}; |
240 | return unless $p->{c_source}; |
241 | return unless $p->{c_sources}; |
242 | |
243 | push @{$p->{include_dirs}}, $p->{c_source}; |
244 | unless ( $p->{extra_compiler_flags} && $p->{extra_compiler_flags} =~ /DARCHNAME/) { |
245 | $p->{extra_compiler_flags} .= " -DARCHNAME=" . $self->{config}{archname}; |
246 | } |
247 | print STDERR "[SDL::Build] extra compiler flags" . $p->{extra_compiler_flags} . "\n"; |
248 | |
249 | foreach my $file (map($p->{c_source} . "/$_", @{$p->{c_sources}})) { |
250 | push @{$p->{objects}}, $self->compile_c($file); |
251 | } |
252 | } |
253 | |
254 | # Override to create a MacOS Bundle |
255 | sub build_bundle |
256 | { |
257 | return; |
258 | } |
259 | |
260 | # Override Install method for darwin |
261 | sub ACTION_install { |
262 | my ($self) = @_; |
263 | require ExtUtils::Install; |
264 | $self->depends_on('build'); |
265 | $self->get_arch($^O)->build_bundle(); |
266 | ExtUtils::Install::install($self->install_map, 1, 0, $self->{args}{uninst}||0); |
267 | } |
268 | |
8fde61e3 |
269 | 1; |