Brought all packages under eye of strict, warnings and love of Carp, For
[sdlgit/SDL_perl.git] / make / lib / SDL / Build.pm
1 #
2 # Copyright (C) 2004 chromatic
3 # Copyright (C) 2004 David J. Goehrig
4 #
5
6 package SDL::Build;
7
8 use strict;
9 use warnings;
10 use Carp;
11 use base 'Module::Build';
12
13 use File::Spec;
14 use Data::Dumper;
15 use Config;
16
17 # Module::Build doesn't seem to have a way to use separate flags for separate
18 # XS files, so here's the override that makes separate files build correctly:
19 sub process_xs
20 {
21         my ($self, $file) = @_;
22
23         my $properties                   = $self->{properties};
24
25         my $file_args                    = $self->notes( 'file_flags' )->{$file};
26         my @old_values                   = @$properties{ keys %$file_args };
27         @$properties{ keys %$file_args } = values %$file_args;
28         $self->SUPER::process_xs( $file );
29         @$properties{ keys %$file_args } = @old_values;
30 }
31
32 # every platform has slightly different library and header paths
33 sub get_arch
34 {
35         my ($self, $os)   = @_;
36         my $modpath       = File::Spec->catfile(
37                 'SDL', 'Build', ucfirst( $os ) . '.pm' );
38         my $module        = 'SDL::Build::' . ucfirst( $os );
39
40         require $modpath or croak "No module for $os platform\n";
41
42         return $module;
43 }
44
45 # which headers are installed?
46 sub find_subsystems
47 {
48         my ($self, $subsystems, $libraries) = @_;
49         my %includes_libs                   = $self->fetch_includes();
50         my %enabled;
51
52         while ( my ($name, $subsystem) = each %$subsystems )
53         {
54                 for my $library (@{ $subsystem->{libraries} })
55                 {
56                         my $lib = $libraries->{$library}
57                                 or croak "Unknown library '$library' for '$name'\n";
58
59                         my ($inc_dir, $link_dir)   =
60                                 $self->find_header( $lib->{header}, \%includes_libs );
61                         $enabled{$name}{ $library } = $inc_dir ? [ $inc_dir, $link_dir ]
62                                 : 0;
63                 }
64         }
65
66         return \%enabled;
67 }
68
69 # set the define flags for the libraries we have
70 sub build_defines
71 {
72         my ($self, $libraries, $build_systems) = @_;
73
74         my %defines;
75
76         while (my ($subsystem, $buildable) = each %$build_systems)
77         {
78                 for my $build (grep { $buildable->{ $_ } } keys %$buildable)
79                 {
80                         push @{ $defines{ $subsystem } }, "-D$libraries->{$build}{define}";
81                 }
82         }
83
84         return \%defines;
85 }
86
87 # set the include paths for the libraries we have
88 sub build_includes
89 {
90         my ($self, $libraries, $build_systems) = @_;
91
92         my %includes;
93
94         while (my ($subsystem, $buildable) = each %$build_systems)
95         {
96                 my %sub_include;
97                 for my $build (grep { $buildable->{ $_ } } keys %$buildable)
98                 {
99                         $sub_include{ $buildable->{ $build }[0] }++;
100                 }
101
102                 $includes{ $subsystem } = [ map { "-I$_" } keys %sub_include ];
103         }
104
105         return \%includes;
106 }
107
108 # set the linker paths and flags for the libraries we have
109 sub build_links
110 {
111         my ($self, $libraries, $build_systems) = @_;
112
113         my %links;
114
115         while (my ($subsystem, $buildable) = each %$build_systems)
116         {
117                 my %sub_links;
118                 for my $build (grep { $buildable->{ $_ } } keys %$buildable)
119                 {
120                         $sub_links{ $buildable->{ $build }[1] }++;
121                         push @{ $links{ $subsystem }{libs} }, "-l$build";
122                 }
123
124                 $links{ $subsystem }{paths} = [ map { "-L$_" } keys %sub_links ];
125         }
126
127         return \%links;
128 }
129
130 # save this all in a format process_xs() can understand
131 sub set_flags
132 {
133         my ($self, $subsystems, $build, $defines, $includes, $links,
134             $sdl_compile, $sdl_link) = @_;
135
136         my %file_flags;
137
138         while (my ($subsystem, $buildable) = each %$build)
139         {
140                 my $sub_file     = $subsystems->{$subsystem}{file}{to};
141                 my $sub_includes = join(' ', @{ $includes->{$subsystem} } );
142
143                 $file_flags{ $sub_file } = 
144                 {
145                         extra_compiler_flags =>
146                         [
147                                 @{ $includes->{$subsystem} },
148                                 split(' ',$sdl_compile),
149                                 @{ $defines->{$subsystem} },
150                                 ( defined $Config{usethreads} ? ('-DUSE_THREADS', '-fPIC') : '-fPIC' ),
151                         ],
152                         extra_linker_flags => 
153                         [
154                                 @{ $links->{$subsystem}{paths} },
155                                 split(' ',$sdl_link),
156                                 @{ $links->{$subsystem}{libs} },
157                         ],
158                 },
159         }
160
161         $self->notes( 'file_flags' => \%file_flags );
162 }
163
164 # look for a header somewhere on the system
165 sub find_header
166 {
167         my ($self, $header, $includes) = @_;
168
169         for my $inc_dir (keys %$includes)
170         {
171                 next unless -e File::Spec->catfile( $inc_dir, $header );
172                 return ($inc_dir, $includes->{$inc_dir});
173         }
174 }
175
176 sub write_sdl_config
177 {
178         my ($self, $config) = @_;
179         my $path            = File::Spec->catfile(qw( lib SDL Config.pm ));
180         my $dd              = Data::Dumper->new( [ $config ], [ 'sdl_config' ] );
181         my $hash            = $dd->Dump();
182         (my $text           = <<'       END_HEADER' . $hash . <<'       END_FOOTER');
183         package SDL::Config;
184
185         my $sdl_config; 
186         END_HEADER
187
188         sub has
189         {
190                 my ($class, $define) = @_;
191                 scalar grep { $$sdl_config{$_}{$define} } keys %$sdl_config;
192         }
193
194         1;
195         END_FOOTER
196
197         $text =~ s/^\t//gm;
198
199         open my $file, '>', $path or croak "Cannot write to '$path': $!\n";
200         print $file $text;
201 }
202
203 1;