跳转到内容
Skip
3.2k

Gradle 项目参考

Gradle 是 Android 的构建系统,相当于 Darwin Swift 开发中的 SwiftPM。当 Skip 构建你的项目时,它会将你的 Swift 代码桥接和/或转译为 Kotlin,并将你的 Package.swift 文件转换为 Skip 插件输出目录中的 build.gradle.kts 文件。这种转换会传递到项目中所有启用了 Skip 的依赖,包括 Skip 核心框架模块。最终形成一个本地互联的 Gradle 项目网络,包含项目整个源代码依赖树。

以下章节详细说明了 Skip 对 Gradle 的使用,包括如何从命令行使用 Gradle 进行构建。

考虑一个通过以下命令创建的最小 Swift 应用项目:

Terminal window
skip init --show-tree --no-build --no-test --no-module-tests --appid=skip.hello.App --version 1.0.0 hello-skip HelloSkip
  • Package.swift 标准 SwiftPM Package
  • README.md
  • Skip.env 项目配置(名称、版本、appid 等)
  • 文件夹Sources
    • 文件夹HelloSkip
      • ContentView.swift
      • HelloSkip.swift
      • HelloSkipApp.swift
      • 文件夹Resources
        • Localizable.xcstrings
      • 文件夹Skip
        • skip.yml 模块配置(依赖、构建模式)
  • 文件夹Android
    • 文件夹app
      • build.gradle.kts 顶层 Gradle 构建配置
      • proguard-rules.pro
      • 文件夹src
        • 文件夹main
          • AndroidManifest.xml Android 项目元数据
          • 文件夹kotlin
            • 文件夹hello
              • 文件夹skip
                • Main.kt Android 应用入口
    • 文件夹gradle
      • 文件夹wrapper
        • gradle-wrapper.properties
    • gradle.properties
    • settings.gradle.kts
  • 文件夹Darwin
    • 文件夹Assets.xcassets
      • 文件夹AccentColor.colorset
        • Contents.json
      • 文件夹AppIcon.appiconset
        • Contents.json
      • Contents.json
    • Entitlements.plist
    • HelloSkip.xcconfig iOS 项目配置
    • 文件夹HelloSkip.xcodeproj Xcode 项目
      • project.pbxproj
    • 文件夹Sources
      • Main.swift iOS 应用入口

hello-skip 文件夹中运行 swift build 会构建模块并执行 Android 转译。

生成的项目层级结构如下:

hello-skip swift build output
hello-skip % tree .build/plugins/outputs/hello-skip/HelloSkip/skipstone/
  • 文件夹.build/plugins/outputs/hello-skip/HelloSkip/skipstone/
    • 文件夹HelloSkip
      • build.gradle.kts
      • proguard-rules.pro
      • 文件夹src
        • 文件夹main
          • 文件夹kotlin
            • 文件夹hello
              • 文件夹skip
                • ContentView.kt
                • HelloSkip.kt
                • HelloSkipApp.kt
          • 文件夹resources
            • 文件夹hello
              • 文件夹skip
                • 文件夹Resources
                  • Localizable.xcstrings -> /private/tmp/hello-skip/Sources/HelloSkip/Resources/Localizable.xcstrings
                  • resources.lst
    • HelloSkip.skipcode.json
    • 文件夹SkipFoundation/ -> ../../../skip-foundation/SkipFoundation/skipstone/SkipFoundation
    • 文件夹SkipLib/ -> ../../../skip-lib/SkipLib/skipstone/SkipLib
    • 文件夹SkipModel/ -> ../../../skip-model/SkipModel/skipstone/SkipModel
    • 文件夹SkipUI/ -> ../../../skip-ui/SkipUI/skipstone/SkipUI
    • 文件夹SkipUnit/ -> ../../../skip-unit/SkipUnit/skipstone/SkipUnit
    • 文件夹gradle
      • 文件夹wrapper
        • gradle-wrapper.properties
    • gradle.properties
    • settings.gradle.kts

生成的 Gradle 项目层级结构不仅包含指向当前项目插件输出的链接,还包含指向每个依赖模块的项目输出的链接。这些依赖是在依赖项目上运行 Skip 插件时自动创建的。


Gradle 项目可以手动运行,可以从 Android Studio 运行,也可以使用 gradle 命令行工具运行。使用 skip init 创建的 Skip 应用项目有一个包含 settings.gradle.kts 文件的根 Android/ 文件夹。可以在 Android Studio 中打开它,也可以直接从命令行运行。

$ skip init --appid=com.xyz.HelloSkip hello-skip HelloSkip
Initializing Skip library hello-skip
[✓] Create project hello-skip (0.73s)
[✓] Resolve dependencies (5.89s)
[✓] Build hello-skip (15.2s)
[✓] Created module HelloSkip in ~/Desktop/hello-skip/HelloSkip.xcodeproj
$ cd hello-skip
$ swift build --build-tests
Fetched https://github.com/skiptools/skip.git (0.92s)
[294/294] Linking libHelloSkip.dylib
Build complete! (23.13s)
$ skip gradle -p .build/plugins/outputs/hello-skip/HelloSkip/skipstone/HelloSkip test
GRADLE> > Task :HelloSkip:preBuild UP-TO-DATE
48 collapsed lines
GRADLE> > Task :HelloSkip:testDebugUnitTest
GRADLE> > Task :HelloSkip:test
GRADLE>
GRADLE> BUILD SUCCESSFUL in 20s
GRADLE> 204 actionable tasks: 204 executed
note: Gradle SUCCESSFUL
$ skip gradle -p Android/ assemble
GRADLE> > Task :app:preBuild UP-TO-DATE
GRADLE> > Task :app:preDebugBuild UP-TO-DATE
GRADLE> > Task :app:mergeDebugNativeDebugMetadata NO-SOURCE
GRADLE> > Task :app:generateDebugBuildConfig
GRADLE> > Task :HelloSkip:preBuild UP-TO-DATE
GRADLE> > Task :SkipUI:bundleReleaseAar
GRADLE> > Task :HelloSkip:compileDebugJavaWithJavac NO-SOURCE
GRADLE> > Task :app:processReleaseJavaRes
GRADLE> > Task :HelloSkip:extractDebugAnnotations
GRADLE> > Task :HelloSkip:mergeDebugGeneratedProguardFiles
GRADLE> > Task :HelloSkip:mergeDebugConsumerProguardFiles
GRADLE> > Task :SkipUI:assembleRelease
GRADLE> > Task :SkipUI:assemble
GRADLE> > Task :HelloSkip:mergeDebugJavaResource
GRADLE> > Task :app:compileDebugKotlin
GRADLE> > Task :HelloSkip:syncDebugLibJars
GRADLE> > Task :app:compileDebugJavaWithJavac
GRADLE> > Task :app:mergeReleaseJavaResource
GRADLE> > Task :app:dexBuilderDebug
GRADLE> > Task :app:processDebugJavaRes
GRADLE> > Task :app:mergeDebugGlobalSynthetics
GRADLE> > Task :app:mergeProjectDexDebug
GRADLE> > Task :app:mergeLibDexDebug
GRADLE> > Task :HelloSkip:bundleDebugAar
GRADLE> > Task :HelloSkip:assembleDebug
GRADLE> > Task :HelloSkip:assemble
GRADLE> > Task :app:mergeDebugJavaResource
GRADLE> > Task :app:minifyReleaseWithR8
GRADLE> > Task :app:shrinkReleaseRes
GRADLE> > Task :app:packageRelease
GRADLE> > Task :app:createReleaseApkListingFileRedirect
GRADLE> > Task :app:assembleRelease
GRADLE> > Task :app:assemble
GRADLE>
GRADLE> BUILD SUCCESSFUL in 53s
GRADLE> 403 actionable tasks: 403 executed

构建产生的 .apk 将放置在 .build/Android/app/outputs/apk/ 文件夹中:

$ ls -lah .build/Android/app/outputs/apk/*/*.apk
57M .build/Android/app/outputs/apk/debug/app-debug.apk
13M .build/Android/app/outputs/apk/release/app-release-unsigned.apk

一个有效的 Skip 项目必须在每个启用了 Skip 的模块中包含一个 Skip/skip.yml 文件。这个文件是一个 YAML 文档,描述了模块在 Android/Gradle 世界中的表示。在构建过程中,这个文件会与所有依赖项目的 skip.yml 文件合并,用于影响 Gradle 项目的创建方式。使用 skip.yml 可以自定义 Gradle 构建过程,或添加对 Java 或 Kotlin 外部库的依赖,然后可以直接从 Skip 代码中使用这些库。

Gradle 项目使用 settings.gradle.ktsbuild.gradle.kts 文件进行配置,就像 Swift Package Manager 项目使用 Package.swift 一样。这些是 kotlin-script 文件,可以配置构建过程的所有方面,从编译参数到输出后处理。更多信息请参阅 https://docs.gradle.org/current/userguide/writing_build_scripts.html

Skip 通过从 SwiftPM 的 Package.swift 依赖结合每个项目的 Skip/skip.yml 文件内容自动派生有效的 Gradle 项目,从而抽象了框架项目的 Gradle 项目配置细节。Skip 构建插件会在其输出过程中生成 Gradle 项目文件夹层级结构。

框架项目与应用项目的区别在于,应用项目会展示各种 Gradle 应用级构建文件(Android/settings.gradle.ktsAndroid/app/build.gradle.kts),而框架项目则为生成的 Android 项目生成并维护构建结构。Skip 将生成的 Gradle 项目以及任何生成的 Kotlin 代码视为临时文件。清理构建可能会删除这些文件,重新运行转译器会覆盖任何更改。除非你(手动)导出或归档 Gradle 项目,否则它可能随时被覆盖。

当从命令行使用 swift buildskip test 构建时,gradle 项目将输出到 .build/plugins/outputs/ 文件夹,每个项目位于各自的包名目录中。从 Xcode 构建时,输出则放置在 ~/Library/Developer/Xcode/DerivedData/ProjectName-identifier/SourcePackages/plugins/ 中。

Skip 插件在一个限制性沙箱中运行,该沙箱限制了插件可以写入的输出文件夹。因此,每个单独的依赖都输出到各自的独立文件夹中,每个依赖项目通过创建符号链接来引用该项目的本地输出。例如,可以看到 HelloSkip 应用对 Skip Core 框架的本地依赖:

Skip build output file layout
$ tree -L 5 .build/plugins/outputs
  • 文件夹.build/plugins/outputs
    • 文件夹hello-skip
      • 文件夹HelloSkip
        • 文件夹skipstone
          • 文件夹HelloSkip
            • build.gradle.kts
            • proguard-rules.pro
            • src
          • HelloSkip.skipcode.json
          • 文件夹SkipFoundation/ -> ../../../skip-foundation/SkipFoundation/skipstone/SkipFoundation
          • 文件夹SkipLib/ -> ../../../skip-lib/SkipLib/skipstone/SkipLib
          • 文件夹SkipModel/ -> ../../../skip-model/SkipModel/skipstone/SkipModel
          • 文件夹SkipUI/ -> ../../../skip-ui/SkipUI/skipstone/SkipUI
          • 文件夹SkipUnit/ -> ../../../skip-unit/SkipUnit/skipstone/SkipUnit
          • 文件夹gradle
            • wrapper
          • gradle.properties
          • settings.gradle.kts
    • 文件夹skip-foundation
      • 文件夹SkipFoundation
        • 文件夹skipstone
          • 文件夹SkipFoundation
            • build.gradle.kts
            • proguard-rules.pro
            • src
          • SkipFoundation.skipcode.json
          • 文件夹SkipLib/ -> ../../../skip-lib/SkipLib/skipstone/SkipLib
          • 文件夹SkipUnit/ -> ../../../skip-unit/SkipUnit/skipstone/SkipUnit
          • 文件夹gradle
            • wrapper
          • gradle.properties
          • settings.gradle.kts
    • 文件夹skip-lib
      • 文件夹SkipLib
        • 文件夹skipstone
          • 文件夹SkipLib
            • build.gradle.kts
            • proguard-rules.pro
            • src
          • SkipLib.skipcode.json
          • 文件夹SkipUnit/ -> ../../../skip-unit/SkipUnit/skipstone/SkipUnit
          • 文件夹gradle
            • wrapper
          • gradle.properties
          • settings.gradle.kts
    • 文件夹skip-model
      • 文件夹SkipModel
        • 文件夹skipstone
          • 文件夹SkipLib/ -> ../../../skip-lib/SkipLib/skipstone/SkipLib
          • 文件夹SkipModel
            • build.gradle.kts
            • proguard-rules.pro
            • src
          • SkipModel.skipcode.json
          • 文件夹SkipUnit/ -> ../../../skip-unit/SkipUnit/skipstone/SkipUnit
          • 文件夹gradle
            • wrapper
          • gradle.properties
          • settings.gradle.kts
    • 文件夹skip-ui
      • 文件夹SkipUI
        • 文件夹skipstone
          • 文件夹SkipFoundation/ -> ../../../skip-foundation/SkipFoundation/skipstone/SkipFoundation
          • 文件夹SkipLib/ -> ../../../skip-lib/SkipLib/skipstone/SkipLib
          • 文件夹SkipModel/ -> ../../../skip-model/SkipModel/skipstone/SkipModel
          • 文件夹SkipUI
            • build.gradle.kts
            • proguard-rules.pro
            • src
          • SkipUI.skipcode.json
          • 文件夹SkipUnit/ -> ../../../skip-unit/SkipUnit/skipstone/SkipUnit
          • 文件夹gradle
            • wrapper
          • gradle.properties
          • settings.gradle.kts
    • 文件夹skip-unit
      • 文件夹SkipUnit
        • 文件夹skipstone
          • 文件夹SkipUnit
            • build.gradle.kts
            • proguard-rules.pro
            • src
          • SkipUnit.skipcode.json
          • 文件夹gradle
            • wrapper
          • gradle.properties
          • settings.gradle.kts

有关已发布输出格式的更多信息,请参阅将项目作为模块发布和 Android Gradle 插件上传你的库


每个 Skip 应用项目都依赖于 Skip 核心框架,其中包含任何应用的五个核心模块,其 skip.yml 文件可以作为有用的示例:SkipUISkipModelSkipFoundationSkipLibSkipUnit。这些项目会自动依次转译,形成一个项目链接网络,构成一个可构建的 Gradle 项目。由于这些是在本地检出的依赖,它们的转译输出可以通过模块转译过程中创建的相对符号链接从 Gradle 中引用。

阅读依赖文档以了解有关使用 skip.yml 添加 Java/Kotlin 依赖的更多信息。