Home | History | Annotate | Download | only in buildSrc
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 import android.support.build.ApiModule
     17 import java.nio.file.Path;
     18 import java.nio.file.Paths;
     19 
     20 /**
     21  * To add platform specific code to a library:
     22  * 1) add the related source set into the studioCompat map (defined below)
     23  * 2) In your build gradle file, call:
     24  *    * createApiSourceSets(project, gradle.ext.studioCompat.modules.<PROJECT>.apiTargets)
     25  *    * setApiModuleDependencies(project, dependencies, gradle.ext.studioCompat.modules.<PROJECT>.dependencies)
     26  */
     27 
     28 def studioCompat = [
     29     enableApiModules : hasProperty('android.injected.invoked.from.ide'),
     30     modules : [
     31         compat : [
     32             apiTargets : [
     33                 new ApiModule("gingerbread",9),
     34                 new ApiModule("honeycomb",11),
     35                 new ApiModule("honeycomb_mr1",12),
     36                 new ApiModule("honeycomb_mr2",13),
     37                 new ApiModule("ics",14),
     38                 new ApiModule("ics-mr1",15),
     39                 new ApiModule("jellybean", 16),
     40                 new ApiModule("jellybean-mr1",17),
     41                 new ApiModule("jellybean-mr2",18),
     42                 new ApiModule("kitkat",19),
     43                 new ApiModule("api20",20),
     44                 new ApiModule("api21",21),
     45                 new ApiModule("api22",22),
     46                 new ApiModule("api23",23),
     47                 new ApiModule("api24", ApiModule.CURRENT)
     48             ],
     49             dependencies : [":support-annotations"],
     50             folder : "compat",
     51             moduleName : "support-compat"
     52         ],
     53         mediacompat : [
     54                 apiTargets : [
     55                         new ApiModule("ics",14),
     56                         new ApiModule("jellybean-mr2",18),
     57                         new ApiModule("kitkat",19),
     58                         new ApiModule("api21",21),
     59                         new ApiModule("api22",22),
     60                         new ApiModule("api23",23),
     61                         new ApiModule("api24", ApiModule.CURRENT)
     62                 ],
     63                 dependencies : [":support-compat"],
     64                 folder : "media-compat",
     65                 moduleName : "support-media-compat"
     66         ],
     67         coreutils : [
     68                 apiTargets : [
     69                         new ApiModule("gingerbread",9),
     70                         new ApiModule("honeycomb",11),
     71                         new ApiModule("jellybean", 16),
     72                         new ApiModule("kitkat",19),
     73                         new ApiModule("api20",20),
     74                         new ApiModule("api21",21),
     75                         new ApiModule("api23",23),
     76                         new ApiModule("api24", ApiModule.CURRENT)
     77                 ],
     78                 dependencies : [":support-compat"],
     79                 folder : "core-utils",
     80                 moduleName : "support-core-utils"
     81         ],
     82         coreui : [
     83                 apiTargets : [
     84                         new ApiModule("honeycomb",11),
     85                         new ApiModule("ics",14),
     86                         new ApiModule("jellybean-mr2",18),
     87                         new ApiModule("api21",21)
     88                 ],
     89                 dependencies : [":support-compat"],
     90                 folder : "core-ui",
     91                 moduleName : "support-core-ui"
     92         ],
     93         fragment : [
     94                 apiTargets : [
     95                         new ApiModule("gingerbread",9),
     96                         new ApiModule("honeycomb",11),
     97                         new ApiModule("jellybean", 16),
     98                         new ApiModule("api21",21)
     99                 ],
    100                 dependencies : [":support-media-compat", ":support-core-ui", ":support-core-utils"],
    101                 folder : "fragment",
    102                 moduleName : "support-fragment"
    103         ],
    104         v13 : [
    105             apiTargets : [
    106                 new ApiModule("ics", 14),
    107                 new ApiModule("ics-mr1", 15),
    108                 new ApiModule("api23", 23),
    109                 new ApiModule("api24", 24),
    110                 new ApiModule("api25", ApiModule.CURRENT)
    111             ],
    112             dependencies : [":support-v4"],
    113             folder : "v13",
    114             moduleName : "support-v13"
    115         ],
    116         mediaRouter : [
    117             apiTargets : [
    118                 new ApiModule("jellybean", 16),
    119                 new ApiModule("jellybean-mr1", 17),
    120                 new ApiModule("jellybean-mr2", 18),
    121                 new ApiModule("api24", ApiModule.CURRENT)
    122             ],
    123             folder : "v7/mediarouter",
    124             moduleName : "support-mediarouter-v7"
    125         ]
    126     ]
    127 ]
    128 
    129 /**
    130  * Adds a link to the previous ApiModule for each module. This information is later used when
    131  * setting dependencies.
    132  */
    133 def setupDependencies(projectConfig) {
    134     projectConfig.apiTargets.eachWithIndex { entry, index ->
    135         entry.parentModuleName = projectConfig.moduleName
    136         entry.prev = index == 0 ? null : projectConfig.apiTargets[index - 1]
    137     }
    138 }
    139 gradle.ext.currentSdk = studioCompat.enableApiModules ? ApiModule.CURRENT : 'current'
    140 
    141 // the hashmap from apiModuleProjectFolder -> ApiModule
    142 gradle.ext.folderToApiModuleMapping = new HashMap()
    143 
    144 /**
    145  * For each APIModule in the given projectConfig, creates a gradle module. These modules use the
    146  * common `apiModule.gradle` build file.
    147  */
    148 def createModules(projectConfig) {
    149     Path buildFile = Paths.get(file("apiModule.gradle").toURI())
    150     projectConfig.apiTargets.each { ApiModule module  ->
    151         logger.info "creating ${module.moduleName}"
    152         module.setParentModuleDependencies(projectConfig.dependencies)
    153         include "${module.moduleName}"
    154         def folder = new File(rootDir, "${projectConfig.folder}/${module.folderName}")
    155         project("${module.moduleName}").projectDir = folder
    156         project("${module.moduleName}").buildFileName = Paths.get(folder.toURI()).relativize(buildFile)
    157         gradle.ext.folderToApiModuleMapping[folder.canonicalPath] = module
    158     }
    159 }
    160 
    161 /**
    162  * returns the APIModule for the given project.
    163  */
    164 ApiModule getApiModule(Project project) {
    165     return gradle.ext.folderToApiModuleMapping[project.projectDir.canonicalPath]
    166 }
    167 
    168 studioCompat.modules.each { k, v ->
    169     setupDependencies(v)
    170 }
    171 // create these fake modules only if Studio opens the project.
    172 if (studioCompat.enableApiModules) {
    173     // validate we have the 99 folder, otherwise it wont work
    174     def currentSdkPrebuilt = file("${rootProject.projectDir}/../../prebuilts/sdk/" +
    175             "${ApiModule.CURRENT}/")
    176     if (!currentSdkPrebuilt.exists()) {
    177         throw new GradleScriptException(
    178                 "You need a symlink in prebuilts/sdk/${ApiModule.CURRENT} that points to"
    179                         + " prebuilts/sdk/current."
    180                         + "Without it, studio cannot understand current SDK.\n"
    181                         + "> ln -s ../../prebuilts/sdk/current "
    182                         + "../../prebuilts/sdk/${ApiModule.CURRENT}\n"
    183                 , new Exception())
    184     }
    185     Properties localProps = new Properties()
    186     def localPropsStream = new FileInputStream(file("${rootProject.projectDir}/local.properties"))
    187     try {
    188         localProps.load(localPropsStream)
    189         def sdkDir = localProps.get("sdk.dir")
    190         if (sdkDir != null && sdkDir != "") {
    191             throw new GradleScriptException("You should not have sdk.dir in local.properties because"
    192                     + " it overrides android.dir and prevents studio from seeing current sdk. "
    193                     + " Studio may add it by mistake, just remove it and it will work fine.",
    194             new Exception())
    195         }
    196     } finally {
    197         localPropsStream.close()
    198     }
    199     studioCompat.modules.each { k, v ->
    200         createModules(v)
    201     }
    202 }
    203 gradle.ext.studioCompat = studioCompat
    204 gradle.ext.getApiModule = this.&getApiModule
    205