Use NDK for building android target objects

This commit is contained in:
ILyoan 2013-03-15 17:32:39 +09:00
parent 1ded138851
commit 0f89eab89d
2 changed files with 57 additions and 11 deletions

View File

@ -167,15 +167,18 @@ pub mod write {
use back::link::{output_type_assembly, output_type_bitcode}; use back::link::{output_type_assembly, output_type_bitcode};
use back::link::{output_type_exe, output_type_llvm_assembly}; use back::link::{output_type_exe, output_type_llvm_assembly};
use back::link::{output_type_object}; use back::link::{output_type_object};
use back::link::output_type;
use driver::session::Session; use driver::session::Session;
use driver::session; use driver::session;
use lib::llvm::llvm; use lib::llvm::llvm;
use lib::llvm::{False, True, ModuleRef, mk_pass_manager, mk_target_data}; use lib::llvm::{False, True, ModuleRef, mk_pass_manager, mk_target_data};
use lib; use lib;
use core::prelude::*;
use core::libc::{c_char, c_int, c_uint}; use core::libc::{c_char, c_int, c_uint};
use core::path::Path; use core::path::Path;
use core::str; use core::str;
use core::run;
pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool { pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
if ot == output_type_assembly || ot == output_type_object || if ot == output_type_assembly || ot == output_type_object ||
@ -185,7 +188,8 @@ pub mod write {
return false; 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 { unsafe {
let opts = sess.opts; let opts = sess.opts;
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
@ -201,7 +205,7 @@ pub mod write {
if opts.save_temps { if opts.save_temps {
match opts.output_type { match output_type {
output_type_bitcode => { output_type_bitcode => {
if opts.optimize != session::No { if opts.optimize != session::No {
let filename = output.with_filetype("no-opt.bc"); let filename = output.with_filetype("no-opt.bc");
@ -262,7 +266,7 @@ pub mod write {
llvm::LLVMPassManagerBuilderDispose(MPMB); llvm::LLVMPassManagerBuilderDispose(MPMB);
} }
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } 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 LLVMOptNone = 0 as c_int; // -O0
let LLVMOptLess = 1 as c_int; // -O1 let LLVMOptLess = 1 as c_int; // -O1
let LLVMOptDefault = 2 as c_int; // -O2, -Os let LLVMOptDefault = 2 as c_int; // -O2, -Os
@ -290,8 +294,8 @@ pub mod write {
} }
let mut FileType; let mut FileType;
if opts.output_type == output_type_object || if output_type == output_type_object ||
opts.output_type == output_type_exe { output_type == output_type_exe {
FileType = lib::llvm::ObjectFile; FileType = lib::llvm::ObjectFile;
} else { FileType = lib::llvm::AssemblyFile; } } else { FileType = lib::llvm::AssemblyFile; }
// Write optimized bitcode if --save-temps was on. // Write optimized bitcode if --save-temps was on.
@ -307,7 +311,7 @@ pub mod write {
pm = mk_pass_manager(); pm = mk_pass_manager();
// Save the assembly file if -S is used // 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( let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple, sess.targ_cfg.target_strs.target_triple,
|buf_t| { |buf_t| {
@ -328,8 +332,8 @@ pub mod write {
// Save the object file for -c or --save-temps alone // Save the object file for -c or --save-temps alone
// This .o is needed when an exe is built // This .o is needed when an exe is built
if opts.output_type == output_type_object || if output_type == output_type_object ||
opts.output_type == output_type_exe { output_type == output_type_exe {
let _: () = str::as_c_str( let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple, sess.targ_cfg.target_strs.target_triple,
|buf_t| { |buf_t| {
@ -375,7 +379,7 @@ pub mod write {
return; return;
} }
if opts.output_type == output_type_llvm_assembly { if output_type == output_type_llvm_assembly {
// Given options "-S --emit-llvm": output LLVM assembly // Given options "-S --emit-llvm": output LLVM assembly
str::as_c_str(output.to_str(), |buf_o| { str::as_c_str(output.to_str(), |buf_o| {
llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)}); llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)});
@ -391,6 +395,34 @@ pub mod write {
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } 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();
}
}
} }

View File

@ -323,9 +323,23 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg,
}; };
time(time_passes, ~"LLVM passes", || // NOTE: Android hack
link::write::run_passes(sess, llmod, 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)); &outputs.obj_filename));
}
let stop_after_codegen = let stop_after_codegen =
sess.opts.output_type != link::output_type_exe || sess.opts.output_type != link::output_type_exe ||