1 | #!/usr/bin/perl -w |
---|
2 | use strict; |
---|
3 | |
---|
4 | # Copyright 2008, Andrew Ross andy@plausible.org |
---|
5 | # Distributable under the terms of the GNU GPL, see COPYING for details |
---|
6 | |
---|
7 | # The Android toolchain is ... rough. Rather than try to manage the |
---|
8 | # complexity directly, this script wraps the tools into an "agcc" that |
---|
9 | # works a lot like a gcc command line does for a native platform or a |
---|
10 | # properly integrated cross-compiler. It accepts arbitrary arguments, |
---|
11 | # but interprets the following specially: |
---|
12 | # |
---|
13 | # -E/-S/-c/-shared - Enable needed arguments (linker flags, include |
---|
14 | # directories, runtime startup objects...) for the |
---|
15 | # specified compilation mode when building under |
---|
16 | # android. |
---|
17 | # |
---|
18 | # -O<any> - Turn on the optimizer flags used by the Dalvik build. No |
---|
19 | # control is provided over low-level optimizer flags. |
---|
20 | # |
---|
21 | # -W<any> - Turn on the warning flags used by the Dalvik build. No |
---|
22 | # control is provided over specific gcc warning flags. |
---|
23 | # |
---|
24 | # Notes: |
---|
25 | # + The prebuilt arm-eabi-gcc from a built (!) android source |
---|
26 | # directory must be on your PATH. |
---|
27 | # + All files are compiled with -fPIC to an ARMv5TE target. No |
---|
28 | # support is provided for thumb. |
---|
29 | # + No need to pass a "-Wl,-soname" argument when linking with |
---|
30 | # -shared, it uses the file name always (so don't pass a directory in |
---|
31 | # the output path for a shared library!) |
---|
32 | |
---|
33 | # Dance around to find the actual android toolchain path (it's very |
---|
34 | # deep, so links on $PATH are going to be common. |
---|
35 | my $GCC = `which arm-eabi-gcc`; |
---|
36 | $GCC = qx(cd `dirname $GCC`; /bin/pwd); |
---|
37 | chomp $GCC; |
---|
38 | die "bad arm-eabi-gcc path" if $GCC !~ /(.*)\/prebuilt\//; |
---|
39 | my $DROID = $1; |
---|
40 | |
---|
41 | my $ALIB = "$DROID/out/target/product/vision/obj/lib"; |
---|
42 | my $TOOLCHAIN = "$DROID/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1"; |
---|
43 | |
---|
44 | my @include_paths = ( |
---|
45 | "-I$DROID/system/core/include", |
---|
46 | "-I$DROID/hardware/libhardware/include", |
---|
47 | "-I$DROID/hardware/ril/include", |
---|
48 | "-I$DROID/dalvik/libnativehelper/include", |
---|
49 | "-I$DROID/frameworks/base/include", |
---|
50 | "-I$DROID/external/skia/include", |
---|
51 | "-I$DROID/out/target/product/vision/obj/include", |
---|
52 | "-I$DROID/bionic/libc/arch-arm/include", |
---|
53 | "-I$DROID/bionic/libc/include", |
---|
54 | "-I$DROID/bionic/libstdc++/include", |
---|
55 | "-I$DROID/bionic/libc/kernel/common", |
---|
56 | "-I$DROID/bionic/libc/kernel/arch-arm", |
---|
57 | "-I$DROID/bionic/libm/include", |
---|
58 | "-I$DROID/bionic/libm/include/arch/arm", |
---|
59 | "-I$DROID/bionic/libthread_db/include", |
---|
60 | "-I$DROID/bionic/libm/arm", |
---|
61 | "-I$DROID/bionic/libm", |
---|
62 | "-I$DROID/out/target/product/vision/obj/SHARED_LIBRARIES/libm_intermediates"); |
---|
63 | |
---|
64 | my @preprocess_args = ( |
---|
65 | "-D__ARM_ARCH_5__", |
---|
66 | "-D__ARM_ARCH_5T__", |
---|
67 | "-D__ARM_ARCH_5E__", |
---|
68 | "-D__ARM_ARCH_5TE__", # Already defined by toolchain |
---|
69 | "-DANDROID", |
---|
70 | "-DSK_RELEASE", |
---|
71 | "-DNDEBUG", |
---|
72 | "-include", "$DROID/system/core/include/arch/linux-arm/AndroidConfig.h", |
---|
73 | "-UDEBUG"); |
---|
74 | |
---|
75 | my @warn_args = ( |
---|
76 | "-Wall", |
---|
77 | "-Wno-unused", # why? |
---|
78 | "-Wno-multichar", # why? |
---|
79 | "-Wstrict-aliasing=2"); # Implicit in -Wall per texinfo |
---|
80 | |
---|
81 | my @compile_args = ( |
---|
82 | "-march=armv5te", |
---|
83 | "-mtune=xscale", |
---|
84 | "-msoft-float", |
---|
85 | "-mthumb-interwork", |
---|
86 | "-fpic", |
---|
87 | "-fno-exceptions", |
---|
88 | "-ffunction-sections", |
---|
89 | "-funwind-tables", # static exception-like tables |
---|
90 | "-fstack-protector", # check guard variable before return |
---|
91 | "-fmessage-length=0"); # No line length limit to error messages |
---|
92 | |
---|
93 | my @optimize_args = ( |
---|
94 | "-O2", |
---|
95 | "-finline-functions", |
---|
96 | "-finline-limit=300", |
---|
97 | "-fno-inline-functions-called-once", |
---|
98 | "-fgcse-after-reload", |
---|
99 | "-frerun-cse-after-loop", # Implicit in -O2 per texinfo |
---|
100 | "-frename-registers", |
---|
101 | "-fomit-frame-pointer", |
---|
102 | "-fstrict-aliasing", # Implicit in -O2 per texinfo |
---|
103 | "-funswitch-loops"); |
---|
104 | |
---|
105 | my @link_args = ( |
---|
106 | "-Bdynamic", |
---|
107 | "-Wl,-T,$DROID/build/core/armelf.x", |
---|
108 | "-Wl,-dynamic-linker,/system/bin/linker", |
---|
109 | "-Wl,--gc-sections", |
---|
110 | "-Wl,-z,nocopyreloc", |
---|
111 | "-Wl,--no-undefined", |
---|
112 | "-Wl,-rpath-link=$ALIB", |
---|
113 | "-L$ALIB", |
---|
114 | "-nostdlib", |
---|
115 | "$ALIB/crtend_android.o", |
---|
116 | "$ALIB/crtbegin_dynamic.o", |
---|
117 | "$TOOLCHAIN/lib/gcc/arm-eabi/4.3.1/interwork/libgcc.a", |
---|
118 | "-lc", |
---|
119 | "-lm"); |
---|
120 | |
---|
121 | # Also need: -Wl,-soname,libXXXX.so |
---|
122 | my @shared_args = ( |
---|
123 | "-nostdlib", |
---|
124 | "-Wl,-T,$DROID/build/core/armelf.xsc", |
---|
125 | "-Wl,--gc-sections", |
---|
126 | "-Wl,-shared,-Bsymbolic", |
---|
127 | "-L$ALIB", |
---|
128 | "-Wl,--no-whole-archive", |
---|
129 | "-lc", |
---|
130 | "-lm", |
---|
131 | "-Wl,--no-undefined", |
---|
132 | "$TOOLCHAIN/lib/gcc/arm-eabi/4.3.1/interwork/libgcc.a", |
---|
133 | "-Wl,--whole-archive"); # .a, .o input files go *after* here |
---|
134 | |
---|
135 | # Now implement a quick parser for a gcc-like command line |
---|
136 | |
---|
137 | my %MODES = ("-E"=>1, "-c"=>1, "-S"=>1, "-shared"=>1); |
---|
138 | |
---|
139 | my $mode = "DEFAULT"; |
---|
140 | my $out; |
---|
141 | my $warn = 0; |
---|
142 | my $opt = 0; |
---|
143 | my @args = (); |
---|
144 | my $have_src = 0; |
---|
145 | while(@ARGV) { |
---|
146 | my $a = shift; |
---|
147 | if(defined $MODES{$a}) { |
---|
148 | die "Can't specify $a and $mode" if $mode ne "DEFAULT"; |
---|
149 | $mode = $a; |
---|
150 | } elsif($a eq "-o") { |
---|
151 | die "Missing -o argument" if !@ARGV; |
---|
152 | die "Duplicate -o argument" if defined $out; |
---|
153 | $out = shift; |
---|
154 | } elsif($a =~ /^-W.*/) { |
---|
155 | $warn = 1; |
---|
156 | } elsif($a =~ /^-O.*/) { |
---|
157 | $opt = 1; |
---|
158 | } else { |
---|
159 | if($a =~ /\.(c|cpp|cxx)$/i) { $have_src = 1; } |
---|
160 | push @args, $a; |
---|
161 | } |
---|
162 | } |
---|
163 | |
---|
164 | my $need_cpp = 0; |
---|
165 | my $need_compile = 0; |
---|
166 | my $need_link = 0; |
---|
167 | my $need_shlink = 0; |
---|
168 | if($mode eq "DEFAULT") { $need_cpp = $need_compile = $need_link = 1; } |
---|
169 | if($mode eq "-E") { $need_cpp = 1; } |
---|
170 | if($mode eq "-c") { $need_cpp = $need_compile = 1; } |
---|
171 | if($mode eq "-S") { $need_cpp = $need_compile = 1; } |
---|
172 | if($mode eq "-shared") { $need_shlink = 1; } |
---|
173 | |
---|
174 | if($have_src and $mode ne "-E") { $need_cpp = $need_compile = 1; } |
---|
175 | |
---|
176 | # Assemble the command: |
---|
177 | my @cmd = ("arm-eabi-gcc"); |
---|
178 | if($mode ne "DEFAULT") { @cmd = (@cmd, $mode); } |
---|
179 | if(defined $out) { @cmd = (@cmd, "-o", $out); } |
---|
180 | if($need_cpp) { @cmd = (@cmd, @include_paths, @preprocess_args); } |
---|
181 | if($need_compile){ |
---|
182 | @cmd = (@cmd, @compile_args); |
---|
183 | if($warn) { @cmd = (@cmd, @warn_args); } |
---|
184 | if($opt) { @cmd = (@cmd, @optimize_args); } |
---|
185 | } |
---|
186 | if($need_link) { @cmd = (@cmd, @link_args); } |
---|
187 | if($need_shlink) { @cmd = (@cmd, @shared_args); } |
---|
188 | @cmd = (@cmd, @args); |
---|
189 | |
---|
190 | #print join(" ", @cmd), "\n"; # Spit it out if you're curious |
---|
191 | exec(@cmd); |
---|