@@ -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,111 @@ 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
+ let patches: Vec < ( & str , & ' static str ) > = vec ! [
121
+ ( "SDL2-2.0.8-4234-mac-os-dylib-fix.patch" ,
122
+ include_str!( "patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch" ) ) ,
123
+ ] ;
124
+ let sdl_version = format ! ( "SDL2-{}" , LASTEST_SDL2_VERSION ) ;
125
+
126
+ for patch in & patches {
127
+ // Only apply patches that apply to the current version of SDL2
128
+ if !patch. 0 . starts_with ( & sdl_version) {
129
+ continue ;
130
+ }
131
+ let mut patch_set = unidiff:: PatchSet :: new ( ) ;
132
+ patch_set. parse ( patch. 1 ) . expect ( "Error parsing diff" ) ;
133
+
134
+ for modified_file in patch_set. modified_files ( ) {
135
+ use std:: io:: { Write , BufRead } ;
136
+
137
+ let file_path = sdl2_source_path. join ( modified_file. path ( ) ) ;
138
+ let old_path = sdl2_source_path. join ( format ! ( "{}_old" , modified_file. path( ) ) ) ;
139
+ fs:: rename ( & file_path, & old_path)
140
+ . expect ( & format ! (
141
+ "Rename of {} to {} failed" ,
142
+ file_path. to_string_lossy( ) ,
143
+ old_path. to_string_lossy( ) ) ) ;
144
+
145
+ let dst_file = fs:: File :: create ( file_path) . unwrap ( ) ;
146
+ let mut dst_buf = io:: BufWriter :: new ( dst_file) ;
147
+ let old_file = fs:: File :: open ( old_path) . unwrap ( ) ;
148
+ let mut old_buf = io:: BufReader :: new ( old_file) ;
149
+ let mut cursor = 0 ;
150
+
151
+ for ( i, hunk) in modified_file. into_iter ( ) . enumerate ( ) {
152
+ // Write old lines from cursor to the start of this hunk.
153
+ let num_lines = hunk. source_start - cursor - 1 ;
154
+ for _ in 0 ..num_lines {
155
+ let mut line = String :: new ( ) ;
156
+ old_buf. read_line ( & mut line) . unwrap ( ) ;
157
+ dst_buf. write_all ( line. as_bytes ( ) ) . unwrap ( ) ;
158
+ }
159
+ cursor += num_lines;
160
+
161
+ // Skip lines in old_file, and verify that what we expect to
162
+ // replace is present in the old_file.
163
+ for expected_line in hunk. source_lines ( ) {
164
+ let mut actual_line = String :: new ( ) ;
165
+ old_buf. read_line ( & mut actual_line) . unwrap ( ) ;
166
+ actual_line. pop ( ) ; // Remove the trailing newline.
167
+ if expected_line. value != actual_line {
168
+ panic ! ( "Can't apply patch; mismatch between expected and actual in hunk {}" , i) ;
169
+ }
170
+ }
171
+ cursor += hunk. source_length ;
172
+
173
+ // Write the new lines into the destination.
174
+ for line in hunk. target_lines ( ) {
175
+ dst_buf. write_all ( line. value . as_bytes ( ) ) . unwrap ( ) ;
176
+ dst_buf. write_all ( b"\n " ) . unwrap ( ) ;
177
+ }
178
+ }
179
+
180
+ // Write all remaining lines from the old file into the new.
181
+ for line in old_buf. lines ( ) {
182
+ dst_buf. write_all ( & line. unwrap ( ) . into_bytes ( ) ) . unwrap ( ) ;
183
+ dst_buf. write_all ( b"\n " ) . unwrap ( ) ;
184
+ }
185
+ }
186
+ // TODO: This is entirely untested code. There are likely bugs here, and
187
+ // this really should be part of the unidiff library, not a function
188
+ // defined here. Hopefully this gets moved somewhere else before it
189
+ // bites someone.
190
+ for removed_file in patch_set. removed_files ( ) {
191
+ fs:: remove_file ( sdl2_source_path. join ( removed_file. path ( ) ) )
192
+ . expect (
193
+ & format ! ( "Failed to remove file {} from {}" ,
194
+ removed_file. path( ) ,
195
+ sdl2_source_path. to_string_lossy( ) ) ) ;
196
+ }
197
+ // TODO: This is entirely untested code. There are likely bugs here, and
198
+ // this really should be part of the unidiff library, not a function
199
+ // defined here. Hopefully this gets moved somewhere else before it
200
+ // bites someone.
201
+ for added_file in patch_set. added_files ( ) {
202
+ use std:: io:: Write ;
203
+
204
+ // This should be superfluous. I don't know how a new file would
205
+ // ever have more than one hunk.
206
+ assert ! ( added_file. len( ) == 1 ) ;
207
+ let file_path = sdl2_source_path. join ( added_file. path ( ) ) ;
208
+ let mut dst_file = fs:: File :: create ( & file_path)
209
+ . expect ( & format ! (
210
+ "Failed to create file {}" ,
211
+ file_path. to_string_lossy( ) ) ) ;
212
+ let mut dst_buf = io:: BufWriter :: new ( & dst_file) ;
213
+
214
+ for line in added_file. into_iter ( ) . nth ( 0 ) . unwrap ( ) . target_lines ( ) {
215
+ dst_buf. write_all ( line. value . as_bytes ( ) ) . unwrap ( ) ;
216
+ dst_buf. write_all ( b"\n " ) . unwrap ( ) ;
217
+ }
218
+ }
219
+ }
220
+ }
221
+
115
222
// compile a shared or static lib depending on the feature
116
223
#[ cfg( feature = "bundled" ) ]
117
224
fn compile_sdl2 ( sdl2_build_path : & Path , target_os : & str ) -> PathBuf {
@@ -333,6 +440,7 @@ fn main() {
333
440
let sdl2_compiled_path: PathBuf ;
334
441
#[ cfg( feature = "bundled" ) ] {
335
442
let sdl2_source_path = download_sdl2 ( ) ;
443
+ patch_sdl2 ( sdl2_source_path. as_path ( ) ) ;
336
444
sdl2_compiled_path = compile_sdl2 ( sdl2_source_path. as_path ( ) , target_os) ;
337
445
338
446
let sdl2_downloaded_include_path = sdl2_source_path. join ( "include" ) ;
0 commit comments