From 0f89eab89d9a6af9c4536a943c646ebe41b13002 Mon Sep 17 00:00:00 2001 From: ILyoan Date: Fri, 15 Mar 2013 17:32:39 +0900 Subject: [PATCH] Use NDK for building android target objects --- src/librustc/back/link.rs | 50 ++++++++++++++++++++++++++++------- src/librustc/driver/driver.rs | 18 +++++++++++-- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 84836568029..e7a971a98a1 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -167,15 +167,18 @@ pub mod write { use back::link::{output_type_assembly, output_type_bitcode}; use back::link::{output_type_exe, output_type_llvm_assembly}; use back::link::{output_type_object}; + use back::link::output_type; use driver::session::Session; use driver::session; use lib::llvm::llvm; use lib::llvm::{False, True, ModuleRef, mk_pass_manager, mk_target_data}; use lib; + use core::prelude::*; use core::libc::{c_char, c_int, c_uint}; use core::path::Path; use core::str; + use core::run; pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool { if ot == output_type_assembly || ot == output_type_object || @@ -185,7 +188,8 @@ pub mod write { return false; } - pub fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) { + pub fn run_passes(sess: Session, llmod: ModuleRef, + output_type: output_type, output: &Path) { unsafe { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } @@ -201,7 +205,7 @@ pub mod write { if opts.save_temps { - match opts.output_type { + match output_type { output_type_bitcode => { if opts.optimize != session::No { let filename = output.with_filetype("no-opt.bc"); @@ -262,7 +266,7 @@ pub mod write { llvm::LLVMPassManagerBuilderDispose(MPMB); } if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } - if is_object_or_assembly_or_exe(opts.output_type) || opts.jit { + if is_object_or_assembly_or_exe(output_type) || opts.jit { let LLVMOptNone = 0 as c_int; // -O0 let LLVMOptLess = 1 as c_int; // -O1 let LLVMOptDefault = 2 as c_int; // -O2, -Os @@ -290,8 +294,8 @@ pub mod write { } let mut FileType; - if opts.output_type == output_type_object || - opts.output_type == output_type_exe { + if output_type == output_type_object || + output_type == output_type_exe { FileType = lib::llvm::ObjectFile; } else { FileType = lib::llvm::AssemblyFile; } // Write optimized bitcode if --save-temps was on. @@ -307,7 +311,7 @@ pub mod write { pm = mk_pass_manager(); // Save the assembly file if -S is used - if opts.output_type == output_type_assembly { + if output_type == output_type_assembly { let _: () = str::as_c_str( sess.targ_cfg.target_strs.target_triple, |buf_t| { @@ -328,8 +332,8 @@ pub mod write { // Save the object file for -c or --save-temps alone // This .o is needed when an exe is built - if opts.output_type == output_type_object || - opts.output_type == output_type_exe { + if output_type == output_type_object || + output_type == output_type_exe { let _: () = str::as_c_str( sess.targ_cfg.target_strs.target_triple, |buf_t| { @@ -375,7 +379,7 @@ pub mod write { return; } - if opts.output_type == output_type_llvm_assembly { + if output_type == output_type_llvm_assembly { // Given options "-S --emit-llvm": output LLVM assembly str::as_c_str(output.to_str(), |buf_o| { llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)}); @@ -391,6 +395,34 @@ pub mod write { if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } } } + + pub fn run_ndk(sess: Session, assembly: &Path, object: &Path) { + let cc_prog: ~str = match &sess.opts.android_cross_path { + &Some(copy path) => { + fmt!("%s/bin/arm-linux-androideabi-gcc", path) + } + &None => { + sess.fatal(~"need Android NDK path for building \ + (--android-cross-path)") + } + }; + let mut cc_args = ~[]; + cc_args.push(~"-c"); + cc_args.push(~"-o"); + cc_args.push(object.to_str()); + cc_args.push(assembly.to_str()); + + let prog = run::program_output(cc_prog, cc_args); + + if prog.status != 0 { + sess.err(fmt!("building with `%s` failed with code %d", + cc_prog, prog.status)); + sess.note(fmt!("%s arguments: %s", + cc_prog, str::connect(cc_args, ~" "))); + sess.note(prog.err + prog.out); + sess.abort_if_errors(); + } + } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 509ef704b07..d84f77cec34 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -323,9 +323,23 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg, }; - time(time_passes, ~"LLVM passes", || - link::write::run_passes(sess, llmod, + // NOTE: Android hack + if sess.targ_cfg.arch == session::arch_arm && + (sess.opts.output_type == link::output_type_object || + sess.opts.output_type == link::output_type_exe) { + let output_type = link::output_type_assembly; + let obj_filename = outputs.obj_filename.with_filetype("s"); + + time(time_passes, ~"LLVM passes", || + link::write::run_passes(sess, llmod, output_type, + &obj_filename)); + + link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename); + } else { + time(time_passes, ~"LLVM passes", || + link::write::run_passes(sess, llmod, sess.opts.output_type, &outputs.obj_filename)); + } let stop_after_codegen = sess.opts.output_type != link::output_type_exe ||