Is it possible to compile managed source with different compiler flags than unmanaged source? - scala

I've added the -Xlinter and -Ywarn-unused-import scalac flags to a project of mine. The problem is that I'm using a source generator and it creates code that doesn't pass all the checks - there are dead code and unused import warnings. Is there a way for me to have a different set of scalacOptions for managed vs. unmanaged code?

I'll copy what Seth answered in comment section.
Using subprojects is the right way to go about this.

Related

Xcode: stop lines of code / functions from compiling

I have common files in several projects and I need to stop from compiling some lines and functions for project A, meanwhile it should be compiled for project B.
I know that I can use preprocessor. But it's not convenient for me. Is there any way to stop lines of code from compiling with condition like below?
#if PhotosModuleSettings.type == .documents
... do not commpile
#endif
What's not convenient about using the preprocessor? You can specify the preprocessor macros in build settings of each target, or you can use .xcconfig files to specify them.
There's another simple way to do it, however. Separate the lines and functions that you want to conditionally compile into separate files. Maybe by using Swift extensions or subclassing or just separate global functions, etc..whatever. Then just choose which target(s) and/or project(s) you want those files added as membership.
Depending on your desire to refactor your code to make such a file separation, the preprocessor macros may be the better way to go, though.
You will need to make use of pre processor macros.
Add a configuration for your project, and use that in the pre processor macros.
You can set the value for these configuration in the pre processor macros section for your targets based on your build configuration.
Here is a detailed blog related to the same concept

Is there any options to disable source maps generation in ScalaJS sbt plugin?

I would like to disable source maps generation for fullOptJS (production mode).
It is not always appropriate to have all the information about original Scala source files.
I didn't find any suitable options to disable output entirely or something similar?
Is there any link to the documentation with all the options available for scalajs sbt plugin?
Thanks for any help
The sbt setting scalaJSLinkerConfig, of type StandardLinker.Config, contains all the options you can possibly give to the Scala.js linker, i.e., the thing that optimizes everything and emits a .js file. For some reason, Scaladoc refuses to display the comments on of the vals, although they exist in the source code.
You can see there a val sourceMap: Boolean, which clearly configures whether the linker is going to emit source maps. You can set it to false in fullOptJS with the following sbt incantation, to be placed in the .settings(...) of the relevant project:
scalaJSLinkerConfig in (Compile, fullOptJS) ~= { _.withSourceMap(false) }
(see also this answer about what ~= means in sbt)

How can I change the compiler flags of an sbt project without causing recompilation?

It often comes up during testing and debugging a Scala project built with sbt that I need to pass some extra compiler flags for a particular file. For example -Xlog-implicits to debug implicit resolution problems. However, changing scalacOptions either in build.sbt or the console invalidates the cache and causes the whole project / test suite to be recompiled. In addition to being annoying to wait so long, this also means that a lot of noise from irrelevant files is printed. Instead it would be better if I could compile a specific file with some extra flags from the sbt console, but I did not find a way to do this.
Problem
The reason why changing the scalac options triggers recompilation is because Zinc, Scala's incremental compiler, cannot possibly now which compiler flags affect the semantics of the incremental compilation, so it's pessimistic about it. I believe this can be improved, and some whitelisted flags can be supported, so that next time people like you don't have to ask about it.
Nevertheless, there's a solution to this problem and it's more generic than it looks like at first sight.
Solution
You can create a subproject in your sbt build which is a copy of the project you want to "log implicits" in, but with -Xlog-implicits enabled by default.
// Let's say foo is your project definition
lazy val foo = project.settings(???)
// You define the copy of your project like this
lazy val foo-implicits = foo
.copy(id = "foo-implicits")
.settings(
target := baseDirectory.value./("another-target"),
scalacOptions += "-Xlog-implicits"
)
Note the following properties of this code snippet:
We redefine the project ID because when we reuse a project definition the ID is still the same as the previous one (foo in this case). Sbt fails when there are projects that share the same id.
We redefine the target directory because we want to avoid recompilation. If we keep the same as before, then recompiling foo-implicits will delete the compilation products of the previous compilation (and viceversa). That's exactly what we want to avoid.
We add -Xlog-implicits to the Scalac options as you request in this question. In a generic solution, this piece of code should go away.
When is this useful?
This is useful not only for your use case, but when you want to have different modules of the same project in different Scala versions. The following has two benefits:
You don't use cross-compilation in sbt ++, which is known to have some memory issues.
You can add new library dependencies that only exist for a concrete Scala version.
It has more applications, but I hope this addresses your question.

How to avoid recompiling on changes in *.scala.html files

I am using play framework v2.3. The problem I am facing is that any change in html and refreshing browser causes recompilation of the complete code. Can I avoid this?
Twirl templates are compiled, as stated by the docs:
Templates are compiled as standard Scala functions, following a simple naming convention. If you create a views/Application/index.scala.html template file, it will generate a views.html.Application.index class that has an apply() method.
There is no way to disable this behavior because it works this way by design. My suggestion here is use ~ (tilde) before SBT commands so things will happen as you save the file, per instance:
sbt ~run
This will recompile the changed file (and possible others), every time you change and save it. Also, sbt has some options that can possibly help you here: withNameHashing.
See sbt docs to understand how it works. To enable it, add the following line to your build.sbt file:
incOptions := incOptions.value.withNameHashing(nameHashing = true)

How to share code between project and build definition project in SBT

If I have written some source code in my build definition project (in /project/src/main/scala) in SBT. Now I want to use these classes also in the project I am building. Is there a best practice? Currently I have created a custom Task that copies the .scala files over.
Those seem like unnecessarily indirect mechanisms.
unmanagedSourceDirectories in Compile += baseDirectory.value / "project/src/main"
Sharing sourceDirectories as in extempore's answer is the simplest way to go about it, but unfortunately it won't work well with IntelliJ because the project model doesn't allow sharing source roots between multiple modules.
Seth Tisue's approach will work, but requires rebuilding to update sources.
To actually share the sources and have IntelliJ pick up on it directly, you can define a module within the build.
The following approach seems to only work in sbt 1.0+
Create a file project/metabuild.sbt:
val buildShared = project
val buildRoot = (project in file("."))
.dependsOn(buildShared)
and in your build.sbt:
val buildShared = ProjectRef(file("project"), "buildShared")
val root = (project in file("."))
.dependsOn(buildShared)
Then put your shared code in project/buildShared/src/main/scala/ and refresh. Your project will look something like this in IntelliJ:
Full example project: https://github.com/jastice/shared-build-sources
Can you make the following work? Put the source code for the classes in question should be part of your project, not part of your build definition; the “task which serializes a graph of Scala objects using Kryo and writes them as files into the classpath of the project” part sounds like a perfect job for resourceGenerators (see http://www.scala-sbt.org/0.13.2/docs/Howto/generatefiles.html). Then the only remaining problem is how to reference the compiled classes from your resource generator. I'm not familiar with Kryo. In order to use it, do you need to have the compiled classes on the classpath at the time your generator is compiled, or do they just need to be on the classpath on runtime? If the latter is sufficient, that's easier. You can get a classloader from the testLoader in Test key, load the class and instantiate some objects via reflection, and then call Kryo.
If you really need the compiled classes to be on the classpath when your resource generator is compiled, then you have a chicken and egg problem where the build can't be compiled until the project has been compiled, but of course the project can't be compiled before the build definition has been compiled, either. In that case it seems to me you have no choices other than:
1) the workaround you're already doing ("best practice" in this case would consist of using sourceGenerators to copy the sources out of your build definition and into target/src_managed)
2) put the classes in question in a separate project and depend on it from both your build and your project. this is the cleanest solution overall, but you might consider it too heavyweight.
Hope this helps. Interested in seeing others' opinions on this, too.