You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Gradle Kotlin DSL发布Kotlin MPP元数据的规范实现问询

Fixing Cross-MPP Dependency Resolution for Shared JSON Utilities

Great question—this is a common gotcha with Kotlin Multiplatform (MPP) library publishing, especially when dealing with Gradle metadata and cross-MPP dependencies. Let's break down what's happening and how to fix it properly.

What's the Root Issue?

Your core problem is that your MPP library's publication metadata isn't structured correctly for other MPP projects to consume. The official documentation's promise of "single dependency auto-resolves target-specific artifacts" relies on your library publishing valid Gradle metadata that links the common metadata publication to your JVM/JS target artifacts.

Your current afterEvaluate hack works, but it's a workaround for missing proper publication configuration. The forced cast to MavenPublication and ad-hoc artifact ID renaming are red flags that we can clean up.

The Proper Solution

We'll fix this by aligning your publication setup with Kotlin MPP's conventions, eliminating the need for messy afterEvaluate logic while ensuring Gradle can correctly resolve your library across MPP projects.

Step 1: Ensure Targets and Source Sets Are Complete

First, make sure your kotlin block explicitly declares both JVM and JS targets (your provided build script was missing JS—likely a copy-paste oversight):

Step 2: Clean Up Publication Configuration

Instead of using afterEvaluate, use Gradle's type-safe withType API to configure all MavenPublication instances cleanly. This avoids forced casts and ensures we follow Kotlin's MPP naming conventions:

  • The metadata publication uses your base project name as the artifact ID
  • JVM/JS target publications use {project-name}-{target-name} as their artifact ID

Full Revised build.gradle.kts

group = "org.example"
version = "1.0-SNAPSHOT"

plugins {
    kotlin("multiplatform") version "1.3.72"
    `maven-publish`
}

repositories {
    mavenCentral()
}

kotlin {
    // Declare both JVM and JS targets
    jvm()
    js {
        browser() // Use nodejs() if targeting Node.js instead of browsers
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(kotlin("stdlib-common"))
            }
        }
        val jvmMain by getting {
            dependencies {
                implementation(kotlin("stdlib"))
            }
        }
        val jsMain by getting {
            dependencies {
                implementation(kotlin("stdlib-js"))
            }
        }
    }
}

publishing {
    // Configure all Maven publications type-safely
    publications.withType<MavenPublication> {
        artifactId = if (name.contains("metadata")) {
            project.name
        } else {
            "${project.name}-$name"
        }
    }

    // Add repository configuration (local or remote)
    repositories {
        mavenLocal() // For testing local consumption
        // Uncomment and configure for remote publishing:
        // maven {
        //     url = uri("https://your-repo-url.com")
        //     credentials {
        //         username = System.getenv("REPO_USER")
        //         password = System.getenv("REPO_PASS")
        //     }
        // }
    }
}

Why This Works Better

  1. No Hacky afterEvaluate: Gradle's withType<MavenPublication> automatically targets all publications generated by the Kotlin MPP plugin, so we don't need to wait for evaluation to modify them.
  2. Type Safety: No forced casts—we're explicitly working with MavenPublication instances, avoiding runtime errors.
  3. Convention-Aligned Naming: This setup matches Kotlin MPP's expected artifact naming pattern, which is what Gradle metadata relies on to link the common metadata artifact to your JVM/JS artifacts.

Testing the Fix

  1. Publish your library to mavenLocal() using ./gradlew publishToMavenLocal
  2. In your other MPP project, add this dependency to the commonMain source set:
    dependencies {
        implementation("org.example:${your-library-name}:1.0-SNAPSHOT")
    }
    
  3. Gradle will now automatically resolve the correct JVM/JS artifacts for each target—no need to add separate dependencies per target!

Bonus: Upgrade for Easier Setup

If you can upgrade to Kotlin 1.4+, the MPP plugin handles artifact ID naming automatically by default, eliminating the need for custom publication configuration entirely. Even if you stick with 1.3.72, the above setup is the cleanest, most maintainable fix.

内容的提问来源于stack exchange,提问作者Marvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:12:48