A Gradle plugin that helps you speed up builds by excluding unnecessary modules.

Overview

🧘 Focus

A Gradle plugin that generates module-specific settings.gradle files, allowing you to focus on a specific feature or module without needing to sync the rest of your monorepo.

The Focus plugin evaluates your project setup and creates a unique settings.gradle file for the module you want to focus on, which only includes the dependencies required by that module. It then creates a .focus file that references the currently focused module.

With these files in place only the modules that you need will be configured by Gradle when you sync your project. Deleting the .focus file, which can be done using the clearFocus task, will revert to using the includes file to configure your entire project.

Setup

Apply the plugin in your settings.gradle file.

// settings.gradle(.kts)
plugins {
  id("com.dropbox.focus")
}

Move all non-required include statements into settings-all.gradle. Projects that are always included can remain in your main settings.gradle file.

// settings-all.gradle(.kts)
include ':sample:app2'
include ':sample:lib2c'
include ':sample:lib-shared'

include ':sample:moved'
project(':sample:moved').projectDir = new File("sample/lib-moved")

Optionally configure the plugin if you'd like to use different settings files than the defaults:

// settings.gradle(.kts)
focus {
  // The name of the settings file
  allSettingsFileName = "settings-all.gradle" // Default
  focusFileName = ".focus"  // Default
}

Whether or not you configure a custom focus file, it should be added to your .gitignore file as its meant for a specific developer's workflow.

Usage

The Focus plugin adds a few tasks for you to interact with in your Gradle builds. Using these tasks you can create module specific settings files that will be automatically used by Gradle to configure only the modules which are required.

For example, say you're currently working on the app module :sample:app2 and only need to run that module and it's dependencies. You can use the following flow to reduce the number of modules that are loaded and synced into your IDE to speed up development.

# When you start work on the app2 module, bring it into focus
./gradlew :sample:app2:focus

# Click the Sync Elephant to have your IDE reload the gradle config, and you'll only have
# :sample:app2 and it's dependencies loaded by the IDE, allowing you to build and run the sample app
# and it's tests without having to sync the rest of the project.

# If you want to spend time in a specific dependency, you can bring that into focus and sync your
# IDE for even more fine grained development
./gradlew :sample:lib2b:focus

# When you want to clear focus and get back to the entire project, simply use the clearFocus task.
./gradlew clearFocus

Tasks

focus

A focus task is added to all subprojects, and allows you to focus on just that module.

createFocusSettings

A createFocusSettings task is created for each subproject, and is responsible for finding a module's dependencies and creating a module-specific settings file. This is a dependency of the focus task and likely not necessary to call on it's own.

clearFocus

A clearFocus task is added to the root project, and allows you to remove any previously focused modules.

License

Copyright (c) 2022 Dropbox, Inc.

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.
Comments
  • Disable configuration caching on CreateFocusSettingsTask

    Disable configuration caching on CreateFocusSettingsTask

    Partially handles #2 but doesn't implement actual support for configuration caching. This instead marks this task as incompatible with it, allowing Gradle to gracefully fall back to regular mode when this task runs rather than require users to manually disable CC first.

    Gradle 7.5 will introduce APIs for depending on the resolved dependency graph in a CC-friendly way, but that's not ready yet. Example of that can be found here though: https://github.com/adammurdoch/dependency-graph-as-task-inputs/blob/main/plugins/src/main/java/TestPlugin.java#L31-L35

    Note this also raises the minimum Gradle version to 7.4 unless you want to dynamically gate the API call at runtime on the gradle version

    opened by ZacSweers 9
  • Not compatible with configuration cache

    Not compatible with configuration cache

    Running with configuration caching yields the following errors

    * What went wrong:
    Configuration cache problems found in this build.
    
    10 problems were found storing the configuration cache, 2 of which seem unique.
    - Task `:tooling:vulcan:createFocusSettings` of type `com.dropbox.focus.CreateFocusSettingsTask`: invocation of 'Task.project' at execution time is unsupported.
      See https://docs.gradle.org/7.4/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
    - Task `:tooling:vulcan:focus` of type `com.dropbox.focus.FocusTask`: invocation of 'Task.project' at execution time is unsupported.
      See https://docs.gradle.org/7.4/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
    
    See the complete report at file:///Users/zsweers/dev/slack/android3/build/reports/configuration-cache/7g4wvgv20v66oia9a3wlgl3fw/4wl3j2ake574xd7cq4p2iiwz7/configuration-cache-report.html
    > Invocation of 'Task.project' by task ':tooling:vulcan:createFocusSettings' at execution time is unsupported.
    > Invocation of 'Task.project' by task ':tooling:vulcan:focus' at execution time is unsupported.
    
    
    opened by ZacSweers 3
  • Generated focus.settings.gradle doesn't respect includeBuild statements

    Generated focus.settings.gradle doesn't respect includeBuild statements

    In our project s_ettings.gradle_ we use includeBuild statement to add in classpath separate project. Focus plugin generates focus.settings.gradle without that statement, that's why included project is missing and project configuration become broken.

    For example: original settings.gradle

    includeBuild("path_to_project")
    include ':app'
    

    generated settings.gradle

    include ':app'
    

    Need to point out that included project is not directly used in dependencies section of any subproject. It only contains gradle scripts that is applied at each subprojects.

    As workaround, I'm using project.tasks.findByName("createFocusSettings").finalizedBy(myTask) to intercept in settings creation process and append in file missing statements. May be you'll provide special configuration property in focus's extension, to allow edit generated settings file?

    opened by ConstOrVar 2
  • Support running a Gradle Task from right click on a subproject in IDE

    Support running a Gradle Task from right click on a subproject in IDE

    Our team recently added the Focus gradle plugin, which adds tasks like :subproject:focus.

    I'd love support in the IDE to be able to right click and run specific Gradle tasks from the right-click on subproject context menu.

    For example, I have a subproject: :util:app-in-foreground-observer. I would like to be able to right click on the subproject from the left side project menu in Android Studio and see a context menu with:

    Run Gradle Task `:util:app-in-foreground-observer:focus`
    

    While this is a useful feature for Focus, it makes sense that the IDE as a whole supports executing generating Gradle tasks from the context of a subproject, so I filed https://youtrack.jetbrains.com/issue/IDEA-291803 as well

    opened by ZakTaccardi 2
  • java.lang.NoSuchMethodError: 'void com.dropbox.focus.CreateFocusSettingsTask.notCompatibleWithConfigurationCache(java.lang.String)'

    java.lang.NoSuchMethodError: 'void com.dropbox.focus.CreateFocusSettingsTask.notCompatibleWithConfigurationCache(java.lang.String)'

    Hello! It seems to have done everything according to the documentation, but it appears only in the ClearFocus root project.

    image image image

    Can you tell me what I could do wrong or is it some kind of mistake on your side?

    opened by Turalllb 2
  • focus.settings.gradle not being generated

    focus.settings.gradle not being generated

    I'm trying to integrate the plugin into our large mono-repo, the focus task generates the .focus file but not the focus.settings.gradle file and thus Gradle is unable to find the file.

    I have not configured the plugin, I have:

    • settings.gradle file containing gradleEnterprise and repository configurations
    • settings-all.gradle containing a groovy script that dynamically fetches all the projects in our mono-repo

    Is there another requirement that must be done? Thanks

    opened by JavierTobar 1
  • What is the profit from Focus in the android application

    What is the profit from Focus in the android application

    image

    Tell me how Focus can help me, if I write an android application and every time I launch the app module, does gradle work for a long time? It seems nothing, because my app module in gradle has all the other modules as dependencies. And if I focus on a particular module, make changes to it and try to compile the app module, I get an error like this : Project with path ':chat' could not be found in project ':app'

    opened by Turalllb 1
  • Support focusing multiple subprojects

    Support focusing multiple subprojects

    We have have multiple subprojects per feature. So let's say we have a "Sign In" feature, and have tagged a number of subprojects to be under that feature.

    Would be nice to allow a developer working on the "Sign In" feature to run:

    ./gradlew signInFocus
    

    That would "focus" all subprojects with that tag

    opened by ZakTaccardi 1
  • I am getting below error while integrating

    I am getting below error while integrating

    • What went wrong: Could not resolve all artifacts for configuration 'classpath'.

    Could not resolve com.dropbox.focus:focus:0.4.0. Required by: unspecified:unspecified:unspecified > com.dropbox.focus:com.dropbox.focus.gradle.plugin:0.4.0 Unable to find a matching variant of com.dropbox.focus:focus:0.4.0: - Variant 'apiElements' capability com.dropbox.focus:focus:0.4.0: - Incompatible attributes: - Required org.gradle.jvm.version '8' and found incompatible value '11'. - Required org.gradle.usage 'java-runtime' and found incompatible value 'java-api'. - Other attributes: - Found org.gradle.category 'library' but wasn't required. - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Found org.gradle.jvm.environment 'standard-jvm' but wasn't required. - Required org.gradle.libraryelements 'jar' and found compatible value 'jar'. - Found org.gradle.status 'release' but wasn't required. - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required. - Variant 'runtimeElements' capability com.dropbox.focus:focus:0.4.0: - Incompatible attribute: - Required org.gradle.jvm.version '8' and found incompatible value '11'. - Other attributes: - Found org.gradle.category 'library' but wasn't required. - Required org.gradle.dependency.bundling 'external' and found compatible value 'external'. - Found org.gradle.jvm.environment 'standard-jvm' but wasn't required. - Required org.gradle.libraryelements 'jar' and found compatible value 'jar'. - Found org.gradle.status 'release' but wasn't required. - Required org.gradle.usage 'java-runtime' and found compatible value 'java-runtime'. - Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.

    • Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

    • Get more help at https://help.gradle.org

    pluginManagement {
        repositories {
            mavenCentral()
            gradlePluginPortal()
        }
    }
    
    plugins {
        id("com.dropbox.focus") version "0.4.0"
    }
    
    ...included projects here 
    

    settings-all.gradle is empty for now

    opened by 1q09 0
  • Self resolving project dependencies aren't included in generated settings file.

    Self resolving project dependencies aren't included in generated settings file.

    If a project depends on another via a SelfResolvingDependency, then resolve(true) must be called to resolve the actual dependency, otherwise it won't be added to the generated settings file.

    bug 
    opened by rharter 0
  • Regenerate focus.settings.gradle when new module asi added

    Regenerate focus.settings.gradle when new module asi added

    When I'm focused to module A and add (or merge) new module B to settings-all.gradle, gradle doesn't know module B when gradle sync and I have to call focus task again to generate new focus.settings.gradle.

    Would it be possible that focus recognize during gradle sync that settings-all.gradle was changed and regenerate focus.settings.gradle automatically so I don't need to call focus task again?

    opened by MichalKlusak 0
  • Documentation is unclear

    Documentation is unclear

    I was trying to use focus for my project, but I was not able to set it up properly for the following reasons:

    • Documentation is unclear: There is a mix between .gradle files and .kts files in the documentation and in the sample. It should either or, but don't mix both at the same time
    • Only the focus task appears in the task list in Android Studio (right pane)
    • Focus can't be found in settings.gradle.kts, see screenshot for reference
    • The focus gradle file is missing in this repo. For a complete sample, this would be great to have

    Gradle version: 7.3 AGP version: 7.1.0

    image

    Maybe someone can help out

    opened by ThomasRichtsfeld 4
  • Generated focus.settings.gradle disappear on clean/rebuild

    Generated focus.settings.gradle disappear on clean/rebuild

    Plugin works great! But when trigger clean or rebuild (from Android Studio), all build directories will be removed. So generated focus.settings.gradle will be deleted and project will be broken (.focus file exists, but points at nowhere now). How do you solve that problem in your team?

    As workaround I'm replacing path where generated focus.settings.gradle will be saved - select root folder of target project, which placed in focus.

    opened by ConstOrVar 2
Owner
Dropbox
Dropbox
Graphfity is a Gradle Plugin which creates a dependency node diagram graph about your internal modules dependencies, specially useful if you are developing a multi-module application

Graphfity creates a dependency nodes diagram graph about your internal modules dependencies, specially useful if you are developing a multi-module app

Iván Carrasco 27 Dec 20, 2022
A Gradle Plugin to determine which modules were affected by a set of files in a commit.

A Gradle Plugin to determine which modules were affected by a set of files in a commit. One use case for this plugin is for developers who would like to only run tests in modules which have changed in a given commit.

Dropbox 491 Dec 23, 2022
Gradle Plugin that determines if modules are Kotlin Multiplatform (KMP) ready.

Gradle Plugin that determines if modules are Kotlin Multiplatform (KMP) ready. KMP Ready means that the code is Kotlin Multiplatform compatible.

Sam Edwards 58 Dec 22, 2022
Gradle plugin to ease Kotlin IR plugin development and usage in multimodule gradle projects

Gradle plugin to ease Kotlin IR plugin development and usage in multimodule gradle projects. Former: kotlin-ir-plugin-adapter-gradle

null 2 Mar 8, 2022
A Gradle plugin that generates plugin.yml for Bukkit/BungeeCord/Nukkit plugins based on the Gradle project

plugin-yml is a simple Gradle plugin that generates the plugin.yml plugin description file for Bukkit plugins, bungee.yml for Bungee plugins or nukkit.yml for Nukkit plugins based on the Gradle project. Various properties are set automatically (e.g. project name, version or description) and additional properties can be added using a simple DSL.

Plexus 0 Apr 10, 2022
A Gradle plugin helps to proxy all the BuildConfig fields in the Android project.

Readme A Gradle plugin helps to proxy all the BuildConfig fields in the Android project. Background In android BuildConfig, We might have different co

Jack Chen 4 Oct 11, 2021
Gradle Plugin that allows you to decompile bytecode compiled with Jetpack Compose Compiler Plugin into Java and check it

decomposer Gradle Plugin that allows you to decompile bytecode compiled with Jetpack Compose Compiler Plugin into Java and check it How to use Run bui

Takahiro Menju 56 Nov 18, 2022
Gradle Plugin to automatically upgrade your gradle project dependencies and send a GitHub pull request with the changes

Gradle Plugin to automatically upgrade your gradle project dependencies and send a GitHub pull request with the changes

Dipien 142 Dec 29, 2022
Gradle plugin which validates the licenses of your dependency graph match what you expect

Gradle plugin which validates the licenses of your dependency graph match what you expect

Cash App 502 Dec 31, 2022
A simple gradle plugin that lets you create a download asset from zeplin and convert them to vector drawables automatically

A simple gradle plugin that lets you create a download asset from zeplin and convert them to vector drawables automatically elephant project using 100% Kotlin and be up and running in a few seconds.

Qifan Yang 21 Sep 21, 2022
Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms.

CompleteKotlin Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms. What this plugin provides This zero-conf

Louis CAD 235 Jan 3, 2023
A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

Rikka apps 124 Dec 31, 2022
Grazel is a Gradle plugin to automate generation of valid Bazel files for a given Android/Kotlin/Java project.

Grazel Grazel stands for Gradle to Bazel. It is a Gradle plugin that enables you to migrate Android projects to Bazel build system in an incremental a

Grab 228 Jan 2, 2023
Gradle Plugin for Continuous Integration of AppSweep App Testing.

This Gradle plugin can be used to continuously integrate app scanning using AppSweep into your Android app build process

Guardsquare 28 Nov 13, 2022
Artifactory is a gradle plugin to assist in developing Minecraft mods that can target different modloaders.

Artifactory Artifactory is a gradle plugin to assist in developing Minecraft mods that can target different modloaders. Currently, Fabric and Forge ar

Zach Kozar 3 Dec 29, 2021
EasyVersion is a Gradle plugin that manage your app or library version.

EasyVersion EasyVersion is a Gradle plugin that manage your app or library version. Before Downloading Create easy_version.json in your root project d

Kosh Sergani 8 Nov 26, 2022
Android Gradle Plugin -- Auto Check big image and compress image in building.

McImage I will continue to update, please rest assured to use 中文文档 Android优雅的打包时自动化获取全部res资源 McImage is a Non-invasive plugin for compress all res in

smallSohoSolo 1.1k Dec 28, 2022
Gradle plugin that generates a Swift Package Manager manifest and an XCFramework to distribute a Kotlin Multiplatform library for Apple platforms.

Multiplatform Swift Package This is a Gradle plugin for Kotlin Multiplatform projects that generates an XCFramework for your native Apple targets and

Georg Dresler 262 Jan 5, 2023
Gradle Plugin for publishing artifacts to Sonatype and Nexus

Introduction Due to Sonatype's strict validation rules, the publishing requirement must be satisfied by every artifact which wants to be published to

Johnson Lee 21 Oct 14, 2022