SBT: Exclude resource subdirectory - scala

I've been using Gradle for most of my Scala projects, but I want to evaluate the suitability of SBT as a replacement. One of the things I've done in Gradle is to exclude a certain resource directory from the final build (for example, using CoffeeScript to write JavaScript files that will be included as final resources).
In Gradle, I'd do this by:
sourceSets {
main {
resources {
exclude 'com/example/export/dev' // exclude development resources
}
}
}
And this would exclude the resource package com.example.export.dev package from the final build.
How would I do the same in SBT? I've tried
unmanagedResourceDirectories in Compile -= (resourceDirectory in Compile).value / "com/example/export/dev"
but that doesn't do a thing (I understand why, but that doesn't really help). And the documentation on the SBT web site only talks about excluding file patterns (at Classpaths, sources, and resources).
As a more descriptive image, say we have the following resource directory structure:
com
\---example
\---export
\---dev
\---something
In the final output, I want:
com
\---example
\---export
\---something

The way to think in SBT is a bit different and I know it can be hard at first.
In your example, you need to modify the task that generate the resource files (or the task that selects the folders to look for resource files).
Here is an example of how I can select only the resource files that start with character 'a'.
(unmanagedResources in Compile) := (unmanagedResources in Compile).value.filter(_.getName.startsWith("a"))
Similarly if you want to modify the entire directory of the resource files you can do that like this:
(unmanagedResourceDirectories in Compile) := (unmanagedResourceDirectories in Compile).value.filter(_.getName.startsWith("a"))
Obviously my filters here are just and example, you can have any complex pattern that Scala supports.
The nice thing about SBT is that it's interactive. So you can check the result of your task by simply typing these at the REPL of your project:
> show compile:unmanagedResources
> show compile: unmanagedResourceDirectories
To check all the dependencies to the task do this from the REPL:
> inspect tree compile:unmanagedResources
Assumption:
SBT knows where to find all resources using the standard maven build directory layout. The above solution assumes that all resources are under the /resources directory. You can then access them from your Scala code using getClass.getResource("/folderInsideResources/file.txt").
Here is a sample directory layout for a mixed Java/Scala project with resources:
.
├── main
│   ├── java
│   │   └── com
│   │   └── a
│   │   └── b
│   │   └── Hello.java
│   ├── resources
│   │   ├── a.tx
│   │   └── b.tx
│   └── scala
│   └── com
│   └── a
│   └── b
│   └── ScalaHello.scala
└── test
├── resources
└── scala
└── com
└── a
└── b
└── ScalaHello.scala
To access the resource file just use:
getClass.getResource("/a.txt")
getClass.getResource("/b.txt")

From https://github.com/sbt/sbt-jshint/issues/14:
excludeFilter in unmanagedResources := {
val public = ((resourceDirectory in Compile).value / "com" / "example" / "export" / "dev").getCanonicalPath
new SimpleFileFilter(_.getCanonicalPath startsWith public)
}

Related

Yocto: Add debug mode for a bsp recipe which is using a scc file

I need to add debug mode (enable/disable a few kernel config) to a kernel recipe. The recipe resides under recipes-kernel.
We have this inside recipe linux-yocto-onl_5.10.bb:
...
SRC_URI += "\
git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.10;destsuffix=kernel-meta \
file://my-kmeta;type=kmeta;name=my-kmeta;destsuffix=my-kmeta
"
We have this directory structure inside recipe folder:
.
└── my-kmeta
├── bsp
│   ├── armel-iproc
│   │   ├── armel-iproc.cfg
│   │   ├── armel-iproc.scc
│   │   ├── ... (some patches)
│   │   ├── extraconfigs.cfg
│   │   └── extraconfigs_debug.cfg
└── ...
This is content of armel-iproc.scc:
define KMACHINE armel-iproc
define KTYPE standard
define KARCH arm
patch ...
kconf hardware armel-iproc.cfg
kconf non-hardware extraconfigs.cfg
I tried two solution without success:
First I've added another .scc file and appended it to SRC_URI of the recipe. Inside that scc file just added kconf extraconfigs_debug.cfg. after baking the recipe, the config file seems copied to the build directory, but inside the .config file in build directory the changes aren't applied.
The second approach is defining two recipes, one for release and another for debug, for this I need to have two .scc files: one armel-iproc.scc and the other is armel-iproc_debug.scc, the second included the first plus kconfing extraconfigs_debug.cfg. After baking the debug recipe (by including armel-iproc_debug.scc to SRC_URI), I got errors indicating that bsp/armel-iproc is not found.

Scala share resources folder to open a file

This is my folder structure and I am trying to load the "grammar.txt" file from resources folder but I get not found error.
val source = Source.fromResource("grammar.txt")
Folder structure:
➜ cfg-tools tree -L 4
.
├── build.sbt
├── src
│   ├── main
│   │   └── scala
│   │   ├── Builer.scala
│   │   ├── Driver.scala
│   │   ├── tokens.scala
│   │   └── Tools.scala
│   ├── resources
│   │   └── grammar.txt
build.sbt
name := "cfg-tools"
version := "0.1"
scalaVersion := "3.0.2"
Compile / unmanagedResourceDirectories += sourceDirectory.value / "resources"
You don't need the custom SBT configuration: just use the standard place for resources which is src/main/resources (note that it's in main subfolder compared to your current structure).

How to publish Test Only Objects in a sbt project

I have been developing a common library for my team, where I need to provide mock data for end users to write unit-test code. Ideally, the mock object should only be available to tests of packages referencing mine, but I am not sure how to do this.
My package structure is:
├── common
│   ├── src
│   │   ├── main
│   │   │   ├── resources
│   │   │   └── scala
│   │   └── test
│   │   ├── resources
│   │   └── scala
│   │   └── MockData.scala // <--- object defined here
├── build.sbt
In my build.sbt, I have
Test / publishArtifact := true
Test / publish := true
packageBin / publishArtifact := true
And I use sbt clean; sbt compile; sbt publishLocal to publish my library locally.
In the project referencing the above library, I added the following to the build.sbt:
ThisBuild / libraryDependencies ++= Seq(
"org.my" %% "common" % "0.0.1",
"org.my" %% "common" % "0.0.1" % Test,
)
but when writing tests, I cannot find objects defined in MockData.scala.
Please provide some hints, much appreciated.
------------------ UPDATE ------------------
After googling around, I'd decided to write a separate module for publishing test data only. So my package structure becomes:
├── common
│   ├── src
│   │   ├── main
│   │   │   ├── resources
│   │   │   └── scala
│   │   └── test
│   │   ├── resources
│   │   └── scala
├── common-testkit
│   ├── src
│   │   └── main
│   │      ├── resources
│   │      └── scala
│   │   └── MockData.scala // <--- object defined here
├── build.sbt
The issue is in the way you ask to retrieve the test code in your other project.
"org.my" %% "common" % "0.0.1" % Test means to depends on the "main" code of project common when running the tests of your other project. That's what the scope Test (after the version) means.
What you want is to depend on the "test code" of common project when running your tests. This is done by specifying what is called a "classifier" in sbt:
"org.my" %% "common" % "0.0.1" % Test classifier "tests"

cucumber-scala and Play Framework integration testing

I've managed to get cucumber-scala up and running on a Play/Scala. Now I want to run the entire play application so that I can use something like Selenium to test my application.
My Current attempts have lead me to
val app = new FakeApplication()
val port = 3333
lazy val browser: TestBrowser = TestBrowser.of(webDriverClass, Some("http://localhost:" + port))
lazy val server = TestServer(port, app)
Of course this FakeApplication() is not configured in any way... Am I approaching this incorrectly? This application is also multi-module and Ideally I would like to have the feature tests run per module (see output from tree below)
├── README.md
├── build.sbt
├── conf
│   ├── application.conf
│   └── routes
├── logs
│   └── application.log
├── modules
│   ├── module1
│   │   ├── app
│   │   ├── conf
│   │   ├── target
│   │   └── test
│   └── module2
│   ├── app
│   ├── conf
│   └── target
└── project
   ├── build.properties
   ├── plugins.sbt
   ├── project
   │   └── target
   └── target
   ├── config-classes
   ├── resolution-cache
   ├── scala-2.10
   └── streams
I am aware that Play has a selenium integration which can be used to drive my tests. However I have a business requirement for feature files, as they are used as a reporting mechanism. I am not absolutely tied to Cucumber so if anyone is aware of a way of driving browser based tests using Feature files that would also be acceptable to me?
Thanks,
Ben
Update:
I was running through IntelliJ, which causes a server to run with no routes or anything provided. I assume this is because it runs with a default blank application.
However When running through sbt test I get the following output:
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error in custom provider, Configuration error: Configuration error[Router not found: admin.Routes]
while locating play.api.inject.guice.FakeRouterProvider
while locating play.api.routing.Router
for parameter 0 at play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:200)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for parameter 4 at play.api.DefaultApplication.<init>(Application.scala:221)
at play.api.DefaultApplication.class(Application.scala:221)
while locating play.api.DefaultApplication
while locating play.api.Application
If you're using the default configuration settings for IntegrationTest in sbt, and ScalaTestPlusPlay, here are the directories to use:
src/it/scala – scala IT code
src/it/java – java IT code
src/it/resources – resources, including configuration
Place your application.conf and routes files in the resources directory and FakeApplication will pick it up. You can also set the paths in your sbt script to some other place.
If all of your development/integration testing machines are Unix-like and you use git for VC, you can use a relative symlink1 to your real routes file.
For Windows or other VCS's, you'll likely have to copy the routes file and do double maintenance.
1 symlink using a relative path to the original, e.g., ../../../conf/routes.

Scala home directory for creating Scala project in IntelliJ IDEA

I'm new to both Scala and IntelliJ. I've installed Scala plugin for IntelliJ
I've installed Scala in my Ubuntu system with
sudo apt-get install scala
When I try to create new scala project, I'm required to do Scala Settings.
But the problem is I couldn't find the the home directory for my Scala installation.
What is the home directory for Scala in my ubuntu?
Thanks.
The plugin wants to know where the Scala libraries are installed (as it would want to know where the Java SDK is located for a Java module). Note that for different Scala projects you might use different versions of Scala: 2.9.0 or 2.10.2, etc. The dialog offers to download them or you can go to the Scala site and download them yourself. For example, I downloaded scala-2.10.2.tgz from http://www.scala-lang.org/download/ and expanded it in /home/glenn/Applications/Scala/ to
/home/glenn/Applications/Scala/scala-2.10.2/. This latter path is what goes in the "Set Scala Home" field in the dialog.
Note that in my case this is preferable to using the apt-get installation of Scala because the API changes so much that I usually end up with different versions of Scala for different projects that I experiment with.
Follow the version links at http://www.scala-lang.org/download/all.html to the version page with the download for the docs.
Note that for me, IDEA wanted the docs to be in the "doc/scala-devel-docs" directory, whereas the downloaded docs decompressed to "scala-docs-2.10.2". I made a link so that IDEA can find them. My 2.10.2 directory looks like this, now.
scala-2.10.2
├── bin
├── doc
│   ├── scala-devel-docs -> scala-docs-2.10.2
│   ├── scaladoc
│   │   └── lib
│   ├── scala-docs-2.10.2
│   │   └── api
│   └── tools
│   ├── css
│   └── images
├── examples
│   ├── actors
│   ├── monads
│   ├── parsing
│   │   └── lambda
│   ├── tcpoly
│   │   └── monads
│   └── xml
│   └── phonebook
├── lib
├── man
│   └── man1
├── misc
│   └── scala-devel
│   └── plugins
└── src
Run
$ dpkg -L scala
It will show a list of files in that package. Search for scalac:
$ dpkg -L scala | grep scalac
It will be something like /usr/share/scala/bin/scalac. Strip off /bin/scalac part and you will get Scala home: /usr/share/scala.
Update
It seems that there is no dedicated Scala home in Ubuntu. scala-library package files are installed simply to /usr/share/java. I guess then that the most simple way to get proper Scala home is to download a tarball from http://scala-lang.org/, extract it somewhere and use extracted directory as Scala home.