@@ -12,6 +12,8 @@ extern crate tar;
12
12
extern crate flate2;
13
13
#[ cfg( feature="bundled" ) ]
14
14
extern crate reqwest;
15
+ #[ cfg( feature="bundled" ) ]
16
+ extern crate unidiff;
15
17
16
18
#[ macro_use]
17
19
extern crate cfg_if;
@@ -112,6 +114,126 @@ fn download_sdl2() -> PathBuf {
112
114
sdl2_build_path
113
115
}
114
116
117
+ // apply patches to sdl2 source
118
+ #[ cfg( feature = "bundled" ) ]
119
+ fn patch_sdl2 ( sdl2_source_path : & Path ) {
120
+ // vector of <(patch_file_name, patch_file_contents)>
121
+ let patches: Vec < ( & str , & ' static str ) > = vec ! [
122
+ // This patch fixes a CMake installation bug introduced in SDL2 2.0.4 on
123
+ // the Mac OS platform. Without this patch, the libSDL2.dylib generated
124
+ // during the SDL2 build phase will be overwritten by a symlink pointing
125
+ // to nothing. A variation of this patch was accepted upstream and
126
+ // should be included in SDL2 2.0.9.
127
+ // https://bugzilla.libsdl.org/show_bug.cgi?id=4234
128
+ ( "SDL2-2.0.8-4234-mac-os-dylib-fix.patch" , include_str!( "patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch" ) ) ,
129
+ ] ;
130
+ let sdl_version = format ! ( "SDL2-{}" , LASTEST_SDL2_VERSION ) ;
131
+
132
+ for patch in & patches {
133
+ // Only apply patches whose file name is prefixed with the currently
134
+ // targeted version of SDL2.
135
+ if !patch. 0 . starts_with ( & sdl_version) {
136
+ continue ;
137
+ }
138
+ let mut patch_set = unidiff:: PatchSet :: new ( ) ;
139
+ patch_set. parse ( patch. 1 ) . expect ( "Error parsing diff" ) ;
140
+
141
+ // For every modified file, copy the existing file to <file_name>_old,
142
+ // open a new copy of <file_name>. and fill the new file with a
143
+ // combination of the unmodified contents, and the patched sections.
144
+ // TOOD: This code is untested (save for the immediate application), and
145
+ // probably belongs in the unidiff (or similar) package.
146
+ for modified_file in patch_set. modified_files ( ) {
147
+ use std:: io:: { Write , BufRead } ;
148
+
149
+ let file_path = sdl2_source_path. join ( modified_file. path ( ) ) ;
150
+ let old_path = sdl2_source_path. join ( format ! ( "{}_old" , modified_file. path( ) ) ) ;
151
+ fs:: rename ( & file_path, & old_path)
152
+ . expect ( & format ! (
153
+ "Rename of {} to {} failed" ,
154
+ file_path. to_string_lossy( ) ,
155
+ old_path. to_string_lossy( ) ) ) ;
156
+
157
+ let dst_file = fs:: File :: create ( file_path) . unwrap ( ) ;
158
+ let mut dst_buf = io:: BufWriter :: new ( dst_file) ;
159
+ let old_file = fs:: File :: open ( old_path) . unwrap ( ) ;
160
+ let mut old_buf = io:: BufReader :: new ( old_file) ;
161
+ let mut cursor = 0 ;
162
+
163
+ for ( i, hunk) in modified_file. into_iter ( ) . enumerate ( ) {
164
+ // Write old lines from cursor to the start of this hunk.
165
+ let num_lines = hunk. source_start - cursor - 1 ;
166
+ for _ in 0 ..num_lines {
167
+ let mut line = String :: new ( ) ;
168
+ old_buf. read_line ( & mut line) . unwrap ( ) ;
169
+ dst_buf. write_all ( line. as_bytes ( ) ) . unwrap ( ) ;
170
+ }
171
+ cursor += num_lines;
172
+
173
+ // Skip lines in old_file, and verify that what we expect to
174
+ // replace is present in the old_file.
175
+ for expected_line in hunk. source_lines ( ) {
176
+ let mut actual_line = String :: new ( ) ;
177
+ old_buf. read_line ( & mut actual_line) . unwrap ( ) ;
178
+ actual_line. pop ( ) ; // Remove the trailing newline.
179
+ if expected_line. value != actual_line {
180
+ panic ! ( "Can't apply patch; mismatch between expected and actual in hunk {}" , i) ;
181
+ }
182
+ }
183
+ cursor += hunk. source_length ;
184
+
185
+ // Write the new lines into the destination.
186
+ for line in hunk. target_lines ( ) {
187
+ dst_buf. write_all ( line. value . as_bytes ( ) ) . unwrap ( ) ;
188
+ dst_buf. write_all ( b"\n " ) . unwrap ( ) ;
189
+ }
190
+ }
191
+
192
+ // Write all remaining lines from the old file into the new.
193
+ for line in old_buf. lines ( ) {
194
+ dst_buf. write_all ( & line. unwrap ( ) . into_bytes ( ) ) . unwrap ( ) ;
195
+ dst_buf. write_all ( b"\n " ) . unwrap ( ) ;
196
+ }
197
+ }
198
+ // For every removed file, simply delete the original.
199
+ // TODO: This is entirely untested code. There are likely bugs here, and
200
+ // this really should be part of the unidiff library, not a function
201
+ // defined here. Hopefully this gets moved somewhere else before it
202
+ // bites someone.
203
+ for removed_file in patch_set. removed_files ( ) {
204
+ fs:: remove_file ( sdl2_source_path. join ( removed_file. path ( ) ) )
205
+ . expect (
206
+ & format ! ( "Failed to remove file {} from {}" ,
207
+ removed_file. path( ) ,
208
+ sdl2_source_path. to_string_lossy( ) ) ) ;
209
+ }
210
+ // For every new file, copy the entire contents of the patched file into
211
+ // a newly created <file_name>.
212
+ // TODO: This is entirely untested code. There are likely bugs here, and
213
+ // this really should be part of the unidiff library, not a function
214
+ // defined here. Hopefully this gets moved somewhere else before it
215
+ // bites someone.
216
+ for added_file in patch_set. added_files ( ) {
217
+ use std:: io:: Write ;
218
+
219
+ // This should be superfluous. I don't know how a new file would
220
+ // ever have more than one hunk.
221
+ assert ! ( added_file. len( ) == 1 ) ;
222
+ let file_path = sdl2_source_path. join ( added_file. path ( ) ) ;
223
+ let mut dst_file = fs:: File :: create ( & file_path)
224
+ . expect ( & format ! (
225
+ "Failed to create file {}" ,
226
+ file_path. to_string_lossy( ) ) ) ;
227
+ let mut dst_buf = io:: BufWriter :: new ( & dst_file) ;
228
+
229
+ for line in added_file. into_iter ( ) . nth ( 0 ) . unwrap ( ) . target_lines ( ) {
230
+ dst_buf. write_all ( line. value . as_bytes ( ) ) . unwrap ( ) ;
231
+ dst_buf. write_all ( b"\n " ) . unwrap ( ) ;
232
+ }
233
+ }
234
+ }
235
+ }
236
+
115
237
// compile a shared or static lib depending on the feature
116
238
#[ cfg( feature = "bundled" ) ]
117
239
fn compile_sdl2 ( sdl2_build_path : & Path , target_os : & str ) -> PathBuf {
@@ -333,6 +455,7 @@ fn main() {
333
455
let sdl2_compiled_path: PathBuf ;
334
456
#[ cfg( feature = "bundled" ) ] {
335
457
let sdl2_source_path = download_sdl2 ( ) ;
458
+ patch_sdl2 ( sdl2_source_path. as_path ( ) ) ;
336
459
sdl2_compiled_path = compile_sdl2 ( sdl2_source_path. as_path ( ) , target_os) ;
337
460
338
461
let sdl2_downloaded_include_path = sdl2_source_path. join ( "include" ) ;
0 commit comments