Commit | Line | Data |
bfd90409 |
1 | #!/usr/bin/env perl |
2 | # |
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 |
29 | # |
30 | |
31 | package SDL::Build; |
32 | |
33 | use strict; |
34 | use base 'Module::Build'; |
35 | |
36 | use File::Spec; |
37 | use Data::Dumper; |
38 | use Config; |
39 | |
40 | # Module::Build doesn't seem to have a way to use separate flags for separate |
41 | # XS files, so here's the override that makes separate files build correctly: |
42 | sub process_xs |
43 | { |
44 | my ($self, $file) = @_; |
45 | |
46 | my $properties = $self->{properties}; |
47 | my $file_args = $self->notes( 'file_flags' )->{$file}; |
48 | my @old_values = @$properties{ keys %$file_args }; |
49 | @$properties{ keys %$file_args } = values %$file_args; |
50 | |
51 | $self->SUPER::process_xs( $file ); |
52 | @$properties{ keys %$file_args } = @old_values; |
53 | } |
54 | |
55 | |
56 | # every platform has slightly different library and header paths |
57 | sub get_arch |
58 | { |
59 | my ($self, $os) = @_; |
60 | my $modpath = File::Spec->catfile( |
61 | 'SDL', 'Build', ucfirst( $os ) . '.pm' ); |
62 | my $module = 'SDL::Build::' . ucfirst( $os ); |
63 | |
64 | require $modpath or die "No module for $os platform\n"; |
65 | |
66 | return $module; |
67 | } |
68 | |
69 | # which headers are installed? |
70 | sub find_subsystems |
71 | { |
72 | my ($self, $subsystems, $libraries) = @_; |
73 | my %includes_libs = $self->fetch_includes(); |
74 | my %enabled; |
75 | |
76 | while ( my ($name, $subsystem) = each %$subsystems ) |
77 | { |
78 | for my $library (@{ $subsystem->{libraries} }) |
79 | { |
80 | my $lib = $libraries->{$library} |
81 | or die "Unknown library '$library' for '$name'\n"; |
82 | |
83 | my ($inc_dir, $link_dir) = |
84 | $self->find_header( $lib->{header}, \%includes_libs ); |
85 | $enabled{$name}{ $library } = $inc_dir ? [ $inc_dir, $link_dir ] |
86 | : 0; |
87 | } |
88 | } |
89 | |
90 | return \%enabled; |
91 | } |
92 | |
93 | # set the define flags for the libraries we have |
94 | sub build_defines |
95 | { |
96 | my ($self, $libraries, $build_systems) = @_; |
97 | |
98 | my %defines; |
99 | |
100 | while (my ($subsystem, $buildable) = each %$build_systems) |
101 | { |
102 | for my $build (grep { $buildable->{ $_ } } keys %$buildable) |
103 | { |
104 | push @{ $defines{ $subsystem } }, "-D$libraries->{$build}{define}"; |
105 | } |
106 | } |
107 | |
108 | return \%defines; |
109 | } |
110 | |
111 | # set the include paths for the libraries we have |
112 | sub build_includes |
113 | { |
114 | my ($self, $libraries, $build_systems) = @_; |
115 | |
116 | my %includes; |
117 | |
118 | while (my ($subsystem, $buildable) = each %$build_systems) |
119 | { |
120 | my %sub_include; |
121 | for my $build (grep { $buildable->{ $_ } } keys %$buildable) |
122 | { |
123 | $sub_include{ $buildable->{ $build }[0] }++; |
124 | } |
125 | |
126 | $includes{ $subsystem } = [ map { "-I$_" } keys %sub_include ]; |
127 | } |
128 | |
129 | return \%includes; |
130 | } |
131 | |
132 | # set the linker paths and flags for the libraries we have |
133 | sub build_links |
134 | { |
135 | my ($self, $libraries, $build_systems) = @_; |
136 | |
137 | my %links; |
138 | |
139 | while (my ($subsystem, $buildable) = each %$build_systems) |
140 | { |
141 | my %sub_links; |
142 | for my $build (grep { $buildable->{ $_ } } keys %$buildable) |
143 | { |
144 | $sub_links{ $buildable->{ $build }[1] }++; |
145 | push @{ $links{ $subsystem }{libs} }, "-l$build"; |
146 | } |
147 | |
148 | $links{ $subsystem }{paths} = [ map { "-L$_" } keys %sub_links ]; |
149 | } |
150 | |
151 | return \%links; |
152 | } |
153 | |
154 | # save this all in a format process_xs() can understand |
155 | sub set_flags |
156 | { |
157 | my ($self, $subsystems, $build, $defines, $includes, $links, |
158 | $sdl_compile, $sdl_link) = @_; |
159 | |
160 | my %file_flags; |
161 | |
162 | while (my ($subsystem, $buildable) = each %$build) |
163 | { |
164 | my $sub_file = $subsystems->{$subsystem}{file}{to}; |
165 | my $sub_includes = join(' ', @{ $includes->{$subsystem} } ); |
166 | |
167 | $file_flags{ $sub_file } = |
168 | { |
169 | extra_compiler_flags => |
170 | [ |
171 | @{ $includes->{$subsystem} }, |
172 | split(' ',$sdl_compile), |
173 | @{ $defines->{$subsystem} }, |
174 | ( defined $Config{usethreads} ? ('-DUSE_THREADS', '-fPIC') : ('-fPIC' )), |
175 | ], |
176 | extra_linker_flags => |
177 | [ |
178 | @{ $links->{$subsystem}{paths} }, |
179 | split(' ',$sdl_link), |
180 | @{ $links->{$subsystem}{libs} }, |
181 | ], |
182 | }, |
183 | } |
184 | |
185 | $self->notes( 'file_flags' => \%file_flags ); |
186 | } |
187 | |
188 | # look for a header somewhere on the system |
189 | sub find_header |
190 | { |
191 | my ($self, $header, $includes) = @_; |
192 | |
193 | for my $inc_dir (keys %$includes) |
194 | { |
195 | next unless -e File::Spec->catfile( $inc_dir, $header ); |
196 | return ($inc_dir, $includes->{$inc_dir}); |
197 | } |
198 | } |
199 | |
200 | sub write_sdl_config |
201 | { |
202 | my ($self, $config) = @_; |
203 | my $path = File::Spec->catfile(qw( lib SDL Config.pm )); |
204 | my $dd = Data::Dumper->new( [ $config ], [ 'sdl_config' ] ); |
205 | my $hash = $dd->Dump(); |
206 | (my $text = <<' END_HEADER' . $hash . <<' END_FOOTER'); |
207 | package SDL::Config; |
208 | |
209 | my $sdl_config; |
210 | END_HEADER |
211 | |
212 | sub has |
213 | { |
214 | my ($class, $define) = @_; |
215 | scalar grep { $$sdl_config{$_}{$define} } keys %$sdl_config; |
216 | } |
217 | |
218 | 1; |
219 | END_FOOTER |
220 | |
221 | $text =~ s/^\t//gm; |
222 | |
223 | open my $file, '>', $path or die "Cannot write to '$path': $!\n"; |
224 | print $file $text; |
225 | } |
226 | |
227 | # Subclass Darwin to build Objective-C addons |
228 | |
229 | sub filter_support { |
230 | my $self = shift; |
231 | print STDERR "[SDL::Build] generic filter\n"; |
232 | return (); |
233 | } |
234 | |
235 | sub process_support_files { |
236 | my $self = shift; |
237 | my $p = $self->{properties}; |
238 | return unless $p->{c_source}; |
239 | return unless $p->{c_sources}; |
240 | |
241 | push @{$p->{include_dirs}}, $p->{c_source}; |
242 | unless ( $p->{extra_compiler_flags} && $p->{extra_compiler_flags} =~ /DARCHNAME/) { |
243 | $p->{extra_compiler_flags} .= " -DARCHNAME=" . $self->{config}{archname}; |
244 | } |
245 | print STDERR "[SDL::Build] extra compiler flags" . $p->{extra_compiler_flags} . "\n"; |
246 | |
247 | foreach my $file (map($p->{c_source} . "/$_", @{$p->{c_sources}})) { |
248 | push @{$p->{objects}}, $self->compile_c($file); |
249 | } |
250 | } |
251 | |
252 | # Override to create a MacOS Bundle |
253 | sub build_bundle |
254 | { |
255 | return; |
256 | } |
257 | |
258 | # Override Install method for darwin |
259 | sub ACTION_install { |
260 | my ($self) = @_; |
261 | require ExtUtils::Install; |
262 | $self->depends_on('build'); |
263 | $self->get_arch($^O)->build_bundle(); |
264 | ExtUtils::Install::install($self->install_map, 1, 0, $self->{args}{uninst}||0); |
265 | } |
266 | |
267 | 1; |