sifue's blog

プログラマな二児の父の日常 ポートフォリオは www.soichiro.org

Scala2.9.1でEclipse3.6.2を使ってMavenビルドする方法

最近Scala勉強中ですが、maven-scala-pluginを使ってScalaのコードをビルドしようとしたところ、Scalaのバージョンが2.8.0だったり、そもそもデフォルトのpom.xmlじゃ動かなかったので、そのために修正した方法を以下にまとめておきました。
(ただ、Scalaのビルドはsbtの方が断然楽なので、giter8で作ったテンプレートをsbtでビルドして、SbtEclipsifyでEclipseに読み込む方法も断然ありだと思います。)


前提として、Eclipse3.6.2(helios)にScala IDE for Eclipse 2.0.0とe2eclipseが既にインストール済みの状態で進めていきます。Eclipse3.6.2のダウンロード及び、Scala IDE for Eclipse2.0.0とe2eclipseのアップデートサイトの登録からのインストール方法については、以下のサイトの参照のこと。

Eclipse.org - Helios Simultaneous Release!
Scala IDE for Eclipse 2.0.0
m2eclipse: Maven in Eclipse


というわけで、早速Eclipseを適当なワークスペース名で起動して、パッケージエクスプローラで右クリックして、New > Otherを選択します。


ここで、Maven > Maven Projectを選択してNext > をクリック。


ワークスペースの場所やワーキングセットは特に設定せずにNext > をクリック。


ちょっとロードに時間がかかりますが、少し待つとNexus Indexerのカタログ内のArchetypeの選択にて以下が出現するので選択します。

scala-tools.org.archetypes scala-archetypes-simple 1.3

を選択。なぜか、一度アップデートを一度走らせるまではバージョンが1.1だったりしますが、あとで書き換えてしまうので、特に問題はありません。



Group IdやArtifact Idを設定する。自分は、Group Idはorg.soichiro、Artifact Idは、scala-studyにしました。Versionは、0.0.1-SNAPSHOTのままで、パッケージ名は自動的に入力されるのでそのままで。これでFinish。


無事、プロジェクトが作成されるが、いろいろ赤いw


というわけで一つ一つ解決していきます。まず、pom.xml自体があれScala2.8.0向けなので以下に書き換えます。既に、後で通常のmaven環境で実行するためのlancherの設定も書き加えてありますが、とりあえずひな形として以下を使います。Group IdやArtifact Id、lancherのmainClassは随意書き換えてください。なおmainClassのパッケージ名は-が_に置換されているので要注意。


なお、参考にさせてもらったのは以下のサイト。残念ながら本家の情報更新が古い。。。
gist: 1196756
maven-scala-plugin


追記
Mavenリポジトリの登録サイトではなく、Githubの方にmavenプラグインの最新ドキュメントがあるようです。id:xuweiさん、情報ありがとうございます。
Github内のscala-maven-plugin

<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>org.soichiro</groupId>
	<artifactId>scala-study</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>${project.artifactId}</name>
	<description>My wonderfull scala app</description>
	<inceptionYear>2010</inceptionYear>
	<licenses>
		<license>
			<name>My License</name>
			<url>http://....</url>
			<distribution>repo</distribution>
		</license>
	</licenses>

	<properties>
		<maven.compiler.source>1.5</maven.compiler.source>
		<maven.compiler.target>1.5</maven.compiler.target>
		<encoding>UTF-8</encoding>
		<scala.version>2.9.1</scala.version>
	</properties>

	<repositories>
		<repository>
			<id>scala-tools.org</id>
			<name>Scala-Tools Maven2 Repository</name>
			<url>http://scala-tools.org/repo-releases</url>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>scala-tools.org</id>
			<name>Scala-Tools Maven2 Repository</name>
			<url>http://scala-tools.org/repo-releases</url>
		</pluginRepository>
	</pluginRepositories>

	<dependencies>
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-library</artifactId>
			<version>${scala.version}</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.scala-tools.testing</groupId>
			<artifactId>specs_${scala.version}</artifactId>
			<version>1.6.9</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.scalatest</groupId>
			<artifactId>scalatest_${scala.version}</artifactId>
			<version>1.6.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<sourceDirectory>src/main/scala</sourceDirectory>
		<testSourceDirectory>src/test/scala</testSourceDirectory>
		<plugins>
			<plugin>
				<groupId>org.scala-tools</groupId>
				<artifactId>maven-scala-plugin</artifactId>
				<version>2.15.0</version>
				<configuration>
					<launchers>
						<launcher>
							<id>default</id>
							<mainClass>org.soichiro.scala_study.App</mainClass>
							<!-- args are optional -->
							<args>
								<arg>arg1</arg>
								<arg>arg2</arg>
								<arg>arg3</arg>
							</args>
							<!-- jvmArgs are optional -->
							<jvmArgs>
								<jvmArg>-Xmx128m</jvmArg>
								<!-- jvmArg>-Djava.library.path=...</jvmArg -->
							</jvmArgs>
						</launcher>
						<!-- you could define other launcher -->
					</launchers>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>compile</goal>
							<goal>testCompile</goal>
						</goals>
						<configuration>
							<args>
								<arg>-make:transitive</arg>
								<arg>-dependencyfile</arg>
								<arg>${project.build.directory}/.scala_dependencies</arg>
							</args>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<useFile>false</useFile>
					<disableXmlReport>true</disableXmlReport>
					<!-- If you have classpath issue like NoDefClassError,... -->
					<!-- useManifestOnlyJar>false</useManifestOnlyJar -->
					<includes>
						<include>**/*Test.*</include>
						<include>**/*Suite.*</include>
					</includes>
				</configuration>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!--This plugin's configuration is used to store Eclipse m2e settings 
					only. It has no influence on the Maven build itself. -->
				<plugin>
					<groupId>org.eclipse.m2e</groupId>
					<artifactId>lifecycle-mapping</artifactId>
					<version>1.0.0</version>
					<configuration>
						<lifecycleMappingMetadata>
							<pluginExecutions>
								<pluginExecution>
									<pluginExecutionFilter>
										<groupId>org.scala-tools</groupId>
										<artifactId>
											maven-scala-plugin
    								</artifactId>
										<versionRange>
											[2.15.0,)
    								</versionRange>
										<goals>
											<goal>compile</goal>
											<goal>testCompile</goal>
										</goals>
									</pluginExecutionFilter>
									<action>
										<ignore></ignore>
									</action>
								</pluginExecution>
							</pluginExecutions>
						</lifecycleMappingMetadata>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

無事、編集が済んだら保存してコンパイルを待ちます。
だが、それでも赤い。



どうやらScalaのパスが正しく認識されていないようなので、ScalaのNatureを足します。パッケージエクスプローラの右クリックから、Configure > Add Scala Natureを選択。



これで再度ビルドが走ります。念のため、一度、クリーニング。メニューバーからProject > Cleanを選択。それで再度待ちます。だが、それでも赤い。



Mavenの設定をアップデートしろということなので、従います。


パッケージエクスプローラで、プロジェクトのルートノードを選択して、Maven > Update Project Configuration...を選択。


特に何も考えずにOKをクリックすると。無事エラーの消えたScala2.9.1のMavenプロジェクトが完成します。


org.soichiro.scala_study.Appというオブジェクトが、HelloWorld!を記述しているので、実際に右クリックRun As > Scala Applicationを実行して実行確認してみましょう。Debug Asだとブレークポイントも使えます。


というわけで、早速、ビルド、テスト、インストールしてみます。プロジェクトのルートノードを選択して、Run As > Maven Installを実行。


コンソールに以下が出力されます。

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building scala-study 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ scala-study ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ scala-study ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-scala-plugin:2.15.0:compile (default) @ scala-study ---
[INFO] Checking for multiple versions of scala
[INFO] includes = [**/*.scala,**/*.java,]
[INFO] excludes = []
[INFO] /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/src/main/scala:-1: info: compiling
[INFO] Compiling 1 source files to /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/target/classes at 1333073535276
[INFO] No known dependencies. Compiling everything
[WARNING] warning: there were 1 deprecation warnings; re-run with -deprecation for details
[WARNING] one warning found
[INFO] prepare-compile in 0 s
[INFO] compile in 5 s
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ scala-study ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ scala-study ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-scala-plugin:2.15.0:testCompile (default) @ scala-study ---
[INFO] Checking for multiple versions of scala
[INFO] includes = [**/*.scala,**/*.java,]
[INFO] excludes = []
[INFO] /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/src/test/scala:-1: info: compiling
[INFO] Compiling 3 source files to /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/target/test-classes at 1333073541161
[INFO] No known dependencies. Compiling everything
[WARNING] warning: there were 1 deprecation warnings; re-run with -deprecation for details
[WARNING] one warning found
[INFO] prepare-compile in 0 s
[INFO] compile in 11 s
[INFO] 
[INFO] --- maven-surefire-plugin:2.6:test (default-test) @ scala-study ---
[INFO] Surefire report directory: /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running samples.ListSuite
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.598 sec
Running samples.StackSuite
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.032 sec
Running samples.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running samples.MySpecTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 2, Time elapsed: 0.233 sec

Results :

Tests run: 9, Failures: 0, Errors: 0, Skipped: 2

[INFO] 
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ scala-study ---
[INFO] Building jar: /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/target/scala-study-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ scala-study ---
[INFO] Installing /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/target/scala-study-0.0.1-SNAPSHOT.jar to /Users/soichiro/.m2/repository/org/soichiro/scala-study/0.0.1-SNAPSHOT/scala-study-0.0.1-SNAPSHOT.jar
[INFO] Installing /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/pom.xml to /Users/soichiro/.m2/repository/org/soichiro/scala-study/0.0.1-SNAPSHOT/scala-study-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25.060s
[INFO] Finished at: Fri Mar 30 11:12:38 JST 2012
[INFO] Final Memory: 9M/81M
[INFO] ------------------------------------------------------------------------

無事、ビルド、テストが成功。ちゃんとJUnitとScalatest、specsのそれぞれのテストも問題なく流れています。そして成果物が、targetフォルダの中に生成されています。


これで無事完了ですが、実際に成果物をコンソール上で実行してみます。実行にはMavenが必要となるので以下のサイトを参考にインストールの事。ちょっと下の方にインストール方法が書いてあります。ちなみにバージョンは2.2.1を使って試しました。


Download Maven


では、実際にmaven-scala-pluginで書かれていた実行方法を試してみます。(MacOSXで実行していますが、Winでも同様に行えるはずです。)

$ cd /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study
$ mvn scala:run
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building scala-study
[INFO]    task-segment: [scala:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing scala:run
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/src/main/resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [scala:compile {execution: default}]
[INFO] Checking for multiple versions of scala
[INFO] includes = [**/*.scala,**/*.java,]
[INFO] excludes = []
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources {execution: default-testResources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/soichiro/Dropbox/Dev/eclipse/workspace_scala/scala-study/src/test/resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [scala:testCompile {execution: default}]
[INFO] Checking for multiple versions of scala
[INFO] includes = [**/*.scala,**/*.java,]
[INFO] excludes = []
[INFO] Nothing to compile - all classes are up to date
[INFO] [scala:run {execution: default-cli}]
[INFO] Checking for multiple versions of scala
[INFO] launcher 'default' selected => org.soichiro.scala_study.App
Hello World!
concat arguments = arg1arg2arg3
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Fri Mar 30 11:14:52 JST 2012
[INFO] Final Memory: 17M/81M
[INFO] ------------------------------------------------------------------------

というわけで、無事、素のmaven環境でもHello World!の実行を確認できました。
これで、Scala2.9.1とEclipseMavenを使ったビルド方法は完了です。
お疲れ様でした。


なお、プラグインなどを作る際には、

Creating/Using a Scalac plugin
が参考になりそうです。Mavenを使ったビルドはpom.xmlデバッグが本当に大変なので頑張ってください。(個人的にはJava複雑なことをするならAnt&Ivyがいいかなぁなんて思っています。Scalaにはsbtあるので、正直何が生き残っていくのかまだわかりません。)