Gradle高级用法【2】-SourceSet

2018/01/14

Tags: gradle

起因

fork了一个项目,准备用kotlin完全重写,但是又想提交在同一个项目上,而且不污染原作者的代码。于是研究了一下可行方案:

最后决定使用方案2。话不多说,方案详细是这样的:
新开一个productFlavor,使用不同的SourceSet装载自己的一份完整代码,包括核心(src)、资源(res,assets)、清单(manifest.xml)。使用姿势大概是这样的:
在app的build.gradle文件中:

android {
    ...
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aild.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
        kotlin {
            java.srcDirs = ['src-dev']
        }
    }

}

其中的定义见代码,这里略过。

我的踩坑记录

一开始我的配置是这样的

    sourceSets {
        kotlin {
            manifest.srcFile 'src/main/KotlinAndroidManifest.xml'
            java.srcDirs = 'src/main/kotlin'
            res.srcDirs = 'src/main/res-kotlin'
        }
    }
    productFlavors {
        kotlin {}
    }

目录结构: qq 20180114135346 看上去很完美。
运行,报错:
Error:Cannot cast object 'src/main/kotlin' with class 'java.lang.String' to class 'java.lang.Iterable'
稍微想了一下,哦,原来是java.srcDirsres.srcDirs不能直接用一个引号,需要使用数组(Iterable)。改成

 java.srcDirs = ['src/main/kotlin']
 res.srcDirs = ['src/main/res-kotlin']

依旧报错。又查了一下,发现有souceset是有一个默认集main的,如果使用默认的souceset需要加上。

sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
        }
        kotlin {
            manifest.srcFile 'src/main/KotlinAndroidManifest.xml'
            java.srcDirs = ['src/main/kotlin']
            res.srcDirs = ['src/main/res-kotlin']
        }
    }

嗯,编译不报错了,运行又报错。又发现一个问题:左下角的切换productflavor里面只有一个kotlin的,默认那个哪去了?百思不得其解,查了好多,后面发现直接简单粗暴的给一个默认flavor命名为normal:

productFlavors {
        normal {}
        kotlin {}
    }

    sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
        }

        normal {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
        }

        kotlin {
            manifest.srcFile 'src/main/KotlinAndroidManifest.xml'
            java.srcDirs = ['src/main/kotlin']
            res.srcDirs = ['src/main/res-kotlin']
        }
    }

normal的sourceset就和main一致。果然出现了

qq 20180114140529

已经规避但是也需要注意的坑

根据建议需要在application节点添加

tools:replace="android:theme"

添加以后build发现还有一条类似的错误是关于

tools:replace="android:name"

解决办法是使用

tools:replace="android:name,android:theme"

如果还有更多就用逗号隔开。