Developer Relations Engineer
As Android apps grow and AI coding assistants become essential, using executable code to configure your build can create bottlenecks with slow sync times, fragile logic, and added complexity.
Enter Lightbuild: Google's declarative, config-driven interface to the build engine, designed for modern Android development.
In this session, we'll explore Lightbuild's new approach to managing builds and how to use it to build a demo app. Learn how decoupling build config from execution delivers faster project opens with lightning-fast sync in Android Studio, while offering a predictable schema for safer, more reliable AI editing. We’ll also cover Lightbuild's agent-friendly CLI tools for creating reproducible builds across local machines, teams, and CI/CD pipelines
resolved.deps files. These files can also serve as lock files during CI/CD builds.query and resolve that can output JSON for agentic workflows. Lightbuild is currently available in Android Studio Canary for experimental use.Transcript
Hello, everyone.
My name is Juan Sebastian Oviedo.
I am a product manager in the Android Developer Experience team.
I'm here with Scott, and today we are excited to share with you an early look at Lightbuild, a new experimental build experience for Android apps.
I'll go over the context for this project, the philosophy behind it, and why we believe that now is the right time to rethink how Android projects are configured.
I'll also go over how this new approach sets us up for the future of Android app development.
Let's start with some context on how things work today.
Gradle and imperative build scripts give developers the ability to programmatically define almost anything about their builds.
You can, for example, have a logic that dynamically computes version codes based on Git history, or define a custom task that transforms assets.
// build.gradle.kts
android {
compileSdk = 37
buildTypes {
debug {
// Custom logic in build script
val commit = providers.exec {
commandLine("git", "rev-parse",
"--short", "HEAD")
}.standardOutput.asText.get()
.trim()
versionNameSuffix = "-$commit"
}
}
}Alongside Gradle, there's AGP or the Android Gradle Plugin, which takes Gradle's general-purpose engine and adapts it to the Android toolchain.
Together, Gradle and AGP form a dynamic system that powers the build configuration experience for millions of production apps today.
Due to this flexibility, our development tools operate within a specific architectural life cycle.
When you open a project, you switch branches or you edit a build file, the IDE needs to have a clear map, a clear understanding of your project configuration, so it can power features like code completion and code navigation.
Because build files are written in an imperative, Turing-complete language, the only general way for the IDE to know what the configuration is for it to run the build scripts.
During IDE sync, the build system goes through a configuration phase.
It evaluates your build scripts, it executes plugin logic, and it constructs the project model.
This aligns Android Studio's view of your project with your actual project configuration.
As developers, the thing you care about most is delivering a great Android app and getting it to your users.
However, managing build scripts, keeping AGP up to date, and keeping the project in sync with the IDE takes time and effort.
There are several initiatives across both Google and the broader ecosystem working to improve the developer experience in this area.
Initiatives like Declarative Gradle and the Kotlin toolchain aim to replace executable build scripts with declarative build configuration.
In Android Studio, we have the AGP Upgrade Assistant, which guides you through the changes needed to go from one version of AGP to another.
We also provide an upgrade skill that agents can install and follow to upgrade AGP.
Additionally, we are investing in areas like phased sync and resilient sync, so that developers have a better experience when syncing and importing their projects.
Each of these efforts targets a piece of the puzzle so that developers can spend more time creating their apps and less time building their projects, managing their build files, and syncing their projects.
Alongside this efforts, we asked ourselves a broader question.
What if we reimagined the way projects are configured from the ground up?
When we look at the way modern Android apps are architected today, we see a major shift toward heavy modularization.
Large code bases often have dozens, or even hundreds of modules: UI modules, feature modules, domain modules, and data modules.
And while the root application might occasionally need custom packaging, the vast majority of those library modules follow a standardized repeatable pattern.
They don't actually need to have arbitrary executable code in their build files.
All they need is a clear way to state their structure and their dependencies.
That observation led us to create Lightbuild.
Lightbuild rests on two pillars.
First, it uses a declarative syntax for configuration, providing for a clear separation between build configuration and logic.
And second, it delivers a fast IDE sync experience through ahead-of-time dependency resolution.
I'll go over each of these pillars in detail so you can see how they impact your daily workflow.
Let's start with the pillar of declarative build configuration.
Take a look at the file on the left side of the screen.
This represents the configuration for a module today.
// build.gradle.kts
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.compose)
}
val gitCommit = providers.exec {
commandLine("git", "rev-parse", "--short", "HEAD")
}.standardOutput.asText.get().trim()
android {
namespace = "com.example.app"
compileSdk = 37
defaultConfig {
minSdk = 24
buildConfigField("String", "GIT_COMMIT",
"\"$gitCommit\"")
}
buildFeatures {
compose = true
buildConfig = true
}
}
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
...Because this file is executable code, it can have local variable definitions, calls to custom helper functions or convention plugins, conditional statements and in-line task definitions.
In order for the IDE to know what this configuration resolves to, it actually needs to run the script.
Now take a look at the file on the right side of the screen.
This is the Lightbuild configuration for a similar module.
# lightbuild.yaml
group: "com.example"
version: "1.0.0"
platform: android
type: library
android:
namespace: "com.example.app"
compileSdk:
version:
release:
apiLevel: 37
minSdk:
version:
release:
apiLevel: 24
dependencies:
maven:
- androidx.core:core-ktx:1.10.1
- androidx.lifecycle:lifecycle-runtime-ktx:2.6.1
- androidx.activity:activity-compose:1.8.0This file is purely declarative data.
There are no local variable definitions, no calls to custom helper functions and no conditional statements or inline task definitions.
It clearly states the type of the module, its SDK targets and its dependencies.
If a new engineer joins your team and they open this file, they will have no custom build idioms to decipher, and every Lightbuild module in every Lightbuild project uses the same immediately readable language.
While the separation between configuration and logic is great for human readability, it's even more transformative for agent-assisted workflows.
As developers adopt agents as part of their workflow, those agents need to be able to read and modify build configuration.
However, they don't have a way to predict the side effects of a configuration change other than by actually building the project.
Adding a single line to a configuration file could conflict with a dynamically computed variable elsewhere in the project or with a convention plugin.
In Lightbuild, your project's configuration is a deterministic, static data graph.
This means that agents can inspect that graph, understand the module topology and modify it using a known schema.
An agent can see the list of modules, the list of dependencies and their versions, update dependencies or even add a brand-new feature module simply by reading and writing structured data.
It makes your project's configuration a first-class citizen for agent-assisted workflows.
Another detail that I want to highlight at this point is the fact that Lightbuild is not a plug-in to a build system, but it is an interface to the build engine.
The version of Lightbuild, the preview that we're releasing today uses Gradle under the hood as its execution engine.
However, the architectural approach that we followed with Lightbuild makes it so that Android Studio, the IDE, sees and treats the project as a Lightbuild project.
Now let's go over the second pillar, which is all about developer productivity and flow: fast IDE sync.
Even as developers adopt agents as part of their workflow, Android Studio remains an essential tool for interactive tasks, for example, to review Compose UI previews or to step through code in the debugger as part of investigating an issue, or to analyze a performance with the profiler.
Because your project's configuration is a deterministic, static data graph, the IDE doesn't need to go through a script evaluation phase or to execute plugin code to understand your project.
Whether you open a project, edit a build file or switch branches, the IDE can process that information quickly and get you right to your tools.
One of the reasons this speed and reliability are possible is the way Lightbuild handles dependencies.
Normally, when you declare a dependency, the build system needs to go through a tree of transitive dependencies to gather version information and to resolve conflicts.
In Lightbuild, whenever your dependencies change, the tool automatically computes the transitive dependency information and writes it to a resolved.deps file inside of each module directory.
This makes it so that when the project is opened again in the future or it gets rebuilt, neither the IDE nor the build tool need to recompute that transitive dependency information.
We recommend checking these files into source control so that when you send changes to your teammates for review, they can, two things, they can see if there were any changes to the transitive dependency information, plus their machines will not need to recompute that transitive dependency information.
Additionally, by checking this information into source control, you make it so that you, your teammates, and your CI/CD pipelines can build with the same dependency versions every time.
We are thrilled to announce that Lightbuild is available as an early preview in Android Studio Canary and also through standalone CLI tools.
Please keep in mind that this version of Lightbuild is experimental, so it doesn't have all of the features that you need to build and maintain a production application.
Please continue to use AGP and Gradle for your production applications while trying out Lightbuild in demo and experimental projects.
You can get started today by going to goo.gle/lightbuild, and we look forward to getting your feedback so you can help us shape the product as it evolves.
Now, I'll pass the presentation over to Scott so he can show you Lightbuild in action.
Thank you, Juan.
My name is Scott Myers.
I'm an Android Developer Relations Engineer, and we've been working on Lightbuild for a while and we're excited to show you how you can actually get your hands on it today and play with it.
So, the first thing you'll want to do is go to the link that Juan mentioned, goo.gle/lightbuild or just do a search for Lightbuild.
And it should take you to this documentation page that'll have all the steps you need to get started, including installing a Canary version of Android Studio, cause remember this is still in preview, it's not yet in the stable version of Android Studio.
And also, there's a Lightbuild CLI that you can install to get the full benefits of the agentic experience with Lightbuild.
So, once you have that set up, like I have here on my machine, I've got the latest Android Studio Canary running.
And now I'm going to step through actually creating a demo Lightbuild project and show you how you can do it, today, even.
So, first, I'll go to the New Project wizard.
I'll choose, the Empty Activity, hit Next.
And now you'll see that this is the normal, project detail screen, but at the bottom here, there's a new option.
Under build configuration language, you can choose Lightbuild.
And it'll remind you that this is experimental before you hit Finish.
And you'll see that right away, our project is synced with the IDE and up and running, ready for us to work with.
Now let's take a look at the project structure of a typical Lightbuild project.
So, this is just the, default Android template that you get when you're creating a new application.
It just says, "Hello, world!"
So it's a simple way to start.
And you'll see that at the root level of our project here, we have a file called project.lightbuild.yaml.
This gives us the global settings for our entire project.
So, you can give your project a name, you list all the modules in your project, say which external repositories you pull your dependencies from, and then the versions that are globally applied, to the different parts of your project here.
So, we see that we have two modules here, app and app-core.
And that's because all Lightbuild projects have at least two modules.
And that's because it's required to have at least one app module and at least one library module.
And I'll get into why in a second.
So, first let's take a look at this app module.
If I expand it here, you see that at the root level of the module, there's a lightbuild.yaml file, which every module's going to have.
In here, it has some basic information.
We're working on the Android platform, obviously.
And this module is of type application.
You can list out your SDK target versions, your application ID, et cetera, and then you list all of the modules that this application module depends on.
Now, what's interesting about this application module that's a little different from the standard Android template is that there's nothing in the source folder.
So, in Lightbuild, application modules do not contain any source code.
And the reason for that is that this app module is not going to change very often, but it takes some time to build.
So, if you keep all of your, application code within your library modules, then each build is going to happen faster cuz it won't have to recompute and repackage everything in the app module.
So, next let's take a look at the app-core module, which is, the library module this application module depends on.
And you can see that this module actually does have source code in it.
It has our, main logic here.
It just says, "Hello, world!"
And if I take a look at the lightbuild.yaml file in this module, you can see it's of type library.
And here it's also setting some SDK version numbers, but it's listing all of the external dependencies that we have, within this module.
And it's also declaring our unit and instrumented tests.
So next, let's take a look at another file you might have noticed in here, and Juan spoke a little bit about this, there's a resolved.deps file inside of every module.
And this is a file that's automatically generated by Lightbuild.
So, that means you should not edit it manually, but it will contain a list of all the resolved dependencies within this module.
So, all of your dependencies and transitive dependencies are already here.
So, that means that when your application's opened in the IDE or when you go to make a build, you don't have to figure this out, at that time because it's already figured out ahead of time and checked into your project.
Next let's take a look at, an example of how Lightbuild actually improves the developer experience with project sync.
So, now I'm back in my root level project.lightbuild.yaml, global settings here that lists all the modules in my application.
And normally, when you're editing configuration or build configuration files, you'll notice that there's a sync button that shows up that takes some time to process all those due to the processes that Juan was describing where it has to do a partial build by executing all your build scripts and then syncing that model with the IDE.
So, let's do like a fairly major change for this little project.
We'll just delete one of the modules.
And you can see that this module, before I hit the save button, it's recognized by the IDE because you can tell that it's bold here.
It recognized the source directory, the test directories.
And as soon as I hit save, after I made that change, you can see that this module is instantly gone from the project.
And if I undo that change again and hit save, it's back just as quickly.
So, this is the example of the fast IDE sync that Lightbuild brings to your projects.
So additionally, you can just do all the normal commands that you're used to in Android Studio.
You can hit the run button.
It will compile your app and run it here.
This particular demo app is not very big, but I'll zoom in to show that it's saying hello Android.
You can run your tests just as you normally would by going into your test file, running it from the gutter like this.
And it's actually invoking Lightbuild here behind the scenes to run these tests.
So, all this works as you'd expect.
But next I want to show how would you use Lightbuild if you are not in Android Studio, if you're using some other agentic flow.
And for that, we have the command-line.
So, in the CLI for Lightbuild, I'll just run the basic help command.
And yeah, all the typos that you see in this project today are mine.
So, Lightbuild is going to have several different commands that are built into it like Oh, sorry, I'm running this outside of a project.
It keeps telling me that.
Yes, live demo.
So, first, before I run any Lightbuild commands, let me create a Lightbuild project.
And for that, I'm going to use android create, which is our standard command-line tool for creating new project templates.
I'll use the empty-activity-lightbuild template and name my app, Lightbuild Demo, and put it in the demo output directory.
Okay, so now if I enter that directory and I type lightbuild -h, I'll see all the different commands that Lightbuild has available.
So we have a lot of things that you'd expect: build, clean, test.
But there's a few new ones.
There's a resolve command, which actually runs through your project's dependencies and generates those resolved.deps files that I showed earlier.
And there's a query command, and that lets you and your agents understand the structure of your project better.
So, first, why don't I show off that new query command?
So, if I just look at the structure of this project using the command line, it's the same one that I had in the Android Studio demo.
But this isn't telling me that much about how my project is laid out.
So, if I do lightbuild query, and I take a look at, say, this app module, and I'll use this special syntax to say, "Show me everything that's under this app module."
And it gives me this nice table of different targets that I can build within the app module.
So, it has the APKs and AABs for both the debug and the release binaries.
And if I just run the app target, it'll build everything.
And there's also a way to specify the output as JSON.
And so that way Oh, sorry.
Again, all of my typos are real today.
Here, let me use the interactive lightbuild help to make sure I'm doing this correctly.
Huh…
Yeah, that should be working.
All right.
Well, if anyone can tell me what I'm doing wrong, talk to me after this talk.
But anyway, instead of this table, you can also output your your Lightbuild commands as JSON, which is easier for your agents.
--format json…
Oh, format.
Oh, sorry.
Thank you.
This is live developer feedback.
Thank you.
Okay, yes, and there's also that output command which I can also demo, maybe with your help.
So if I output the files instead of the targets, this will show me the locations of all the different binaries within my build.
So this is just a way for you and your agents to be able to explore, understand your project better from the command line using Lightbuild.
Then, obviously, there's that lightbuild resolve command that I mentioned earlier, that will generate all of your resolved.deps files.
That one also has some extra features in it.
Like, for example, there's this locked dependencies parameter, and so with that, instead of just generating these files, it'll actually just compare the contents of the files to the dependencies you have declared in your build config.
And if there's any differences, it'll let you know, and fail the build.
So, in that way, these resolved dependencies files can act as lock files like for example, if you're building your app in a CI/CD system for production, you'll want to know if any dependencies are changing during that build.
Also let's see, Lightbuild has a test feature built in, and you can also just run all the tests under this library module, for example, right from the command line.
And there's one more thing I want to show.
Just that it also has the help available that will give you a very complete list of all the building of all the parameters and sub commands that you can use.
That's available for your agent, so this is that output for the agent.
All right.
So, now that we've seen some simple projects with Lightbuild, I want to show what a little bit more ambitious project looks like.
So we have a sample app that's made available by the Android team called Now in Android that gives you some of the latest Android features, shows you how to use them, shows some best practices.
It's a highly modular application.
It's broken up into I think maybe 32 different modules.
So this is what it looks like in GitHub.
But I'm going to switch back to Android Studio, where ahead of time, I've already used my agent.
I was using Gemini Argon to convert the Now in Android project over to Lightbuild.
So, this isn't something that we've published, this is just something I did on my own.
And you can see that even though this project in my project.lightbuild.yaml has all these different modules, it's still opened incredibly fast, and synced with this IDE in a very fast way.
Another thing that you'll want to notice about this particular project, is that it was using some build flavors, or special build configs, in order to have both a demo build and a prod build, which each one had a slightly different way of presenting the app.
The demo one would use built in data sources, and the prod version actually goes out to the network and pulls data.
And so in order to do that with Lightbuild, the way that it handles things like different build configs or product flavors, is that you go into your application module, and you specify that this application module is, for example, the demo application.
And so, it will rely on all the core components, but then it also pulls in special settings just for the demo version of the app.
So, in this way, you can have multiple application modules.
Each one can represent like say, a paid or free version of your app.
And you still get the benefits of the application module being an empty shell with no code in it itself that gets built much faster, and whenever your libraries change, only those need to be recompiled in order to build your app again.
And let's just take a look and see if this Now in Android app is being successfully built with Lightbuild with all its 32 different modules.
Yeah, there it is.
And I do want to point out that more things we learned from doing experiments like this was that Lightbuild doesn't always support every single build feature you might need.
Like, for example, the Now in Android app relies on a Hilt plug-in, in order to use Hilt, and Lightbuild doesn't yet have support for that kind of thing.
So, my agent was able to figure out a work-around around it, and still get the Hilt support in there without really changing much of the code in the project itself.
Like, all the code in all these modules is the same as the original repo.
But that's something to de-- definitely keep in mind for when you're experimenting and demoing Lightbuild yourself, is that not everything in your current project is going to be supported in terms of build configuration.
So, that's why Lightbuild is still in preview, still in Android Studio Canary.
And with that, I would like to switch back to the slides.
And yeah, just to wrap up everything we talked about here, so remember Lightbuild, it's a new build platform for Android, experimental right now.
It has a declarative build configuration, so you're not running any executable code in your build configs and that unlocks a lot of great features with fast IDE sync and more efficient builds.
It has first-class AI agent support, at the command line, it has all those features that you helped me demo today.
So we invite you to try it and use it for demo and experimental projects.
And also Juan and I, and some of the engineers on the team will be at the Agentic AI booth for any questions you have.
So thank you very much.
// build.gradle.kts
android {
compileSdk = 37
buildTypes {
debug {
// Custom logic in build script
val commit = providers.exec {
commandLine("git", "rev-parse",
"--short", "HEAD")
}.standardOutput.asText.get()
.trim()
versionNameSuffix = "-$commit"
}
}
}// build.gradle.kts
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.compose)
}
val gitCommit = providers.exec {
commandLine("git", "rev-parse", "--short", "HEAD")
}.standardOutput.asText.get().trim()
android {
namespace = "com.example.app"
compileSdk = 37
defaultConfig {
minSdk = 24
buildConfigField("String", "GIT_COMMIT",
"\"$gitCommit\"")
}
buildFeatures {
compose = true
buildConfig = true
}
}
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
...# lightbuild.yaml
group: "com.example"
version: "1.0.0"
platform: android
type: library
android:
namespace: "com.example.app"
compileSdk:
version:
release:
apiLevel: 37
minSdk:
version:
release:
apiLevel: 24
dependencies:
maven:
- androidx.core:core-ktx:1.10.1
- androidx.lifecycle:lifecycle-runtime-ktx:2.6.1
- androidx.activity:activity-compose:1.8.0