Как исправить ошибку “Unresolved reference: flutterRoot” в файле settings.gradle.kts при добавлении локального репозитория maven для pluginManagement в Flutter?
Я столкнулся с ошибкой компиляции в файле settings.gradle.kts при попытке добавить локальный репозиторий плагина Flutter внутри блока pluginManagement. Сообщение об ошибке: “Unresolved reference: flutterRoot”, что указывает на то, что переменная flutterRoot, определенная вверху файла, не находится в области видимости внутри блока pluginManagement.
Вот мой текущий файл settings.gradle.kts:
import java.util.Properties
import java.io.File
fun loadLocalProperties(rootDir: File): Properties {
val props = Properties()
val localPropsFile = File(rootDir, "local.properties")
if (localPropsFile.isFile) {
localPropsFile.inputStream().use { props.load(it) }
}
return props
}
val localProperties = loadLocalProperties(rootProject.projectDir)
val flutterRoot = localProperties.getProperty("flutter.sdk")
?: error("flutter.sdk not set in local.properties")
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
// Ошибка возникает на следующей строке
maven(url = File(flutterRoot, "packages/flutter_tools/gradle/flutter_plugin_loader_repo").toURI())
}
}
plugins {
id("com.android.settings") version "8.3.0"
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
}
include(":app", ":modelComponent")
project(":modelComponent").projectDir = file("modelComponent")
Как правильно определить переменную flutterRoot, чтобы она была доступна внутри блока pluginManagement в Gradle Kotlin DSL?
Ошибка “Unresolved reference: flutterRoot” возникает из-за того, что переменные, определенные на верхнем уровне settings.gradle.kts, недоступны внутри блока pluginManagement из-за ограничений области видимости в Gradle Kotlin DSL. Для решения этой проблемы необходимо переместить определение переменной внутрь блока pluginManagement, где оно требуется.
Вот исправленная версия вашего settings.gradle.kts:
import java.util.Properties
import java.io.File
pluginManagement {
// Определяем flutterRoot внутри этого блока, где он нужен
val flutterRoot = run {
val properties = java.util.Properties()
val localPropsFile = File(rootProject.projectDir, "local.properties")
if (localPropsFile.isFile) {
localPropsFile.inputStream().use { properties.load(it) }
}
val flutterSdkPath = properties.getProperty("flutter.sdk")
?: error("flutter.sdk not set in local.properties")
flutterSdkPath
}
repositories {
google()
mavenCentral()
gradlePluginPortal()
// Теперь flutterRoot доступен здесь
maven(url = File(flutterRoot, "packages/flutter_tools/gradle/flutter_plugin_loader_repo").toURI())
}
}
plugins {
id("com.android.settings") version "8.3.0"
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
}
include(":app", ":modelComponent")
project(":modelComponent").projectDir = file("modelComponent")
Содержание
- Понимание проблемы области видимости
- Правильное определение переменной в pluginManagement
- Альтернативные решения
- Лучшие практики для конфигурации Flutter Gradle
- Устранение распространенных проблем
Понимание проблемы области видимости
Основная проблема заключается в том, как Gradle Kotlin DSL обрабатывает область видимости переменных в файлах настроек. Как упоминается в документации Gradle Kotlin DSL, переменные, определенные на верхнем уровне settings.gradle.kts, автоматически недоступны внутри вложенных блоков, таких как pluginManagement.
Это фундаментальное ограничение Kotlin DSL в файлах настроек Gradle. Обсуждение на форумах Gradle подтверждает, что “переменные, определенные в settings.gradle.kts, не могут быть использованы в блоке plugins” - и то же ограничение применимо к pluginManagement.
Правильное определение переменной в pluginManagement
Решение заключается в определении переменной flutterRoot непосредственно внутри блока pluginManagement, где она требуется. Этот подход соответствует стандартному шаблону, используемому в официальной документации Flutter:
pluginManagement {
val flutterRoot = run {
val properties = java.util.Properties()
val localPropsFile = File(rootProject.projectDir, "local.properties")
if (localPropsFile.isFile) {
localPropsFile.inputStream().use { properties.load(it) }
}
val flutterSdkPath = properties.getProperty("flutter.sdk")
?: error("flutter.sdk not set in local.properties")
flutterSdkPath
}
repositories {
google()
mavenCentral()
gradlePluginPortal()
maven(url = File(flutterRoot, "packages/flutter_tools/gradle/flutter_plugin_loader_repo").toURI())
}
}
Этот подход гарантирует, что переменная находится в правильной области видимости и доступна внутри блока repositories.
Альтернативные решения
1. Использование хука settingsEvaluated
Для более сложных сценариев можно использовать хук settingsEvaluated:
settingsEvaluated { settings ->
val flutterRoot = run {
val properties = java.util.Properties()
val localPropsFile = File(rootProject.projectDir, "local.properties")
if (localPropsFile.isFile) {
localPropsFile.inputStream().use { properties.load(it) }
}
val flutterSdkPath = properties.getProperty("flutter.sdk")
?: error("flutter.sdk not set in local.properties")
flutterSdkPath
}
settings.pluginManagement.repositories.apply {
maven(url = File(flutterRoot, "packages/flutter_tools/gradle/flutter_plugin_loader_repo").toURI())
}
}
2. Предопределенный путь к Flutter SDK
Если вам нужна переменная flutterRoot в нескольких местах, определите ее один раз в pluginManagement, а затем ссылайтесь на нее:
pluginManagement {
val flutterRoot = run {
val properties = java.util.Properties()
val localPropsFile = File(rootProject.projectDir, "local.properties")
if (localPropsFile.isFile) {
localPropsFile.inputStream().use { properties.load(it) }
}
val flutterSdkPath = properties.getProperty("flutter.sdk")
?: error("flutter.sdk not set in local.properties")
flutterSdkPath
}
repositories {
google()
mavenCentral()
gradlePluginPortal()
maven(url = File(flutterRoot, "packages/flutter_tools/gradle/flutter_plugin_loader_repo").toURI())
}
}
// Теперь вы можете использовать flutterRoot в других частях вашего файла настроек
// Она будет доступна в области видимости скрипта настроек
Лучшие практики для конфигурации Flutter Gradle
1. Следование официальным шаблонам Flutter
Документация Flutter показывает рекомендуемый подход для обработки путей к SDK Flutter:
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
2. Обработка ошибок
Всегда включайте правильную обработку ошибок при чтении свойств:
val flutterRoot = run {
val properties = java.util.Properties()
val localPropsFile = File(rootProject.projectDir, "local.properties")
if (localPropsFile.isFile) {
localPropsFile.inputStream().use { properties.load(it) }
}
val flutterSdkPath = properties.getProperty("flutter.sdk")
?: error("flutter.sdk not set in local.properties")
flutterSdkPath
}
3. Порядок конфигурации репозиториев
Настраивайте репозитории в правильном порядке - сначала локальные, затем удаленные:
repositories {
mavenLocal() // Если у вас есть локальные плагины
maven(url = File(flutterRoot, "packages/flutter_tools/gradle/flutter_plugin_loader_repo").toURI())
google()
mavenCentral()
gradlePluginPortal()
}
Устранение распространенных проблем
1. Ошибки “Файл не найден”
Если вы сталкиваетесь с ошибками, связанными с файлами, убедитесь, что файл local.properties существует и имеет правильный путь:
flutter config --android-sdk <путь-к-vour-sdk>
2. Проблемы с разрешением репозиториев
Если плагины не могут быть разрешены, проверьте конфигурацию репозиториев:
settingsEvaluated { settings ->
settings.pluginManagement.resolutionStrategy {
eachPlugin {
// При необходимости принудительно используйте конкретные версии
when (requested.id.id) {
"com.android.application" -> useVersion("8.3.0")
}
}
}
}
3. Синтаксические ошибки Kotlin DSL
Убедитесь, что вы используете правильный синтаксис Kotlin DSL:
// Правильно
maven(url = File(flutterRoot, "path/to/repo").toURI())
// Неправильно
maven { url = "$flutterRoot/path/to/repo" }
Ключевой вывод заключается в том, что в файлах настроек Gradle Kotlin DSL переменные должны быть определены в той же области видимости, где они используются. Для блоков pluginManagement это означает определение переменных непосредственно внутри этого блока, а не на верхнем уровне файла.
Источники
- Gradle Kotlin DSL Primer - Официальная документация
- Документация Android Gradle Plugin Flutter
- Форумы Gradle: Обсуждение области видимости переменных Kotlin DSL
- Stack Overflow: Неопределенная ссылка в Settings Gradle KTS
- Документация по конфигурации плагинов Flutter
Заключение
Ошибка “Unresolved reference: flutterRoot” является распространенной проблемой при работе с Gradle Kotlin DSL в проектах Flutter. Решение заключается в понимании ограничений области видимости переменных и определении переменных в соответствующей области видимости. Переместив определение переменной flutterRoot внутрь блока pluginManagement, вы гарантируете ее доступность там, где это необходимо. Всегда следуйте официальным шаблонам Flutter и включайте правильную обработку ошибок для надежной конфигурации. Помните, что в settings.gradle.kts область видимости переменных строго ограничена местом их определения, поэтому планируйте свою конфигурацию соответствующим образом.