ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

expo-gradle-plugin 完全指南:Expo 模块自动链接的 Android 构建管线

expo-gradle-plugin 完全指南:Expo 模块自动链接的 Android 构建管线 expo-gradle-plugin 完全指南Expo 模块自动链接的 Android 构建管线【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo导读expo-gradle-plugin是 Expo 模块自动链接autolinking体系在 Android 侧的构建基础设施。它以三个 Gradle 插件加一个共享代码库的形式把 Expo 模块从node_modules无缝接入 Android 工程expo-autolinking-settings-plugin负责在settings.gradle阶段解析模块清单expo-autolinking-plugin负责把模块挂入依赖图并生成运行时包列表expo-root-project负责统一 SDK 版本、CMake 路径上限与 lint 策略。读完本文你将掌握这套插件各自的职责边界、配置方式expo.autolinking、expo.android.*系列 Gradle 属性、底层执行流程以及如何借助源码与测试验证它的行为。该插件的完整源码位于 packages/expo-modules-autolinking/android/expo-gradle-plugin仓库根目录下的 README.md 是它的官方说明文档本文以其为主体展开。一、整体架构三个插件 一个共享工程项目由以下部分组成组成部分应用位置作用expo-autolinking-settings-plugin根settings.gradle自动链接入口把模块纳入项目层级、添加 Maven 仓库、链接自定义插件、暴露配置expo-autolinking-plugin由expo包自动应用用户不直接 apply把已链接模块加入依赖图、保证求值顺序、生成包列表文件expo-root-project根build.gradle项目模板已内置统一全项目共享的版本默认值、lint 与 CMake 策略sharedexpo-autolinking-plugin-shared前两个插件的公共依赖存放配置模型、命令行构造器、Gradle 扩展等公共代码其中shared工程即 expo-autolinking-plugin-shared它包含了两个插件共用的ExpoAutolinkingConfig配置模型、AutolinkingCommandBuilder命令行构造器以及ExpoGradleExtension等。二、expo-autolinking-settings-plugin一切自动链接的入口2.1 职责定位该插件是整套体系的入口点必须由最终用户在应用根settings.gradle文件中手动 apply。官方 README 明确了它的四项职责把所有 Expo 模块加入项目层级includeBuild意义上的项目树但不把它们加入依赖图——模块由expo包统一依赖而不是直接挂在 app 工程下添加额外的 Maven 仓库链接link并应用自定义 Gradle 插件暴露 autolinking 配置通过expoAutolinking/expoGradle扩展。2.2 源码实现剖析在 ExpoAutolinkingSettingsPlugin.kt 中插件 apply 时依次完成在 Gradle 的 extra properties 中标记expoAutolinkingSettingsPlugin true供后续插件探测调用settings.addBuildCache()添加构建缓存创建expoAutolinking扩展类型为ExpoAutolinkingSettingsExtension通过 Node 解析require.resolve(expo-modules-autolinking/package.json, { paths: [require.resolve(expo/package.json)] })定位expo-gradle-plugin目录见getExpoGradlePluginsFileL50-L63若该目录存在则向根工程的 buildscript classpath 注入expo.modules:expo-autolinking-plugin与expo.modules:expo-max-sdk-override-plugin并includeBuild该 Gradle 插件工程L29-L45在:app项目应用com.android.application插件后自动为其套上expo-max-sdk-override-pluginL65-L81。注意其中的容错逻辑如果找不到:app项目插件只输出一条提示日志而不会导致构建失败。2.3 扩展配置projectRoot、searchPaths、excludeExpoAutolinkingSettingsExtension.kt 定义了用户在settings.gradle中可配置的选项配置项类型说明projectRootFileReact Native 工程根目录默认settings.rootDir供不遵循/android目录结构的工程使用searchPathsListString?相对 app 根目录的路径列表autolinking 脚本在这些路径下搜索 Expo 模块excludeListString?排除的包名列表useExpoModules()方法启用 Expo 模块自动链接核心调用useExpoVersionCatalog(...)方法从 React Native 的gradle/libs.versions.toml创建expoLibs版本目录支持override回调与reactNativeVersionCatalog路径覆盖当projectRoot与settings.rootDir不一致时rnConfigCommand会自动追加--project-root与--source-dir参数L25-L35。典型用法可在测试工程中见到同样的骨架见 ExpoAutolinkingSettingsPluginTest.kt// settings.gradle plugins { id(expo-autolinking-settings) } expoAutolinking.useExpoModules() include(:app)2.4 SettingsManager解析与链接的执行核心useExpoModules()最终委托给 SettingsManager.kt通过AutolinkingCommandBuilder().command(resolve).useJson()构造命令在projectRoot下以node执行expo-modules-autolinking resolve把 JSON 输出反序列化为ExpoAutolinkingConfigL51-L66link()阶段把每个未走发布物publication的模块linkProject、把所有自定义插件linkPlugin、把所有 AAR 工程linkAarProjectL163-L171在beforeProject钩子里把预编译 AAR 制品挂到对应名字的项目上在beforeRootProject钩子里为所有项目注入config.extraDependencies声明的额外 Maven 仓库、把插件加入 buildscript classpath、并为使用发布物的项目添加本地 Maven 仓库默认来自https://maven.pkg.github.com/expo/expo见 L113-L145最后创建expoGradle扩展ExpoGradleExtension把完整配置暴露给所有子项目L157。配置模型定义在 ExpoAutolinkingConfig.kt它承载了模块列表、额外依赖、核心特性、Gradle 插件、AAR 工程、发布物groupId:artifactId:version:repository等完整数据结构GradlePlugin.classpathCoordinate会根据sourceDir或version拼出 classpath 坐标L147-L155。三、expo-autolinking-plugin依赖图接入与包列表生成3.1 职责与触发方式该插件不应由最终用户直接 apply而是由expo包在应用自身时触发。官方 README 列出的职责确保所有依赖在expo包之前完成求值evaluation把前面已链接的模块加入依赖图创建生成包列表文件的任务。3.2 源码实现剖析ExpoAutolinkingPlugin.kt 的实现要点从 Gradle 全局扩展中取出ExpoGradleExtension若缺失会抛出明确的IllegalStateException提示必须在settings.gradle中调用useExpoModulesL23-L24找到:app工程把 app 的flavorDimensions与缺失的productFlavors复制到 expo 库工程保证多风味构建时依赖可解析L30-L31 及 L119-L188把配置中的工程按是否走发布物分为两组源码工程通过evaluationDependsOndependencies.add(api, subproject)加入依赖图发布物工程直接以groupId:artifactId:version坐标加入L33-L51注册generatePackagesList与generateInlineModules两个任务并挂到preBuild之前执行L56-L62依据 AGP 版本选择源码注册方式AGP 9走 Variant Sources APIvariant.sources.kotlin.addGeneratedSourceDirectoryAGP 8走传统sourceSets.main.java.srcDirsL64-L87。3.3 生成的包列表ExpoModulesPackageList 与 ExpoModulesV2ModuleListGeneratePackagesListTask.kt 负责把配置序列化进 Kotlin 源文件ExpoModulesPackageList.kt实现ModulesProvider生成packagesList、modulesMap模块类 → 事件名映射、getServices()列表L82-L144ExpoModulesV2ModuleList.kt实现ExpoModulesV2Provider为新一代模块系统io.github.expo.modules.v2.modules.Module生成类清单L61-L80。任务使用Input的配置hash做增量构建失效判断hash由 ExpoGradleExtension.kt 对配置字符串计算 MD5 得到。另有 GenerateInlineModulesTask.kt 通过node expo/bin/autolinking expo-modules-autolinking mirror-kotlin-inline-modules镜像 Kotlin inline 模块并强制每次构建都重新生成outputs.upToDateWhen { false }。四、expo-root-project全项目的默认版本与构建策略4.1 职责定位该插件应应用到根build.gradle官方说明项目模板已内置这一步骤。其职责集中在 ExpoRootProjectPlugin.kt定义全项目共享的默认版本跳过 autolinked 原生模块的 lint-vital 分析除非显式开启 lint通过android.cmakeVersion属性统一覆盖所有模块的 CMake 版本为所有用 CMake 构建原生代码的模块设置CMAKE_OBJECT_PATH_MAX1024。4.2 默认版本来自 React Native 版本目录的兜底值defineDefaultPropertiesL171-L214优先从expoLibs版本目录即 React Native 的gradle/libs.versions.toml经由useExpoVersionCatalog注入读取缺失时使用内置默认值属性默认值说明buildToolsVersion37.0.0Android Build ToolsminSdkVersion24最低 SDKcompileSdkVersion37编译 SDKtargetSdkVersion36目标 SDKndkVersion27.1.12297006NDK 版本kotlinVersion2.2.0Kotlin 版本kspVersion由 KSPLookup 推导依据 Kotlin 版本自动匹配低于最低支持版本会抛出异常提示更新kotlinVersion或显式设置kspVersionL181-L200采用setIfNotExist语义仅当属性未被外部定义时才写入用户工程里的显式设置永远优先L216-L222。4.3 lint-vital 跳过策略disableLinkedModulesLintWhenRequestedL146-L161在未启用 lint时对两类模块禁用lintVitalAnalyze*任务源码位于node_modules下的第三方 React Native 库应用了expo-module-gradle-plugin的 Expo 模块。app 自身的 lint-vital 不受影响。实现上有意保留了廉价的generate*LintVitalModel任务——app 的lintVitalReportRelease依赖每个依赖的 vital model若缺失会报 Lint model ... does not exist见 L131-L145 的注释说明。开启 lint 的方式isLinkedModuleLintEnabled# gradle.properties expo.android.enableLinttrue或设置环境变量EXPO_ANDROID_ENABLE_LINTtrueGradle 属性优先。4.4 统一 CMake 版本android.cmakeVersionmaybeOverrideCmakeVersionL33-L50读取android.cmakeVersion属性对所有应用了com.android.application/com.android.library的子项目强制设置externalNativeBuild.cmake.version# gradle.properties android.cmakeVersion3.22.14.5 深度解析CMAKE_OBJECT_PATH_MAX 长路径问题这是 README 中着墨最多的实战问题核心结论如下。背景CMake 会预估生成工具Ninja、编译器、归档器能处理的最长目标文件路径但它并不知道这些工具的真实上限只能用一个保守的硬编码值Windows 上 250 字符、其他平台 1000 字符一旦路径超限就提前失败——即便底层工具本身支持更长路径。在 pnpm monorepo 这类深层嵌套结构下尤其是 Windows路径很容易撞线。插件的默认行为setDefaultCmakeObjectPathMaxL76-L90在所有应用了com.android.baseapp/library 共同基类的项目上向defaultConfig.externalNativeBuild.cmake.arguments追加-DCMAKE_OBJECT_PATH_MAXvalue从而把上限提升到 1024macOS 的安全上限Windows 需开启长路径支持Linux 通常允许 4096。配置表官方 README 原文控制属性为expo.android.cmakeObjectPathMax取值行为未设置或为空使用默认值1024大于等于128的整数CMake 最小值使用给定值0退出该机制保留 CMake 平台默认值配置方式示例# gradle.properties expo.android.cmakeObjectPathMax2048或在命令行传递./gradlew assembleRelease -Pexpo.android.cmakeObjectPathMax2048校验逻辑cmakeObjectPathMaxL96-L115会把非法值非整数或小于 128回退为默认值并打印告警提示开发者使用 ≥128 的整数、删除该属性使用推荐值、或设为0保留 CMake 默认。模块级覆盖某个模块若在externalNativeBuild.cmake.arguments中自行传入-DCMAKE_OBJECT_PATH_MAX由于该参数在 CMake 命令行上出现得更晚会覆盖插件设置的全局值。与 android.cmakeVersion 的配合提高CMAKE_OBJECT_PATH_MAX只是去掉了 CMake 的保守猜测。若工具链真正不支持长路径——例如 Android Gradle 插件默认捆绑的 CMake 3.22.1 所带的 Ninja 缺少长路径支持——则应改用android.cmakeVersion属性选择更新的 CMake 版本其 Ninja 支持长路径。五、shared 工程两个插件的公共基座expo-autolinking-plugin-shared提供两插件共用的代码按模块可分为配置模型ExpoAutolinkingConfig、ExpoModule、GradleProject、GradlePlugin、GradleAarProject、Publication、MavenRepo等见 configuration命令行构造器AutolinkingCommandBuilder负责拼装react-native-config与resolve命令及 JSON 输出参数Gradle 扩展ExpoGradleExtension承载完整配置与 MD5 哈希供expo-autolinking-plugin消费工具类Os平台判断、Colors/Emojis日志美化。此外expo-autolinking-plugin下还有一个相对独立的expo-max-sdk-override-plugin位于 expo-max-sdk-override-plugin含ExpoMaxSdkOverridePlugin、FindPermissionsToOverride等负责在发布构建中分析 AndroidManifest 并覆盖权限的 maxSdkVersion。六、测试与验证如何确认插件行为仓库为插件提供了 Gradle TestKit 集成测试最直接的验证样例是 ExpoAutolinkingSettingsPluginTest.ktapplies settings plugin在临时工程中执行 Gradle 构建并断言BUILD SUCCESSFULinjects expo gradle extension运行:app:gradleExpoExtension任务并断言expoGradle扩展注入成功returns correct config把插件内部的expoAutolinking.config与直接运行expo-modules-autolinking resolve得到的配置做序列化等值比较验证插件解析路径与 Node 脚本一致L37-L55。测试工程本身复现了真实的最小用法settings.gradle中plugins { id(expo-autolinking-settings) }expoAutolinking.useExpoModules()配合include(:app)L130-L140。对CMAKE_OBJECT_PATH_MAX与 lint 策略可直接阅读 ExpoRootProjectPlugin.kt 中的对应函数注释与测试理解其边界行为。七、实践建议与排错速查接入顺序先在根settings.gradle应用expo-autolinking-settings并调用useExpoModules()expo包与项目模板会自动完成其余插件的接入用户通常无需手动 applyexpo-autolinking-plugin。Windows 长路径构建失败优先设置expo.android.cmakeObjectPathMax建议先用默认 1024若仍失败再用android.cmakeVersion切换到 Ninja 支持长路径的 CMake 版本。发布物prebuilt与源码构建模块可通过buildFromSourceRegex配置中的configuration.buildFromSource强制绕过发布物改走源码构建shouldUsePublicationScript支持用 Groovy 脚本动态决策见 SettingsManager.kt。版本覆盖优先级expo-root-project的所有默认值都是兜底语义——用户在gradle.properties、build.gradle或版本目录中的显式配置优先。排错入口插件在构建输出中打印Using expo modules及各模块版本列表绿色、[ExpoRootProject]版本汇总、额外 Maven 仓库等日志便于确认 autolinking 实际解析结果。从 README.md 的职责划分到源码中每一处钩子的挂载点expo-gradle-plugin的设计思路始终一致settings 阶段解析与链接、expo 包阶段挂依赖、root 阶段定策略。理解这三层分工就能在遇到 Expo Android 构建问题时快速定位该检查哪个插件、哪个属性。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表