android build system

1、gcc编译参数详解

1)-E

指示编译器对输入文件进行预处理,并将结果输出到标准输出(控制台)。预处理包括头文件的包含、宏定义的扩展、条件编译的选择等。

2)-D和-U

-D在命令行定义宏,作用等同于在代码中进程宏定义;-U用于取消宏定义。

例如–DDEBUG=1   <=>#define DEBUG 1

#include <stdio.h>
int main()
{
    printf("hello world!\n");	
    #ifdef DEBUG
      printf("hello debug!\n");	
    #endif
    return 0;
}

不带—D进行编译的输出结果

hxiong@www_hxiong_com /cygdrive/e/project/cygwin_project/c_project/debug
$ gcc -o main main.c
hxiong@www_hxiong_com /cygdrive/e/project/cygwin_project/c_project/debug
$ ./main
hello world!

hxiong@www_hxiong_com /cygdrive/e/project/cygwin_project/c_project/debug
$

带—D进行编译的输出结果

hxiong@www_hxiong_com /cygdrive/e/project/cygwin_project/c_project/debug
$ gcc -DDEBUG=1 -o main main.c
hxiong@www_hxiong_com /cygdrive/e/project/cygwin_project/c_project/debug
$ ./main
hello world!
hello debug!

hxiong@www_hxiong_com /cygdrive/e/project/cygwin_project/c_project/debug
$

3)-S

指示编译器产生汇编代码文件后停止,汇编代码缺省的文件后缀名是.s

例如gcc –S main.c            

会生成main.s文件,内容如下

	.file	"main.c"
	.def	__main;	.scl	2;	.type	32;	.endef
	.section .rdata,"dr"
.LC0:
	.ascii "hello world!\0"
	.text
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	$32, %rsp
	.seh_stackalloc	32
	.seh_endprologue
	call	__main
	leaq	.LC0(%rip), %rcx
	call	puts
	movl	$0, %eax
	addq	$32, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (GNU) 4.9.3"
	.def	puts;	.scl	2;	.type	32;	.endef

4)-c

指示编译器只编译源文件,但不进行连接,生成的文件为.o,这是可以重定向的目标程序。

5)-o

指示编译器为生成的可执行文件指定文件名,也就是设置可执行文件的文件名

6)-g

指示编译器产生可以被gnu调试工具进行调试的程序。

7)-l

用来指定程序要连接的库,例如 gcc –lc 实际上是链接libc.so库,也就是去掉了库前面的lib和后面的.so。

8)-L

指定连接的库文件所在的目录,例如gcc –L/usr/lib –lc就是链接/usr/lib目录下的libc.so库。

9)-include和-I

-include指定要包含的头文件,-I用于指定头文件所在的目录。

10)-Wl

WL后面的参数会传给链接程序

11)-shared

生成共享目标文件,通常用于编译动态库文件。

2、编译可执行程序

我们以cameraserve为例,Android.mk指定了编译的规则

frameworks\av\camera\cameraserver\Android.mk

# LOCAL_PATH重新赋值为当前的路径
LOCAL_PATH:= $(call my-dir)
# 清除之前设置的LOCAL_XXX变量,除了LOCAL_PATH
include $(CLEAR_VARS)
# 设置需要需要编译的源文件
LOCAL_SRC_FILES:= \
	main_cameraserver.cpp
# 设置需要链接的动态库
LOCAL_SHARED_LIBRARIES := \
	libcameraservice \
	libcutils \
	libutils \
	libbinder \
	libcamera_client
# 设置编译出来的目标文件名
LOCAL_MODULE:= cameraserver
LOCAL_32_BIT_ONLY := true
# gcc编译参数的设置
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
# 设置rc文件
LOCAL_INIT_RC := cameraserver.rc
# 指定要编译成可执行程序文件
include $(BUILD_EXECUTABLE)

BUILD_EXECUTABLE定义在

build\core\config.mk

…
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
…

所以include $(BUILD_EXECUTABLE) 实际上是 include build/core/executable.mk

 

我们继续看executable.mk 做了什么事

差不多是做了一大堆的设置和检查工作,最后include executable_internal.mk

build\core\executable.mk

…
# check if non-preferred arch is supported
include $(BUILD_SYSTEM)/module_arch_supported.mk
ifeq ($(my_module_arch_supported),true)
# non-preferred arch is supported
OVERRIDE_BUILT_MODULE_PATH :=
LOCAL_BUILT_MODULE :=
LOCAL_INSTALLED_MODULE :=
LOCAL_INTERMEDIATE_TARGETS :=
include $(BUILD_SYSTEM)/executable_internal.mk
endif
…

我们继续往下看executable_internal.mk 做了什么事

build\core\executable_internal.mk

…
ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)  #这里表示编译静态可执行程序
$(linked_module): $(my_target_crtbegin_static_o) $(all_objects) $(all_libraries) $(my_target_crtend_o)
	$(transform-o-to-static-executable)
	$(PRIVATE_POST_LINK_CMD)
else  #否则编译动态可执行程序,需要连接动态库
$(linked_module): $(my_target_crtbegin_dynamic_o) $(all_objects) $(all_libraries) $(my_target_crtend_o)
	$(transform-o-to-executable)
	$(PRIVATE_POST_LINK_CMD)
endif
…

$(linked_module):针对cameraserver out/target/product/$(project)/arm/EXECUTABLES/cameraserver_intermediates/LINKED/cameraserver

$( my_target_crtbegin_dynamic_o): out/target/product/$(project)/arm/lib/ crtbegin_dynamic.o

$(all_objects):是out/target/product/$(project)/arm/EXECUTABLES/cameraserver_intermediates/main_cameraserver.o

$(all_libraries):是out/target/product/$(project)/arm/lib/cameraservice.so 也就是LOCAL_SHARED_LIBRARIES引用的so,当然还包括libc.so libm.so

$(my_target_crtend_o):是out/target/product/$(project)/arm/lib/crtend_android.o

$( transform-o-to-executable) 是执行gcc编译命令的命令行。

定义在build\core\ definitions.mk

define transform-o-to-executable
@echo "target Executable: $(PRIVATE_MODULE) ($@)"
@mkdir -p $(dir $@)
$(transform-o-to-executable-inner)
endef
makefile中的define endef可以认为它就是定义了一个函数,里面的内容就是执行的命令。

define transform-o-to-executable-inner
$(hide) $(PRIVATE_CXX) -pie \
	-nostdlib -Bdynamic \
	-Wl,-dynamic-linker,$(PRIVATE_LINKER) \
	-Wl,--gc-sections \
	-Wl,-z,nocopyreloc \
	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
	-Wl,-rpath-link=$(PRIVATE_TARGET_OUT_INTERMEDIATE_LIBRARIES) \
	$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O) \
	$(PRIVATE_ALL_OBJECTS) \
	-Wl,--whole-archive \
	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
	-Wl,--no-whole-archive \
	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_COVERAGE_LIB)) \
	$(PRIVATE_TARGET_LIBATOMIC) \
	$(PRIVATE_TARGET_LIBGCC) \
	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
	-o $@ \
	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
	$(PRIVATE_LDFLAGS) \
	$(PRIVATE_TARGET_CRTEND_O) \
	$(PRIVATE_LDLIBS)
endef
transform-o-to-executable-inner里面就是gcc编译出可执行程序的命令,在知道gcc命令参数的情况下,我们把里面的参数还原出来。

$(hide):这里就是一个字符@  @放在命令的前面是在执行的时候不将命令打印出来。

$(PRIVATE_CXX):这里是prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-g++

所以$(hide) $(PRIVATE_CXX) 就是调用g++程序来进行编译,后面就都是gcc/g++的相关参数了,前面有讲一些。

-pie 加了这个参数后,程序的地址是可以变化的。

-Wl,-dynamic-linker 用于设置动态链接器

$(PRIVATE_LINKER): 这里是 /system/bin/linker64  (64位)

$(PRIVATE_TARGET_GLOBAL_LD_DIRS):这里是-Lout/target/product/$(project)/arm/lib

$(PRIVATE_TARGET_OUT_INTERMEDIATE_LIBRARIES):这里是out/target/product/$(project)/arm/lib

$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O):这里是out/target/product/$(project)/arm/lib/crtbegin_dynamic.o

$(PRIVATE_ALL_OBJECTS):这里是out/target/product/$(project)/arm/EXECUTABLES/cameraserver_intermediates/main_cameraserver.o

$(PRIVATE_TARGET_LIBGCC) 是prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9/libgcc.a

$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES))执行的结果是得到需要连接的lib库,比如 lcameraservice lbinder lc lutils ... 也就是LOCAL_SHARED_LIBRARIES包含的库和必需的库,用空格分开。

$@ 是out/target/product/$(project)/arm/EXECUTABLES/cameraserver_intermediates/LINKED/cameraserver

$(PRIVATE_TARGET_GLOBAL_LDFLAGS)是-WL,-z,noexecstack  –WL,-z,relro –WL,-z,now –WL,…

–WL,-z,now 表示函数立刻绑定

$(PRIVATE_TARGET_CRTEND_O) 是out/target/product/$(project)/arm/lib/ crtend_android.o





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值