2017-01-25 5 views
1

私は自分のSBT内に複数のサブプロジェクトを持っていますが、1つはサーバー(playframeworkベース)です。もう1つはclientside(scala.js) 2つの間の通信protobuf(scalapb)の形で。ScalaPBとScala.jsとScala(jvm) - リンクエラーが発生しました

さて、これは私のbuild.sbt次のとおりです。

lazy val generalSettings = Seq(
    organization := "tld.awesomeness", 
    version := "0.0.1", 
    scalaVersion := "2.12.1" 
) 

val CrossDependencies = new 
    { 
    val scalaTest = "org.scalatest" %% "scalatest" % "3.0.1" % "test" 
    val scalactic = "org.scalactic" %% "scalactic" % "3.0.1" 
    val scalaTags = "com.lihaoyi" %% "scalatags" % "0.6.2" 
    } 

lazy val proto = (project in file("modules/proto")) 
    .settings(generalSettings: _*) 
    .settings(
    PB.targets in Compile := Seq(
     scalapb.gen() -> (sourceManaged in Compile).value 
    ), 
    // If you need scalapb/scalapb.proto or anything from google/protobuf/*.proto 
    libraryDependencies ++= Seq(
     "com.trueaccord.scalapb" %% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf", 
     "com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion, 
     "com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf" 
    ) 
) 

lazy val play = (project in file("modules/play")) 
    .enablePlugins(PlayScala) 
    .settings(generalSettings: _*) 
    .settings(
    name := "play", 
    libraryDependencies ++= Seq(
     CrossDependencies.scalaTest, 
     CrossDependencies.scalactic, 
     CrossDependencies.scalaTags, 
     "com.typesafe.play" %% "play-json" % "2.6.0-M1"), 
    scalaJSProjects := Seq(client), 
    pipelineStages in Assets := Seq(scalaJSPipeline), 
    compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value 
) 
    .aggregate(slick) 
    .dependsOn(slick) 
    .aggregate(flyway) 
    .dependsOn(flyway) 
    .aggregate(proto) 
    .dependsOn(proto) 

lazy val client = (project in file("modules/client")) 
    .enablePlugins(ScalaJSPlugin, ScalaJSWeb) 
    .settings(generalSettings: _*) 
    .settings(
    name := "client", 
    libraryDependencies += CrossDependencies.scalaTags, 
    persistLauncher := true 
) 
    .aggregate(proto) 
    .dependsOn(proto) 

// Loads the jvm project at sbt startup 
onLoad in Global := (Command.process("project play", _: State)) compose (onLoad in Global).value 

fork in run := true 

、これはplugins.sbtです:

// Scala.JS 
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.14") 
addSbtPlugin("com.vmunier" % "sbt-web-scalajs" % "1.0.2") 

// Play 
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.0-SNAPSHOT") 

// Proto 
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.3" exclude ("com.trueaccord.scalapb", "protoc-bridge_2.10")) 
libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin-shaded" % "0.5.47" 

これは1つのprotoファイルです:コンパイル後

syntax = "proto3"; 

package tld.awesomeness.proto; 

message Test { 
    int32 id = 1; 
    string email = 2; 
} 

私はTest.class

を取得今、私がしようと、クライアントで

private def doSend(ws: WebSocket): Unit = 
{ 
    val msg = Test().withId(1337) 
    val a: ArrayBuffer = new ArrayBuffer(msg.toByteArray.length) 
    msg.toByteArray 
    ws.send(a) 
} 

(私はそれを介して文字列を送信したときのWebSocket自体はすべてうまく働いていた!)

今私は、この巨大なスタックトレースを取得:

[info] Fast optimizing /home/sorona/awesomeness/modules/client/target/scala-2.12/client-fastopt.js 
[error] Referring to non-existent class tld.awesomeness.proto.Test.Test$ 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
[error] Referring to non-existent class tld.awesomeness.proto.Test.Test 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test.toByteArray()[scala.Byte 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test.withId(scala.Int)tld.awesomeness.proto.Test.Test 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test$.apply$default$2()java.lang.String 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test$.apply$default$1()scala.Int 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test.<init>(scala.Int,java.lang.String) 
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit 
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event 
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit 
[error] called from tld.awesomeness.Main$.main()scala.Unit 
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object 
[error] called from tld.awesomeness.Main$.main 
[error] exported to JavaScript with @JSExport 
[error] involving instantiated classes: 
[error] tld.awesomeness.ScalaJSTest$ 
[error] tld.awesomeness.Main$ 
java.lang.RuntimeException: There were linking errors 
     at scala.sys.package$.error(package.scala:27) 
     at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:133) 
     at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:86) 
     at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun$4.apply(LinkerFrontend.scala:54) 
     at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun$4.apply(LinkerFrontend.scala:54) 
     at org.scalajs.core.tools.logging.Logger$class.time(Logger.scala:28) 
     at org.scalajs.sbtplugin.Loggers$SbtLoggerWrapper.time(Loggers.scala:7) 
     at org.scalajs.core.tools.linker.frontend.LinkerFrontend.link(LinkerFrontend.scala:53) 
     at org.scalajs.core.tools.linker.Linker$$anonfun$link$1.apply$mcV$sp(Linker.scala:50) 
     at org.scalajs.core.tools.linker.Linker$$anonfun$link$1.apply(Linker.scala:49) 
     at org.scalajs.core.tools.linker.Linker$$anonfun$link$1.apply(Linker.scala:49) 
     at org.scalajs.core.tools.linker.Linker.guard(Linker.scala:67) 
     at org.scalajs.core.tools.linker.Linker.link(Linker.scala:49) 
     at org.scalajs.core.tools.linker.ClearableLinker$$anonfun$link$1.apply(ClearableLinker.scala:51) 
     at org.scalajs.core.tools.linker.ClearableLinker$$anonfun$link$1.apply(ClearableLinker.scala:51) 
     at org.scalajs.core.tools.linker.ClearableLinker.linkerOp(ClearableLinker.scala:62) 
     at org.scalajs.core.tools.linker.ClearableLinker.link(ClearableLinker.scala:51) 
     at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6$$anonfun$apply$7.apply(ScalaJSPluginInternal.scala:251) 
     at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6$$anonfun$apply$7.apply(ScalaJSPluginInternal.scala:239) 
     at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:253) 
     at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:253) 
     at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:267) 
     at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:263) 
     at sbt.Difference.apply(Tracked.scala:224) 
     at sbt.Difference.apply(Tracked.scala:206) 
     at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:263) 
     at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:262) 
     at sbt.Difference.apply(Tracked.scala:224) 
     at sbt.Difference.apply(Tracked.scala:200) 
     at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:262) 
     at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:260) 
     at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6.apply(ScalaJSPluginInternal.scala:256) 
     at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6.apply(ScalaJSPluginInternal.scala:237) 
     at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47) 
     at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40) 
     at sbt.std.Transform$$anon$4.work(System.scala:63) 
     at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228) 
     at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228) 
     at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17) 
     at sbt.Execute.work(Execute.scala:237) 
     at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228) 
     at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228) 
     at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159) 
     at sbt.CompletionService$$anon$2.call(CompletionService.scala:28) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
     at java.lang.Thread.run(Thread.java:745) 
[error] (client/compile:fastOptJS) There were linking errors 

私のideはすべてを見つけましたが、明らかに私は何か間違っています。私はすでにhttps://github.com/thesamet/scalapbjs-testを見ましたが、無駄です。コメントの後、私はbuild.sbtを変更:

問題は、その行val msg = Test().withId(1337)

編集と表示されます

lazy val proto = (crossProject in file("modules/proto")) 
    .settings(generalSettings: _*) 
    .settings(
    PB.targets in Compile := Seq(
     scalapb.gen() -> (sourceManaged in Compile).value 
    )). 
    jvmSettings(
    libraryDependencies += "com.trueaccord.scalapb" %% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf", 
    PB.targets in Compile := Seq(
     scalapb.gen() -> (sourceManaged in Compile).value 
    ) 
). 
    jsSettings(
    libraryDependencies ++= Seq(
     "com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion, 
     "com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf" 
    ), 
    PB.targets in Compile := Seq(
     scalapb.gen() -> (sourceManaged in Compile).value 
    ) 
) 

lazy val protoJs = proto.js 
lazy val protoJVM = proto.jvm 

lazy val play = (project in file("modules/play")) 
    .enablePlugins(PlayScala) 
    .settings(generalSettings: _*) 
    .settings(
    name := "play", 
    libraryDependencies ++= Seq(
     CrossDependencies.scalaTest, 
     CrossDependencies.scalactic, 
     CrossDependencies.scalaTags, 
     "com.typesafe.play" %% "play-json" % "2.6.0-M1"), 
    scalaJSProjects := Seq(client), 
    pipelineStages in Assets := Seq(scalaJSPipeline), 
    compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value 
) 
    .aggregate(slick) 
    .dependsOn(slick) 
    .aggregate(flyway) 
    .dependsOn(flyway) 
    .aggregate(protoJVM) 
    .dependsOn(protoJVM) 

lazy val client = (project in file("modules/client")) 
    .enablePlugins(ScalaJSPlugin, ScalaJSWeb) 
    .settings(generalSettings: _*) 
    .settings(
    name := "client", 
    libraryDependencies += CrossDependencies.scalaTags, 
    persistLauncher := true 
) 
    .aggregate(protoJs) 
    .dependsOn(protoJs) 

今どちらplayclientがproto-クラスを解決することができます:(

(また、私は余分なPB.targets in Compile...を知っている、私はちょうど共有がそこで動作しないかもしれないと思ったので、私は両方

+1

'proto'は' crossProject'でなければなりません。JVMプロジェクト 'play'とJSプロジェクト' client'の両方が依存しているからです。 – sjrd

+0

@sjrdあなたは例を挙げることができますか?私はhttps://www.scala-js.org/doc/project/cross-build.htmlについて知っていますが、実際これをここで忘れました。 Mea culpa。しかし今、私はそれを追加しました。私はクラスがもう見つからないので、protobufプロジェクトは1つのsrcフォルダを持っていてもjsとjava用にコンパイルされている必要があると仮定します。 – Sorona

+0

プラットフォーム固有のソースディレクトリがない場合は、 'crossProject.crossType(CrossType.Pure)'を使用してください。 – sjrd

答えて

4

純粋なCrossProjectでは、ScalaPBがプロトファイルを探すべき実際のパスを指定する必要があります(推測される値は間違っています)。これは最小限の例です:

関連する問題