1、 # make clean-helloworld “make clean-$(LOCAL_MODULE)”是Android編譯環境提供的make clean的方式。 Android編譯環境提供了”showcommands”選項來顯示編譯命令行,我們可以通過打開這個選項來查看一些編譯時的細節。 2、使用showcommands選項重新編譯helloworld: # make helloworld showcommands build/core/product_config.mk:229: WARNING: adding test OTA key target thumb C: helloworld <= development/hello/hello.c prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc -I system/core/include -I hardware/libhardware/include -I hardware/ril/include -I dalvik/libnativehelper/include -I frameworks/base/include -I external/skia/include -I out/target/product/generic/obj/include -I bionic/libc/arch-arm/include -I bionic/libc/include -I bionic/libstdc++/include -I bionic/libc/kernel/common -I bionic/libc/kernel/arch-arm -I bionic/libm/include -I bionic/libm/include/arch/arm -I bionic/libthread_db/include -I development/hello -I out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates -c -fno-exceptions -Wno-multichar -march=armv5te -mtune=xscale -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -include system/core/include/arch/linux-arm/AndroidConfig.h -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -DSK_RELEASE -DNDEBUG -O2 -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -MD -o out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o development/hello/hello.c target Executable: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld) prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-g++ -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld -Lout/target/product/generic/obj/lib -Wl,-rpath-link=out/target/product/generic/obj/lib -lc -lstdc++ -lm out/target/product/generic/obj/lib/crtbegin_dynamic.o out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o -Wl,--no-undefined prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a out/target/product/generic/obj/lib/crtend_android.o target Non-prelinked: helloworld (out/target/product/generic/symbols/system/bin/helloworld) out/host/linux-x86/bin/acp -fpt out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld out/target/product/generic/symbols/system/bin/helloworld target Strip: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/helloworld) out/host/linux-x86/bin/soslim --strip --shady --quiet out/target/product/generic/symbols/system/bin/helloworld --outfile out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/helloworld Install: out/target/product/generic/system/bin/helloworld out/host/linux-x86/bin/acp -fpt out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/helloworld out/target/product/generic/system/bin/helloworld 從上面的命令行可以看到,Android編譯環境所用的交叉編譯工具鏈是prebuilt/linux-x86/toolchain /arm-eabi-4.2.1/bin/arm-eabi-gcc,-I和-L參數指定了所用的C庫頭文件和動態庫文件路徑分別是bionic /libc/include 和out/target/product/generic/obj/lib,其他還包括很多編譯選項以及-D所定義的預編譯宏。 我們可以利用上面的編譯命令,稍加簡化來手工編譯helloworld程序。先手工刪除上次編譯得到的helloworld程序: # rm out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o # rm out/target/product/generic/system/bin/helloworld 再用gcc編譯,生成目標文件: # prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc -I bionic/libc/arch-arm/include -I bionic/libc/include -I bionic/libc/kernel/common -I bionic/libc/kernel/arch-arm -c -fno-exceptions -Wno-multichar -march=armv5te -mtune=xscale -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -include system/core/include/arch/linux-arm/AndroidConfig.h -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -DSK_RELEASE -DNDEBUG -O2 -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -MD -o out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o development/hello/hello.c 與Android.mk編譯參數比較,上面主要減少了不必要的-I參數。 接下來生成可執行文件: # prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld -Lout/target/product/generic/obj/lib -Wl,-rpath-link=out/target/product/generic/obj/lib -lc -lm out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o out/target/product/generic/obj/lib/crtbegin_dynamic.o -Wl,--no-undefined ./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a out/target/product/generic/obj/lib/crtend_android.o 這裏值得留意的是參數“-Wl,-dynamic-linker,/system/bin/linker”,它指定了Android專用的動態鏈接器/system/bin/linker,而不是通常所用的ld.so。 3、生成的可執行程序可用file和readelf命令來查看一下: # file out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped # readelf -d out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld |grep NEEDED 0x00000001 (NEEDED) Shared library: [libc.so] 0x00000001 (NEEDED) Shared library: [libm.so] 這是ARM格式的動態鏈接可執行文件,運行時需要libc.so和libm.so。“not stripped”表示它還沒被STRIP。嵌入式系統中爲節省空間通常將編譯完成的可執行文件或動態庫進行STRIP,即去掉其中多餘的符號表信息。在 前面“make helloworld showcommands”命令的最後我們也可以看到,Android編譯環境中使用了out/host/linux-x86/bin/soslim工具 進行STRIP。 有關Android Toolchain的其他一些內容可參考:Android Toolchain與Bionic Libc 4、由linux-arm.mk 開始分析 先看看註釋部分(eclair) 1 # Configuration for Linux on ARM. 2 # Included by combo/select.make 3 4 # You can set TARGET_ARCH_VARIANT to use an arch version other 5 # than ARMv5TE. Each value should correspond to a file named 6 # $(BUILD_COMBOS)/arch/<name>.mk which must contain 7 # makefile variable definitions similar to the preprocessor 8 # defines in system/core/include/arch/<combo>/AndroidConfig.h. Their 9 # purpose is to allow module Android.mk files to selectively compile 10 # different versions of code based upon the funtionality and 11 # instructions available in a given architecture version. 12 # 13 # The blocks also define specific arch_variant_cflags, which 14 # include defines, and compiler settings for the given architecture 15 # version. 16 # 17 ifeq ($(strip $(TARGET_ARCH_VARIANT)),) 18 TARGET_ARCH_VARIANT := armv5te 19 endif 你可以通過設定TARGET_ARCH_VARIANT=yournane而不採用android默認使用的ARMv5TE指令集。你的yourname的值應該當和$(BUILD_COMBOS)/arch/<name>.mk中的name名稱相同。 system/core/include/arch/linux-arm/AndroidConfig.h中定義了arm編譯時的一些定義供C/C++程序引用,這些定義的目的是允許Android.mk 可以根據指定的硬件架構的功能和指令的不同可以有選擇性進行編譯。 20 21 # TARGET_ARCH_VARIANT used to be called TARGET_ARCH_VERSION 22 # to avoid any weirdness, issue an error message if the latter 23 # is defined. 24 # 25 ifneq ($(strip $(TARGET_ARCH_VERSION)),) 26 $(info Definition for TARGET_ARCH_VERSION encountered !) 27 $(info This variable has been renamed TARGET_ARCH_VARIANT, please update your build files !!) 28 $(error Aborting the build.) 29 endif 30 31 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk 32 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),) 33 $(error Unknown ARM architecture version: $(TARGET_ARCH_VARIANT)) 34 endif 35 36 include $(TARGET_ARCH_SPECIFIC_MAKEFILE) TARGET_ARCH_VARIANT 會被 TARGET_ARCH_VERSION調用, TARGET_ARCH_VERSION不能被直接聲明,否則會報錯。 根據 TARGET_ARCH_VARIANT的設置加載對應的build/core/combo/arch/arm/armv???.mk文件。 38 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else 39 ifeq ($(strip $($(combo_target)TOOLS_PREFIX)),) 40 $(combo_target)TOOLS_PREFIX := \ 41 prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.4.0/bin/arm-eabi- 42 endif 43 44 $(combo_target)CC := $($(combo_target)TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX) 45 $(combo_target)CXX := $($(combo_target)TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX) 46 $(combo_target)AR := $($(combo_target)TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX) 47 $(combo_target)OBJCOPY := $($(combo_target)TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX) 48 $(combo_target)LD := $($(combo_target)TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX) 49 50 $(combo_target)NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined 51 52 TARGET_arm_CFLAGS := -O2 \ 53 -fomit-frame-pointer \ 54 -fstrict-aliasing \ 55 -funswitch-loops \ 56 -finline-limit=300 如果你想採用自己的交叉編譯器,可以通過設定TARGET_TOOLS_PREFIX來達到效果。否則android會採用自己的prebuild 的交叉編譯器。
thumb來進行源碼編譯。
thumb,則強制使用 thumb的交互方式。
CUSTOM_KERNEL_HEADERS 進行定義,那麼默認的系統頭文件位置在out爲根目錄的位置。 TARGET_ARCH_VARIANT 和其關聯的兩個重要的文件 build/core/combo/arch/arm/armv???.mk 以及
system/core/include/arch/linux-arm/AndroidConfig.h, 這些確定你編譯的細節。 TARGET_ARCH_VARIANT應該可以設定在你的 product.mk中。 雖然android建議不要修改這些文件,但我們可以修改這些文件來達到特殊目的。 |
Android編譯環境 相關
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.