Skip to content

Commit 53e7fb8

Browse files
authored
Merge branch 'master' into master
2 parents e5100d1 + ef36bb8 commit 53e7fb8

File tree

5 files changed

+259
-45
lines changed

5 files changed

+259
-45
lines changed

scripts/travis-install-sdl2.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tar xzf sdl2.tar.gz
77
pushd SDL2-* && ./configure && make && sudo make install && popd
88
wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz
99
wget -q https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz
10-
wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz
10+
wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.2.tar.gz
1111
wget -q -O SDL2_gfx-1.0.1.tar.gz https://sourceforge.net/projects/sdl2gfx/files/SDL2_gfx-1.0.1.tar.gz/download
1212
tar xzf SDL2_ttf-*.tar.gz
1313
tar xzf SDL2_image-*.tar.gz

sdl2-sys/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ optional = true
3939
version = "0.2"
4040
optional = true
4141

42+
[build-dependencies.unidiff]
43+
version = "0.2.1"
44+
optional = true
45+
4246
[build-dependencies]
4347
cfg-if = "0.1"
4448

@@ -49,7 +53,7 @@ use-pkgconfig = ["pkg-config"]
4953
use-bindgen = ["bindgen"]
5054
static-link = []
5155
use_mac_framework = []
52-
bundled = ["cmake", "reqwest", "tar", "flate2"]
56+
bundled = ["cmake", "reqwest", "tar", "flate2", "unidiff"]
5357
mixer = []
5458
image = []
5559
ttf = []

sdl2-sys/build.rs

+173-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ extern crate tar;
1212
extern crate flate2;
1313
#[cfg(feature="bundled")]
1414
extern crate reqwest;
15+
#[cfg(feature="bundled")]
16+
extern crate unidiff;
1517

1618
#[macro_use]
1719
extern crate cfg_if;
@@ -112,6 +114,126 @@ 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+
// 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+
115237
// compile a shared or static lib depending on the feature
116238
#[cfg(feature = "bundled")]
117239
fn compile_sdl2(sdl2_build_path: &Path, target_os: &str) -> PathBuf {
@@ -281,14 +403,60 @@ fn link_sdl2(target_os: &str) {
281403
}
282404
}
283405

406+
fn find_cargo_target_dir() -> PathBuf {
407+
// Infer the top level cargo target dir from the OUT_DIR by searching
408+
// upwards until we get to $CARGO_TARGET_DIR/build/ (which is always one
409+
// level up from the deepest directory containing our package name)
410+
let pkg_name = env::var("CARGO_PKG_NAME").unwrap();
411+
let mut out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
412+
loop {
413+
{
414+
let final_path_segment = out_dir.file_name().unwrap();
415+
if final_path_segment.to_string_lossy().contains(&pkg_name) {
416+
break;
417+
}
418+
}
419+
if !out_dir.pop() {
420+
panic!("Malformed build path: {}", out_dir.to_string_lossy());
421+
}
422+
}
423+
out_dir.pop();
424+
out_dir.pop();
425+
out_dir
426+
}
427+
428+
fn copy_dynamic_libraries(sdl2_compiled_path: &PathBuf, target_os: &str) {
429+
// Windows binaries do not embed library search paths, so successfully
430+
// linking the DLL isn't sufficient to find it at runtime -- it must be
431+
// either on PATH or in the current working directory when we run binaries
432+
// linked against it. In other words, to run the test suite we need to
433+
// copy sdl2.dll out of its build tree and down to the top level cargo
434+
// binary output directory.
435+
if target_os.contains("windows") {
436+
let sdl2_dll_name = "sdl2.dll";
437+
let sdl2_bin_path = sdl2_compiled_path.join("bin");
438+
let target_path = find_cargo_target_dir();
439+
440+
let src_dll_path = sdl2_bin_path.join(sdl2_dll_name);
441+
let dst_dll_path = target_path.join(sdl2_dll_name);
442+
443+
fs::copy(&src_dll_path, &dst_dll_path)
444+
.expect(&format!("Failed to copy SDL2 dynamic library from {} to {}",
445+
src_dll_path.to_string_lossy(),
446+
dst_dll_path.to_string_lossy()));
447+
}
448+
}
449+
284450
fn main() {
285451
let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
286452
let host = env::var("HOST").expect("Cargo build scripts always have HOST");
287453
let target_os = get_os_from_triple(target.as_str()).unwrap();
288454

455+
let sdl2_compiled_path: PathBuf;
289456
#[cfg(feature = "bundled")] {
290457
let sdl2_source_path = download_sdl2();
291-
let sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os);
458+
patch_sdl2(sdl2_source_path.as_path());
459+
sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os);
292460

293461
let sdl2_downloaded_include_path = sdl2_source_path.join("include");
294462
let sdl2_compiled_lib_path = sdl2_compiled_path.join("lib");
@@ -311,6 +479,10 @@ fn main() {
311479
}
312480

313481
link_sdl2(target_os);
482+
483+
#[cfg(all(feature = "bundled", not(feature = "static-link")))] {
484+
copy_dynamic_libraries(&sdl2_compiled_path, target_os);
485+
}
314486
}
315487

316488
#[cfg(not(feature = "bindgen"))]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# HG changeset patch
2+
# User Drew Pirrone-Brusse <[email protected]>
3+
# Date 1537744393 14400
4+
# Sun Sep 23 19:13:13 2018 -0400
5+
# Node ID b66fb83b6897137c1c2b857ee5490e602f8c31b0
6+
# Parent f1084c419f33610cf274e309a8b2798d2ae665c7
7+
Correct the name of the SDL shared library in CMake for Mac OS
8+
9+
diff -r f1084c419f33 -r b66fb83b6897 CMakeLists.txt
10+
--- a/CMakeLists.txt Thu Mar 01 08:26:10 2018 -0800
11+
+++ b/CMakeLists.txt Sun Sep 23 19:13:13 2018 -0400
12+
@@ -1704,7 +1704,9 @@
13+
if(SDL_SHARED)
14+
add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
15+
if(APPLE)
16+
- set_target_properties(SDL2 PROPERTIES MACOSX_RPATH 1)
17+
+ set_target_properties(SDL2 PROPERTIES
18+
+ MACOSX_RPATH 1
19+
+ OUTPUT_NAME "SDL2-${LT_RELEASE}")
20+
elseif(UNIX AND NOT ANDROID)
21+
set_target_properties(SDL2 PROPERTIES
22+
VERSION ${LT_VERSION}
23+
@@ -1810,16 +1812,14 @@
24+
25+
if(NOT (WINDOWS OR CYGWIN))
26+
if(SDL_SHARED)
27+
- if (APPLE)
28+
- set(SOEXT "dylib")
29+
- else()
30+
- set(SOEXT "so")
31+
- endif()
32+
+ set(SOEXT ${CMAKE_SHARED_LIBRARY_SUFFIX}) # ".so", ".dylib", etc.
33+
+ get_target_property(SONAME SDL2 OUTPUT_NAME)
34+
if(NOT ANDROID)
35+
install(CODE "
36+
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
37+
- \"libSDL2-2.0.${SOEXT}\" \"libSDL2.${SOEXT}\")")
38+
- install(FILES ${SDL2_BINARY_DIR}/libSDL2.${SOEXT} DESTINATION "lib${LIB_SUFFIX}")
39+
+ \"lib${SONAME}${SOPOSTFIX}${SOEXT}\" \"libSDL2${SOPOSTFIX}${SOEXT}\")"
40+
+ WORKING_DIR "${SDL2_BINARY_DIR}")
41+
+ install(FILES ${SDL2_BINARY_DIR}/libSDL2${SOPOSTFIX}${SOEXT} DESTINATION "lib${LIB_SUFFIX}")
42+
endif()
43+
endif()
44+
if(FREEBSD)

0 commit comments

Comments
 (0)