sbt with extra unmanagedSourceDirectories don't work with Intellij - intellij-idea

I use sbt-projectmatrix for a project like this:
// project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.8.0")
// build.sbt
val foo = projectMatrix
.jvmPlatform(Seq("2.13.6", "2.12.15"))
.settings(
Compile / unmanagedSourceDirectories += (ThisBuild / baseDirectory).value / "shared"
)
// foo/src/main/scala/Foo.scala
object Foo {
val s = "foo"
def sharedS = Shared.s
}
// shared/Shared.scala
object Shared {
val s = "shared"
def fooS = Foo.s
}
When I import into Intellij, it complain:
Duplicate content roots detected: Path [/tmp/bug] of module [bug] was removed from modules [shared-sources]
Then Intellij don't know Shared.s in Foo.scala (it mark Shared red with error "Cannnot resolve symbol Shared") and don't know Foo.s in Shared.scala.
Any workaround please?
Extra info:
In my real project, I have other val bar = projectMatrix.. and foo and bar share some scala source which I put in shared folder
EDIT: Sorry. I have just found that this issue don't related to sbt-projectmatrix: Replace projectMatrix by project in build.sbt => same problem.

Related

Javacpp: problem with linked library - symbol not found in flat namespace

I'm trying to use javacpp library. I've prepared c-lib with one function
char * hello(const char * name);
and build it with cmake (on mac, with clang++)
Also I've prepared config file for javacpp
package arrival;
import org.bytedeco.javacpp.annotation.*;
import org.bytedeco.javacpp.tools.*;
#Properties(
value = #Platform(
includepath = {"/Users/valentina.baranova/external/kotlin-cloud/greeter/include/"},
include = {"greeter.h"},
library = "greeter-jni",
link = {"greeter"},
linkpath = {"/Users/valentina.baranova/external/kotlin-cloud/greeter/build/"}
),
target = "arrival.greeter"
)
public class GreeterConfig implements InfoMapper {
public void map(InfoMap infoMap) {
}
}
javacpp prepared library libgreeter-jni.dylib, but when I try to call hello function I got an error
dlopen(/Users/valentina.baranova/external/kotlin-cloud/greeter-javacpp/target/classes/arrival/macosx-x86_64/libgreeter-jni.dylib, 0x0001): symbol not found in flat namespace '__Z5helloPKc'
What I'm doing wrong? In debug I see that Loader.load() loads both libraries.
UPD:
Loader.load() is loaded in autogenerated greeter class.
Function hello there is in both libraries but it has different name
nm libgreeter-jni.dylib | grep hello
0000000000001f70 T _Java_arrival_greeter_hello__Ljava_lang_String_2
0000000000001ce0 T _Java_arrival_greeter_hello__Lorg_bytedeco_javacpp_BytePointer_2
U __Z5helloPKc
nm libgreeter.dylib | grep hello
0000000000003f50 T _hello

Failed to build Kotlin code with proto models using Bazel

I'm trying to use compiled proto models into my kotlin code. Project is managed by bazel. So I reproduce problem with simple "HelloWorld" project.
WORKSPACE
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
RULES_KOTLIN_VERSION = "9051eb053f9c958440603d557316a6e9fda14687"
http_archive(
name = "io_bazel_rules_kotlin",
sha256 = "c36e71eec84c0e17dd098143a9d93d5720e81b4db32bceaf2daf939252352727",
strip_prefix = "rules_kotlin-%s" % RULES_KOTLIN_VERSION,
url = "https://github.com/bazelbuild/rules_kotlin/archive/%s.tar.gz" % RULES_KOTLIN_VERSION,
)
load("#io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains")
kotlin_repositories()
kt_register_toolchains()
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-master",
urls = ["https://github.com/protocolbuffers/protobuf/archive/master.zip"],
)
load("#com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
protobuf_deps()
BUILD
load("#io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
load("#rules_java//java:defs.bzl", "java_binary", "java_lite_proto_library", "java_proto_library")
load("#rules_proto//proto:defs.bzl", "proto_library")
package(default_visibility = ["//visibility:public"])
proto_library(
name = "clicklocation_proto",
srcs = ["ClickLocation.proto"],
)
java_proto_library(
name = "clicklocation_java_lite_proto",
deps = [":clicklocation_proto"],
)
kt_jvm_library(
name = "app_lib",
srcs = ["Main.kt"],
deps = [":clicklocation_java_lite_proto"]
)
java_binary(
name = "myapp",
main_class = "MyApp",
runtime_deps = [":app_lib"],
)
Proto file
syntax = "proto2";
package objectrecognition;
option java_package = "com.kshmax.objectrecognition.proto";
option java_outer_classname = "ClickLocationProtos";
message ClickLocation {
required float x = 1;
required float y = 2;
}
Main.kt
import com.kshmax.objectrecognition.proto.ClickLocationProtos
class MyApp {
companion object {
#JvmStatic
fun main(args: Array<String>) {
val location = ClickLocationProtos.ClickLocation.newBuilder()
location.x = 0.1f
location.y = 0.2f
location.build()
}
}
}
I have done it as described in protocolbuffers/protobuf repository examples .
But I got an error:
error: supertypes of the following classes cannot be resolved. Please
make sure you have the required dependencies in the classpath: class
com.kshmax.objectrecognition.proto.ClickLocationProtos.ClickLocation,
unresolved supertypes: com.google.protobuf.GeneratedMessageV3 class
com.kshmax.objectrecognition.proto.ClickLocationProtos.ClickLocationOrBuilder,
unresolved supertypes: com.google.protobuf.MessageOrBuilder class
com.kshmax.objectrecognition.proto.ClickLocationProtos.ClickLocation.Builder,
unresolved supertypes: com.google.protobuf.GeneratedMessageV3.Builder
What am I doing wrong?
The code that uses protobuf needs to depend on the protobuf library itself.
In theory, this could be exported by the rule, but since it doesn't work, I would add a dep on protobuf directly, similarly to BuildEventServiceTest
deps= [
"#com_google_protobuf//:protobuf_java",
"my_foo_java_proto",
]
or java_lite_proto_library / "#com_google_protobuf//:protobuf_java_lite" where the remote repository was defined in the WORKSPACE as
http_archive(
name = "com_google_protobuf",
patch_args = ["-p1"],
patches = ["#io_bazel//third_party/protobuf:3.11.3.patch"],
patch_cmds = EXPORT_WORKSPACE_IN_BUILD_FILE,
patch_cmds_win = EXPORT_WORKSPACE_IN_BUILD_FILE_WIN,
sha256 = "cf754718b0aa945b00550ed7962ddc167167bd922b842199eeb6505e6f344852",
strip_prefix = "protobuf-3.11.3",
urls = [
"https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v3.11.3.tar.gz",
"https://github.com/protocolbuffers/protobuf/archive/v3.11.3.tar.gz",
],
)
(I'm not sure you need the patch, and there might be a more recent version; look at the example)

Migrate CRUD Plugin from Play 1.2.4 to 2.5.x : views compilation errors

i'm new on Playframework and i need to migrate the CRUD Plugin from Play-1.2.4 to a module on Play-2.5.x. I'm facing some strange problems with the views. For example the form.scala.html component have the following errors :
app\views\tags\crud\form.scala.html:28: not found: type fieldName
app\views\tags\crud\form.scala.html:28: variable fieldsHandler of type Array[String] does not take type parameters.
app\views\tags\crud\form.scala.html:31: not found: value field
Here is a piece of code of the form file :
#(fields: List[String], obj: Object, typ: controllers.CRUD.ObjectType)(body: Html)
#import scala.Predef; var currentObject: Object = null; var currentType: controllers.CRUD.ObjectType = null; var fieldsHandler = new Array[String](10);
#for(fieldName <- fields) {
var am : String = "";
var field = #currentType.getField(fieldName);
#if(field == null){
throw new play.exceptions.TagInternalException("Field not found -> " + #fieldName)
}
#if(field.typ == "text") {
#tags.crud.textField(fieldName, currentObject[fieldName])
}
#if(field.typ == "password") {
#tags.crud.passwordField(fieldName, currentObject[fieldName])
}
#if(field.typ == "binary"){
#tags.crud.fileField(fieldName, currentObject[fieldName], currentObject.id )
}
}
--> 80% of the compile errors are related to variable recognition !
A piece from build.sbt file:
scalaVersion := "2.11.7"
lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean, SbtTwirl)
fork in run := true
Any idea ? Your help will be appreciated. Thanks.
I understood that the principle of the crud plugin is in contradiction with the new logic of compiling scala templates. So I started on a new generic implementation of crud.
Thank you

Why can I not pickle my case classes? What should I do to solve this manually next time?

Edit 2: Observations and questions
I am pretty sure along with the commenter below Justin that the problem is due to an errant build.sbt configuration. However, this is the first time I have seen an errant build.sbt configuration that literally works for everything else except for pickers. Maybe that is becaus they use macros and I as a rule avoid them.
Why would it matter whether Flow.merge is used vs Flow.map if the problem is with the sbt?
Suspicious build.sbt extract
lazy val server = project
.dependsOn(sharedJvm, client)
Suspicious stack trace
So this is the top of the stack: it goes from a method I cannot find to the linking environment to the string encoding utils. Ok.
server java.lang.RuntimeException: stub
Huh? stub?
server at scala.sys.package$.error(package.scala:27)
server at scala.scalajs.runtime.package$.linkingInfo(package.scala:143)
server at scala.scalajs.runtime.package$.environmentInfo(package.scala:137)
HUH?
server at scala.scalajs.js.Dynamic$.global(Dynamic.scala:78)
???
server at boopickle.StringCodec$.encodeUTF8(StringCodec.scala:56)
Edit 1: My big and beautiful build.sbt might be the problem
What you cannot see is that I organized in my project folder:
JvmDependencies.scala which has regular Jvm dependencies
SjsDependencies.scala which has Def.settingsKeys of libraryDependencies on JsModuleIDs
WebJarDependencies.scala which has javascripts and css's
build.sbt
lazy val shared = (crossProject.crossType(CrossType.Pure) in file("shared"))
.configure(_.enablePlugins(ScalaJSPlugin))
.settings(SjsDependencies.pickling.toSettingsDefinition(): _*)
.settings(SjsDependencies.tagsAndDom.toSettingsDefinition(): _*)
.settings(SjsDependencies.css.toSettingsDefinition(): _*)
lazy val sharedJvm = shared.jvm
lazy val sharedJs = shared.js
lazy val cmdlne = project
.dependsOn(sharedJvm)
.settings(
libraryDependencies ++= (
JvmDependencies.commandLine ++
JvmDependencies.logging ++
JvmDependencies.akka ++
JvmDependencies.serialization
)
)
lazy val client = project
.enablePlugins(ScalaJSPlugin, SbtWeb, SbtSass)
.dependsOn(sharedJs)
.settings(
(SjsDependencies.shapeless ++ SjsDependencies.audiovideo ++ SjsDependencies.databind ++ SjsDependencies.functional ++ SjsDependencies.lensing ++ SjsDependencies.logging ++ SjsDependencies.reactive).toSettingsDefinition(),
jsDependencies ++= WebjarDependencies.js,
libraryDependencies ++= WebjarDependencies.notJs,
persistLauncher in Compile := true
)
lazy val server = project
.dependsOn(sharedJvm, client)
.enablePlugins(SbtNativePackager)
.settings(
copyWebJarResources := { streams.value.log("Copying webjar resources")
val `Web Modules target directory` = (resourceManaged in Compile).value / "assets"
val `Web Modules source directory` = (WebKeys.assets in Assets in client).value / "lib"
final class UsefulFileFilter(acceptable: String*) extends FileFilter {
// TODO ADJUST TO EXCLUDE JS MAP FILES
import scala.collection.JavaConversions._
def accept(file: File) = (file.isDirectory && FileUtils.listFiles(file, acceptable.toArray, true).nonEmpty) || acceptable.contains(file.ext) && !file.name.contains(".js.")
}
val `file filter` = new UsefulFileFilter("css", "scss", "sass", "less", "map")
IO.createDirectory(`Web Modules target directory`)
IO.copyDirectory(source = `Web Modules source directory`, target = `Web Modules target directory` / "script")
FileUtils.copyDirectory(`Web Modules source directory`, `Web Modules target directory` / "style", `file filter`)
},
// run the copy after compile/assets but before managed resources
copyWebJarResources <<= copyWebJarResources dependsOn(compile in Compile, WebKeys.assets in Compile in client, fastOptJS in Compile in client),
managedResources in Compile <<= (managedResources in Compile) dependsOn copyWebJarResources,
watchSources <++= (watchSources in client),
resourceGenerators in Compile <+= Def.task {
val files = ((crossTarget in(client, Compile)).value ** ("*.js" || "*.map")).get
val mappings: Seq[(File,String)] = files pair rebase((crossTarget in(client, Compile)).value, ((resourceManaged in Compile).value / "assets/").getAbsolutePath )
val map: Seq[(File, File)] = mappings.map { case (s, t) => (s, file(t))}
IO.copy(map).toSeq
},
reStart <<= reStart dependsOn (managedResources in Compile),
libraryDependencies ++= (
JvmDependencies.akka ++
JvmDependencies.jarlocating ++
JvmDependencies.functional ++
JvmDependencies.serverPickling ++
JvmDependencies.logging ++
JvmDependencies.serialization ++
JvmDependencies.testing
)
)
Edit 0: A very obscure chat thread has a guy saying what I am feeling: no, not **** scala, but
Mark Eibes #i-am-the-slime Oct 15 2015 09:37
#ochrons I'm still fighting. I can't seem to pickle anything anymore.
https://gitter.im/scala-js/scala-js/archives/2015/10/15
I have a rather simple requirement - I have one web socket route on a akka http server that is defined AkkaServerLogEventToMessageHandler():
object AkkaServerLogEventToMessageHandler
extends Directives {
val sourceOfLogs =
Source.actorPublisher[AkkaServerLogMessage](AkkaServerLogEventPublisher.props) map {
event ⇒
BinaryMessage(
ByteString(
Pickle.intoBytes[AkkaServerLogMessage](event)
)
)
}
def apply(): server.Route = {
handleWebSocketMessages(
Flow[Message].merge(sourceOfLogs)
)
}
}
This fits into a tiny set of routes in the most obvious way.
Now why is that I cannot get boopickle, upickle, or prickle to serialize something as simple as this stupid case class?
sealed case class AkkaServerLogMessage(
message: String,
level: Int,
timestamp: Long
)
No nesting
All primitive types
No generics
Only three of them
These all produced roughly the same error
Using all three of the common picklers to write
Using TextMessage instead of BinaryMessage and the corresponding upickle or prickle writeJs or whatever methods
Varying the case class down to nothing (nothing, as in no members)
Varying the input itself to the case class
Importing various permutations of Implicits and underscore stuff
... specifically, they gave me variations on the same stupid error (not the same error, but considerably similar)
server [ERROR] [04/21/2016 22:04:00.362] [app-akka.actor.default-dispatcher-7] [akka.actor.ActorSystemImpl(app)] WebSocket handler failed with stub
server java.lang.RuntimeException: stub
server at scala.sys.package$.error(package.scala:27)
server at scala.scalajs.runtime.package$.linkingInfo(package.scala:143)
server at scala.scalajs.runtime.package$.environmentInfo(package.scala:137)
server at scala.scalajs.js.Dynamic$.global(Dynamic.scala:78)
server at boopickle.StringCodec$.encodeUTF8(StringCodec.scala:56)
server at boopickle.Encoder.writeString(Codecs.scala:338)
server at boopickle.BasicPicklers$StringPickler$.pickle(Pickler.scala:183)
server at boopickle.BasicPicklers$StringPickler$.pickle(Pickler.scala:134)
server at boopickle.PickleState.pickle(Pickler.scala:511)
server at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1$Pickler$macro$1$2$.pickle(AkkaServerLogEventToMessageHandler.scala:35)
server at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1$Pickler$macro$1$2$.pickle(AkkaServerLogEventToMessageHandler.scala:35)
server at boopickle.PickleImpl$.apply(Default.scala:70)
server at boopickle.PickleImpl$.intoBytes(Default.scala:75)
server at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1.apply(AkkaServerLogEventToMessageHandler.scala:35)
server at shindig.clientaccess.handler.AkkaServerLogEventToMessageHandler$$anonfun$1.apply(AkkaServerLogEventToMessageHandler.scala:31)
This worked
Not using Flow.merge (defeats the purpose, I want to keep sending out put with logs)
Using a static value
Other useless things
Appeal
Please let me know where and why I am stupid... I spent four hours on this problem today in different forms, and it is driving me nuts.
In your build.sbt, you have:
lazy val shared = (crossProject.crossType(CrossType.Pure) in file("shared"))
.configure(_.enablePlugins(ScalaJSPlugin))
Do not do this. You must not enable the Scala.js plugin on a cross-project, ever. This also adds it to the JVM side, which will wreak havoc. Most notably, this will cause %%% to resolve the Scala.js artifacts of your dependencies in the JVM project, and that is really bad. This is what causes your issue.
crossProject already adds the Scala.js plugin to the JS part, and only that one. So simply remove that enablePlugins line.
Mystery solved. Thanks to #Justin du Coeur for pointing me in the right direction.
The reason boopickle wasn't working in particular was because in the dependency chain I was including both the sjs and the jvm version of boopickle in the server project.
I removed the server dependsOn for client and for sharedJs and also removed boopickle from the shared dependencies. Now it works.

Define a variable and set it to a default value if something goes wrong during definition

I have the following code in my build.gradle
Contents in version.properties are:
buildVersion=1.2.3
Value of $v variable during the Gradle build is coming as: 1.2.3
Value of $artifactoryVersion variable in JENKINS build is coming as: 1.2.3.1, 1.2.3.2, 1.2.3.x ... and so on where the 4th digit is Jenkins BUILD_NUMBER available to gradle build script during Jenkins build.
BUT, when I'm running this build.gradle on my desktop where I dont have BUILD_NUMBER variable available or set in my ENVIRONMENT variables, I get an error saying trim() can't work on null. (as there's no BUILD_NUMBER for Desktop/local build).
I'm trying to find a way i.e.
What should I code in my script so that if BUILD_NUMBER is not available, then instead of gradle build processing failing for an error, it'd set jenkinsBuild = "0" (hard coded) otherwise, pick what it gets during Jenkins build.
For ex: in Bash, we set a variable var1=${BUILD_NUMBER:-"0"} which will set var1 to a valid Jenkins BUILD number if it's available and set to a value, otherwise if it's NULL, then var1 = "0".
I DON'T want to have each developer/user set this BUILD_NUMBER in some property file. All I want is, if this variable doesn't exist, then the code should put "0" in jenkinsBuilds variable and doesn't error out during desktop builds. I know during Jenkins build, it's working fine.
// Build Script
def fname = new File( 'version.properties' )
Properties props = new Properties()
props.load( new FileInputStream( fname ) )
def v = props.get( 'buildVersion' )
def env = System.getenv()
def jenkinsBuild = env['BUILD_NUMBER'].trim()
if( jenkinsBuild.length() > 0 ) {
artifactoryVersion = "$v.$jenkinsBuild"
}
All you need is some regular Java/Groovy code:
def jenkinsBuild = System.getenv("BUILD_NUMBER") ?: "0"
The code above uses Groovy's "elvis" operator, and is a shorthand for the following code, which uses Java's ternary operator:
def buildNumber = System.getenv("BUILD_NUMBER")
def jenkinsBuild = buildNumber != null ? buildNumber : "0"
Here's the answer to using a Java plain object (JDK8):
public class Sample {
private String region;
private String fruit;
public Sample() {
region = System.getenv().getOrDefault("REGION", null);
fruit = System.getenv().getOrDefault("FRUIT", "apple");
}
}
With the Env-Inject plugin you can get and set build parameters.
For example, under "Inject environment variables to the build process", add a Groovy script such as:
def paramsMap = [:]
def build = Thread.currentThread().executable
def my_var = build.getEnvVars()["MY_PARAM"]
if (!my_var) paramsMap.put("MY_PARAM", "default value")
// Return parameters map
out.println("Injecting parameters:\n" + paramsMap)
return paramsMap