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

如何在Kotlin Compose Multi Platform中添加macOS专属代码与配置?

在KMM项目中添加macOS专属代码的配置指南

问题描述

我需要编写macOS专属代码(比如蓝牙权限这类需要Objective-C/Swift实现的底层功能),当前通过项目向导创建的KMM项目目录结构只有:

  • commonMain
  • androidMain
  • desktopMain

请问:

  1. 如何创建macOS专属的main文件夹并编写代码?能否自行创建该目录?
  2. 需要对Gradle进行哪些正确配置?

当前我的Gradle配置文件如下:

import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.composeMultiplatform)
    alias(libs.plugins.composeCompiler)
}

kotlin {
    androidTarget {
        @OptIn(ExperimentalKotlinGradlePluginApi::class)
        compilerOptions {
            jvmTarget.set(JvmTarget.JVM_11)
        }
    }
    
    jvm("desktop")
    macosArm64()
    applyDefaultHierarchyTemplate()

    sourceSets {
        val desktopMain by getting
        
        androidMain.dependencies {
            implementation(compose.preview)
            implementation(libs.androidx.activity.compose)
        }
        commonMain.dependencies {
            implementation(compose.runtime)
            implementation(compose.foundation)
            implementation(compose.material)
            implementation(compose.ui)
            implementation(compose.components.resources)
            implementation(compose.components.uiToolingPreview)
            implementation(libs.androidx.lifecycle.viewmodel)
            implementation(libs.androidx.lifecycle.runtime.compose)
        }
        desktopMain.dependencies {
            implementation(compose.desktop.currentOs)
            implementation(libs.kotlinx.coroutines.swing)
        }
        val jvmAndMacos by creating {
            dependsOn(commonMain.get())
        }

        macosArm64Main.get().dependsOn(jvmAndMacos)
        jvmMain.get().dependsOn(jvmAndMacos)
    }
}

android {
    namespace = "com.shekhar.multiplatformapp"
    compileSdk = libs.versions.android.compileSdk.get().toInt()

    defaultConfig {
        applicationId = "com.shekhar.multiplatformapp"
        minSdk = libs.versions.android.minSdk.get().toInt()
        targetSdk = libs.versions.android.targetSdk.get().toInt()
        versionCode = 1
        versionName = "1.0"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
}

dependencies {
    debugImplementation(compose.uiTooling)
}

compose.desktop {
    application {
        mainClass = "com.shekhar.multiplatformapp.MainKt"

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "com.shekhar.multiplatformapp"
            packageVersion = "1.0.0"
        }
    }
}

解决方案

1. 创建macOS专属源码目录

可以自行创建macOS对应的源码目录,目录结构要和Gradle的sourceSet对应:

  • 针对Apple Silicon(M系列)芯片:src/macosArm64Main/kotlin(放Kotlin代码)、src/macosArm64Main/swift(放Swift/Objective-C代码)
  • 针对Intel芯片:src/macosX64Main/kotlin、src/macosX64Main/swift
  • 可选:创建src/macosMain/kotlin作为通用macOS源码目录,让两种架构共享代码(需要在Gradle中配置关联)

2. Gradle配置调整

步骤1:添加需要的macOS架构

在kotlin块中,确保声明了需要支持的macOS架构,比如同时兼容Arm64和Intel:

kotlin {
    // ... 保留现有androidTarget、jvm("desktop")配置
    macosArm64()
    macosX64() // 加上这行支持Intel芯片
    applyDefaultHierarchyTemplate()
}

步骤2:配置sourceSets关联

在sourceSets块中,为macOS的代码目录添加依赖和专属配置:

sourceSets {
    // ... 保留现有androidMain、commonMain、desktopMain配置
    
    // 配置通用macOS sourceSet(可选,让两个架构共享代码)
    val macosMain by creating {
        dependsOn(commonMain.get())
    }
    
    // 配置Arm64专属代码
    val macosArm64Main by getting {
        dependsOn(macosMain)
        dependencies {
            implementation(libs.kotlinx.coroutines.core) // 添加macOS专属依赖
        }
    }
    
    // 配置X64专属代码
    val macosX64Main by getting {
        dependsOn(macosMain)
        dependencies {
            implementation(libs.kotlinx.coroutines.core)
        }
    }
}

步骤3:配置Compose Desktop的macOS分发

如果用了Compose Multiplatform,当前配置里的TargetFormat.Dmg已经支持macOS安装包,还可以添加专属配置比如图标:

compose.desktop {
    application {
        mainClass = "com.shekhar.multiplatformapp.MainKt"
        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "com.shekhar.multiplatformapp"
            packageVersion = "1.0.0"
            
            // macOS专属配置示例
            macOS {
                // iconFile.set(file("src/macosMain/resources/app-icon.icns")) // 可选设置应用图标
            }
        }
    }
}

步骤4:Swift/Objective-C代码调用

直接在对应的swift目录下创建.swift或.m文件,Kotlin可以通过Kotlin/Native interop直接调用:
比如创建src/macosArm64Main/swift/BluetoothPermission.swift:

import CoreBluetooth

func requestBluetoothPermission() {
    let centralManager = CBCentralManager(delegate: nil, queue: nil)
    centralManager.scanForPeripherals(withServices: nil)
}

然后在macOS的Kotlin代码中调用:

// macosArm64Main中的Kotlin代码
external fun requestBluetoothPermission()

fun checkBluetoothPermission() {
    requestBluetoothPermission()
}

3. 修改后的完整Gradle配置

import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.composeMultiplatform)
    alias(libs.plugins.composeCompiler)
}

kotlin {
    androidTarget {
        @OptIn(ExperimentalKotlinGradlePluginApi::class)
        compilerOptions {
            jvmTarget.set(JvmTarget.JVM_11)
        }
    }
    
    jvm("desktop")
    macosArm64()
    macosX64() // 添加Intel芯片支持
    applyDefaultHierarchyTemplate()

    sourceSets {
        val desktopMain by getting
        val macosArm64Main by getting
        val macosX64Main by getting
        
        // 通用macOS sourceSet,可选
        val macosMain by creating {
            dependsOn(commonMain.get())
        }
        macosArm64Main.dependsOn(macosMain)
        macosX64Main.dependsOn(macosMain)
        
        androidMain.dependencies {
            implementation(compose.preview)
            implementation(libs.androidx.activity.compose)
        }
        commonMain.dependencies {
            implementation(compose.runtime)
            implementation(compose.foundation)
            implementation(compose.material)
            implementation(compose.ui)
            implementation(compose.components.resources)
            implementation(compose.components.uiToolingPreview)
            implementation(libs.androidx.lifecycle.viewmodel)
            implementation(libs.androidx.lifecycle.runtime.compose)
        }
        desktopMain.dependencies {
            implementation(compose.desktop.currentOs)
            implementation(libs.kotlinx.coroutines.swing)
        }
        macosArm64Main.dependencies {
            implementation(libs.kotlinx.coroutines.core)
        }
        macosX64Main.dependencies {
            implementation(libs.kotlinx.coroutines.core)
        }
    }
}

android {
    namespace = "com.shekhar.multiplatformapp"
    compileSdk = libs.versions.android.compileSdk.get().toInt()

    defaultConfig {
        applicationId = "com.shekhar.multiplatformapp"
        minSdk = libs.versions.android.minSdk.get().toInt()
        targetSdk = libs.versions.android.targetSdk.get().toInt()
        versionCode = 1
        versionName = "1.0"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
}

dependencies {
    debugImplementation(compose.uiTooling)
}

compose.desktop {
    application {
        mainClass = "com.shekhar.multiplatformapp.MainKt"

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "com.shekhar.multiplatformapp"
            packageVersion = "1.0.0"
            // macOS专属配置示例
            macOS {
                // 可选:设置应用图标
                // iconFile.set(file("src/macosMain/resources/app-icon.icns"))
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:30:59