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