NDK - gcc与makefile

Android开发时,有时候需要移植第三方库进项目,需要对第三方库进行交叉编译生成Android可用的动态库或者静态库。因此需要了解c/c++的编译的基本使用,了解相应的参数设置。

Android的Android.mk就是Makefile单元,很多第三方库直接提供makefile,虽然Google推荐使用CMake,但是一些老项目还是使用的mk。因此还是需要能读懂Android.mk文件。

如果出去面试,说会NDK开发,但是不了解makefile,别人是不会信服的。好了好了,不扯皮子了,进入今天的主题。

gcc / g++ / clang

clang
clang 是一个C、C++、Object-C的轻量级编译器。基于LLVM(LLVM是以c++编写而成的架构编译器的框架系统,可以说是一个用于开发编译器相关的库)
gcc
GNU C编译器,原本只能处理C,后来扩展也可以出了C++。(GNU计划,又称格奴计划,目标是创建一套完全自由的操作系统)
g++
GNU C++编译器

  • gcc和g++都能够编译c/c++,但是编译时候行为不同。
  • clang也是一个编译器,对比gcc,它具有编译速度更快、编译产出更小等优点,但是某些软件在使用clang编译时候因为源码中内容的问题会出现错误。
  • clang++与clang就相当于gcc与g++。

gcc与g++的对比:

  • 后缀为.c的源文件,gcc把它当作是C程序,而g++当作是C++程序;后缀为.cpp的,两者都会认为是c++程序
  • g++会自动链接c++标准库stl,gcc不会
  • gcc不会定义__cplusplus宏,而g++会

编译器过程

一个C/C++文件要经过:预处理(preprocessing)编译(compilation)汇编(assembly)链接(linking)才能变成可执行文件。
1、预处理
gcc -E test.c -o test.i ; -E的作用是让gcc在预处理结束后停止编译。预处理阶段主要处理includedefine等。它把include倒入的h文件插入到include所在的位置,把源程序中使用到的define定义的宏用实际的字符串代替。
2、编译阶段
gcc -S test.i -o test.s ; -S的作用是编译结束后,生成汇编文件。gcc首先检查代码规范性、是否有语法错误等,以确定代码的实际工作内容,检查无误后,gcc把代码翻译成汇编语言。
3、汇编阶段
gcc -c test.s -o test.o ; 将.s文件翻译成二进制机器指令.o文件
4、链接阶段
gcc -o test test.s ; 链接阶段链接的是 函数库。在test.c中并没有定义某些函数,且在预编译中包含进的stdio.h等库中也有此函数的申明。系统将这些函数的实现都被做到名为 libc.so的动态库。

Makefile

Makefile:自动化编译,告诉make命令如何编译和链接,即make工具的配置脚本。定义一系列的规则来指定哪些文件需要先编译后编译,如何进行链接等等操作。
Makefile规则:
在Makefile中的命令,必须要以[Tab]键开始,不要使用空格space键。

target : prerequisites ...
    command
---------------------------------------------------------------------------------------------------------------------------
    target:是目标文件,可以是object file 也可以是执行文件,也可以是一个标签
    prerequisites:生成target文件需要的的文件或者其他target
    command: 就是make需要执行的命令(任意的shell命令)

#gcc -o
#gcc -c
a.o:a.cpp c.h
    gcc -c a.cpp
test:a.o 
    gcc -o test a.o 
----------------------------------------------------------------------------------------------------------------------------
#一步到位,make会自动推到生成a.o,不需要上面的复杂步骤
test2:
    gcc -o test2 a.cpp \
b.cpp

clean:
    rm test test2 a.o b.o
say:
    echo 'test'

#clean 和say 是标签,并不生成 clean这个文件,这样的target称之为‘伪目标’
#伪目标的名字不能和文件名重复
#如果当前目录下有文件/文件夹 名字为clean,运行make clean 会报错:
#    make: 'clean' is up to date
#如何避免伪目标和标签冲突呢,可以使用特殊标记
.PHONY: clean
clean:
    rm test a.o
#变量,相当于c中的宏
#申明变量
objects = a.o b.o
test:${objects}
    gcc -o test ${objects}
clean:
    rm test ${objects}
#include
#include make.clean
mk=make.clean
include ${make}
#条件语句
ifeq ($(CC),gcc)
    $(CC) -o foo $(objects) $(libs_for_gcc)
else
    $(CC) -o foo $(objects) $(normal_libs)
endif

#输出信息
output=2333
${warning ${output}}
${info ${output}}

Android.mk

微小的GNU make片段
将源文件分组为模块。模块是静态库、共享库或者独立可执行文件。mk中可以定义一个或多个模块,也可以在多个模块中使用同一个源文件

#源文件在的位置。宏函数 my-dir 返回当前目录(包含 Android.mk 文件本身的目录)的路径。
LOCAL_PATH := $(call my-dir)
#引入其他makefile文件。CLEAR_VARS 变量指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量
#不会清理 LOCAL_PATH 变量
include $(CLEAR_VARS)
#存储您要构建的模块的名称 每个模块名称必须唯一,且不含任何空格
#如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。
LOCAL_MODULE := caterpillar
#包含要构建到模块中的 C 和/或 C++ 源文件列表 以空格分开
LOCAL_SRC_FILES := caterpillar.cpp
#构建动态库
include $(BUILD_SHARED_LIBRARY)

定义自己的任意变量。在定义变量时请注意,NDK 构建系统会预留以下变量名称:

  • 以 LOCAL_ 开头的名称,例如 LOCAL_MODULE。
  • 以 PRIVATE_、NDK_ 或 APP 开头的名称。构建系统在内部使用这些变量。
  • 小写名称,例如 my-dir。构建系统也是在内部使用这些变量。
  • 如果为了方便而需要在 Android.mk 文件中定义自己的变量,建议在名称前附加 MY_。

常用内置变量

变量名 含义 示例
BUILD_STATIC_LIBRARY 构建静态库 include $(BUILD_STATIC_LIBRARY)
PREBUILT_SHARED_LIBRARY 预编译共享库 include $(PREBUILT_SHARED_LIBRARY)
PREBUILT_STATIC_LIBRARY 预编译静态库 include $(PREBUILT_STATIC_LIBRARY)
TARGET_PLATFORM Android API 版本 TARGET_PLATFORM := android-22
TARGET_ARCH CUP架构 arm arm64 x86 x86_64
TARGET_ARCH_ABI CPU架构 armeabi armeabi-v7a arm64-v8a

模块描述变量

变量名 描述
LOCAL_MODULE_FILENAME 覆盖构建系统默认用于其生成的文件的名称 LOCAL_MODULE := foo LOCAL_MODULE_FILENAME := libnewfoo
LOCAL_CPP_FEATURES 特定 C++ 功能 支持异常:LOCAL_CPP_FEATURES := exceptions
LOCAL_C_INCLUDES 头文件目录查找路径 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CFLAGS 构建C 的编译参数
LOCAL_CPPFLAGS 构建c++编译参数
LOCAL_STATIC_LIBRARIES 依赖的静态库模块列表
LOCAL_SHARED_LIBRARIES 依赖的共享库模块列表
LOCAL_WHOLE_STATIC_LIBRARIES --whole-archive 将未使用的函数符号也加入编译进入这个模块
LOCAL_LDLIBS 依赖 系统库 LOCAL_LDLIBS := -l

引入其他模块

#将一个新的路径添加到NDK_MODULE_PATH变量
#NDK_MODULE_PATH 变量是系统的环境变量
$(call imort-add-path,$(LOCAL_PATH)/platform/third_party/android/prebuilt)
#包含cocosdenshion/android目录下的mk文件
$(call import-module,CocosDenshion/android)

Application.mk

不同于Android.mk,定义的都是一些全局(项目)的配置
常用内置变量

变量名 含义 参数
APP_OPTIM release、debug
APP_CFLAGS 构建c编译参数
APP_CPPFLAGS 构建cpp编译参数
APP_ABI 生成的cpu架构 armeabi、armeabi-v7a、armeabl-v8a、x86、x86_64、mips、mips64、all
APP_PLATFORM platform版本 android-8、android-9等等
APP_STL 构建时最小c++运行是库 libstdc++、gabi++_static、gabi++_shared、stlport_static、gnustl_static、gnustl_shared、c++_static、c++_shared
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342