@@ -12,6 +12,8 @@ extern crate tar;
1212extern crate flate2;
1313#[ cfg( feature="bundled" ) ]
1414extern crate reqwest;
15+ #[ cfg( feature="bundled" ) ]
16+ extern crate unidiff;
1517
1618#[ macro_use]
1719extern crate cfg_if;
@@ -112,6 +114,111 @@ fn download_sdl2() -> PathBuf {
112114 sdl2_build_path
113115}
114116
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+
115222// compile a shared or static lib depending on the feature
116223#[ cfg( feature = "bundled" ) ]
117224fn compile_sdl2 ( sdl2_build_path : & Path , target_os : & str ) -> PathBuf {
@@ -333,6 +440,7 @@ fn main() {
333440 let sdl2_compiled_path: PathBuf ;
334441 #[ cfg( feature = "bundled" ) ] {
335442 let sdl2_source_path = download_sdl2 ( ) ;
443+ patch_sdl2 ( sdl2_source_path. as_path ( ) ) ;
336444 sdl2_compiled_path = compile_sdl2 ( sdl2_source_path. as_path ( ) , target_os) ;
337445
338446 let sdl2_downloaded_include_path = sdl2_source_path. join ( "include" ) ;
0 commit comments