上篇介绍了编译器,如果直接使用编译器管理我们的大中型项目,会相当痛苦而且根本无法维护。为了提效,于是产生了各种编译工具。所以今天介绍移动端开发对应的的编译工具。
Apache Ant
还记得那个用eclipse开发Android的年代吗?eclipse就是基于Ant工具来构建Android项目的。
Apache Ant 是由 Java 语言开发的工具,由 Apache 软件基金会所提供。Ant 是一个将软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发。Apache Ant 的配置文件写成 XML 容易维护和书写,而且结构很清晰。
Ant 环境安装与配置
- 下载ant,mirror.esocc.com/apache//ant…
- 解压缩,配置ANT_HOME环境变量;
- 验证是否安装成功:
ant -version
Ant 构建文件
一般来说,Ant 的构建文件默认为 build.xml,放在项目顶层目录中。然而,并没有限制构建文件必须命名为 bulid.xml,也并不限制放在项目顶层目录中。你可以将构建文件命名为其他名字,也可以将它放在项目的其他地方。
Ant构建脚本主要要理解projct、target、task三个概念:
project
<project name="demo" default="hello">
属性:
- name : 项目名称
- default:指定运行的target名称,没有指定时使用缺省的target;
- basedir:基准路径,其他的相对路径都是基于这个基准路径的;
- description:项目描述信息。
target
<target name="hello" depends="build,combineJavaScript" description="compile all source files into a single stand-alone script." />
属性:
- name:target名称,这个属性是必须的;
- depends:依赖目标,非必须
- if:当属性设置时才执行该target,非必须;
- unless:当属性没有设置时才执行该target,非必须;
- description:target的描述信息,非必须;
一个target可以依赖于其他target。例如hello依赖于 build target 和 combineJaveScript target,ant 会按照 depends 中 target 出现的顺序依次执行,并且每个 target 只会被执行一次,即使有多个target依赖于他。
task
Task分为内置task和自定义task,每个task都是一段可执行的代码。
1.内置task
<copy file="${xxx}/xxx.java" tofile="${zzz}/xxx.js" />
2.自定义task
调用任务:
<glslToJavascript minify="${build.minification}" minifystatefile="${buildDirectory}/minifyShaders.state"> <glslfiles dir="${shadersDirectory}" includes="**/*.glsl" /> <existingjsfiles dir="${shadersDirectory}" includes="**/*.js" excludes="*.profile.js" /> </glslToJavascript>
定义任务:
<scriptdef name="glslToJavascript" language="javascript" src="${tasksDirectory}/glslToJavaScript.js" manager="bsf" classpathref="javascriptClassPath" loaderref="javascript.loader"> <attribute name="minify" /> <attribute name="minifystatefile" /> <element name="glslfiles" type="fileset" /> <element name="existingjsfiles" type="fileset" /> </scriptdef>
构建文件配置示例:
<target name="build" description="Compile main source tree java files"> <mkdir dir="${build.dir}"/> <javac destdir="${build.dir}" source="1.5" target="1.5" debug="true" deprecation="false" optimize="false" failonerror="true"> <src path="${src.dir}"/> <classpath refid="master-classpath"/> </javac> </target>
编译项目
编写好build.xml文件后,在该文件所在路径下执行ant即可完成编译。
Eclipse集成Ant
Eclipse中已经集成了Ant,我们可以直接在Eclipse中运行Ant。我们可以通过创建项目自动生成build.xml,直接编译。
具体可参考官网:ant.apache.org/ 以及中文教程:www.w3cschool.cn/ant/4xdp1hw…
maven
Apache Maven 是一个潜在的基于java的apache ant的构建工具的替代者。目前大部分的java项目都基于maven来管理。二者之间的关系和特点如下:
- ant脚本是可以直接运行在maven中的。maven和ant最大的差别就是在于maven的编译以及所有的脚本都有一个基础,就是POM(project object model)。这个模型定义了项目的方方面面,然后各式各样的脚本在这个模型上工作,而ant完全是自己定义。
- Maven对所依赖的包有明确的定义,如使用那个包,版本是多少,一目了然。而ant则通常是简单的inclde所有的jar。导致的最终结果就是,你根本无法确定JBoss中的lib下的common-logging是哪个版本的,唯一的方法就是打开 META-INF目录下MANIFEST.MF。估计JBoss迟早会转向Maven的。
- Maven是基于中央仓库的编译,即把编译所需要的资源放在一个中央仓库里,如jar,tld,pom,等。当编译的时候,maven会自动在仓库中找到相应的包,如果本地仓库没有,则从设定好的远程仓库中下载到本地。这一切都是自动的,而ant需要自己定义了。这个好处导致的结果就是,用maven编译的项目在发布的时候只需要发布源码,小得很,而反之,ant的发布则要把所有的包一起发布,显然maven又胜了一筹。
- maven有大量的重用脚本可以利用,如生成网站,生成javadoc,sourcecode reference,等。而ant都需要自己去写。试试 maven site的效果。
- maven目前不足的地方就是没有象ant那样成熟的GUI界面,不过mavengui正在努力中。目前使用maven最好的方法还是命令行,又快又方便。
配置maven环境
1.下载解压(以Mac环境为例):
$ curl -O http://mirrors.hust.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz $ tar -xvf apache-maven-3.3.9-bin.tar.gz $ sudo mv -f apache-maven-3.3.9 /usr/local/
2.配置环境变量:
vim ~/.bash_profile export MAVEN_HOME=/usr/local/apache-maven-3.3.9 export PATH=${PATH}:${MAVEN_HOME}/bin
3.加载配置文件:source ~/.bash_profile
4.验证是否生效:
$ mvn -v Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00) Maven home: /usr/local/apache-maven-3.3.9 ...
Maven POM配置
POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
执行任务或目标时,Maven 会在当前目录中查找 POM。它读取 POM,获取所需的配置信息,然后执行目标。
POM 中可以指定以下配置:
- 项目依赖
- 插件
- 执行目标
- 项目构建 profile
- 项目版本
- 项目开发者列表
- 相关邮件列表信息
Maven 构建Java项目
执行mvn clean package
即可自动构建。执行完后,我们已经构建了自己的项目并创建了最终的 jar 文件,关于命令的解释:
- 我们给了 maven 两个目标,首先清理目标目录(clean),然后打包项目构建的输出为 jar(package)文件。
- 打包好的 jar 文件可以在 target 中获得,名称为 xxx-1.0-SNAPSHOT.jar。
gradle
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。
面向Java应用为主。当前其支持的语言C++、Java、Groovy、Kotlin、Scala和Swift,计划未来将支持更多的语言。
Maven有一些天然的缺陷:
- Maven的配置文件是XML格式的,假如你的项目依赖的包比较多,那么XML文件就会变得非常非常长;
- XML文件不太灵活,假如你需要在构建过程中添加一些自定义逻辑,搞起来非常麻烦;
- Maven非常的稳定,但是相对的就是对新版java支持不足,哪怕就是为了编译java11,也需要更新内置的Maven插件。
Gradle里有两个基本概念:项目(projects)和任务(tasks)。项目由多个任务组成,一个项目可以理解为提供给不同设备的构建版本,如桌面版、网页版、安卓版、iOS版等等,也可以理解为一种行为,例如部署应用到生产环境。任务相当于Ant的target,可以理解成一个构建中原子性的工作,例如编译、打包、执行等。需要注意的是,Ant中他自己的命令例如javac、copy等也叫做task,但Ant的task远没有Gradle的task那么自由。
Gradle的构建分两个阶段,第一阶段是设置阶段(configuration phase),分析构建脚本,处理依赖关系和执行顺序等,脚本本身也需要依赖来完成自身的分析。第二阶段是执行阶段(execution phase),此阶段真正构建项目并执行项目下的各个任务。
Ant与Maven对于Gradle,前者编写容易,但功能有限,需要人工操作的过程也多;后者依托于庞大的依赖仓库,因此有着强大的外部依赖管理,但添加本地依赖并不方便,且项目不能灵活修改。而Gradle能很好地结合Ant与Maven各自的优点,可以随意的编写任务并组合成项目,直接利用Maven仓库,并且能很好的支持传递依赖和内部依赖
总结类比一下:Ant是自己织布制衣服,Maven是去商店买衣服,Gradle是3D打印衣服。
gradle环境安装
- 官网下载:gradle.org/releases/
- 解压安装
- 配置环境变量:GRADLE_HOME
- 使用gradle进行命令编译打包等
参考
- 官网地址:gradle.org/
make
上面介绍的以编译Java项目为主,下面主要编译C/C++项目。
make构建规则都写在Makefile文件里面,要学会如何Make命令,就必须学会如何编写Makefile文件。
make语法相当复杂,我们这里展示一个最简单的示例:
.SUFFIXES:.c.o CC=gcc SRCS=main.c OBJS=$(SRCS:.c=.o) EXEC=mytime start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) @echo '----------OK--------' .c.o: $(CC) -o $@ -c $< clean: rm -f $(OBJS)
cmake
CMake是一种跨平台编译工具。CMake主要是编写CMakeLists.txt文件
通过cmake命令将CMakeLists.txt文件转化为make所需要的Makefile文件,最后用make命令编译源码生成可执行程序或者库文件。
ninjia
Ninja 是Google的一名程序员推出的注重速度的构建工具,一般在Unix/Linux上的程序通过make/makefile来构建编译,而Ninja通过将编译任务并行组织,大大提高了构建速度。我一般是通过cmake来生成ninja的配置,进而进行编译。
像我们Andorid的源代码AOSP以及Webrtc的编译都用到了ninjia。
Makefile是设计来给人手写的,而Ninja设计出来是给其它程序生成的。 如果说Makefile是C语言,那么Ninja就是汇编语言。 如果说Makefile是一个DSL,那么Ninja就是一种配置文件。 Makefile支持分支、循环等流程控制,而Ninja只支持一些固定形式的配置。
二者的相同点是,都是为了控制编译流程而设计。 所以,他们的核心功能,都是指定目标,以及目标之间的依赖关系,自动计算执行顺序。
与Makefile相比,由于Ninja仅仅专注于核心的功能,所以有轻巧、速度快的优点。
Makefile默认文件名为Makefile
或makefile
,也常用.make
或.mk
作为文件后缀。 Ninja的默认文件名是build.ninja
,其它文件也以.ninja
为后缀。 执行Makefile的程序,默认是GNU make,也有一些其它的实现。 Ninja的执行程序,就是ninja
命令。
在Android项目中,make
需要编译主机上安装,作为环境的一部分。 而ninja
命令则是Android平台代码自带。
find prebuilts/ -name ninja prebuilts/build-tools/linux-x86/asan/bin/ninja prebuilts/build-tools/linux-x86/bin/ninja prebuilts/build-tools/darwin-x86/bin/ninja
参考
- 工具地址:github.com/ninja-build…
- 《Android中的Ninja简介》
- 《Android中的Kati》
- 《使用ninja命令提高单模块编译效率》
- 《在Android平台开发环境安装ninja》
- 《Android编译系统中的Android.bp、Blueprint与Soong》
- 《Android.mk的深入介绍》
bazel
bazel前面文章做过较详细介绍,它是一个开源的构建和测试工具,类似于Make、Maven和Gradle。它使用人类可读的高级构建语言。Bazel支持多种语言的项目,并为多种平台构建输出。Bazel支持跨多个存储库和大量用户的大型代码库。
qmake
qmake是类似于cmake的工具,它是qt带的编译工具。Qt [1] 是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。
编写好cpp文件后,分别执行命令: qmake -project、qmake、make,然后执行就可以了,其实也只最终将配置文件转换成makefile进行编译。
参考
xmake
xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。
虽然,简单易用是 xmake 的一大特色,但 xmake 的功能也是非常强大的,既能够像 Make/Ninja 那样可以直接编译项目,也可以像 CMake/Meson 那样生成工程文件,还有内置的包管理系统来帮助用户解决 C/C++依赖库的集成使用问题。
目前,xmake主要用于C/C++项目的构建,但是同时也支持其他native语言的构建,可以实现跟C/C++进行混合编译,同时编译速度也是非常的快,可以跟Ninja持平。
参考
GNU AUTOCONF&AUTOMAKE
在大型C/C++项目(比如ffmpeg、openssl等)中,都会给我们提供一个Configure文件,一般都是我们执行这个文件后,再执行make,这个文件怎么生成的呢?就是通过autoconf。
总结
本文主要对移动端开发中常用到的编译工具做了简要介绍,主要包括Java和C/C++,了解编译工具有助于我们自己开发效率自动化构建的效率工具,也可以帮助我们快速上手流行的大型开源项目,对这些项目进行编译、裁剪、修改等操作。后续会针对具体项目对文章中介绍的工具做详细介绍和分析。