How to map files by extension in sbt? - scala

I want to compile WSDL files with the sbt-xjc plugin. By default, it looks for all the *.xsd files and I want to look for *.wsdl files. I tried this syntax:
sources in (Compile, xjc) ++= unmanagedResourceDirectories.value.flatMap(dirs => (dirs ** "*.wsdl").get)
But I get an error at sbt compile:
Reference to undefined setting:
*:unmanagedResourceDirectories from compile:xjc::sources (build.sbt:76)
Did you mean web-assets:unmanagedResourceDirectories ?
How can I add all the *.wsdl files to xjc?

Related

CoffeeScript and sbt-concat

I'm having trouble concatenating and fingerprinting all the CoffeeScript files in Play application. Everything works fine for JavaScript files with build.sbt like this one
pipelineStages := Seq(concat, digest)
Concat.groups := Seq(
"javascripts/app.js" -> group(((sourceDirectory in Assets).value / "javascripts") * "*.js")
)
But when sourceDirectory is changed to resourcesManaged that supposedly contains compiled CoffeeScript files sbt-concat doesn't pick them up.
sbt-coffeescript, and all other official source task plugins, don't put their files in resourcesManaged in Assets, but instead their own sub-directory in target/web/<taskname>. They scope the resourcesManaged setting to their main task, in this case this means resourcesManaged in (Assets, coffeescript) and resourcesManaged in (TestAssets, coffeescript).
When you run sbt coffeescript you can see the files are output to target/web/coffeescript/main. You can verify this by running show web-assets:coffeescript::resourceManaged from the sbt console.

Include generated resources in a jar (SBT)

I've been writing an SBT plugin that generates resources into resource_managed. I'm now looking to include these generated resources in the generated jar as the SBT docs detail:
Generating resources:
By default, generated resources are not included in the packaged source artifact. To do so, add them as you would other mappings. See Adding files to a package
I've read the docs but honestly how to do this I can't figure out. Can anyone explain it or point me to another project that does this so I can see how they do it?
First just to clarify, they are included in jars containing compiled classes. They are not included in jars containing sources.
By default, generated resources are not included in the packaged
source artifact.
For packageBin the generated files should already be included - just make sure you return all generated files from the generator method. Assuming you want to package them in the sources artifact, this is what you have to do.
Let's assume you have a generator that generates a property file.
lazy val generatePropertiesTask = Def.task {
val file = (Compile / resourceManaged).value / "stack-overflow" / "res.properties"
val contents = s"name=${name.value}\nversion=${version.value}"
IO.write(file, contents)
Seq(file)
}
resourceGenerators in Compile += generatePropertiesTask.taskValue
To include that in the generated sources you have to tell sbt to where the res.properties must be copied in the generated sources artefact. The task, which generates the packaged sources is called packageSrc, therefore you have to set mappings scoped to that task.
mappings in (Compile, packageSrc) += {
((resourceManaged in Compile).value / "stack-overflow" / "res.properties") -> "path/in/jar/res.properties"
}
Because your generator can generate many tasks, and mapping each by hand would be a tedious task, sbt gives you an utility to map multiple paths at once.
mappings in (Compile, packageSrc) ++= {
val allGeneratedFiles = ((resourceManaged in Compile).value ** "*") filter { _.isFile }
allGeneratedFiles.get pair relativeTo((resourceManaged in Compile).value)
}
The first line finds all generated files using path finders and second line maps them to their path in the target jar.

How do I invoke a shell command during a Play 2.0 build (sbt)?

I would like to add a symlink from the .git/hooks directory to a file in my working tree during a regular Play! framework 2.0 build. According to the Play documentation, all sbt functionality is available as normal in a Play build. Based on google searches, I'm trying to add this code to the ApplicationBuild object in my project/Build.scala file:
val symlinkGitPrepushHookTask = compile in Compile <<= compile in Compile map {comp =>
val output = "ln -sf ../../.hooks/pre-push.py .git/hooks/pre-push".!!
print(output)
comp
}
From my reading of the sbt docs, this should be adding a dependency to the compile task in the Compile scope. The dependency is on its existing value, but with my additional function mapped to it. Now when the compile task runs, my anonymous function should be run too. This does not successfully create the symlink, and does not even seem to run.
Immediately after posting this, I thought I would try adding the example I had found to the project/plugins.sbt file. This works, although it seems an abuse of a file to specify plugins.
... existing plugins.sbt content ...
compile in Compile <<= compile in Compile map { comp =>
"ln -sf ../../.hooks/pre-push.py .git/hooks/pre-push".!!
comp
}
The blank line is critical, as this is the delimiter in the .sbt format.

SBT accessing sub directories

My project file structure looks like this:
build.sbt
lib
project
src
target
test
Inside lib folder I have sub folders that contain additional jar files. How can I get SBT to recognize sub-folders or to treat jar files recursively?
EDIT:
thanks to #Jhonny Everson I am able to get this working. Here is how:
added the following line in my build.sbt
unmanagedJars in Compile <++= baseDirectory map { base =>
val baseDirectories = (base / "lib" / "mycustomlib" )
val customJars = (baseDirectories ** "*.jar")
customJars.classpath
}
Note that the base directory is where build.sbt is located.
if you put jars on lib folder, Sbt will use them automatically. You can use unmanagedJars directive to specify multiple directories in which jar files can be found. See https://github.com/harrah/xsbt/wiki/Library-Management#manual-dependency-management
I wanted to implement something like vim's pathogen and here's what I came up with:
unmanagedJars in Compile ++= {
val libs = baseDirectory.value / "lib"
val subs = (libs ** "*") filter { _.isDirectory }
val targets = ( (subs / "target") ** "*" ) filter {f => f.name.startsWith("scala-") && f.isDirectory}
((libs +++ subs +++ targets) ** "*.jar").classpath
}
Using sbt 0.13.x or any typesafe-activator relying on it, this will check /lib, /lib/* and /lib/*/target/scala-* for JARs and load them into the classpath. If the example isn't clear enough to understand what's going on, it might help to know that baseDirectory.value, libs, subs and targets are sbt.Pathfinder instances.

Filtering resources in SBT

I am trying to setup SBT to compile an existing project which does not use the maven directory structure. I am using the full configuration and have set my javaSource & resourceDirectory settings as follows:
def settings = Defaults.defaultSettings ++ Seq(
resourceDirectory in Compile <<= baseDirectory( _ / "java" ),
javaSource in Compile <<= baseDirectory( _ / "java" )
)
Now I want to be able to filter the resources we include in the jar artifact, as we currently do with ant, plus exclude .java files as our resources are mixed in with source code. For example:
<fileset dir="java" includes="**/*.txt, **/*.csv" excludes="**/*.java" />
Is there any way to do this?
Use defaultExcludes scoped for the unmanagedResources task and optionally the configuration. For example, this setting excludes .java files from the main resources:
defaultExcludes in Compile in unmanagedResources := "*.java"
in Compile restricts this setting to only apply to main resources. By using in Test instead, it would apply only to test resources. By omitting a configuration (that is, no in Compile or in Test), the setting would apply to both main and test resources.
in unmanagedResources applies these excludes for resources only. To apply excludes to sources, for example, the scope would be in unmanagedSources. The reason for the unmanaged part is to emphasize that these apply to unmanaged (or manually edited) sources only.
The defaultExcludes key has type sbt.FileFilter, so the setting value must be of this type. In the example above, "*.java" is implicitly converted to a FileFilter. * is interpreted as a wildcard and so the filter accepts files with a name that ends in '.java'. To combine filters, you use || and &&. For example, if .scala files needed to be excluded as well, the argument to := would be:
"*.java" || "*.scala"
In the original Ant fileset, the include and exclude filters select mutually exclusive sets of files, so only one is necessary.
It is also possible to directly build the Seq[File] for unmanagedResources. For example:
unmanagedResources in Compile <<=
unmanagedResourceDirectories in Compile map { (dirs: Seq[File]) =>
( dirs ** ("*.txt" || "*.csv" -- "*.java") ).get
}
The ** method selects all descendents that match the FileFilter argument. You can verify that the files are selected as you expect by running show unmanaged-resources.
For sbt 1.48 I needed this style:
.settings(
Compile / sources := Seq(file("/path/to/your/file"))
)