diff --git a/ci/ios/deploy_and_run_ios_binary_on_ios_simulator.py b/ci/ios/deploy_and_run_ios_binary_on_ios_simulator.py
deleted file mode 100755
index 40c00bb57354b3627c3fd3f02baa4a77d42b9c4a..0000000000000000000000000000000000000000
--- a/ci/ios/deploy_and_run_ios_binary_on_ios_simulator.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-#
-# This is a script to deploy and execute a binary on an x86-64 iOS simulator.
-# The primary use of this is to be able to run unit tests on the simulator and retrieve the results.
-#
-# To do this through Cargo instead, use Dinghy (https://github.com/snipsco/dinghy): 
-# cargo dinghy install, then cargo dinghy test.
-
-import os.path
-import subprocess
-import sys
-import time
-
-# Step one: Wrap as an app
-def package_as_simulator_app(crate_name, test_binary_path):
-	print 'Packaging simulator app'
-	subprocess.call(['rm', '-rf', 'ios_simulator_app'])
-	subprocess.check_call(['mkdir', 'ios_simulator_app'])
-	subprocess.check_call(['cp', test_binary_path, 'ios_simulator_app/' + crate_name])
-	f = open('ios_simulator_app/Info.plist', 'w')
-	f.write('<?xml version="1.0" encoding="UTF-8"?>\n'
-			'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
-			'<plist version="1.0">\n'
-			'	<dict>\n'
-			'		<key>CFBundleExecutable</key>\n'
-			'		<string>' + crate_name + '</string>\n'
-			'		<key>CFBundleIdentifier</key>\n'
-			'		<string>com.rust.unittests</string>\n'
-			'		<key>UIRequiredDeviceCapabilities</key>\n'
-			'		<array>\n'
-			'			<string>x86_64</string>\n'
-			'		</array>\n'
-			'	</dict>\n'
-			'</plist>\n')
-
-# Step two: Start the iOS simulator
-def start_simulator():
-	print 'Looking for iOS simulator'
-	xcrun_list = subprocess.Popen(['xcrun', 'simctl', 'list'], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
-	simulator_exists = False
-	simulator_booted = False
-	found_rust_sim = False
-	for line in xcrun_list.stdout:
-		if "rust_ios" in line:
-			if found_rust_sim == True:
-				raise Exception("Duplicate rust_ios simulators found. Please double-check xcrun simctl list.")
-			simulator_exists = True
-			simulator_booted = "(Booted)" in line
-			found_rust_sim = True
-	
-	if simulator_exists == False:
-		print 'Creating iOS simulator'
-		subprocess.check_output(['xcrun',  'simctl', 'create', 'rust_ios', 'com.apple.CoreSimulator.SimDeviceType.iPhone-SE', 'com.apple.CoreSimulator.SimRuntime.iOS-10-2'])
-	elif simulator_booted == True:
-		print 'Shutting down already-booted simulator'
-		subprocess.call(['xcrun', 'simctl', 'shutdown', 'rust_ios'])
-	
-	print 'Starting iOS simulator'
-	# We can't uninstall the app (if present) as that will hang if the simulator isn't completely booted; just erase the simulator instead.
-	subprocess.check_call(['xcrun', 'simctl', 'erase', 'rust_ios'])
-	subprocess.check_call(['xcrun', 'simctl', 'boot', 'rust_ios'])
-
-# Step three: Install the app
-def install_app_to_simulator():
-	print 'Installing app to simulator'	
-	subprocess.check_call(['xcrun', 'simctl', 'install', 'booted', 'ios_simulator_app/'])
-
-# Step four: Run the app
-def run_app_on_simulator():
-	print 'Running app'
-	try:
-		test_run = subprocess.Popen(['xcrun', 'simctl', 'launch', '--console', 'booted', 'com.rust.unittests'], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
-		test_run_passed = False
-		for line in test_run.stdout:
-			sys.stdout.write(line)
-			if test_run_passed == False:
-				# Based on all.rs test output
-				test_run_passed = 'PASSED' in line and 'tests' in line
-		
-		sys.stdout.flush()
-		if test_run_passed == False:
-			raise Exception('Some tests failed')
-	finally:
-		print 'Shutting down simulator'
-		subprocess.call(['xcrun', 'simctl', 'shutdown', 'rust_ios'])
-
-# Run all steps in sequence
-# TODO 1: Use a /tmp place for the app instead of current dir?
-def main():
-	if len(sys.argv) != 2:
-		print 'usage: ' + os.path.basename(sys.argv[0]) + ' executable'
-		sys.exit(-1)
-	
-	crate_name = os.path.basename(sys.argv[1])
-	test_binary_path = sys.argv[1]
-
-	package_as_simulator_app(crate_name, test_binary_path)
-	start_simulator()
-	install_app_to_simulator()
-	run_app_on_simulator()
-
-# Entry point
-if __name__ == '__main__':
-    main()
\ No newline at end of file
diff --git a/ci/ios/deploy_and_run_on_ios_simulator.rs b/ci/ios/deploy_and_run_on_ios_simulator.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b36bef8dbbca470be27045409430a6f9d7bece00
--- /dev/null
+++ b/ci/ios/deploy_and_run_on_ios_simulator.rs
@@ -0,0 +1,132 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// This is a script to deploy and execute a binary on an x86-64 iOS simulator.
+// The primary use of this is to be able to run unit tests on the simulator and retrieve the results.
+//
+// To do this through Cargo instead, use Dinghy (https://github.com/snipsco/dinghy): 
+// cargo dinghy install, then cargo dinghy test.
+
+use std::env;
+use std::fs::File;
+use std::io::Write;
+use std::path::Path;
+use std::process;
+use std::process::Command;
+
+// Step one: Wrap as an app
+fn package_as_simulator_app(crate_name: &str, test_binary_path: &Path) {
+    println!("Packaging simulator app");
+    Command::new("rm").arg("-rf").arg("ios_simulator_app").status().unwrap();
+    Command::new("mkdir").arg("ios_simulator_app").check_status();
+    Command::new("cp").arg(test_binary_path).arg(["ios_simulator_app/", crate_name].join("")).check_status();
+    let mut f = File::create("ios_simulator_app/Info.plist").unwrap();
+    f.write_all(&[
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+        "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">",
+        "<plist version=\"1.0\">",
+        "    <dict>",
+        "        <key>CFBundleExecutable</key>",
+      &["        <string>", crate_name, "</string>"].join(""),
+        "        <key>CFBundleIdentifier</key>",
+        "        <string>com.rust.unittests</string>",
+        "        <key>UIRequiredDeviceCapabilities</key>",
+        "        <array>",
+        "            <string>x86_64</string>",
+        "        </array>",
+        "    </dict>",
+        "</plist>"].join("\n").into_bytes()).unwrap();
+}
+
+// Step two: Start the iOS simulator
+fn start_simulator() {
+    println!("Looking for iOS simulator");
+    let output = Command::new("xcrun").arg("simctl").arg("list").output().unwrap();
+    let mut simulator_exists = false;
+    let mut simulator_booted = false;
+    let mut found_rust_sim = false;
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    for line in stdout.lines() {
+        if line.contains("rust_ios") {
+            if found_rust_sim {
+                panic!("Duplicate rust_ios simulators found. Please double-check xcrun simctl list.");
+            }
+            simulator_exists = true;
+            simulator_booted = line.contains("(Booted)");
+            found_rust_sim = true;
+        }
+    }
+
+    if simulator_exists == false {
+        println!("Creating iOS simulator");
+        Command::new("xcrun").arg("simctl").arg("create").arg("rust_ios")
+            .arg("com.apple.CoreSimulator.SimDeviceType.iPhone-SE").arg("com.apple.CoreSimulator.SimRuntime.iOS-10-2").check_status();
+    } else if simulator_booted == true {
+        println!("Shutting down already-booted simulator");
+        Command::new("xcrun").arg("simctl").arg("shutdown").arg("rust_ios").check_status();
+    }
+
+    println!("Starting iOS simulator");
+    // We can't uninstall the app (if present) as that will hang if the simulator isn't completely booted;just erase the simulator instead.
+    Command::new("xcrun").arg("simctl").arg("erase").arg("rust_ios").check_status();
+    Command::new("xcrun").arg("simctl").arg("boot").arg("rust_ios").check_status();
+}
+
+// Step three: Install the app
+fn install_app_to_simulator() {    
+    println!("Installing app to simulator");
+    Command::new("xcrun").arg("simctl").arg("install").arg("booted").arg("ios_simulator_app/").check_status();
+}
+
+// Step four: Run the app
+fn run_app_on_simulator() {
+    println!("Running app");
+    let output = Command::new("xcrun").arg("simctl").arg("launch").arg("--console").arg("booted").arg("com.rust.unittests").output().unwrap();
+    let mut test_run_passed = false;
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    for line in stdout.lines() {
+        println!("{}", line);
+        
+        if test_run_passed == false {
+            // Based on all.rs test output
+            test_run_passed = line.contains("PASSED") && line.contains("tests");
+        }
+    }
+
+    println!("Shutting down simulator");
+    Command::new("xcrun").arg("simctl").arg("shutdown").arg("rust_ios").check_status();
+    assert!(test_run_passed);
+}
+
+trait CheckStatus {
+    fn check_status(&mut self);
+}
+
+impl CheckStatus for Command {
+    fn check_status(&mut self) {
+        assert!(self.status().unwrap().success());
+    }
+}
+
+pub fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() != 2 {
+        println!("Usage: {:?} executable", Path::new(&args[0]).file_name().unwrap());
+        process::exit(-1);
+    }
+    
+    let test_binary_path = Path::new(&args[1]);
+    let crate_name = test_binary_path.file_name().unwrap();
+
+    package_as_simulator_app(crate_name.to_str().unwrap(), test_binary_path);
+    start_simulator();
+    install_app_to_simulator();
+    run_app_on_simulator();
+}
\ No newline at end of file
diff --git a/ci/run.sh b/ci/run.sh
index 3419090f0a726df9386664c60a366ae80e14a832..d33af30fd91c716122970c76467cabca8fafee3f 100755
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -114,11 +114,13 @@ case "$TARGET" in
     ;;
 
   i386-apple-ios)
-    python ./ci/ios/deploy_and_run_ios_binary_on_ios_simulator.py $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    rustc -O ./ci/ios/deploy_and_run_on_ios_simulator.rs
+    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     ;;
 
   x86_64-apple-ios)
-    python ./ci/ios/deploy_and_run_ios_binary_on_ios_simulator.py $CARGO_TARGET_DIR/$TARGET/debug/libc-test 
+    rustc -O ./ci/ios/deploy_and_run_on_ios_simulator.rs
+    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/libc-test
     ;;
 
   arm-unknown-linux-gnueabihf)