MavenのactiveByDefaultにはクセがある

Posted at 2018-06-11

Mavenで複数のプロファイルを切替える場合に、そのデフォルトとして、プロファイルをマークするのが activeByDefault という設定なわけですが、これの挙動が少し想像とズレていたのでそのメモ。

サンプルは以下。
https://github.com/yo1000/example.Maven-ActiveByDefaults

要件

  • Java 1.8.0_121
  • Maven 3.5.3
$ ./mvnw -v
Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T04:49:05+09:00)
Maven home: ~/.m2/wrapper/dists/apache-maven-3.5.3-bin/2c22a6s60afpuloj4v181qvild/apache-maven-3.5.3
Java version: 1.8.0_121, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.3", arch: "x86_64", family: "mac"
1
2
3
4
5
6
7

検証

検証に際し、以下のような pom.xml を用意しました。

<?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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yo1000</groupId>
    <artifactId>example.maven.activeByDefault</artifactId>
    <version>1.0.0</version>

    <name>example.maven.activeByDefault</name>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <profiles>
        <profile>
            <id>A</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                    <version>1.1.0</version>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>B</id>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                    <version>1.2.0</version>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>C</id>
        </profile>
    </profiles>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

検証内容

依存関係の設定が異なる、プロファイルなしと、3つのプロファイルを用意しました。まとめると以下の4つです。

  • プロファイルなし: kotlin-stdlib-1.0.0 に依存
  • プロファイルA: kotlin-stdlib-1.1.0 に依存 ( activeByDefault )
  • プロファイルB: kotlin-stdlib-1.2.0 に依存
  • プロファイルC: 個別の依存設定はないため、プロファイルなしと同義

これらに対し、以下のコマンドを発行したときに、依存関係にどのような変化があるかを検証します。

./mvnw clean dependency:tree -P ${ProfileId}
1

検証結果

以下5パターンの検証をしました。それぞれ結果です。

プロファイルなし

kotlin-stdlib:jar:1.1.0 に依存。 activeByDefault の設定が効いているため、プロファイルAが適用される結果となった。




 


./mvnw clean dependency:tree

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.0:compile
[INFO]    \- org.jetbrains:annotations:jar:13.0:compile
1
2
3
4
5

プロファイルA

kotlin-stdlib:jar:1.1.0 に依存。プロファイルAを指定したため、プロファイルAが適用される結果となった。




 


./mvnw clean dependency:tree -P A

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.0:compile
[INFO]    \- org.jetbrains:annotations:jar:13.0:compile
1
2
3
4
5

プロファイルB

kotlin-stdlib:jar:1.1.0 に依存。プロファイルBを指定したため、プロファイルBが適用される結果となった。




 


./mvnw clean dependency:tree -P B

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.2.0:compile
[INFO]    \- org.jetbrains:annotations:jar:13.0:compile
1
2
3
4
5

プロファイルC

kotlin-stdlib:jar:1.0.0 に依存。プロファイルCを指定したため、プロファイル側での依存はない状態が適用される結果となった。




 


./mvnw clean dependency:tree -P C

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.0.0:compile
[INFO]    \- org.jetbrains.kotlin:kotlin-runtime:jar:1.0.0:compile
1
2
3
4
5

プロファイルX

kotlin-stdlib:jar:1.1.0 に依存。 activeByDefault の設定が効いているため、プロファイルAが適用される結果となった。




 


./mvnw clean dependency:tree -P X

[INFO] com.yo1000:example.maven.activeByDefault:jar:1.0.0
[INFO] \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.0:compile
[INFO]    \- org.jetbrains:annotations:jar:13.0:compile
1
2
3
4
5

実はこのパターンこそが、今回のポストを書く発端となったものでした。 pom.xml に定義されていないプロファイルが指定された場合、どうなるのか。

当初想像していたのは、プロファイルが存在しないため、プロファイル側での依存はない状態 ( kotlin-stdlib:jar:1.0.0 に依存) が適用されるものかと思い込んでいました。

ところが、実際の結果では想像と異なり、存在しないプロファイルが指定された場合、プロファイルが指定されなかった場合と同じように扱われてしまい、 activeByDefault の設定されたプロファイル ( kotlin-stdlib:jar:1.1.0 に依存) が適用されました。

つまり、 activeByDefault というのは pom.xml に定義されていないプロファイルが指定された場合にも、効いてしまうようなのです。

以上のような結果が得られたため、 activeByDefault を使用する場合には、適用されるプロファイルに注意したい。