2012年6月28日 星期四

gcc strict-aliasing是什麼?

  • 前言 
思考下面這一段code
void foo(int *i1, int *i2, int *res)
{
    for(int i=0;i<10;i++){
        *res += *i1 + *i2;
    }
}
如果想要讓這段code變快,我們可能會想要這樣作
void foo(int *i1, int *i2, int *res)
{
    int tmp=*i1 + *i2;
    for(int i=0;i<10;i++)
        *res += tmp;
    }
}
但考慮到當呼叫端是如下就會發生問題:
foo(&v1,&v3,&v3);
我們永遠不知道caller 到底會丟什麼進來。因此,這樣的code是無法最佳化的。那如果是下面這個例子呢?
void foo(int32_t *i1, int32_t *i2, int64_t *res)
{
    for(int i=0;i<10;i++){
        *res += *i1 + *i2;
    }
}
res的type是int64_t理論上應該就不會有問題了吧?如果呼叫端是:
foo(&v1,&v2,(int64_t *)&v3);
就會發生我們預期外的錯誤了。
  • 什麼是strict-aliasing?
為了讓上面這種狀況不會發生最佳化後的結果是我們預期外的,我們就啟用strict-aliasing來避免"不同型態"的指標指向相同的address除非兩種型態是類似的。例如:unsigned int可以alias int但不可以alias double。這麼我們就可以避免上述的情況發生。 
  • 如何啟用strict-aliasing?
在compile時如果我們開啟-O2,-O3,-Os或直接加上-fstrict-aliasing就會啟動fstrict-aliasing的選項。
  • 簡單的方法避免Werror=strict-aliasing
假設我們的程式中需要作轉型例如
int foo() {
    short a[2];
    a[0]=1;
    a[1]=0;
    int *i=(int*)&a;
}
我們可以用union來表達
union union_a {
    int i;
    short s[2];
};
int foo() {
    union union_a u;
    u.i=1;
    u.s[0]=1;
    u.s[1]=0;
}
這樣就不會有warning: dereferencing type-punned pointer will break strict-aliasing rules的warning了。

2012年6月27日 星期三

Compile AOSP with Linaro-4.7 Note

Linaro是一個非營利的組織,主要貢獻了在不同的嵌入式平台的toolchain, kernel, platform移植或最佳化。在應用Linaro對AOSP(Android Opensource Project)最佳化的patch及使用Linaro-4.7的toolchain時會遇到一些問題的整理。
首先,參考Linaro的patch最直接的最佳化方法就是使用-O3以及strict-aliasing來作最佳化如下 :
------------------------ core/combo/TARGET_linux-arm.mk ------------------------
index 9000b86..90719b9 100644
@@ -66,7 +66,7 @@ endif
  
 TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
  
-TARGET_arm_CFLAGS :=    -O2 \
+TARGET_arm_CFLAGS :=    -O3 \
                         -fomit-frame-pointer \
                         -fstrict-aliasing    \
下載Linaro-4.7之後,我們可以利用
$ export TARGET_TOOLS_PREFIX=[Linaro-4.7 path]/bin/arm-eabi-
來讓AOSP切換toolchain編譯。

問題列表:
  1. error: template with C linkage
      原因:錯誤使用 -isystem。例如在AOSP 的build/core/definitions.mk
               Ref.
      解法 :
      - $(addprefix -isystem ,\
      + $(addprefix -I ,\
            $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
      -         $(filter-out $(PRIVATE_C_INCLUDES), \
      +         $(filter-out bionic/% $(PRIVATE_C_INCLUDES), \
                    $(PRIVATE_TARGET_PROJECT_INCLUDES) \
                    $(PRIVATE_TARGET_C_INCLUDES)))) \
      + $(addprefix -isystem ,\
      +     $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
      +         $(filter bionic/%, \
      +             $(filter-out $(PRIVATE_C_INCLUDES), \
      +                 $(PRIVATE_TARGET_PROJECT_INCLUDES) \
      +                 $(PRIVATE_TARGET_C_INCLUDES))))) \
  2. unrecognized command line option '-mno-thumb'
      原因: gcc-4.7似乎沒有-mno-thumb 
      解法:替換成-marm 
  3. -Werror=strict-prototypes
      原因: 在C的話,foo()代表允許無窮的參數,而foo(void)代表"沒有"參數。但是在C++這兩種是一樣的。
      解法:
            將foo()替換成foo(void)
      
  4. dereferencing type-punned pointer will break strict-aliasing rules (Werror=strict-aliasing)
  5. 遇到
    error: ‘truncate’ was not declared in this scope
    error: ‘sleep’ was not declared in this scope
    error: ‘pipe’ was not declared in this scope
    error: there are no arguments to 'offsetof' that depend on a template
    parameter, so a declaration of 'offsetof' must be available
      原因:因為很多標準的C++函式庫的header 都沒有 include unistd.h了。           
      Ref.
      解法 : 加入#include <unistd.h>
  6. 遇到
    error: redeclaration of ‘int i’
    error: ‘int i’ previously declared here
      原因: 重複使用變數,例如
      void f(int);
      
      int main()
      {
          for (int i=0;;++i)
          {
            int i=5;
            f(i);
          }
          return 0;
       }
      Ref. 解法: 不要重複使用"i"
  7. unable to find string literal operator
      原因:  參考Ref. 發生的情形例如
      const char *p = "foobar"__TIME__;
      解法:在macro和 字串中間加個空格
陸續補完中...

2012年6月6日 星期三

Tegra 3 Matrix Mul Performance Test

今天以矩陣相乘為例,測試不同的編譯參數對效能的影響。有些編譯參數應該是沒有直接fit 最佳化的狀況因此最佳化結果不明顯。但這只是初期的測試,未來要更深入的研究一下每一個編譯參數實際上是對什麼case做最佳化。 

測試的數據是以arm-eabi-g++來編譯,後來有試過改成可以讓arm-eabi-gcc來編譯的版本,測試結果其實差不多。以下是測試的程式及環境


  • 測試程式
      #include <sys/time.h>
      #include <math.h>
      #include <stdio.h>
      #include <stdlib.h>
      
      using namespace std;
      
      long double timer[10];
      int matrix_size;
      /*Timer*/
      long double high_prec_time(){
              timeval tv;
              gettimeofday(&tv,0);
              return (long double)tv.tv_sec+tv.tv_usec*1e-6;
      }
      void   set_timer(int k=0){
              timer[k]=high_prec_time();
      }
      double get_timer(int k=0){
              return (double)(high_prec_time()-timer[k]);
      }
      
      /*Matrix Mul*/
      template <class T>
      void _matrix_mul(T *matrixA,T *matrixC){
           T tmpA;
          for(int i=0;i<matrix_size;i++){
              for(int j=0;j<matrix_size;j++){
                  for(int k=0;k<matrix_size;k++){
                      tmpA=*(matrixA+k*matrix_size+j);
                      //cout<<tmpA<<endl;
                      *(matrixC+(i*matrix_size+j)) += tmpA*tmpA;
                  }
              }
          }
      }
      void int_matrix_mul(int matrix_size){
          int matrixA[matrix_size][matrix_size];
          int matrixC[matrix_size][matrix_size];
          //srand(time(0));
          for(int i=0;i<matrix_size;i++){
              for(int j=0;j<matrix_size;j++){
                  matrixA[i][j]=rand()%RAND_MAX;
                  //cout<<matrixA[i][j]<<RAND_MAX<<endl;
                  matrixC[i][j]=0;
              }
          }
          _matrix_mul(&matrixA[0][0],&matrixC[0][0]);
      }
      
      void float_matrix_mul(int matrix_size){
          float matrixA[matrix_size][matrix_size];
          float matrixC[matrix_size][matrix_size];
          //srand(time(0));
          for(int i=0;i<matrix_size;i++){
              for(int j=0;j<matrix_size;j++){
                  matrixA[i][j]=(float)(rand()%RAND_MAX);
                  matrixC[i][j]=0;
              }
          }
          _matrix_mul(&matrixA[0][0],&matrixC[0][0]);
      }
      void double_matrix_mul(int matrix_size){
          double matrixA[matrix_size][matrix_size];
          double matrixC[matrix_size][matrix_size];
          //srand(time(0));
          for(int i=0;i<matrix_size;i++){
              for(int j=0;j<matrix_size;j++){
                  matrixA[i][j]=(double)(rand()%RAND_MAX);
                  matrixC[i][j]=0;
              }
          }
          _matrix_mul(&matrixA[0][0],&matrixC[0][0]);
      }
      
      int main(){
          matrix_size=512;
          set_timer(0);
          int_matrix_mul(matrix_size);
          printf("Integer Matrix Mul spend time: %f",get_timer(0));
          set_timer(0);
          float_matrix_mul(matrix_size);
          printf("Float Matrix Mul spend time: %f",get_timer(0));
          set_timer(0);
          double_matrix_mul(matrix_size);
          printf("Double Matrix Mul spend time: %f",get_timer(0));
      
      }
      
  • 測試環境
      硬體: 
              SOC: TEGRA3
              RAM: 1G 
      軟體:
              ICS 4.0.4
              GCC: arm-eabi-g++ 4.4.3

    測試的方式是每一個編譯出來的執行檔會測試四次,去掉特別大或特別小的值取出三個。測試分別對Integer, Float及 Double的size為256 的square matrix測試。下圖則是測試的結果。

Compiler 做了哪些最佳化?

我們都知道在編譯的時候可以下 O1 O2 等等的最佳化設定,但這些設定到底實際上做了哪些最佳化呢?我們可以利用下面這個指令知道:

$ arm-eabi-gcc -c -Q -O3 --help=optimizers 

以上面這個例子來說,當我們下-O3的時候實際上做了:

The following options control optimizations:
  -O                    
  -Os                           
  -falign-functions             [enabled]
  -falign-jumps                 [enabled]
  -falign-labels                [enabled]
  -falign-loops                 [disabled]
  -fargument-alias              [enabled]
  -fargument-noalias            [disabled]
  -fargument-noalias-anything   [disabled]
  -fargument-noalias-global     [disabled]
  -fasynchronous-unwind-tables   [disabled]
  -fbranch-count-reg            [enabled]
  -fbranch-probabilities        [disabled]
  -fbranch-target-load-optimize  [disabled]
  -fbranch-target-load-optimize2  [disabled]
  -fbtr-bb-exclusive            [disabled]
  -fcaller-saves                [enabled]
  -fcommon                      [enabled]
  -fconserve-stack              [disabled]
  -fcprop-registers             [enabled]
  -fcrossjumping                [enabled]
  -fcse-follow-jumps            [enabled]
  -fcse-skip-blocks             [disabled]
  -fcx-fortran-rules            [disabled]
  -fcx-limited-range            [disabled]
  -fdata-sections               [disabled]
  -fdce                         [enabled]
  -fdefer-pop                   [enabled]
  -fdelayed-branch              [disabled]
  -fdelete-null-pointer-checks   [enabled]
  -fdominance-check             [disabled]
  -fdse                         [enabled]
  -fearly-inlining              [enabled]
  -fexceptions                  [disabled]
  -fexpensive-optimizations     [enabled]
  -ffinite-math-only            [disabled]
  -ffloat-store                 [disabled]
  -fforward-propagate           [enabled]
  -fgcse                        [enabled]
  -fgcse-after-reload           [enabled]
  -fgcse-las                    [disabled]
  -fgcse-lm                     [enabled]
  -fgcse-sm                     [disabled]
  -fgraphite-identity           [disabled]
  -fguess-branch-probability    [enabled]
  -fhandle-exceptions           
  -fif-conversion               [enabled]
  -fif-conversion2              [enabled]
  -finline-functions            [enabled]
  -finline-functions-called-once  [enabled]
  -finline-small-functions      [enabled]
  -fipa-cp                      [enabled]
  -fipa-cp-clone                [enabled]
  -fipa-matrix-reorg            [disabled]
  -fipa-pta                     [disabled]
  -fipa-pure-const              [enabled]
  -fipa-reference               [enabled]
  -fipa-type-escape             [disabled]
  -fivopts                      [enabled]
  -fjump-tables                 [enabled]
  -flimit-hot-components        [disabled]
  -floop-block                  [disabled]
  -floop-interchange            [disabled]
  -floop-strip-mine             [disabled]
  -fmath-errno                  [enabled]
  -fmerge-all-constants         [disabled]
  -fmerge-constants             [enabled]
  -fmodulo-sched                [disabled]
  -fmove-loop-invariants        [enabled]
  -fnon-call-exceptions         [disabled]
  -fomit-frame-pointer          [enabled]
  -foptimize-register-move      [enabled]
  -foptimize-sibling-calls      [enabled]
  -fpack-struct                 [disabled]
  -fpack-struct=        
  -fpeel-loops                  [disabled]
  -fpeephole                    [enabled]
  -fpeephole2                   [enabled]
  -fpessimistic-inline-stack-limit  [enabled]
  -fpredictive-commoning        [enabled]
  -fprefetch-loop-arrays        [disabled]
  -fprofile-dump                [disabled]
  -frecord-options-in-elf       [disabled]
  -freg-struct-return           [enabled]
  -fregmove                     [enabled]
  -frename-registers            [enabled]
  -freorder-blocks              [enabled]
  -freorder-blocks-and-partition  [disabled]
  -freorder-functions           [enabled]
  -frerun-cse-after-loop        [enabled]
  -freschedule-modulo-scheduled-loops  [disabled]
  -frounding-math               [disabled]
  -frtti                        
  -fsample-profile              [disabled]
  -fsample-profile-use-entry    [disabled]
  -fsched-interblock            [enabled]
  -fsched-spec                  [enabled]
  -fsched-spec-load             [disabled]
  -fsched-spec-load-dangerous   [disabled]
  -fsched-stalled-insns         [disabled]
  -fsched-stalled-insns-dep     [enabled]
  -fsched2-use-superblocks      [disabled]
  -fsched2-use-traces           [disabled]
  -fschedule-insns              [enabled]
  -fschedule-insns2             [enabled]
  -fsection-anchors             [enabled]
  -fsel-sched-pipelining        [disabled]
  -fsel-sched-pipelining-outer-loops  [disabled]
  -fsel-sched-reschedule-pipelined  [disabled]
  -fselective-scheduling        [disabled]
  -fselective-scheduling2       [disabled]
  -fshort-double                
  -fshort-enums                 
  -fshort-wchar                 
  -fsignaling-nans              [disabled]
  -fsigned-zeros                [enabled]
  -fsingle-precision-constant   [disabled]
  -fsplit-ivs-in-unroller       [enabled]
  -fsplit-wide-types            [enabled]
  -fstrict-aliasing             [enabled]
  -fstrict-enum-precision       [enabled]
  -fthread-jumps                [enabled]
  -fno-threadsafe-statics       
  -ftoplevel-reorder            [enabled]
  -ftrapping-math               [enabled]
  -ftrapv                       [disabled]
  -ftree-builtin-call-dce       [enabled]
  -ftree-ccp                    [enabled]
  -ftree-ch                     [enabled]
  -ftree-copy-prop              [enabled]
  -ftree-copyrename             [enabled]
  -ftree-cselim                 [enabled]
  -ftree-dce                    [enabled]
  -ftree-dominator-opts         [enabled]
  -ftree-dse                    [enabled]
  -ftree-fre                    [enabled]
  -ftree-loop-distribution      [disabled]
  -ftree-loop-im                [enabled]
  -ftree-loop-ivcanon           [enabled]
  -ftree-loop-linear            [disabled]
  -ftree-loop-optimize          [enabled]
  -ftree-lr-shrinking           [enabled]
  -ftree-lrs                    [disabled]
  -ftree-pre                    [enabled]
  -ftree-reassoc                [enabled]
  -ftree-scev-cprop             [enabled]
  -ftree-sink                   [enabled]
  -ftree-sra                    [enabled]
  -ftree-switch-conversion      [enabled]
  -ftree-ter                    [enabled]
  -ftree-vect-loop-version      [enabled]
  -ftree-vectorize              [enabled]
  -ftree-vrp                    [enabled]
  -funit-at-a-time              [enabled]
  -funroll-all-loops            [disabled]
  -funroll-loops                [disabled]
  -funsafe-loop-optimizations   [disabled]
  -funsafe-math-optimizations   [disabled]
  -funswitch-loops              [enabled]
  -funwind-tables               [disabled]
  -fvar-tracking                [enabled]
  -fvar-tracking-uninit         [disabled]
  -fvariable-expansion-in-unroller  [disabled]
  -fvect-cost-model             [disabled]
  -fvpt                         [disabled]
  -fweb                         [enabled]
  -fwhole-program               [disabled]
  -fwrapv                       [disabled]

Cross Compile C/C++ using arm-eabi-gcc/g++( provide by Android) Directly

上一篇有提到我們可以使用agcc來幫我們解決Include header及Linking Library的問題。但因為他已經預設加入一些額外的編譯參數例如-march=armv5te等等,要一個個修改也頗煩不如直接寫個別project寫一個Makefile。因此參考agcc的方式下面show出我的Makefile的code。
P.S. 如同上一篇,在使用前必須要先Build Android來產生相關的Library

CPP = arm-eabi-g++
CC = arm-eabi-gcc
PRODUCT = cardhu
Android_PATH = /opt/compal/android/15r1
NAME = matrix_mal
CFLAG = -I$(Android_PATH)/system/core/include \
        -I$(Android_PATH)/hardware/libhardware/include \
        -I$(Android_PATH)/hardware/ril/include \
        -I$(Android_PATH)/dalvik/libnativehelper/include\
        -I$(Android_PATH)/frameworks/base/include \
        -I$(Android_PATH)/external/skia/include \
        -I$(Android_PATH)/out/target/product/$(PRODUCT)/obj/include\
        -I$(Android_PATH)/bionic/libc/arch-arm/include\
        -I$(Android_PATH)/bionic/libc/include \
        -I$(Android_PATH)/bionic/libstdc++/include\
        -I$(Android_PATH)/bionic/libc/kernel/common\
        -I$(Android_PATH)/bionic/libc/kernel/arch-arm\
        -I$(Android_PATH)/bionic/libm/include \
        -I$(Android_PATH)/bionic/libm/include/arch/arm \
        -I$(Android_PATH)/bionic/libthread_db/include\
        -I$(Android_PATH)/bionic/libm/arm\
        -I$(Android_PATH)/bionic/libm\
        -I$(Android_PATH)/out/target/product/$(PRODUCT)/obj/SHARED_LIBRARIES/libm_intermediates\
        -include $(Android_PATH)/system/core/include/arch/linux-arm/AndroidConfig.h

LDFLAGS = -mthumb-interwork -fpic -fno-exceptions -ffunction-sections \
        -funwind-tables -fstack-protector\
         -fmessage-length=0 -Bdynamic -Wl,-T,$(Android_PATH)/build/core/armelf.x\
         -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc \
         -Wl,--no-undefined -Wl,-rpath-link=$(Android_PATH)/out/target/product/$(PRODUCT)/obj/lib \
         -L$(Android_PATH)/out/target/product/$(PRODUCT)/obj/lib \
         -nostdlib $(Android_PATH)/out/target/product/$(PRODUCT)/obj/lib/crtend_android.o \
         $(Android_PATH)/out/target/product/$(PRODUCT)/obj/lib/crtbegin_dynamic.o \
         $(Android_PATH)/prebuilt/darwin-x86/toolchain/arm-eabi-4.4.3/lib/gcc/arm-eabi/4.4.3/libgcc.a\
         -lc -lm
                  
IGNORE = -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__\
         -DANDROID -DSK_RELEASE -DNDEBUG  -UDEBUG -march=armv5te -mtune=xscale\
         -msoft-float -mfloat-abi=hard


all:
    $(CPP) $(LDFLAGS) $(CFLAG) -o $(NAME) matrix_mal.cpp

要套用到自己的project只需修改

  1. Line 3: Android編譯的Product,例如如果是模擬器就把PRODUCT改成generic 
  2. Line 4: 修改Android Source Code的位置 Android_PATH
  3. Line 5: Binary的名字 NAME
  4. Line 40: Source Code的名字,替換matrix_mal.cpp
  5. Line 40如果是要編譯C code的話,將 CPP改成CC
另外,如果在編譯的時候想加入額外的參數,可以:
$ make CFLAG+="額外的參數"
或是如果想要指定binary的名稱,可以:
$ make NAME="名稱"

Cross Compile C/C++ using agcc(arm-eabi-gcc/g++ provide by Android)

如果你有Android的 Source Code 然後想要將C/C++ code  cross compile到ARM上面的話,可以使用 Android所提供的cross compiler。但有一個問題是,要真正拿來編譯的時候需要加入很多CFLAG(Include Header Path及Linking Library)。

比較方便的作法是直接使用agcc。這是外國人寫得一個perl的script,避免以後不見先貼上來。

#!/usr/bin/perl -w
use strict;

# Copyright 2008, Andrew Ross andy@plausible.org
# Distributable under the terms of the GNU GPL, see COPYING for details

# The Android toolchain is ... rough.  Rather than try to manage the
# complexity directly, this script wraps the tools into an "agcc" that
# works a lot like a gcc command line does for a native platform or a
# properly integrated cross-compiler.  It accepts arbitrary arguments,
# but interprets the following specially:
#
# -E/-S/-c/-shared - Enable needed arguments (linker flags, include
#                    directories, runtime startup objects...) for the
#                    specified compilation mode when building under
#                    android.
#
# -O - Turn on the optimizer flags used by the Dalvik build.  No
#           control is provided over low-level optimizer flags.
#
# -W - Turn on the warning flags used by the Dalvik build.  No
#           control is provided over specific gcc warning flags.
#
# Notes:
# + The prebuilt arm-eabi-gcc from a built (!) android source
#   directory must be on your PATH.
# + All files are compiled with -fPIC to an ARMv5TE target.  No
#   support is provided for thumb.
# + No need to pass a "-Wl,-soname" argument when linking with
#   -shared, it uses the file name always (so don't pass a directory in
#   the output path for a shared library!)

# Dance around to find the actual android toolchain path (it's very
# deep, so links on $PATH are going to be common.
my $GCC = `which arm-eabi-gcc`;
$GCC = qx(cd `dirname $GCC`; /bin/pwd);
chomp $GCC;
die "bad arm-eabi-gcc path" if $GCC !~ /(.*)\/prebuilt\//;
my $DROID = $1;

my $ALIB = "$DROID/out/target/product/generic/obj/lib";
my $TOOLCHAIN = "$DROID/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1";

my @include_paths = (
    "-I$DROID/system/core/include",
    "-I$DROID/hardware/libhardware/include",
    "-I$DROID/hardware/ril/include",
    "-I$DROID/dalvik/libnativehelper/include",
    "-I$DROID/frameworks/base/include",
    "-I$DROID/external/skia/include",
    "-I$DROID/out/target/product/generic/obj/include",
    "-I$DROID/bionic/libc/arch-arm/include",
    "-I$DROID/bionic/libc/include",
    "-I$DROID/bionic/libstdc++/include",
    "-I$DROID/bionic/libc/kernel/common",
    "-I$DROID/bionic/libc/kernel/arch-arm",
    "-I$DROID/bionic/libm/include",
    "-I$DROID/bionic/libm/include/arch/arm",
    "-I$DROID/bionic/libthread_db/include",
    "-I$DROID/bionic/libm/arm",
    "-I$DROID/bionic/libm",
    "-I$DROID/out/target/product/generic/obj/SHARED_LIBRARIES/libm_intermediates");

my @preprocess_args = (
    "-D__ARM_ARCH_5__",
    "-D__ARM_ARCH_5T__",
    "-D__ARM_ARCH_5E__",
    "-D__ARM_ARCH_5TE__", # Already defined by toolchain
    "-DANDROID",
    "-DSK_RELEASE",
    "-DNDEBUG",
    "-include", "$DROID/system/core/include/arch/linux-arm/AndroidConfig.h",
    "-UDEBUG");

my @warn_args = (
    "-Wall",
    "-Wno-unused", # why?
    "-Wno-multichar", # why?
    "-Wstrict-aliasing=2"); # Implicit in -Wall per texinfo

my @compile_args = (
    "-march=armv5te",
    "-mtune=xscale",
    "-msoft-float",
    "-mthumb-interwork",
    "-fpic",
    "-fno-exceptions",
    "-ffunction-sections",
    "-funwind-tables", # static exception-like tables
    "-fstack-protector", # check guard variable before return
    "-fmessage-length=0"); # No line length limit to error messages

my @optimize_args = (
    "-O2",
    "-finline-functions",
    "-finline-limit=300",
    "-fno-inline-functions-called-once",
    "-fgcse-after-reload",
    "-frerun-cse-after-loop", # Implicit in -O2 per texinfo
    "-frename-registers",
    "-fomit-frame-pointer",
    "-fstrict-aliasing", # Implicit in -O2 per texinfo
    "-funswitch-loops");

my @link_args = (
    "-Bdynamic",
    "-Wl,-T,$DROID/build/core/armelf.x",
    "-Wl,-dynamic-linker,/system/bin/linker",
    "-Wl,--gc-sections",
    "-Wl,-z,nocopyreloc",
    "-Wl,--no-undefined",
    "-Wl,-rpath-link=$ALIB",
    "-L$ALIB",
    "-nostdlib",
    "$ALIB/crtend_android.o",
    "$ALIB/crtbegin_dynamic.o",
    "$TOOLCHAIN/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a",
    "-lc",
    "-lm");
    
# Also need: -Wl,-soname,libXXXX.so
my @shared_args = (
    "-nostdlib",
    "-Wl,-T,$DROID/build/core/armelf.xsc",
    "-Wl,--gc-sections",
    "-Wl,-shared,-Bsymbolic",
    "-L$ALIB",
    "-Wl,--no-whole-archive",
    "-lc",
    "-lm",
    "-Wl,--no-undefined",
    "$TOOLCHAIN/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a",
    "-Wl,--whole-archive"); # .a, .o input files go *after* here

# Now implement a quick parser for a gcc-like command line

my %MODES = ("-E"=>1, "-c"=>1, "-S"=>1, "-shared"=>1);

my $mode = "DEFAULT";
my $out;
my $warn = 0;
my $opt = 0;
my @args = ();
my $have_src = 0;
while(@ARGV) {
    my $a = shift;
    if(defined $MODES{$a}) {
 die "Can't specify $a and $mode" if $mode ne "DEFAULT";
 $mode = $a;
    } elsif($a eq "-o") {
 die "Missing -o argument" if !@ARGV;
 die "Duplicate -o argument" if defined $out;
 $out = shift;
    } elsif($a =~ /^-W.*/) {
 $warn = 1;
    } elsif($a =~ /^-O.*/) {
 $opt = 1;
    } else {
 if($a =~ /\.(c|cpp|cxx)$/i) { $have_src = 1; }
 push @args, $a;
    }
}

my $need_cpp = 0;
my $need_compile = 0;
my $need_link = 0;
my $need_shlink = 0;
if($mode eq "DEFAULT") { $need_cpp = $need_compile = $need_link = 1; }
if($mode eq "-E") { $need_cpp = 1; }
if($mode eq "-c") { $need_cpp = $need_compile = 1; }
if($mode eq "-S") { $need_cpp = $need_compile = 1; }
if($mode eq "-shared") { $need_shlink = 1; }

if($have_src and $mode ne "-E") { $need_cpp = $need_compile = 1; }

# Assemble the command:
my @cmd = ("arm-eabi-gcc");
if($mode ne "DEFAULT") { @cmd = (@cmd, $mode); }
if(defined $out) { @cmd = (@cmd, "-o", $out); }
if($need_cpp) { @cmd = (@cmd, @include_paths, @preprocess_args); }
if($need_compile){
    @cmd = (@cmd, @compile_args);
    if($warn) { @cmd = (@cmd, @warn_args); }
    if($opt) { @cmd = (@cmd, @optimize_args); }
}
if($need_link) { @cmd = (@cmd, @link_args); }
if($need_shlink) { @cmd = (@cmd, @shared_args); }
@cmd = (@cmd, @args);

#print join(" ", @cmd), "\n"; # Spit it out if you're curious
exec(@cmd);
但是,有一個問題是他很多的變數都是寫死得,因此有幾個地方需要修改。下面是我修改的地方。要注意的是,我下面的修改是要編譯C++的程式,如果是要編譯C的話,要記得把g++改成gcc。

  1. Line 37:將路徑修改成你電腦上的arm-eabi-g++的位置
      $GCC = "/opt/compal/android/15r1/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-g++";
  2. Line 40:將$DROID改成你電腦上Android的位置
      my $DROID = "/opt/compal/android/15r1";
  3. Line 42:一般來說,如果是build模擬器的話可以把cardhu改成generic
      my $ALIB = "$DROID/out/target/product/cardhu/obj/lib";
  4. Line 43:一樣修改arm-eabi-g++的位置
      my $TOOLCHAIN = "/opt/compal/android/15r1/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-g++";
  5. Line 119:  
      "/opt/compal/android/15r1/prebuilt/darwin-x86/toolchain/arm-eabi-4.4.3/lib/gcc/arm-eabi/4.4.3/libgcc.a",
  6. Line 134:  d
      "/opt/compal/android/15r1/prebuilt/darwin-x86/toolchain/arm-eabi-4.4.3/lib/gcc/arm-eabi/4.4.3/libgcc.a",