Android - Gradle 小课堂第2课 - SourceSet

Gradle 小课堂系列
Gradle 小课堂第1课 - 入门篇
Gradle 小课堂第2课 - SourceSet

什么是 SourceSet?

SourceSet 就是源码的集合。用来告诉 gradle 我的 java 代码在哪里,我的 resource 目录在哪里等等。默认情况下,只有一个 SourceSet : main,也不用做任何设置就能正常编译项目,实际上是因为 SourceSet 规定了一些默认值,如果按照默认值配置项目(Android Studio 新建项目就按照默认值创建)就不用额外去写配置代码了。

SourceSet 规定的那些默认值是什么?

这个可以通过运行一个 task 来查看,这个 task 就叫 sourceSets,可以在 Android Studio 的 gradle 面板上双击执行,也可以用命令行执行。见下图:

gradle 面板

执行结果片段:

main
----
Compile configuration: compile
build.gradle name: android.sourceSets.main
Java sources: [app\src\main\java]
Manifest file: app\src\main\AndroidManifest.xml
Android resources: [app\src\main\res]
Assets: [app\src\main\assets]
AIDL sources: [app\src\main\aidl]
RenderScript sources: [app\src\main\rs]
JNI sources: [app\src\main\jni]
JNI libraries: [app\src\main\jniLibs]
Java-style resources: [app\src\main\resources]

上面列出的是 main 的默认值,默认情况下还应该打印出这几个的默认值: debug、release、test、testDebug、testRelease、androidTest、androidTestDebug。带 test 字符串的是与测试相关的。debug 和 release 也是默认就创建好的两个 SourceSet。

多个 SourceSet 之间的关系是什么?

先说 main 这个 SourceSet,它是一个共用的 SourceSet,可以认为是所有 SourceSet 的“基类”,任何一个其他的 SourceSet 编译时都会将 main 中的代码包括进去,也就是说 main 中的代码肯定是会参与编译的。

再说 debug 和 release 这两个 SourceSet,他俩是默认的两个 buildType 生成的 SourceSet。buildType 会影响 SourceSet,而且 buildType 与 SourceSet 是一一对应的,只要有一个 buildType 就会有一个 SourceSet 默默地创建出来。可以将这种 SourceSet 记为 buildType 维度的 SourceSet。

如果定义了 productFlavor,如下面代码所示:

android {
    productFlavors {
        huoguo {
        }
        malatang {
        }
    }
}

就会生成两个名为 huoguo 和 malatang 的 SourceSet。productFlavor 也是与 SourceSet 一一对应的。可以将这种 SourceSet 记为 productFlavor 维度的 SourceSet。

那么最终编译的时候到底应该使用哪个 SourceSet?这就要提到 Build Variant,在 Android Studio 中可以在 Build Variants 界面选择,如下图所示:


Build Variants

可以看到两个不同维度的 SourceSet 自由组合了起来,生成了 2 x 2 = 4 个 Build Variant。每次编译只能选择其中一种,也就是说,最终编译使用哪些 SourceSet 是由 buildType 和 productFlavor 共同决定的,而 SourceSet 就起到了区分这些变量的作用,通过 SourceSet 的配置,使得不同的 buildType 和不同的 productFlavor 有机会使用不同的代码来编译。

回到 SourceSet 之间的关系的问题,同一维度下的几个 SourceSet 之间可见是互斥的关系,而不同维度之间的 SourceSet 就是(可能产生的)组合的关系。因此同一维度下的不同 SourceSet 可以使用路径完全相同的类文件,而不用担心类重复的冲突。而不同维度下的 SourceSet 必须考虑到冲突的问题,不能使用路径相同的类文件。

SourceSet 自定义路径

上文提到的 sourceSets task 会打印出所有的目录默认配置,列出的就是所有 SourceSet 可配置的目录,对应的代码如下摘自 DSL 文档的图:

SourceSet 可配置属性

下面举几个常用的例子:

例1:添加一个 java 源码目录的设置

android {
    sourceSets {
        main { // main source set
            java {
                def anotherDir = "......"
                srcDirs anotherDir        // 1 添加
                srcDir anotherDir         // 2 添加
                setSrcDirs([anotherDir])  // 3 重置
                srcDirs = [anotherDir]    // 4 重置
                srcDirs += [anotherDir]   // 5 添加
            }
        }
    }
}

注释 1 与 2 位置的语句是调用了 srcDirs(dir)srcDir(dir) 这两个方法,虽然方法名有单数和复数的区别,实际上这两个方法效果是完全一样的,都是添加一个源码目录。而注释 3 和 4 的语句是等价的,是设置属性 srcDirs,会覆盖之前的值,也就是说设置完成后,只剩下新添加的 anotherDir 了。注释 5 的语句相当于调用 setSrcDirs(getSrcDirs() + [anotherDir]),使用了运算符重载(operator overload),重载了 + 运算,与 1 和 2 是效果相同的。

例2:将 SourceSet 的路径修改为另一套

android {
    sourceSets {
        main {
            def dependSrc = 'juanbing'
            java.srcDirs = ["${dependSrc}/java"]
            assets.srcDirs = ["${dependSrc}/assets"]
            res.srcDirs = ["${dependSrc}/res"]
            manifest.srcFile "${dependSrc}/AndroidManifest.xml"
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容