• Compile a native C Android application


    原文: Compile a native C Android application
    翻译: Zhiwei.Li

    通过上网搜索,你可以发现很多种编译Android native应用的方法.我想说的是,不同的控制台应用, 守护程序(daemon), C/C++库,等等.这些程序在你自己的计算机上
    编译没有任何问题.

    为了给Android编译程序,你需要ARM工具链(toolchain). 我发现有两种主张,分别是使用Android Prebuild toolchain和CodeSourcery
    1)Android Prebuild toolchain
    Android没有使用传统的libc库.相反,它用了Bionic库,一个由Google开发的,用在Android移动软件平台上的轻量级的libc
    Bionic被裁剪到只支持 Android系统.  请看 六百万美元的c程序库

    2)CodeSourcery
    CodeSourcery是ARM的合作伙伴. 专门为ARM处理器开发增强GUN工具链的,并提供验证过的GNU工具链.这些工具链有很多不同的版本.
    对于Android平台,需要 arm-none-linux-gnueabi, 而 arm-none-eabi是没有glibc包含在里面的,主要面向那些编译完整的native库和应用(比如FreeRTOS)
    译者注: arm-none-eabi就是用来编译裸机程序的,请参考 最简单的ARM裸机程序

    我个人的观点,如果白手起家开始创建一个Android的应用程序,你应该选择Bionic.
    但是如果你选择从你的PC环境移植一个库到Android,你应该选择CodeSourcery
    如果你使用到线程或者C++异常,Bionic库也不能完全支持它们(实际上,它根本就不支持异常)

    agcc.pl是Andrew Ross开发的一个脚本,让你以一种很简单的方法来自动包含常用的库,使用Android的ARM工具链gcc
    某种程度上,他像makefile

    第1种方法  使用Makefile和Android NDK

    AR = arm-linux-androideabi-ar
    AS = arm-linux-androideabi-as
    CC = arm-linux-androideabi-gcc
    CXX = arm-linux-androideabi-g++
    LD = arm-linux-androideabi-ld.gold
    
    NDK_KIT = /home/tim/android-ndk-r10b
    PLATF_KIT = platforms/android-9
    
    ARM_INC = $(NDK_KIT)/$(PLATF_KIT)/arch-arm/usr/include
    ARM_LIB = $(NDK_KIT)/$(PLATF_KIT)/arch-arm/usr/lib
    
    OBJS = hello.o
    EXES = hello
    
    hello :  hello.o
    	$(LD) --dynamic-linker=/system/bin/linker -nostdlib 
    		-rpath-link=$(ARM_LIB) 
    		$(ARM_LIB)/crtbegin_dynamic.o 
    		-L$(ARM_LIB)  -lc 
    		-o hello hello.o
    
    hello.o: hello.c
    	$(CC) -I $(ARM_INC) -c hello.c
    
    clean:
    	rm -f $(OBJS) $(EXES)
    

    源代码

    #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
      printf("Hello Android
    ");
      return 0;
    }

    设置环境变量 envsetup.sh

    export PATH=$PATH:/home/tim/android-ndk-r10b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin

    最后,运行 make 就可以了

    关于 -rpath-link选项,请参考 gcc链接选项

    第二种简单方法,使用shell脚本

    #!/bin/sh
    
    OS='linux'
    ANDROIDSDK='android-14'
    
    PROGDIR='/home/tim/android-ndk-r10b/'
    
    PROGDIR=`cd $PROGDIR && pwd`
    ARMEABIGCC=$PROGDIR/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
    ARMEABILIB=$PROGDIR/platforms/$ANDROIDSDK/arch-arm/usr/lib
    ARMEABIINC=$PROGDIR/platforms/$ANDROIDSDK/arch-arm/usr/include
    ARMEABICRT="$ARMEABILIB/crtbegin_dynamic.o $ARMEABILIB/crtend_android.o"
    
    LINKER=/system/bin/linker
    
    echo "GCC:"$ARMEABIGCC "LIB:"$ARMEABILIB "LINKER":$LINKER "PARAMS:"$@
    echo "CRT:"$ARMEABICRT
    
    $ARMEABIGCC $@ -Wl,-rpath-link=$ARMEABILIB,-dynamic-linker=$LINKER -L$ARMEABILIB $ARMEABICRT -I$ARMEABIINC -nostdlib -lc

    保存为b
    ./b hello.c -o hello
    就可以了

    实际就是运行命令

    /home/tim/android-ndk-r10b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc 
      -Wl,-rpath-link=/home/tim/android-ndk-r10b/platforms/android-16/arch-arm/usr/lib,-dynamic-linker=/system/bin/linker 
      -L/home/tim/android-ndk-r10b/platforms/android-16/arch-arm/usr/lib  
      /home/tim/android-ndk-r10b/platforms/android-16/arch-arm/usr/lib/crtbegin_dynamic.o   /home/tim/android-ndk-r10b/platforms/android-16/arch-arm/usr/lib/crtend_android.o  
       -I/home/tim/android-ndk-r10b/platforms/android-16/arch-arm/usr/include -nostdlib -lc 
       hello.c -o hello
    

    crtbegin_dynamic.o 和 crtend_android.o必须配对使用

    第三种方法,用–sysroot也是可以的

    #!/bin/sh
    
    NDK=/home/tim/android-ndk-r8e
    SYSROOT=$NDK/platforms/android-9/arch-arm
    CC="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT"
    CFLAGS='-march=armv7-a -mfloat-abi=softfp -mfpu=neon'
    LDFLAGS='-Wl,--fix-cortex-a8'
    $CC $@

    http://www.srombauts.fr/2011/03/06/standalone-toolchain/

    #include  <stdio.h>
    #include <android/log.h>
    
    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "hello-ndk", __VA_ARGS__))
    
    int main(void)
    {
        printf("Hello from NDKn");
        LOGI("Hello from NDK");
        return 0;
    }

    果然厉害,上面这段代码都可以这样编译

    ./b9 -l log nl.c -o hn

    用Makefile也能搞

    CC  = arm-linux-androideabi-gcc
    CFLAGS  = -Wall -g
    LDFLAGS = -llog
    SRC =hello-ndk.c
    OBJ =$(SRC:.c=.o)
    EXE =hello-ndk
    
    all: $(SRC) $(EXE)
    
    $(EXE): $(OBJ)
        $(CC) -o $@ $^ $(LDFLAGS)
    
    %.o: %.c
        $(CC) -o $@ -c $< $(CFLAGS)
    
    clean:
        rm -f *.o $(EXE)
    

    编译so库也是可以,厉害

    CC  = arm-linux-androideabi-gcc
    CFLAGS  = -Wall -g
    LDFLAGS = -llog -shared
    SRC =hello-ndk.c
    OBJ =$(SRC:.c=.o)
    EXE =libhello-ndk.so
    

    还可以直接运行 gcc

    /home/tim/android-ndk-r10/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=/home/tim/android-ndk-r10/platforms/android-3/arch-arm   -lc -lm   -g main.c -o mm
    

    第4种方法,用ndk-build 
    创建工程目录hello,然后在其下创建子目录jni
    然后在jni下创建两个文件,一个是hello.c,另外一个是Android.mk,内容如下

    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_SRC_FILES:=hello.c
    LOCAL_MODULE := helloworld
    LOCAL_MODULE_TAGS := optional
    include $(BUILD_EXECUTABLE)
    

    其中 LOCAL_MODULE_TAGS := optional  这行可以不要

    进入到hello目录下,运行下面的命令

    # export NDK_PROJECT_PATH=`pwd`
    # ndk-build
    Compile thumb  : helloworld <= hello.c Executable     : helloworld Install        : helloworld => libs/armeabi/helloworld
  • 相关阅读:
    Mysql任务调度
    使用 IntraWeb (18)
    使用 IntraWeb (17)
    替盛大代发的招聘启示
    使用 IntraWeb (16)
    使用 IntraWeb (15)
    使用 IntraWeb (14)
    使用 IntraWeb (13)
    使用 IntraWeb (12)
    使用 IntraWeb (11)
  • 原文地址:https://www.cnblogs.com/GoAhead/p/4186707.html
Copyright © 2020-2023  润新知