自己动手构造编译系统豆瓣
1. 编译调试Android系统原生App - 以Settings为例
本文已过时,最新文章:向大家推荐《使用 AS 开发 System App》 https://xiaozhuanlan.com/system-app
Android原生系统带有许多原生的App,比如 浏览器、录音机、计算器、设置 等,有些时候,我们需要用到一些系统的功能,或者是对已有的功能做二次开发,比如我上学时给一个公司做过一个Launcher和Wizard,就需要用到系统设置中的某些功能,比如Wifi、声音、显示等功能,于是就需要从Settings源码中提取出需要的功能。
特别是公司自己定制Android系统,需要在上面做一些 系统级的App 的时候,原生App已有的功能就可以通过编译其源码的方式直接拿过来改改就能用,而且可用度很高。
这里有两种情况,分为 原生 的和 公司定制 的系统。无论是原生的还是定制的,类似于Settings这样需要使用到 系统级或隐藏API 的App,都需要系统签名文件和编译系统源码后得到相应的jar包才可以在IDE中编译,因为标准SDK根本没有那些API可供调用。
举个栗子:
需要额外的Jar就需要自己编译系统源码啦,这个是比较麻烦的,有兴趣可以试试自己编译定制自己的Android系统。
** 注意,既然是定制的,源码、jar、签名文件,还有系统都是一一对应的,你不能拿其他公司的系统签名来给你公司的系统app签名,这样无法运行的。 **
有了源码,下一步当然是要跑起来啦。
建议都使用Eclipse来编译,不要使用AS,因为AS编译大型的原生App能卡到你吐血,而且出错提示也不友好。但是用过AS的人都不想再碰Eclipse了有没有??别急,可以先用Eclipse编译过了,再贴到AS中,这样好很多,也很节省时间。
初始化:
放入源码:
修正res错误:
修正src错误:
使用到系统级API的,或者AndroidManifest.xml文件中声明了
那么没有系统签名,直接debug签名运行是不行的,需要向底层工程师要系统的签名文件,在源码目录
build\target\proct\security
下的 platform.pk8 和 platform.x509.pem ,如果你想看此次编译Settings是否已成功了,可以适当的在入口加一下Log,然后导出未签名的apk,使用系统签名进行签名后,放到 /system/app/ 下替换掉Settings.apk,然后重启系统,打开设置,看看Logcat是否输出里加入的Log。
在不知道系统签名可以转换成debug签名前,老实说我一直都是用Log的方式调试,太特么痛苦了。现在知道后整个人都懵逼了。
我们都希望可以像调试普通app那样调试系统app,以下是如何通过 openssl 将 platform.pk8 和 platform.x509.pem 转换成 debug.keystore 文件:
三个命令
此方法来自: http://curlog.com/2016/08/30/android-pk2debug-keystore/
Mac自带openssl,linux和Win需要安装。
然后就可以使用得到的debug签名配置到eclipse后愉快的调试啦,当然,得先把系统中已经存在的app先删除掉。然后重启系统,至于如何配置eclipse的debug签名,请Google。
使用过AS后,当然希望在AS中也可以调试系统App,抽空再写篇相关编译和调试的文章。如果这篇文章帮到你了,给个赞呗。
2. 新手如何学习编程
熟悉以下关键东西,可以边学边做,定期训练,经常思考,长期积累:
1、语法。
2、基础理论(数学、数据结构、算法等)。
3、设计方法(编程原则、设计模式、框架设计等)。
4、库(核心、基础、UI、扩展、游戏引擎等)。
5、计算机相关(操作系统、网络、图形学等)。
6、领域知识(游戏设计、网站设计等)。
7、开发工具(编辑器、IDE、自动部署等)。
8、项目管理(进度管理、分工协作、Bug管理、版本控制等)。
最普遍也是最重要的能力:创造力。努力分析并理解好做什么以及怎么做。要知道上面那些东西一开始都是不存在的。
具体方法包括:
1、快速阅读入门教程和书籍,适合学习语言和基础库。比如我学java读的《Java编程思想》,练习题做过一点,然后学ActionScript就没读过书,只读过Adobe官方文档《ActionScript 3.0编程》。
2、阅读库的文档、实例、源码。比如Flash、Flex开发,熟悉官方API很重要,很多细节要具体使用时才注意到,这时候最好做个笔记,虽然我从没看过我的笔记。
3、做一个自己感兴趣或熟悉的小项目,比如我就以黑白棋游戏作为多个语言的试水项目,一样的逻辑,便于把关注点放在语言特点上。
4、自己动手丰衣足食。厨师有菜谱,程序员可没菜谱。比如我做游戏,最关键的游戏编程知识全部是动手学出来的,很少有专门针对某个业务领域(如游戏)的编程书籍,要么是入门书,要么是模式书(如算法)、理论书(图形学),很少有书籍教你如何开发一个45度角地图系统加编辑器的,全靠自己思考,以及看前人的代码,需要时找些网络资料。关键是,可以培养最重要的创造力。
对于算法和设计模式,可以研读下,但是关键还是靠平时如何使用了。新手勉强不来的。
项目管理方面的,就得靠工作经验了,多思考多提意见不要只走流程。
3. 三、内核&文件系统编译
一、编译官方提供的内核源码
1、解压官方提供的内核源码包
2、根据官方提供的配置文件对内核进行配置,方式如下
make ARCH=arm xxxxx_defult_config
cp arch/arm/xxxxx_config .config
3、打开图形界面对内核进行配置,根据需要增加或者删除模块和其他内容
4、对内核进行编译
make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux-uclibcgnueabi- uImage -j6
或者编辑Makefile文件,对其中的ARCH变量和CROSS_COMPILE变量进行修改,然后执行make uImage
5、在编译编译的时候回出现mkimage命令缺失,这个命令是UBootr提供的,在编译的UBoot路径下面找到这个命令,即可直接使用
6、编译的时候各个方面需要一致性,
1、编译的内核的交叉编译工具链如果支持硬件浮点数运算那么在配置内核的时候也需要添加硬件浮点数的支持
Kernel Features --->
[*] Use the ARM EABI to compile the kernel
2、在编译的内核的时候注意保持不要做太多的修改,否则会出问题
7、编译内核模块
make ARCH=arm CROSS_COMPILE=arm-hisiv300-linux-uclibcgnueabi- moles -j6
8、安装内核模块到指定的目录中去
make moles_install ARCH=arm CROSS_COMPILE=arm-hisiv300-linux-uclibcgnueabi- INSTALL_MOD_PATH=/home/fu/hisi/kernel/build
9、不要采用内核模块安装的命令来安装内核,因为内核不需要安装,在arch/arm/boot/uImage就是所需要的内核文件
二、编译官方提供的busybox来构建根文件系统
1、解压需要编译的busybox源码
2、进入源码中对busybox进行配置,主要是配置交叉编译工具链
Busybox Settings --->Build Options ---> 下面有关于busybox是否配置为采用共享库的模式,还有添加交叉编译工具链的前缀
3、配置需要的文件和命令进行添加或者删除
4、然后执行命令make -jn && make install
5、创建根文件系统需要的其他的文件和目录,在一个空白的目录中首先拷贝busybox/_install下面的bin、sbin、usr目录到空白目录中,在空白目录中创建其余的所需要的目录文件 bin dev etc home lib linuxrc mnt opt proc sbin sys tmp usr var等以上目录
6、接下来在lib目录中复制内核模块,在编译内核的时候模块安装在了指定的地方,直接拷贝过来就行。
6、创建文件系统所需要的其他文件,配置文件(最简单的办法就是直接复制busybox文件下面的example文件夹里面的东西)
1、/etc/inittab 填写或者 一下是最基本的,还有其他的需要填写
# /etc/inittab
::sysinit:/etc/init.d/rcS //指定初始化脚本
::askfirst:-/bin/sh //指定第一次输入回车后打开的shell
::ctrlaltdel:/sbin/reboot //指定这三个按键按下后的反应
::shutdown:/bin/umount -a -r //指定关机是进行的操作
2、/etc/init.d/rcS //这个就没有详细额硬性规定了,写入需要初始化的东西即可
#!/bin/sh
mount -a
3、/etc/fstab //写入mount -a是要自动挂载的文件系统
# device mount-point type options mp fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
7、拷贝需要用到的库文件,在交叉编译工具链下面存放
arm-linux-xxxxxx-gcc/lib
海思的开发板是在和tahet/lib下面,切记。
4. linux内核编译详细教程及开发Linux系统
5. 本科独立用C语言完成没有优化的C语言编译器属于什么水平
我觉得水平还是很高的,但意义恐怕不大。编译器技术是非常成熟的领域,而且由于应用场景的限
制实时,复杂的算法已经自动出局了,你可选的东西是有限的。编译器可能有很多实现的形
式,虚拟机/解释器/静态编译器 等,也有成熟的开源实现。作为本科生,而非专门研究该分支的学生,应该合理分配自己学习的时间,如果做这个编译器就干
掉了大半年,那计网和OS这些课程该咋办?
我知道很多人会认为没有做编译器优化特指中段优化,不考虑机器码上的优化比较划水。但编
译器优化是一个很复杂的东西:首先它和你用的IR表示有关而且是强烈耦合,SSA IR基本还
好,有开源代码和文献记载,你想要的都能在网上挖到但这怎么体现你的水平是吧。你
要考虑编译器的性能,尽管编译器的后端优化基本上可以纳入到某种PEabstract interpretation的
范畴中。
要不然你可以通过编写插件的方式白嫖例如visual studio code这类软
件的强大编辑功能,如果你写的不是c compiler,你也可以尽量把语法设计得很像c,这样你又能进一步
白嫖其强大的intellisense code,当然仍然有不少人或者应该说团队达到了这一步,到这里,应该卷死
了99.99%的同行应该毫无问题。
6. 如何自己编译android系统并制作刷机包
android系统制作刷机包方法:
【一】:下载安装最新版ROM助手(市场中有很多类似的制作工具,关键要求操作简单,功能强大),安装程序非常简单,只需在一只蘑菇首页内直接下载,并解压到自己的电脑安装即可。
【二】:如果已经下载了与机型匹配的ROM刷机包,那么现在可以直接打开ROM助手了,接下来绘制专属个性的完美刷机包就从这里开始吧。
【三】:打开软件后,它会自动升级到最新版本,另外打开主界面后,会直观简明的显示出它的所有功能,例如:性能优化,系统精简,预装APK,签名打包等等。提醒大家,不要贪心哦,要根据自己的需求点击需要操作的功能,如系统精简,然后进入操作界面,所有功能全部修改一遍也无妨,反正都是一键操作,省时省力。
7. 怎么样将自己开发的Android应用程序编译到系统Image中
1. 搭建编译环境
编译环境: Ubuntu 10.10
Android版本:Android 2.2
编译过程中可能需要在Ubuntu上安装必要的一些软件,我安装过的包含如下软件,不同的系统可能会有差别:
jdk6(Android官方建议装jdk5,但是我在编译时会遇到Java override问题,改用6没有任何问题), bison, lib64z1-dev, libasound2-dev, flex, gperf, libncurses5-dev
2. 应用程序存放目录
SimpleJNI是采用Android NDK和Java编写的程序,包含apk和so库文件,它的源代码在source tree的development/samples/目录下。
实际上package在编译时所放的目录并没有明确限定,编译后apk和so存放的位置是根据目录下Android.mk所指定的编译类型所决定的,例如:
SimpleJNI根目录下的Android.mk中有一行include $(BUILD_PACKAGE),表示将该目录下的模块编译成package,即apk文件,默认存放的位置为/system/app。
SimpleJNI/jni目录下的Android.mk中有一行为include $(BUILD_SHARED_LIBRARY),表示将该目录下的native.cpp编译为共享库文件,即so文件,默认存放的位置为/system/lib
因此,如果我们想要将自己编写的程序编译至image中,只需要将Eclipse下完成的整个工程到source tree下的某个目录即可,我一般习惯放到packages/apps下。
3. 添加Android.mk
完成了上一步,可以知道,Android.mk在编译中起着至关重要的作用,这其实就是Android编译环境中的make file。为了完成我们的工作,需要在源代码中添加Android.mk。添加自己的Android.mk可以仿照SimpleJNI中的Android.mk,稍微修改即可。我们首先看看SimpleJNI目录下的两个Android.mk的内容:
根目录下的Android.mk
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
LOCAL_PATH:= $(TOP_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := samples
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := SimpleJNI
LOCAL_JNI_SHARED_LIBRARIES := libsimplejni
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)
# ============================================================
# Also build all of the sub-targets under this one: the shared library.
include $(call all-makefiles-under,$(LOCAL_PATH))
根目录下的Android.mk决定了整个工程编译的配置,其中,
LOCAL_PATH 定义了当前的目录
LOCAL_MUDULE_TAGS 定义了当前模块的类型,编译器在编译时会根据类型的不同有些差别,有些tags的mole甚至不会被编译至系统中。LOCAL_MUDULE_TAGS主要有如下几种:user debug eng tests optional samples shell_ash shell_mksh。optional表示在所有版本的编译条件下都被编译至image中,剩下的表示在该版本中才会被编译只image中,如user表示在user版本下才会被编译至image中。
对于包含LOCAL_PACKAGE_NAME的mk文件,该项默认为optinal,具体可以参看build/core/package.mk。SimpleJNI中定义为samples的具体作用我也不太清楚,为了保险起见,我自己的apk一般定义为optional。
LOCAL_SRC_FILES 定义了编译apk所需要的java代码的目录
LOCAL_PACKAGE_NAME 这里需要改成自己的package的名字
LOCAL_JNI_SHARED_LIBRARIES 定义了要包含的so库文件的名字,如果你的程序没有采用JNI,这行不需要。
LOCAL_PROGUARD_ENABLED 定义了Java开发中的ProGuard压缩方法,主要用来分析压缩程序的,在我自己的应用中我没有加这行。
include $(BUILD_PACKAGE) 这行是build的关键,表示当前java代码build成apk
include $(call all-makefiles-under,$(LOCAL_PATH)) 表示需要build该目录下的子目录的文件,这样编译系统就会在当前目录下的子目录寻找Android.mk来编译so等其它程序。
根据上述所写,创建我自己的Android.mk如下:
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
LOCAL_PATH:= $(TOP_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := TestJniApp
LOCAL_JNI_SHARED_LIBRARIES := libtestjniapp
include $(BUILD_PACKAGE)
# ============================================================
# Also build all of the sub-targets under this one: the shared library.
include $(call all-makefiles-under,$(LOCAL_PATH))
看起来很简单吧,基本不需要改动即可。
Jni目录下的Android.mk
由于我们的TestJniApp是用JNI完成的,包含C源代码,因此也需要一个jni目录下的Android.mk。同样首先看看SimpleJNI中jni目录下的Android.mk的内容:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := samples
# This is the target being built.
LOCAL_MODULE:= libsimplejni
# All of the source files that we will compile.
LOCAL_SRC_FILES:= /
native.cpp
# All of the shared libraries we link against.
LOCAL_SHARED_LIBRARIES := /
libutils
# No static libraries.
LOCAL_STATIC_LIBRARIES :=
# Also need the JNI headers.
LOCAL_C_INCLUDES += /
$(JNI_H_INCLUDE)
# No special compiler flags.
LOCAL_CFLAGS +=
# Don't prelink this library. For more efficient code, you may want
# to add this library to the prelink map and set this to true. However,
# it's difficult to do this for applications that are not supplied as
# part of a system image.
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
LOCAL_MODULE 当前模块的名字,即编译后的so文件的名字
LOCAL_SRC_FILES 所要编译的文件
LOCAL_SHARED_LIBRARIES, LOCAL_STATIC_LIBRARIES 该模块要链接的动态库和静态库。
LOCAL_C_INCLUDES 要包含的头文件
LOCAL_CFLAGS C语言编译选项
LOCAL_PRELINK_MODULE 定义是否使用prelink工具,它用事先链接代替运行时链接的方法来加速共享库的加载,不仅可以加快起动速度,还可以减少部分内存开销。
经过修改后,我自己的TestJniApp中jni目录下的Android.mk如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libtestjniapp
LOCAL_SRC_FILES := com_test_app_Jni.c
LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
这里有一点需要注意,如果要将so文件编译入image,必须要修改LOCAL_MODULE_TAGS,将原有的值samples修改为user,或者可以直接删掉 。删掉是因为对于包含LOCAL_MODULE的mk文件,如果没有指定LOCAL_MODULE_TAGS,该项默认为user,而只有定义为user的情况下,才会将so文件编译入image,具体定义可以参看build/core/base_rule.mk。
4. 修改/bulid/target/proct/generic.mk 把工程编译到系统中
至此,还有最后一部工作。为了将工程编译进入image,还需要在/bulid/target/proct/generic.mk文件中将package name添加进去
PRODUCT_PACKAGES := /
AccountAndSyncSettings /
CarHome /
DeskClock /
……
SyncProvider /
TestJniApp
完成上面这些步骤后,在source tree根目录下编译image就可以了。
8. 自己可以编译安卓源码吗
用最新的Ubuntu 16.04,请首先确保自己已经安装了Git.没安装的同学可以通过以下命令进行安装:
sudo apt-get install git git config –global user.email “[email protected]” git config –global user.name “test”
其中[email protected]为你自己的邮箱.
简要说明
android源码编译的四个流程:1.源码下载;2.构建编译环境;3.编译源码;4运行.下文也将按照该流程讲述.
源码下载
由于某墙的原因,这里我们采用国内的镜像源进行下载.
目前,可用的镜像源一般是科大和清华的,具体使用差不多,这里我选择清华大学镜像进行说明.(参考:科大源,清华源)
repo工具下载及安装
通过执行以下命令实现repo工具的下载和安装
mkdir ~/binPATH=~/bin:$PATHcurl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repochmod a+x ~/bin/repo
补充说明
这里,我来简单的介绍下repo工具,我们知道AOSP项目由不同的子项目组成,为了方便进行管理,Google采用Git对AOSP项目进行多仓库管理.在聊repo工具之前,我先带你来聊聊多仓库项目:
我们有个非常庞大的项目Pre,该项目由很多个子项目R1,R2,...Rn等组成,为了方便管理和协同开发,我们为每个子项目创立自己的仓库,整个项目的结构如下:
这里写图片描述
执行完该命令后,再使用make命令继续编译.某些情况下,当你执行jack-admin kill-server时可能提示你命令不存在,此时去你去out/host/linux-x86/bin/目录下会发现不存在jack-admin文件.如果我是你,我就会重新repo sync下,然后从头来过.
错误三:使用emulator时,虚拟机停在黑屏界面,点击无任何响应.此时,可能是kerner内核问题,解决方法如下:
执行如下命令:
通过使用kernel-qemu-armv7内核 解决模拟器等待黑屏问题.而-partition-size 1024 则是解决警告: system partion siez adjusted to match image file (163 MB >66 MB)
如果你一开始编译的版本是aosp_arm-eng,使用上述命令仍然不能解决等待黑屏问题时,不妨编译aosp_arm64-eng试试.
结束吧
到现在为止,你已经了解了整个android编译的流程.除此之外,我也简单的说明android源码的多仓库管理机制.下面,不妨自己动手尝试一下.