Help getting Compose Multiplatform working with Maven

Hi all, first time posting here, good to be here. :slight_smile:

I hope this topic is in the right category; please move if not.

As the title says, I’m after some help on getting Compose Multiplatform to work with Maven. I’ve read the Getting Started README in the GitHub project, but that only talks about using Gradle. I’ve tried looking at the Gradle example project and copying what it’s doing, but I haven’t been successful. I’ve tried some web searching, but haven’t found any info on using it with Maven or fixing the problems I’m facing.

The issues I’m running into are:

  1. Maven tries to include Android libraries, while Gradle is smart enough to exclude them. I was able to solve that by excluding all the Android libraries, but I’d like to not have to do that.
  2. Maven tries to download the AAR files, and again, Gradle doesn’t. I have no idea how to tell Maven to not download AAR files. It wouldn’t even matter, except Maven apparently cannot find the AAR files. org.jetbrains.compose.material:material-ripple:aar:1.2.1 was not found in https://maven.pkg.jetbrains.space/public/p/compose/dev
  3. Maven can’t find some of the Compose libraries: org.jetbrains.compose.desktop:desktop-jvm-windows-x64:jar:1.2.1 was not found in https://maven.pkg.jetbrains.space/public/p/compose/dev

My pom file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>au.com.skater901</groupId>
    <artifactId>pathfinder-character-generator</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Pathfinder Character Generator</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <kotlin.version>1.8.0-BETA</kotlin.version>
        <kotlin.code.style>official</kotlin.code.style>

        <!-- Testing Versions -->
        <junit.version>5.9.1</junit.version>
        <compose.version>1.2.1</compose.version>
    </properties>

    <repositories>
        <repository>
            <id>compose</id>
            <url>https://maven.pkg.jetbrains.space/public/p/compose/dev</url>
        </repository>
        <repository>
            <id>google</id>
            <url>https://dl.google.com/dl/android/maven2/</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

        <!-- Testing Libraries -->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test-junit</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.compose.desktop</groupId>
            <artifactId>desktop-jvm-windows-x64</artifactId>
            <version>${compose.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>androidx.compose.foundation</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>androidx.compose.material</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>androidx.compose.ui</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>androidx.annotation</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <args>-Xexplicit-api=warning</args>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

I can get it to work if I use the desktop-jvm library rather than the desktop-jvm-windows-x64 library, but then I get a runtime error instead:

Exception in thread "main" java.lang.NoSuchMethodError: 'void androidx.compose.ui.window.Application_desktopKt.application$default(boolean, kotlin.jvm.functions.Function1, int, java.lang.Object)'
	at au.com.skater901.TestUIKt.main(TestUI.kt:17)
	at au.com.skater901.TestUIKt.main(TestUI.kt)

My code looks like this:

package au.com.skater901

import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

@Composable
public fun TestUI() {
    MaterialTheme {
        Text("Pathfinder Character Generator")
    }
}

public fun main(): Unit {
    application {
        Window(onCloseRequest = ::exitApplication) {
            TestUI()
        }
    }
}

Please help! I just want to quickly and easily make a UI, not stuff around with dependency management. :frowning:

FWIW for the next person Googling for this problem, I identified the cause of the NoSuchMethodError; Jetpack Compose has its own compiler plugin that modifies every function annotated with @Compose and adds two extra parameters; a Composer scope (or Compose scope?) and an Int for tracking whether a component needs to re-render. You can add the following args to the kotlin-maven-plugin to fix this:

<arg>-Xuse-ir</arg>
<arg>-Xplugin=C:\Users\{home}\.m2\repository\org\jetbrains\compose\compiler\compiler-hosted\1.3.2.3\compiler-hosted-1.3.2.3.jar</arg>

So the full plugin configuration looks like this:

<plugin>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-plugin</artifactId>
    <version>${kotlin.version}</version>
    <executions>
        <execution>
            <id>compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>test-compile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <args>
            <arg>-Xexplicit-api=warning</arg>
            <arg>-Xuse-ir</arg>
            <arg>-Xplugin=C:\Users\{home}\.m2\repository\org\jetbrains\compose\compiler\compiler-hosted\1.3.2.3\compiler-hosted-1.3.2.3.jar</arg>
        </args>
    </configuration>
</plugin>

I’ve had to add the compiler as a dependency to ensure it exists in my local Maven cache:

<dependency>
    <groupId>org.jetbrains.compose.compiler</groupId>
    <artifactId>compiler-hosted</artifactId>
    <version>1.3.2.3</version>
</dependency>

I don’t know if the -Xuse-ir argument is needed, and I recognise that this is definitely not an ideal solution; hard-coding a path to the compiler plugin prevents the project from working on other people’s computers. There may not be an actual Maven plugin for this, though.

Also, this still hasn’t solved my problem; the org.jetbrains.compose.desktop:desktop-jvm library doesn’t bring in a required dependency to make the compiler plugin work, specifically it requires org.jetbrains.skiko.skiko-awt-runtime-windows-x64. I’ve tried going back to org.jetbrains.compose.desktop:desktop-jvm-windows-x64 which does bring it in, but then I’m back to the problem of Maven being unable to find the aar files which I don’t even need.

Have you had any luck getting this to work? As far as I can tell, there is no support for Maven.

Nope, I gave up and just created another project in Gradle. :stuck_out_tongue: It’d be nice if Jetpack Compose could be used with Maven, but I wasn’t invested enough in that outcome to spend the time required to figure it out.