6

I am trying to include JavaFX dependencies for mac OS only, but win are still downloaded. Same goes with linux deps.

pom.xml:

<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-graphics</artifactId>
    <version>11.0.2</version>
    <classifier>linux</classifier>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-controls</artifactId>
    <version>11.0.2</version>
    <classifier>linux</classifier>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-fxml</artifactId>
    <version>11.0.2</version>
    <classifier>linux</classifier>
</dependency>

Maven deps:

deps

pom.xml:

<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-graphics</artifactId>
    <version>11.0.2</version>
    <classifier>mac</classifier>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-controls</artifactId>
    <version>11.0.2</version>
    <classifier>mac</classifier>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-fxml</artifactId>
    <version>11.0.2</version>
    <classifier>mac</classifier>
</dependency>

Maven deps:

deps

How to remove win JavaFX libs or make Maven not do download them?

Same thing happens when i use Ubuntu (Linux). When i classify i want mac libraries, linux libs are downloaded also etc.

Maybe worth noting i am using Eclipse IDE 2021-03 both on Windows and Ubuntu.

Wortig
  • 963
  • 2
  • 11
  • 37

2 Answers2

8

When you use JavaFX via Maven artifacts from Maven Central, you typically add to your pom:

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>16</version>
        </dependency>
    </dependencies>

and it just works on your platform, no need for classifiers.

Now if you check the dependencies, and you are on Linux for instance, you will find:

$ mvn dependency:tree

[INFO]  org.openjfx:javafx-controls:jar:16:compile
[INFO]    +- org.openjfx:javafx-controls:jar:linux:16:compile
[INFO]    \- org.openjfx:javafx-graphics:jar:16:compile
[INFO]       +- org.openjfx:javafx-graphics:jar:linux:16:compile
[INFO]       \- org.openjfx:javafx-base:jar:16:compile
[INFO]          \- org.openjfx:javafx-base:jar:linux:16:compile

Same if you are on Windows or Mac OS.

You can guess how javafx-controls gets the traverse dependencies: via its pom. But how does it get the classifier?

Let's check the pom:

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-controls</artifactId>
    <version>16</version>
    <parent>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx</artifactId>
        <version>16</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>16</version>
            <classifier>${javafx.platform}</classifier>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics</artifactId>
            <version>16</version>
        </dependency>
    </dependencies>
</project>

As you can see, there is already a classifier applied, based on a ${javafx.platform} maven property.

That property is resolved via a the parent pom:

    <parent>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx</artifactId>
        <version>16</version>
    </parent>

If you check its content:

<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>org.openjfx</groupId>
<artifactId>javafx</artifactId>
<version>16</version>
<packaging>pom</packaging>
<name>openjfx</name>
<description>OpenJFX JavaFX</description>
<url>https://openjdk.java.net/projects/openjfx/</url>
<properties>
    <javafx.version>16</javafx.version>
</properties>
<dependencyManagement></dependencyManagement>
<profiles>
    <profile>
        <id>linux</id>
        <activation>
            <os>
                <name>linux</name>
            </os>
        </activation>
        <properties>
            <javafx.platform>linux</javafx.platform>
        </properties>
    </profile>
    // windows profile
    // mac profile
...

So that means that there is a profile that gets activated based on your current platform, and that sets automatically the property ${javafx.platform}, which in turn set your dependencies classifier.

So what happens if you add a different classifier to your JavaFX dependency (and you are on Linux for instance):

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>16</version>
            <classifier>win</classifier>
        </dependency>
    </dependencies>

you will get:

$ mvn dependency:tree

[INFO] \- org.openjfx:javafx-controls:jar:win:16:compile
[INFO]    +- org.openjfx:javafx-controls:jar:linux:16:compile
[INFO]    \- org.openjfx:javafx-graphics:jar:16:compile
[INFO]       +- org.openjfx:javafx-graphics:jar:linux:16:compile
[INFO]       \- org.openjfx:javafx-base:jar:16:compile
[INFO]          \- org.openjfx:javafx-base:jar:linux:16:compile

The dependency is correct, you get the win version first, but then its own pom has a dependency on javafx-controls:${javafx.platform}, which is resolved based on your platform (i.e. Linux), and that explains why you get the platform artifact as well.

I don't see how this can be avoided, as you can't disable the profile activation inside the dependency's pom.

EDIT

If you keep reading the javafx parent pom, there is this profile:

<profile>
            <id>javafx.platform.custom</id>
            <activation>
                <property>
                    <name>javafx.platform</name>
                </property>
            </activation>
            <properties>
                <javafx.platform>${javafx.platform}</javafx.platform>
            </properties>
        </profile>

which is a profile that gets activated if javafx.platform is set, and it overrides previous values of the ${javafx.platform} value.

So I've just tried on Linux (without adding any classifier to the dependency):

$ mvn -Djavafx.platform=win dependency:tree

[INFO] com.gluonhq.samples:hellopi:jar:1.0.0-SNAPSHOT
[INFO] \- org.openjfx:javafx-controls:jar:16:compile
[INFO]    +- org.openjfx:javafx-controls:jar:win:16:compile
[INFO]    \- org.openjfx:javafx-graphics:jar:16:compile
[INFO]       +- org.openjfx:javafx-graphics:jar:win:16:compile
[INFO]       \- org.openjfx:javafx-base:jar:16:compile
[INFO]          \- org.openjfx:javafx-base:jar:win:16:compile

and that works, no more platform classifiers.

Still, your IDE might show platform dependencies, but as long as you run with that property (like mvn -Djavafx.platform=win javafx:run) that should work.

José Pereda
  • 44,311
  • 7
  • 104
  • 132
  • Thanks for explanation. Can `${javafx.platform}` or my platform be "faked" (maybe in pom.xml) to be something else? That might solve my issue, cause i have 3 maven projects, each for each platform. – Wortig Jun 16 '21 at 11:38
  • Yes, at least partially. See my edit. However, you might want to rethink why you need three projects? – José Pereda Jun 16 '21 at 12:01
  • Just for information, i wanted to create same javafx app for each platform, but did not want to include all libs for each platform in one jar. This division to 3 projects came to my mind as good idea since i am not pro with Maven and i have not found out there tutorial how to do it in one project. These 3 projects now share common code via dependency to 4th project, but have javafx libs to one specific platform accordingly. And Yes, IDE still show deps, but that -D javafx.platform... works. – Wortig Jun 16 '21 at 12:50
  • Great, then consider marking the answer as accepted, it could be useful to others too. – José Pereda Jun 16 '21 at 14:21
0

Short answer for Eclipse IDE:

Build config

Create three maven build configurations for each platform and specify parameter javafx.platform with value win, linux or mac for each config.

It is nothing else than adding "-Djavafx.platform={platform}" to mvn command.

However there will be still other platform dependencies shown in Maven Dependencies in Eclipse IDE.

Wortig
  • 963
  • 2
  • 11
  • 37