2013-08-09 8 views
10

Sto provando a eseguire un'applicazione Scala compresso come JAR (incluse le dipendenze), ma questo fallisce fino alla Scala la libreria viene aggiunta utilizzando l'opzione -Xbootclasspath/p."scala.runtime nel mirror del compilatore non trovato", ma funzionante quando avviato con -Xbootclasspath/p: scala-library.jar

invocazione mancanza:

java -jar /path/to/target/scala-2.10/application-assembly-1.0.jar 

Dopo l'applicazione ha fatto parte della sua produzione destinata, la console mostra:

Exception in thread "main" scala.reflect.internal.MissingRequirementError: object scala.runtime in compiler mirror not found. at scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:16) at scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:17) at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:48) at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:40) at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:61) at scala.reflect.internal.Mirrors$RootsBase.getPackage(Mirrors.scala:172) at scala.reflect.internal.Mirrors$RootsBase.getRequiredPackage(Mirrors.scala:175) at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage$lzycompute(Definitions.scala:181) at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage(Definitions.scala:181) at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass$lzycompute(Definitions.scala:182) at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass(Definitions.scala:182) at scala.reflect.internal.Definitions$DefinitionsClass.AnnotationDefaultAttr$lzycompute(Definitions.scala:1015) at scala.reflect.internal.Definitions$DefinitionsClass.AnnotationDefaultAttr(Definitions.scala:1014) at scala.reflect.internal.Definitions$DefinitionsClass.syntheticCoreClasses$lzycompute(Definitions.scala:1144) at scala.reflect.internal.Definitions$DefinitionsClass.syntheticCoreClasses(Definitions.scala:1143) at scala.reflect.internal.Definitions$DefinitionsClass.symbolsNotPresentInBytecode$lzycompute(Definitions.scala:1187) at scala.reflect.internal.Definitions$DefinitionsClass.symbolsNotPresentInBytecode(Definitions.scala:1187) at scala.reflect.internal.Definitions$DefinitionsClass.init(Definitions.scala:1252) at scala.tools.nsc.Global$Run.(Global.scala:1290) at extract.ScalaExtractor$Compiler$2$.(ScalaExtractor.scala:24)

invocazione di lavoro:

java -Xbootclasspath/p:/path/to/home/.sbt/boot/scala-2.10.2/lib/scala-library.jar -jar /path/to/target/scala-2.10/application-assembly-1.0.jar 

La cosa strana su di esso è che il application-assembly-1.0.jar è stato creato in modo che includa tutte le dipendenze nella libreria Scala. Quando si estrae il file JAR, è possibile verificare che siano stati inclusi i file di classe nel pacchetto scala.runtime.

Creazione del file JAR

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1") è stato aggiunto al project/plugins.sbt e l'obiettivo assembly è stato invocato. Un file JAR di circa 25 MB di risultati.

Costruire il JAR con proguard mostra lo stesso comportamento di runtime visto con il file JAR di assembly.

codice di applicazione che fa scattare il codice

Alcuni applicazione MissingRequirementError funziona bene e l'eccezione descritto in precedenza viene attivato non appena il new Run dai seguenti Esegue frammento.

import scala.reflect.internal.util.BatchSourceFile 
import scala.reflect.io.AbstractFile 
import scala.reflect.io.Path.jfile2path 
import scala.tools.nsc.Global 
import scala.tools.nsc.Settings 
… 
import scala.tools.nsc._ 
object Compiler extends Global(new Settings()) { 
    new Run // This is line 24 from the stack trace! 

    def parse(path: File) = { 
    val code = AbstractFile.getFile(path) 
    val bfs = new BatchSourceFile(code, code.toCharArray) 
    val parser = new syntaxAnalyzer.UnitParser(new CompilationUnit(bfs)) 
    parser.smartParse() 
    } 
} 
val ast = Compiler.parse(file) 

tra gli altri, scala-library, scala-compiler e scala-reflect sono definiti come dipendenze in build.sbt.

Per informazioni curiosità/sfondo

Lo scopo dell'applicazione è quello di aiutare nella localizzazione dei programmi Java e Scala. Il compito del frammento di codice sopra è quello di ottenere un AST da un file Scala per trovare le chiamate al metodo in quel punto.

Le domande

  • Data la libreria Scala è incluso nel file JAR, il motivo per cui è necessario chiamare il JAR utilizzando -Xbootclasspath/p:scala-library.jar?
  • Perché altre parti dell'applicazione funzionano correttamente anche se scala.runtime viene segnalato come mancante in seguito?
+0

questo potrebbe essere perché non avete dato alcun percorso di classe a quella esecuzione del compilatore da usare. Invece di 'Global (new Settings())', prova a dargli delle impostazioni che abbiano lo stesso classpath del tuo programma: 'settings.classpath.value = System.getProperty (" java.class.path ")'. – gourlaysama

+1

o forse 'settings.usejavacp.value = true', o qualcosa di simile ... – gourlaysama

+0

Grazie mille per i vostri commenti. Sembra che io abbia erroneamente assunto che le impostazioni del compilatore siano predefinite a quelle del programma di richiamo. L'aggiunta di 'settings.usejavacp.value = true' o' settings processArgumentString "-usejavacp" 'comporterà un compilatore correttamente configurato e quindi un programma di lavoro. –

risposta

9

Il modo più semplice per configurare le impostazioni con tasti familiari:

import scala.tools.nsc.Global 
    import scala.tools.nsc.Settings 
    def main(args: Array[String]) { 
    val s = new Settings 
    s processArgumentString "-usejavacp" 
    val g = new Global(s) 
    val r = new g.Run 
    } 

che funziona per lo scenario.

Ancora più facile:

java -Dscala.usejavacp=true -jar ./scall.jar 

informazioni bonus, mi è capitato di incontrare the enabling commit message:

Went ahead and implemented classpaths as described in email to scala-internals on the theory that at this point I must know what I'm doing.

** PUBLIC SERVICE ANNOUNCEMENT **

If your code of whatever kind stopped working with this commit (most likely the error is something like "object scala not found") you can get it working again with either of:

passing -usejavacp on the command line

set system property "scala.usejavacp" to "true"

Either of these will alert scala that you want the java application classpath to be utilized by scala as well.

+9

Per chiunque riscontri un errore simile durante la configurazione di Scala in Intellij IDEA, aggiungilo a "Opzioni aggiuntive del compilatore" in Struttura del progetto -> Facet -> Scala -> Opzioni del compilatore: "-usejavacp" L'ho usato con successo per risolvere errori fatali: oggetto scala.beans.BeanInfo nel mirror del compilatore non trovato. – Malcolm

Problemi correlati