blob: 1c018d7c1b40b004d174bae53247ea3493792010 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.build.gradle.internal.res
import com.android.SdkConstants
import com.android.build.gradle.internal.scope.BuildArtifactsHolder
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.scope.VariantScope
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.ide.common.symbols.IdProvider
import com.android.ide.common.symbols.SymbolIo
import com.android.ide.common.symbols.SymbolTable
import com.android.ide.common.symbols.parseResourceSourceSetDirectory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskProvider
import java.io.File
import java.io.Serializable
import javax.inject.Inject
/**
* Task for parsing local library resources. It generates the local R-def.txt file containing the
* symbols (see SymbolIo.writeRDef for the format), which is used by the GenerateLibraryRFileTask
* to merge with the dependencies R.txt files to generate the R.txt for this module and the R.jar
* for the universe.
*
* TODO(imorlowska): Make this incremental (at least in the easy cases for now).
* TODO(imorlowska): Refactor the parsers to work with workers, so we can parse files in parallel.
*/
@CacheableTask
abstract class ParseLibraryResourcesTask : NonIncrementalTask() {
@get:InputFiles
@get:PathSensitive(PathSensitivity.NAME_ONLY)
lateinit var platformAttrRTxt: FileCollection
private set
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val inputResourcesDir: DirectoryProperty
@get:OutputFile
abstract val librarySymbolsFile: RegularFileProperty
override fun doTaskAction() {
getWorkerFacadeWithWorkers().use {
it.submit(
ParseResourcesRunnable::class.java,
ParseResourcesParams(
inputResDir = inputResourcesDir.get().asFile,
platformAttrsRTxt = platformAttrRTxt.singleFile,
librarySymbolsFile = librarySymbolsFile.get().asFile
)
)
}
}
data class ParseResourcesParams(
val inputResDir: File,
val platformAttrsRTxt: File,
val librarySymbolsFile: File
) : Serializable
class ParseResourcesRunnable @Inject constructor(private val params: ParseResourcesParams
) : Runnable {
override fun run() {
// IDs do not matter as we will merge all symbols and re-number them in the
// GenerateLibraryRFileTask anyway. Give a fake package for the same reason.
val symbolTable = parseResourceSourceSetDirectory(
params.inputResDir,
IdProvider.constant(),
getAndroidAttrSymbols(),
"local"
)
// Write in the format of R-def.txt since the IDs do not matter. The symbols will be
// written in a deterministic way (sorted by type, then by canonical name).
SymbolIo.writeRDef(symbolTable, params.librarySymbolsFile.toPath())
}
private fun getAndroidAttrSymbols() =
if (params.platformAttrsRTxt.exists())
SymbolIo.readFromAapt(params.platformAttrsRTxt, "android")
else
SymbolTable.builder().tablePackage("android").build()
}
class CreateAction(
variantScope: VariantScope
): VariantTaskCreationAction<ParseLibraryResourcesTask>(variantScope) {
override val name: String
get() = variantScope.getTaskName("parse", "LocalResources")
override val type: Class<ParseLibraryResourcesTask>
get() = ParseLibraryResourcesTask::class.java
override fun handleProvider(taskProvider: TaskProvider<out ParseLibraryResourcesTask>) {
super.handleProvider(taskProvider)
variantScope.artifacts.producesFile(
InternalArtifactType.LOCAL_ONLY_SYMBOL_LIST,
BuildArtifactsHolder.OperationType.INITIAL,
taskProvider,
ParseLibraryResourcesTask::librarySymbolsFile,
SdkConstants.FN_R_DEF_TXT
)
}
override fun configure(task: ParseLibraryResourcesTask) {
super.configure(task)
task.platformAttrRTxt = variantScope.globalScope.platformAttrs
variantScope.artifacts.setTaskInputToFinalProduct(
InternalArtifactType.PACKAGED_RES,
task.inputResourcesDir
)
}
}
}