Reputation: 13108
I am using sbt 1.0.2. My build.sbt is
name := "myprogram"
version := "0.1"
scalaVersion := "2.12.3"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
// https://mvnrepository.com/artifact/net.sf.py4j/py4j
libraryDependencies += "net.sf.py4j" % "py4j" % "0.10.6"
scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-feature",
"-encoding", "UTF-8",
"-Xfuture",
"-Xlint:unsound-match", // Pattern match may not be typesafe.
"-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.
"-Ypartial-unification", // Enable partial unification in type constructor inference
"-Ywarn-dead-code", // Warn when dead code is identified.
"-Ywarn-inaccessible", // Warn about inaccessible types in method signatures.
"-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`.
"-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
"-Ywarn-nullary-unit", // Warn when nullary methods return Unit.
"-Ywarn-unused", // Warn if a method or value is unused.
"-Ywarn-unused:implicits", // Warn if an implicit parameter is unused.
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
"-Ywarn-unused:locals", // Warn if a local definition is unused.
"-Ywarn-unused:params", // Warn if a value parameter is unused.
"-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
"-Ywarn-unused:privates", // Warn if a private member is unused.
"-Ywarn-value-discard" // Warn when non-Unit expression results are unused.
)
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
test in assembly := {}
assemblyJarName in assembly := "myprogram.jar"
exportJars := true
mainClass in Compile := Some("com.company.MyClass")
mainClass in assembly := Some("com.company.MyClass")
mainClass in(Compile, run) := Some("com.company.MyClass")
mainClass in(Compile, packageBin) := Some("com.company.MyClass")
and it seems to compile ok with sbt assembly
, where some of the output is
[warn] Multiple main classes detected. Run 'show discoveredMainClasses' to see the list
[info] Including: py4j-0.10.6.jar
[info] Including: scala-library.jar
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Merging 'META-INF/maven/net.sf.py4j/py4j/pom.properties' with strategy 'discard'
[warn] Merging 'META-INF/maven/net.sf.py4j/py4j/pom.xml' with strategy 'discard'
[warn] Strategy 'discard' was applied to 3 files
Once I go into command line I get
$ java -jar myprogram.jar
no main manifest attribute, in myprogram.jar
I opened up my jar and looked at MANIFEST.MF
and could not find the main there:
Manifest-Version: 1.0
Implementation-Title: myprogram
Implementation-Version: 0.1
Specification-Vendor: default
Specification-Title: myprogram
Implementation-Vendor-Id: default
Specification-Version: 0.1
Implementation-Vendor: default
It might be worth mentioning that my program is mainly in Scala, except for my main class which is in Java.
What do I have to change?
Upvotes: 2
Views: 1353
Reputation: 3514
From the logs you show, my guess is that - in the content of one of the included jars - there's already a META-INF/MANIFEST.MF
, and yours/the one created by sbt assembly - where your main class is declared - gets discarded (I'm not 100% sure though because the content of the manifest you show seems to include stuff that come from your code).
I think this is the indication that your manifest gets discarded:
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
I bet there's already a 'META-INF/MANIFEST.MF' in py4j-0.10.6.jar
.
MergeStrategy.concat
strategy for merging META-INF/MANIFEST.MF
.roughly:
assemblyMergeStrategy in assembly := {
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.concat
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
Upvotes: 2