Quellcode durchsuchen

Merge pull request #66 from windchargerj/xmake_dynamic_info_support

Add XMake Info support
ruki vor 5 Monaten
Ursprung
Commit
313a6fbaa3
24 geänderte Dateien mit 371 neuen und 204 gelöschten Zeilen
  1. 42 75
      build.gradle.kts
  2. 1 1
      src/main/kotlin/io/xmake/actions/BuildAction.kt
  3. 1 1
      src/main/kotlin/io/xmake/actions/CleanAction.kt
  4. 1 1
      src/main/kotlin/io/xmake/actions/CleanConfigurationAction.kt
  5. 1 1
      src/main/kotlin/io/xmake/actions/QuickStartAction.kt
  6. 1 1
      src/main/kotlin/io/xmake/actions/RebuildAction.kt
  7. 1 1
      src/main/kotlin/io/xmake/actions/RunAction.kt
  8. 1 1
      src/main/kotlin/io/xmake/actions/UpdateCmakeListsAction.kt
  9. 1 1
      src/main/kotlin/io/xmake/actions/UpdateCompileCommandsAction.kt
  10. 0 1
      src/main/kotlin/io/xmake/project/toolkit/Toolkit.kt
  11. 16 0
      src/main/kotlin/io/xmake/project/toolkit/ToolkitChangedNotifier.kt
  12. 1 1
      src/main/kotlin/io/xmake/project/toolkit/ToolkitManager.kt
  13. 6 0
      src/main/kotlin/io/xmake/project/toolkit/ui/ToolkitComboBox.kt
  14. 19 21
      src/main/kotlin/io/xmake/run/XMakeRunConfiguration.kt
  15. 18 10
      src/main/kotlin/io/xmake/run/XMakeRunConfigurationEditor.kt
  16. 9 4
      src/main/kotlin/io/xmake/shared/XMakeConfiguration.kt
  17. 0 82
      src/main/kotlin/io/xmake/utils/ConsoleProcessHandler.kt
  18. 1 1
      src/main/kotlin/io/xmake/utils/SystemUtils.kt
  19. 73 0
      src/main/kotlin/io/xmake/utils/info/XMakeInfo.kt
  20. 21 0
      src/main/kotlin/io/xmake/utils/info/XMakeInfoActivity.kt
  21. 6 0
      src/main/kotlin/io/xmake/utils/info/XMakeInfoInstance.kt
  22. 117 0
      src/main/kotlin/io/xmake/utils/info/XMakeInfoManager.kt
  23. 31 0
      src/main/kotlin/io/xmake/utils/info/XMakeInfoTypes.kt
  24. 3 1
      src/main/resources/META-INF/plugin.xml

+ 42 - 75
build.gradle.kts

@@ -1,5 +1,4 @@
-import org.jetbrains.intellij.IntelliJPluginExtension
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
 
 
 fun properties(key: String) = project.findProperty(key).toString()
 fun properties(key: String) = project.findProperty(key).toString()
 
 
@@ -29,7 +28,7 @@ val buildIdeType: String = when (2) {
     else -> "IC"
     else -> "IC"
 }
 }
 
 
-val buildIdeVersion = "2024.3"
+val buildIdeVersion = "2025.1"
 
 
 val runIdeType: String = when (2) {
 val runIdeType: String = when (2) {
     0 -> "IC" // You can build with the Ultimate version, but run with the Community version.
     0 -> "IC" // You can build with the Ultimate version, but run with the Community version.
@@ -39,104 +38,72 @@ val runIdeType: String = when (2) {
     else -> "IC"
     else -> "IC"
 }
 }
 
 
-val runIdeVersion = "2024.3"
+val runIdeVersion = "2025.1"
 
 
 plugins {
 plugins {
     id("java")
     id("java")
-    id("org.jetbrains.intellij") version "1.17.1"
-    id("org.jetbrains.kotlin.jvm") version "1.9.22"
+    id("org.jetbrains.intellij.platform") version "2.5.0"
+    id("org.jetbrains.kotlin.jvm") version "2.1.0"
     id("org.jetbrains.changelog") version "2.2.0"
     id("org.jetbrains.changelog") version "2.2.0"
+    kotlin("plugin.serialization") version "2.1.0"
 }
 }
 
 
 group = "io.xmake"
 group = "io.xmake"
 
 
 repositories {
 repositories {
-    maven("https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository")
+    maven("https://maven.aliyun.com/repository/public/")
+    maven("https://oss.sonatype.org/content/repositories/snapshots/")
     mavenLocal()
     mavenLocal()
     mavenCentral()
     mavenCentral()
     gradlePluginPortal()
     gradlePluginPortal()
-    maven("https://maven.aliyun.com/repository/public/")
-    maven("https://oss.sonatype.org/content/repositories/snapshots/")
-    maven("https://cache-redirector.jetbrains.com/intellij-dependencies")
-}
-
-intellij {
-    type.set(buildIdeType)
-    version.set(buildIdeVersion)
-    downloadSources.set(true)
-    ideaDependencyCachePath.set(dependencyCachePath)
-    updateSinceUntilBuild.set(true)
-    /*
-    plugins.set(
-        listOf(
-            "com.intellij.clion",
-            "com.intellij.cidr.base",
-            "com.intellij.cidr.lang"
-        )
-    )
-     */
-}
-
-tasks {
-    withType<JavaCompile> {
-        sourceCompatibility = "17"
-        targetCompatibility = "17"
-    }
-    withType<KotlinCompile> {
-        kotlinOptions.jvmTarget = "17"
-        kotlinOptions.languageVersion = "2.0"
+    intellijPlatform {
+        defaultRepositories()
     }
     }
+}
 
 
-    test {
-        useJUnit()
-        include("io/xmake/**/**")
-    }
+intellijPlatform{
 
 
-    patchPluginXml {
+    pluginConfiguration {
         version = properties("pluginVersion")
         version = properties("pluginVersion")
-        sinceBuild = properties("pluginSinceBuild")
-        untilBuild = properties("pluginUntilBuild")
         changeNotes = localChangeNotes
         changeNotes = localChangeNotes
-        pluginDescription = localDescription
-    }
-
-    runPluginVerifier {
-        ideVersions.set(
-            listOf(
-                "2023.3",
-                "2024.1",
-                "2024.2",
-                "2024.3"
-            )
-        )
+        description = localDescription
+        ideaVersion {
+            sinceBuild = properties("pluginSinceBuild")
+            untilBuild = properties("pluginUntilBuild")
+        }
     }
     }
 
 
-    // Execute this downloadIde gradle task if missing build.txt in runIde task.
-    register("downloadIde") {
-        group = "Custom Tasks"
-        description = "Downloads a specific version and type of IntelliJ IDEA based on provided parameters."
-
-        doFirst {
-            println("Executing downloadIde task")
-            val intellijExtension = project.extensions.getByType(IntelliJPluginExtension::class.java)
-            val ideVersion = project.findProperty("ideVersion")?.toString() ?: runIdeVersion
-            val ideType = project.findProperty("ideType")?.toString() ?: runIdeType
-
-            intellijExtension.version.set(ideVersion)
-            intellijExtension.type.set(ideType)
+    pluginVerification {
+        ides{
+            select {
+                types = listOf(
+                    IntelliJPlatformType.CLion,
+                    IntelliJPlatformType.IntellijIdeaUltimate,
+                    IntelliJPlatformType.IntellijIdeaCommunity
+                )
+                sinceBuild = "243"
+                untilBuild = "251.*"
+            }
         }
         }
-
-        finalizedBy("setupDependencies")
     }
     }
+}
 
 
-    runIde {
-        ideDir.set(file("deps/${type[runIdeType]}-$runIdeVersion"))
+tasks {
+    test {
+        useJUnit()
+        include("io/xmake/**/**")
     }
     }
 }
 }
 
 
 dependencies {
 dependencies {
-    implementation("org.jetbrains.kotlin:kotlin-stdlib:2.0.0")
+    implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
+    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
     testImplementation("io.mockk:mockk:1.13.12")
     testImplementation("io.mockk:mockk:1.13.12")
+    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
+    intellijPlatform {
+        create(runIdeType, runIdeVersion)
+        bundledPlugin("com.intellij.clion")
+    }
 }
 }
 
 
 val Project.dependencyCachePath
 val Project.dependencyCachePath
@@ -146,4 +113,4 @@ val Project.dependencyCachePath
             cachePath.mkdirs()
             cachePath.mkdirs()
         }
         }
         return cachePath.absolutePath
         return cachePath.absolutePath
-    }
+    }

+ 1 - 1
src/main/kotlin/io/xmake/actions/BuildAction.kt

@@ -42,7 +42,7 @@ class BuildAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/CleanAction.kt

@@ -42,7 +42,7 @@ class CleanAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/CleanConfigurationAction.kt

@@ -31,7 +31,7 @@ class CleanConfigurationAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/QuickStartAction.kt

@@ -29,7 +29,7 @@ class QuickStartAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/RebuildAction.kt

@@ -42,7 +42,7 @@ class RebuildAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/RunAction.kt

@@ -49,7 +49,7 @@ class RunAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/UpdateCmakeListsAction.kt

@@ -65,7 +65,7 @@ class UpdateCmakeListsAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 1 - 1
src/main/kotlin/io/xmake/actions/UpdateCompileCommandsAction.kt

@@ -70,7 +70,7 @@ class UpdateCompileCommandsAction : AnAction() {
                 ConsoleViewContentType.ERROR_OUTPUT
                 ConsoleViewContentType.ERROR_OUTPUT
             )
             )
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Configuration", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
         }
         }

+ 0 - 1
src/main/kotlin/io/xmake/project/toolkit/Toolkit.kt

@@ -23,7 +23,6 @@ data class Toolkit(
     var isRegistered: Boolean = false
     var isRegistered: Boolean = false
     @get:Transient
     @get:Transient
     var isValid: Boolean = true
     var isValid: Boolean = true
-
     @get:Transient
     @get:Transient
     val isOnRemote: Boolean
     val isOnRemote: Boolean
         get() = with(host) { type == ToolkitHostType.WSL || type == ToolkitHostType.SSH }
         get() = with(host) { type == ToolkitHostType.WSL || type == ToolkitHostType.SSH }

+ 16 - 0
src/main/kotlin/io/xmake/project/toolkit/ToolkitChangedNotifier.kt

@@ -0,0 +1,16 @@
+package io.xmake.project.toolkit
+
+import com.intellij.util.messages.Topic
+
+interface ToolkitChangedNotifier {
+
+    fun toolkitChanged(toolkit: Toolkit?)
+
+    companion object {
+        @Topic.ProjectLevel
+        val TOOLKIT_CHANGED_TOPIC: Topic<ToolkitChangedNotifier> = Topic.create(
+            "toolkit changed",
+            ToolkitChangedNotifier::class.java
+        )
+    }
+}

+ 1 - 1
src/main/kotlin/io/xmake/project/toolkit/ToolkitManager.kt

@@ -199,7 +199,7 @@ class ToolkitManager(private val scope: CoroutineScope) : PersistentStateCompone
         this.storage = state
         this.storage = state
     }
     }
 
 
-    fun loadToolkit(toolkit: Toolkit) {
+    private fun loadToolkit(toolkit: Toolkit) {
         scope.launch(Dispatchers.IO) {
         scope.launch(Dispatchers.IO) {
             toolkit.host.loadTarget()
             toolkit.host.loadTarget()
             joinAll()
             joinAll()

+ 6 - 0
src/main/kotlin/io/xmake/project/toolkit/ui/ToolkitComboBox.kt

@@ -1,6 +1,7 @@
 package io.xmake.project.toolkit.ui
 package io.xmake.project.toolkit.ui
 
 
 import ai.grazie.utils.tryRunWithException
 import ai.grazie.utils.tryRunWithException
+import com.intellij.openapi.application.ApplicationManager
 import com.intellij.openapi.diagnostic.logger
 import com.intellij.openapi.diagnostic.logger
 import com.intellij.openapi.project.ProjectManager
 import com.intellij.openapi.project.ProjectManager
 import com.intellij.openapi.ui.ComboBox
 import com.intellij.openapi.ui.ComboBox
@@ -10,6 +11,7 @@ import com.intellij.openapi.ui.validation.validationErrorIf
 import com.intellij.ui.PopupMenuListenerAdapter
 import com.intellij.ui.PopupMenuListenerAdapter
 import com.intellij.ui.SortedComboBoxModel
 import com.intellij.ui.SortedComboBoxModel
 import io.xmake.project.toolkit.Toolkit
 import io.xmake.project.toolkit.Toolkit
+import io.xmake.project.toolkit.ToolkitChangedNotifier
 import io.xmake.project.toolkit.ToolkitManager
 import io.xmake.project.toolkit.ToolkitManager
 import java.awt.event.ItemEvent
 import java.awt.event.ItemEvent
 import java.util.*
 import java.util.*
@@ -174,9 +176,13 @@ class ToolkitComboBox(toolkitProperty: KMutableProperty0<Toolkit?>) : ComboBox<T
         toolkitChangedListeners.add(listener)
         toolkitChangedListeners.add(listener)
     }
     }
 
 
+    val publisher: ToolkitChangedNotifier = ApplicationManager.getApplication().messageBus
+        .syncPublisher(ToolkitChangedNotifier.TOOLKIT_CHANGED_TOPIC)
+
     fun addToolkitChangedListener(action: (Toolkit?) -> Unit) {
     fun addToolkitChangedListener(action: (Toolkit?) -> Unit) {
         toolkitChangedListeners.add(object : ToolkitChangedListener {
         toolkitChangedListeners.add(object : ToolkitChangedListener {
             override fun onToolkitChanged(toolkit: Toolkit?) {
             override fun onToolkitChanged(toolkit: Toolkit?) {
+                publisher.toolkitChanged(toolkit)
                 action(toolkit)
                 action(toolkit)
             }
             }
         })
         })

+ 19 - 21
src/main/kotlin/io/xmake/run/XMakeRunConfiguration.kt

@@ -17,6 +17,8 @@ import io.xmake.project.toolkit.ToolkitManager
 import io.xmake.project.xmakeConsoleView
 import io.xmake.project.xmakeConsoleView
 import io.xmake.shared.xmakeConfiguration
 import io.xmake.shared.xmakeConfiguration
 import io.xmake.utils.SystemUtils
 import io.xmake.utils.SystemUtils
+import io.xmake.utils.info.XMakeInfoManager
+import io.xmake.utils.info.xmakeInfo
 import org.jdom.Element
 import org.jdom.Element
 import kotlin.io.path.Path
 import kotlin.io.path.Path
 
 
@@ -33,10 +35,13 @@ class XMakeRunConfiguration(
     var runTarget: String = "default"
     var runTarget: String = "default"
 
 
     @OptionTag(tag = "platform")
     @OptionTag(tag = "platform")
-    var runPlatform: String = SystemUtils.platform()
+    var runPlatform: String = if (platforms.contains(SystemUtils.platform())) SystemUtils.platform() else "default"
 
 
     @OptionTag(tag = "architecture")
     @OptionTag(tag = "architecture")
-    var runArchitecture: String = getArchitecturesByPlatform(runPlatform).first()
+    var runArchitecture: String = getArchitecturesByPlatform(runPlatform).firstOrNull() ?: "default"
+
+    @OptionTag(tag = "toolchain")
+    var runToolchain: String = toolchains.firstOrNull() ?: "default"
 
 
     @OptionTag(tag = "mode")
     @OptionTag(tag = "mode")
     var runMode: String = "release"
     var runMode: String = "release"
@@ -105,6 +110,8 @@ class XMakeRunConfiguration(
         runToolkit = runToolkit?.let { toolkit ->
         runToolkit = runToolkit?.let { toolkit ->
             ToolkitManager.getInstance().findRegisteredToolkitById(toolkit.id)
             ToolkitManager.getInstance().findRegisteredToolkitById(toolkit.id)
         }
         }
+        // Todo: Optimize to avoid probing delay.
+        XMakeInfoManager.getInstance(project).probeXMakeInfo(runToolkit)
     }
     }
 
 
     override fun checkConfiguration() {
     override fun checkConfiguration() {
@@ -144,29 +151,20 @@ class XMakeRunConfiguration(
         return null
         return null
     }
     }
 
 
-    companion object {
-
-        // the platforms
-        val platforms = arrayOf("macosx", "linux", "windows", "android", "iphoneos", "watchos", "mingw")
+    val platforms: Array<String>
+        get() = project.xmakeInfo.architectures.keys.plus("default").toTypedArray()
 
 
-        // the modes
-        val modes = arrayOf("release", "debug")
+    val toolchains: Array<String>
+        get() = project.xmakeInfo.toolchains.keys.plus("default").toTypedArray()
 
 
-        /*        // the architectures
-                val architectures: Array<String>
-                    get() = getArchitecturesByPlatform(runPlatform)*/
-
-        // get architectures by platform
-        fun getArchitecturesByPlatform(platform: String) = when (platform) {
-            "macosx", "linux", "mingw" -> arrayOf("x86_64", "i386", "arm64")
-            "windows" -> arrayOf("x86", "x64")
-            "iphoneos" -> arrayOf("arm64", "armv7", "armv7s", "x86_64", "i386")
-            "watchos" -> arrayOf("armv7s", "i386")
-            "android" -> arrayOf("armv7-a", "armv5te", "armv6", "armv8-a", "arm64-v8a")
-            else -> arrayOf()
-        }
+    val modes: Array<String>
+        get() = project.xmakeInfo.buildModes.map { it.substringAfter('.') }.toTypedArray()
 
 
+    fun getArchitecturesByPlatform(platform: String): Array<String> {
+        return (project.xmakeInfo.architectures[platform]?.toTypedArray() ?: arrayOf("default"))
+    }
 
 
+    companion object {
         private val Log = Logger.getInstance(XMakeRunConfiguration::class.java.getName())
         private val Log = Logger.getInstance(XMakeRunConfiguration::class.java.getName())
     }
     }
 }
 }

+ 18 - 10
src/main/kotlin/io/xmake/run/XMakeRunConfigurationEditor.kt

@@ -18,9 +18,6 @@ import io.xmake.project.target.TargetManager
 import io.xmake.project.toolkit.Toolkit
 import io.xmake.project.toolkit.Toolkit
 import io.xmake.project.toolkit.ui.ToolkitComboBox
 import io.xmake.project.toolkit.ui.ToolkitComboBox
 import io.xmake.project.toolkit.ui.ToolkitListItem
 import io.xmake.project.toolkit.ui.ToolkitListItem
-import io.xmake.run.XMakeRunConfiguration.Companion.getArchitecturesByPlatform
-import io.xmake.run.XMakeRunConfiguration.Companion.modes
-import io.xmake.run.XMakeRunConfiguration.Companion.platforms
 import io.xmake.shared.xmakeConfiguration
 import io.xmake.shared.xmakeConfiguration
 import io.xmake.utils.execute.SyncDirection
 import io.xmake.utils.execute.SyncDirection
 import io.xmake.utils.execute.transferFolderByToolkit
 import io.xmake.utils.execute.transferFolderByToolkit
@@ -47,13 +44,17 @@ class XMakeRunConfigurationEditor(
     private val targetsModel = DefaultComboBoxModel<String>()
     private val targetsModel = DefaultComboBoxModel<String>()
     private val targetsComboBox = ComboBox(targetsModel).apply { item = runConfiguration.runTarget }
     private val targetsComboBox = ComboBox(targetsModel).apply { item = runConfiguration.runTarget }
 
 
-    private val platformsModel = DefaultComboBoxModel(platforms)
+    private val platformsModel = DefaultComboBoxModel(runConfiguration.platforms)
     private val platformsComboBox = ComboBox(platformsModel).apply { item = runConfiguration.runPlatform }
     private val platformsComboBox = ComboBox(platformsModel).apply { item = runConfiguration.runPlatform }
 
 
-    private val architecturesModel = DefaultComboBoxModel(getArchitecturesByPlatform(runConfiguration.runPlatform))
+    private val architecturesModel =
+        DefaultComboBoxModel(runConfiguration.getArchitecturesByPlatform(runConfiguration.runPlatform))
     private val architecturesComboBox = ComboBox(architecturesModel).apply { item = runConfiguration.runArchitecture }
     private val architecturesComboBox = ComboBox(architecturesModel).apply { item = runConfiguration.runArchitecture }
 
 
-    private val modesModel = DefaultComboBoxModel(modes)
+    private val toolchainsModel = DefaultComboBoxModel(runConfiguration.toolchains)
+    private val toolchainsComboBox = ComboBox(toolchainsModel).apply { item = runConfiguration.runToolchain }
+
+    private val modesModel = DefaultComboBoxModel(runConfiguration.modes)
     private val modesComboBox = ComboBox(modesModel).apply { item = runConfiguration.runMode }
     private val modesComboBox = ComboBox(modesModel).apply { item = runConfiguration.runMode }
 
 
     private val runArguments = RawCommandLineEditor()
     private val runArguments = RawCommandLineEditor()
@@ -80,12 +81,15 @@ class XMakeRunConfigurationEditor(
 
 
         // reset targets
         // reset targets
         targetsModel.removeAllElements()
         targetsModel.removeAllElements()
+
         targetsModel.selectedItem = configuration.runTarget
         targetsModel.selectedItem = configuration.runTarget
 
 
         platformsComboBox.item = configuration.runPlatform
         platformsComboBox.item = configuration.runPlatform
 
 
         architecturesComboBox.item = configuration.runArchitecture
         architecturesComboBox.item = configuration.runArchitecture
 
 
+        toolchainsComboBox.item = configuration.runToolchain
+
         modesComboBox.item = configuration.runMode
         modesComboBox.item = configuration.runMode
 
 
         // reset run arguments
         // reset run arguments
@@ -116,6 +120,8 @@ class XMakeRunConfigurationEditor(
 
 
         configuration.runArchitecture = architecturesComboBox.item
         configuration.runArchitecture = architecturesComboBox.item
 
 
+        configuration.runToolchain = toolchainsComboBox.item
+
         configuration.runMode = modesComboBox.item
         configuration.runMode = modesComboBox.item
 
 
         configuration.runArguments = runArguments.text
         configuration.runArguments = runArguments.text
@@ -168,7 +174,7 @@ class XMakeRunConfigurationEditor(
                 row {
                 row {
                     cell(platformsComboBox).applyToComponent {
                     cell(platformsComboBox).applyToComponent {
                         addItemListener {
                         addItemListener {
-                            val architectures = getArchitecturesByPlatform(selectedItem as String)
+                            val architectures = runConfiguration.getArchitecturesByPlatform(selectedItem as String)
                             with(architecturesModel) {
                             with(architecturesModel) {
                                 removeAllElements()
                                 removeAllElements()
                                 addAll(architectures.toMutableList())
                                 addAll(architectures.toMutableList())
@@ -188,10 +194,10 @@ class XMakeRunConfigurationEditor(
             }.resizableColumn()
             }.resizableColumn()
             panel {
             panel {
                 row {
                 row {
-                    label("Mode:")
+                    label("Toolchain:")
                 }
                 }
                 row {
                 row {
-                    cell(modesComboBox).align(AlignX.FILL)
+                    cell(toolchainsComboBox).align(AlignX.FILL)
                 }
                 }
             }.resizableColumn()
             }.resizableColumn()
         }.layout(RowLayout.PARENT_GRID)
         }.layout(RowLayout.PARENT_GRID)
@@ -214,7 +220,9 @@ class XMakeRunConfigurationEditor(
                         }
                         }
                     }
                     }
                 })
                 })
-            }.align(AlignX.FILL)
+            }.align(AlignX.FILL).resizableColumn()
+            label("Mode:").align(AlignX.FILL)
+            cell(modesComboBox).align(AlignX.FILL)
         }
         }
 
 
         row("Program arguments:") {
         row("Program arguments:") {

+ 9 - 4
src/main/kotlin/io/xmake/shared/XMakeConfiguration.kt

@@ -88,14 +88,19 @@ class XMakeConfiguration(val project: Project) {
                 mutableListOf(
                 mutableListOf(
                     "f",
                     "f",
                     "-y",
                     "-y",
-                    "-p",
-                    configuration.runPlatform,
-                    "-a",
-                    configuration.runArchitecture,
                     "-m",
                     "-m",
                     configuration.runMode,
                     configuration.runMode,
                     "--policies=run.autobuild"
                     "--policies=run.autobuild"
                 )
                 )
+            if (configuration.runPlatform != "default") {
+                parameters.addAll(listOf("-p", configuration.runPlatform))
+            }
+            if (configuration.runArchitecture != "default") {
+                parameters.addAll(listOf("-a", configuration.runArchitecture))
+            }
+            if (configuration.runToolchain != "default" ) {
+                parameters.add("--toolchain=${configuration.runToolchain}")
+            }
             if (configuration.runPlatform == "android" && configuration.androidNDKDirectory != "") {
             if (configuration.runPlatform == "android" && configuration.androidNDKDirectory != "") {
                 parameters.add("--ndk=\"${configuration.androidNDKDirectory}\"")
                 parameters.add("--ndk=\"${configuration.androidNDKDirectory}\"")
             }
             }

+ 0 - 82
src/main/kotlin/io/xmake/utils/ConsoleProcessHandler.kt

@@ -1,82 +0,0 @@
-package io.xmake.utils
-
-import com.intellij.execution.configurations.GeneralCommandLine
-import com.intellij.execution.process.KillableColoredProcessHandler
-import com.intellij.execution.process.ProcessTerminatedListener
-import com.intellij.execution.ui.ConsoleView
-import com.intellij.execution.ui.ConsoleViewContentType
-import com.intellij.openapi.diagnostic.Logger
-import com.intellij.openapi.util.Key
-import java.io.IOException
-import java.io.OutputStreamWriter
-
-@Deprecated("Please refer to runProcessWithHandler.")
-class ConsoleProcessHandler(
-    private val consoleView: ConsoleView,
-    commandLine: GeneralCommandLine,
-    showExitCode: Boolean = false
-) : KillableColoredProcessHandler(commandLine) {
-
-    // the output content
-    var outputContent = ""
-
-    // initialize
-    init {
-
-        // shows exit code upon termination
-        if (showExitCode) {
-            ProcessTerminatedListener.attach(this)
-        }
-    }
-
-    override fun coloredTextAvailable(textOriginal: String, attributes: Key<*>) {
-        append(textOriginal, attributes)
-    }
-
-    // append info to the console view
-    private fun append(s: String, k: Key<*>) {
-        this.consoleView.print(s, ConsoleViewContentType.getConsoleViewType(k))
-        outputContent += s
-    }
-
-    // append input info to the console view
-    fun input(s: String) {
-        try {
-            processInputWriter.append(s)
-        } catch (ex: IOException) {
-            Log.error(ex)
-        }
-    }
-
-    // append input info and flush it
-    fun inputWithFlush(s: String) {
-        try {
-            processInputWriter.append(s)
-            processInputWriter.flush()
-        } catch (ex: IOException) {
-            Log.error(ex)
-        }
-    }
-
-    var _outputStreamWriter: OutputStreamWriter? = null
-    private val processInputWriter: OutputStreamWriter
-        get() {
-            if (_outputStreamWriter == null) {
-                _outputStreamWriter = OutputStreamWriter(processInput)
-            }
-            return _outputStreamWriter ?: OutputStreamWriter(processInput)
-        }
-
-    // flush io
-    fun flush() {
-        try {
-            processInputWriter.flush()
-        } catch (ex: IOException) {
-            Log.error(ex)
-        }
-    }
-
-    companion object {
-        private val Log = Logger.getInstance(ConsoleProcessHandler::class.java.getName())
-    }
-}

+ 1 - 1
src/main/kotlin/io/xmake/utils/SystemUtils.kt

@@ -78,7 +78,7 @@ object SystemUtils {
             }
             }
         } catch (e: XMakeToolkitNotSetException) {
         } catch (e: XMakeToolkitNotSetException) {
             NotificationGroupManager.getInstance()
             NotificationGroupManager.getInstance()
-                .getNotificationGroup("XMake")
+                .getNotificationGroup("XMake.NotificationGroup")
                 .createNotification("Error with XMake Toolkit", e.message ?: "", NotificationType.ERROR)
                 .createNotification("Error with XMake Toolkit", e.message ?: "", NotificationType.ERROR)
                 .notify(project)
                 .notify(project)
             throw ProcessNotCreatedException(e.message ?: "", commandLine)
             throw ProcessNotCreatedException(e.message ?: "", commandLine)

+ 73 - 0
src/main/kotlin/io/xmake/utils/info/XMakeInfo.kt

@@ -0,0 +1,73 @@
+package io.xmake.utils.info
+
+import com.intellij.openapi.diagnostic.logger
+import kotlinx.serialization.json.Json
+
+class XMakeInfo {
+
+    var apis: XMakeApis? = null
+    var architectures: XMakeArchitectures = emptyMap()
+    var buildModes: XMakeBuildModes = emptyList()
+    var envs: XMakeEnvs = emptyMap()
+    var packages: XMakePackages = emptyList()
+    var platforms: XMakePlatforms = emptyList()
+    var policies: XMakePolicies = emptyMap()
+    var rules: XMakeRules = emptyList()
+    var targets: XMakeTargets = emptyList()
+    var toolchains: XMakeToolchains = emptyMap()
+
+    fun parseApis(apiString: String): XMakeApis? {
+        return Json.decodeFromString(apiString)
+    }
+
+    fun parseArchitectures(archString: String): XMakeArchitectures {
+        return Json.decodeFromString(archString)
+    }
+
+    fun parseBuildModes(buildModeString: String): XMakeBuildModes {
+        return Json.decodeFromString(buildModeString)
+    }
+
+    fun parseEnvs(envString: String): XMakeEnvs {
+        // Todo
+        return emptyMap()
+    }
+
+    fun parsePackages(packageString: String): XMakePackages {
+        // Todo
+        return emptyList()
+    }
+
+    fun parsePlatforms(platformString: String): XMakePlatforms {
+        return Json.decodeFromString(platformString)
+    }
+
+    fun parsePolicies(policyString: String): XMakePolicies {
+        // Todo
+        return emptyMap()
+    }
+
+    fun parseRules(ruleString: String): XMakeRules {
+        return Json.decodeFromString(ruleString)
+    }
+
+    fun parseTargets(targetString: String): XMakeTargets {
+        return Json.decodeFromString(targetString)
+    }
+
+    fun parseToolchains(toolchainString: String): XMakeToolchains {
+        return toolchainString.split("\n").associate {
+            it.split(" ", limit = 2).map { s ->
+                s.replace(Regex("\u001B\\[[0-9;]*[A-Za-z]"), "")
+            }.let { (toolchain, description) ->
+                toolchain to description
+            }
+        }.also { Log.info("Parsed XMake Supported Toolchains: ${it.keys}") }
+    }
+
+    companion object {
+        val Log = logger<XMakeInfo>()
+
+    }
+}
+

+ 21 - 0
src/main/kotlin/io/xmake/utils/info/XMakeInfoActivity.kt

@@ -0,0 +1,21 @@
+package io.xmake.utils.info
+
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.startup.ProjectActivity
+import io.xmake.project.toolkit.Toolkit
+import io.xmake.project.toolkit.ToolkitChangedNotifier
+
+class XMakeInfoActivity : ProjectActivity {
+    override suspend fun execute(project: Project) {
+        ApplicationManager.getApplication().messageBus.connect()
+            .subscribe(
+                ToolkitChangedNotifier.TOOLKIT_CHANGED_TOPIC,
+                object : ToolkitChangedNotifier {
+                    override fun toolkitChanged(toolkit: Toolkit?) {
+                        XMakeInfoManager.getInstance(project).probeXMakeInfo(toolkit)
+                    }
+                }
+            )
+    }
+}

+ 6 - 0
src/main/kotlin/io/xmake/utils/info/XMakeInfoInstance.kt

@@ -0,0 +1,6 @@
+package io.xmake.utils.info
+
+import com.intellij.openapi.project.Project
+
+val Project.xmakeInfo: XMakeInfo
+    get() = XMakeInfoManager.getInstance(this).xmakeInfo

+ 117 - 0
src/main/kotlin/io/xmake/utils/info/XMakeInfoManager.kt

@@ -0,0 +1,117 @@
+package io.xmake.utils.info
+
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.openapi.components.Service
+import com.intellij.openapi.components.serviceOrNull
+import com.intellij.openapi.diagnostic.logger
+import com.intellij.openapi.project.Project
+import io.xmake.project.toolkit.Toolkit
+import io.xmake.utils.execute.createProcess
+import io.xmake.utils.execute.runProcess
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+@Service(Service.Level.PROJECT)
+class XMakeInfoManager(val project: Project, private val scope: CoroutineScope) {
+
+    val xmakeInfo: XMakeInfo = XMakeInfo()
+
+    // Todo
+    val cachedXMakeInfoMap: MutableMap<Toolkit, XMakeInfo> = mutableMapOf()
+
+    fun probeXMakeInfo(toolkit: Toolkit?) {
+        scope.launch {
+            toolkit?.let {
+                val apisString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l apis --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val architecturesString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l architectures --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val buildModesString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l buildmodes --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val envsString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l envs --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val packagesString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l packages --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val platformsString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l platforms --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val policiesString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l policies --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val rulesString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l rules --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val targetsString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l targets --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                val toolchainsString = runProcess(
+                    GeneralCommandLine(
+                        "xmake show -l toolchains --json".split(" ")
+                    ).createProcess(it)
+                ).first.getOrDefault("")
+
+                with(xmakeInfo) {
+                    apis = parseApis(apisString)
+                    architectures = parseArchitectures(architecturesString)
+                    buildModes = parseBuildModes(buildModesString)
+                    platforms = parsePlatforms(platformsString)
+                    policies = parsePolicies(policiesString)
+                    rules = parseRules(rulesString)
+//                    targets = parseTargets(targetsString)
+                    toolchains = parseToolchains(toolchainsString)
+
+                    Log.info(
+                        "XMake Info: " +
+                                "$apis, " +
+                                "$architectures, " +
+                                "$platforms, " +
+                                "$policies, " +
+                                "$rules, " +
+                                "$targets, " +
+                                "$toolchains"
+                    )
+                }
+
+                println(xmakeInfo)
+
+            }
+        }
+    }
+
+    companion object {
+        val Log = logger<XMakeInfoManager>()
+        fun getInstance(project: Project): XMakeInfoManager = project.serviceOrNull() ?: throw IllegalStateException()
+    }
+}

+ 31 - 0
src/main/kotlin/io/xmake/utils/info/XMakeInfoTypes.kt

@@ -0,0 +1,31 @@
+package io.xmake.utils.info
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class XMakeApis(
+    @SerialName("description_builtin_apis")
+    val descriptionBuiltinApis: List<String>,
+    @SerialName("description_builtin_module_apis")
+    val descriptionBuiltinModuleApis: List<String>,
+    @SerialName("script_instance_apis")
+    val scriptInstanceApis: List<String>,
+    @SerialName("script_extension_module_apis")
+    val scriptExtensionModuleApis: List<String>,
+    @SerialName("description_scope_apis")
+    val descriptionScopeApis: List<String>,
+    @SerialName("script_builtin_apis")
+    val scriptBuiltinApis: List<String>,
+    @SerialName("script_builtin_module_apis")
+    val scriptBuiltinModuleApis: List<String>,
+)
+typealias XMakeArchitectures = Map<String, List<String>>
+typealias XMakeBuildModes = List<String>
+typealias XMakeEnvs = Map<String, String>
+typealias XMakePackages = List<String>
+typealias XMakePlatforms = List<String>
+typealias XMakePolicies = Map<String, Any>
+typealias XMakeRules = List<String>
+typealias XMakeTargets = List<String>
+typealias XMakeToolchains = Map<String, String>

+ 3 - 1
src/main/resources/META-INF/plugin.xml

@@ -50,7 +50,9 @@
         <runConfigurationProducer implementation="io.xmake.run.XMakeRunConfigurationProducer"/>
         <runConfigurationProducer implementation="io.xmake.run.XMakeRunConfigurationProducer"/>
 
 
         <!-- notifications -->
         <!-- notifications -->
-        <notificationGroup id="XMake" displayType="BALLOON"/>
+        <notificationGroup id="XMake.NotificationGroup" displayType="BALLOON"/>
+
+        <postStartupActivity implementation="io.xmake.utils.info.XMakeInfoActivity"/>
 
 
         <fileType name="xmake.lua" language="xmake.lua" fieldName="INSTANCE"
         <fileType name="xmake.lua" language="xmake.lua" fieldName="INSTANCE"
                   fileNames="xmake.lua" fileNamesCaseInsensitive="xmake.lua"
                   fileNames="xmake.lua" fileNamesCaseInsensitive="xmake.lua"