Skip to content

Commit d7846d8

Browse files
authored
Add Javascript support (#2)
* Add support for Scala.js * Fix override of scalacOptions that thwarts scala.js plugin settings * Add CrossModule top level definition to invoke the CrossProject plugin for cross building * Make module name and dir name parameters Force scala3 configuration on the projects * Further fixes to CrossModule * Set the file and module name directly * No suffix for JVM Platform * Enable the ScalaJSPlugin Force scala3 configuration on the projects * Remove pauses from scripted test execution * Ensure ScalaJSPlugin is enabled * Upgrade dependencies & Fix SBT Plugins * Don't set sbtPlugin any more, just enable SbtPlugin * Upgrade to sbt-git 2.01 * Upgrade to sbt-release 1.4.0 * Upgrade to sbt-sonatype 3.11.1 * Upgrade to sbt-coveralls 1.3.13 * Upgrade to sbt-buildinfo 0.11.0 * Remove sbt-wartremove * Fix test cases to pass
1 parent c6e6d3d commit d7846d8

25 files changed

Lines changed: 385 additions & 143 deletions

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
# sbt-ossuminc
22
Some sbt utilities common to ossuminc projects
3+
4+
[![Scala.js](https://www.scala-js.org/assets/badges/scalajs-1.16.0.svg)](https://www.scala-js.org)
5+
6+
# Publishing
7+

build.sbt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ Global / onChangedBuildSource := ReloadOnSourceChanges
1919

2020
lazy val `sbt-ossuminc` = project
2121
.in(file("."))
22-
.enablePlugins(ScriptedPlugin)
22+
.enablePlugins(SbtPlugin)
2323
.configure(RootProjectInfo.initialize("sbt-ossuminc", startYr = 2015))
2424
.configure(DynamicVersioning.configure)
2525
.configure(Scala2.configure)
2626
.configure(SonatypePublishing.configure)
2727
.settings(
28-
sbtPlugin := true,
2928
name := "sbt-ossuminc",
3029
scalaVersion := "2.12.18",
3130
// Scripted == sbt plugin tests
@@ -50,7 +49,7 @@ addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0")
5049
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
5150
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.10.0")
5251
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.4")
53-
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0")
52+
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.11.1")
5453
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.5.3")
5554

5655
// Scala specific from various places
@@ -59,3 +58,6 @@ addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
5958
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9")
6059
addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.3.11")
6160
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.3")
61+
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
62+
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2")
63+
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2")

project/GitHubPackagesPublishing.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

project/plugins.sbt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,29 @@
1616

1717
// Generic plugins from github.sbt project
1818
addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1")
19-
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.16")
20-
addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.0")
19+
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.0")
20+
addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.1")
2121
addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0")
2222
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1")
23-
addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0")
23+
addSbtPlugin("com.github.sbt" % "sbt-release" % "1.4.0")
2424

2525
addDependencyTreePlugin
2626

2727
// Helpers from other sources
28-
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
28+
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.12.0")
2929
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.10.0")
3030
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.4")
31-
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0")
32-
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.5.3")
31+
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.11.1")
3332

3433
// Scala specific from various places
3534
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.11.1")
3635
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
3736
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9")
38-
addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.3.11")
39-
addSbtPlugin("org.wartremover" % "sbt-wartremover" % "3.1.5")
37+
addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.3.13")
4038
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.4")
39+
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
40+
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2")
41+
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2")
4142

4243
libraryDependencies ++= Seq(
4344
"org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.ossuminc.sbt
2+
3+
import sbt.*
4+
import sbt.Keys.*
5+
import sbtcrossproject.CrossPlugin.autoImport.{JVMCrossProjectOps, JVMPlatform}
6+
import sbtcrossproject.{CrossProject, CrossType, Platform}
7+
import scalajscrossproject.ScalaJSCrossPlugin.autoImport.{JSCrossProjectOps, JSPlatform}
8+
import scalanativecrossproject.ScalaNativeCrossPlugin.autoImport.{NativeCrossProjectOps, NativePlatform}
9+
10+
/** A CrossModule is a module that can be built for JVM, Javascript or Native execution. Use it like:
11+
* {{{val my_project = CrossModule("my_project", Javascript + JVM + Native).configure(...).settings(...)}}}
12+
*/
13+
object CrossModule {
14+
sealed trait Target { def platform: Platform }
15+
case object JVMTarget extends Target { def platform: Platform = JVMPlatform }
16+
case object JSTarget extends Target { def platform: Platform = JSPlatform }
17+
case object NativeTarget extends Target { def platform: Platform = NativePlatform }
18+
19+
/** Define a sub-project or module of the root project. Make sure to use the [[Root]] function before this Module is
20+
* defined. No configuration is applied but you can do that by using the various With.* functions in this plugin.
21+
* `With.typical` is typical for Scala3 development
22+
* @param dirName
23+
* The name of the sub-directory in which the module is located.
24+
* @param modName
25+
* The name of the artifact to be published. If blank, it will default to the dirName
26+
* @return
27+
* The project that was created and configured.
28+
*/
29+
def apply(dirName: String, modName: String = "")(targets: Target*): CrossProject = {
30+
val mname = { if (modName.isEmpty) dirName else modName }
31+
val crossProj = CrossProject(dirName, file(dirName))(targets.map(_.platform): _*)
32+
.crossType(CrossType.Full)
33+
.withoutSuffixFor(JVMPlatform)
34+
.enablePlugins(OssumIncPlugin)
35+
.jvmSettings(
36+
libraryDependencies += "org.scala-js" %% "scalajs-stubs" % "1.1.0" % "provided"
37+
)
38+
.settings(
39+
name := dirName,
40+
moduleName := mname
41+
)
42+
targets.foldLeft(crossProj) { case (cp: CrossProject, target: Target) =>
43+
target match {
44+
case JVMTarget => cp.jvmSettings(moduleName := mname)
45+
case JSTarget => cp.jsSettings(moduleName := mname ++ "-js")
46+
case NativeTarget => cp.nativeSettings(moduleName := mname ++ "-native")
47+
}
48+
}
49+
}
50+
// private def mapToProject(cp: CrossProject, target: Target): Project = {
51+
// target match {
52+
// case JVMTarget => cp.jvm
53+
// case JSTarget => cp.js
54+
// case NativeTarget => cp.native
55+
// }
56+
// }
57+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.ossuminc.sbt
2+
3+
import com.typesafe.sbt.packager.archetypes.JavaAppPackaging
4+
import sbt.Keys.{moduleName, name}
5+
import sbt.{Project, file}
6+
7+
object Module {
8+
9+
/** Define a sub-project or module of the root project. Make sure to use the [[Root]] function before this Module is
10+
* defined. No configuration is applied but you can do that by using the various With.* functions in this plugin.
11+
* `With.typical` is typical for Scala3 development
12+
* @param dirName
13+
* The name of the sub-directory in which the module is located.
14+
* @param modName
15+
* The name of the artifact to be published. If blank, it will default to the dirName
16+
* @return
17+
* The project that was created and configured.
18+
*/
19+
def apply(dirName: String, modName: String = ""): Project = {
20+
Project
21+
.apply(dirName, file(dirName))
22+
.enablePlugins(OssumIncPlugin, JavaAppPackaging)
23+
.settings(
24+
name := dirName,
25+
moduleName := { if (modName.isEmpty) dirName else modName }
26+
)
27+
}
28+
}

src/main/scala/com/ossuminc/sbt/OssumIncPlugin.scala

Lines changed: 20 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,26 @@
11
package com.ossuminc.sbt
22

3-
import com.typesafe.sbt.packager.archetypes.JavaAppPackaging
4-
import com.typesafe.sbt.packager.graalvmnativeimage.GraalVMNativeImagePlugin
5-
import com.typesafe.sbt.packager.universal.UniversalDeployPlugin
63
import sbt.*
74
import sbt.Keys.*
85
import sbt.librarymanagement.Resolver
96

107
object OssumIncPlugin extends AutoPlugin {
118

129
object autoImport {
13-
14-
object Root {
15-
16-
/** Define a Root level project whether it is for a single-project repo or a unirepo with many sub-projects. This
17-
* project is configured with a shell prompt, and the standard project information at ThisBuild scope
18-
* @param ghRepoName
19-
* The name of the github repository we are building
20-
* @param ghOrgName
21-
* THe name of the github organization/user that contains the `ghRepoName`
22-
* @param orgPackage
23-
* The organization part of the JVM package this repo uses for its code
24-
* @param orgName
25-
* The legal name of the organization
26-
* @param orgPage
27-
* The URL of the website to use for the organization
28-
* @param startYr
29-
* The year in which this project started, for copyright purposes
30-
* @param devs
31-
* A list of Developer specifications to include in POM (required by Maven)
32-
* @return
33-
* The project that was created and configured.
34-
*/
35-
def apply(
36-
ghRepoName: String = "",
37-
ghOrgName: String = "ossuminc",
38-
orgPackage: String = "com.ossuminc",
39-
orgName: String = "Ossum, Inc.",
40-
orgPage: URL = url("https://ossuminc.com/"),
41-
maintainerEmail: String = "reid@ossuminc.com",
42-
startYr: Int = 2023,
43-
devs: List[Developer] = List.empty
44-
): Project = {
45-
Project
46-
.apply("root", file(System.getProperty("user.dir")))
47-
.enablePlugins(OssumIncPlugin)
48-
.configure(
49-
helpers.RootProjectInfo.initialize(
50-
ghRepoName,
51-
ghOrgName,
52-
startYr,
53-
orgPackage,
54-
orgName,
55-
orgPage,
56-
maintainerEmail,
57-
devs
58-
),
59-
helpers.Resolvers.configure
60-
)
61-
}
62-
}
63-
64-
object Module {
65-
66-
/** Define a sub-project or module of the root project. Make sure to use the [[Root]] function before this Module
67-
* is defined. No configuration is applied but you can do that by using the various With.* functions in this
68-
* plugin. `With.typical` is typical for Scala3 development
69-
* @param dirName
70-
* The name of the sub-directory in which the module is located.
71-
* @param modName
72-
* The name of the artifact to be published. If blank, it will default to the dirName
73-
* @return
74-
* The project that was created and configured.
75-
*/
76-
def apply(dirName: String, modName: String = ""): Project = {
77-
Project
78-
.apply(dirName, file(dirName))
79-
.enablePlugins(OssumIncPlugin, JavaAppPackaging)
80-
.settings(
81-
name := dirName,
82-
moduleName := { if (modName.isEmpty) dirName else modName }
83-
)
84-
}
85-
}
86-
87-
object Plugin {
88-
89-
/** Define a sub-project that produces an sbt plugin. It is necessary to also have used the [[Root]] function
90-
* because what that function sets up is necessary for publishing this module. scoverage doesn't work with sbt
91-
* plugins so it is disabled.
92-
* @param dirName
93-
* The name of the directory in which the plugin code and tests exist
94-
* @param modName
95-
* The name of the published artifact. If blank, the `dirName` will be used
96-
* @return
97-
* The configured sbt project that is ready to build an sbt plugin
98-
*/
99-
def apply(dirName: String, modName: String = ""): Project = {
100-
Project
101-
.apply(dirName, file(dirName))
102-
.enablePlugins(OssumIncPlugin)
103-
.configure(helpers.Plugin.configure)
104-
.settings(
105-
name := dirName,
106-
moduleName := { if (modName.isEmpty) dirName else modName }
107-
)
108-
}
109-
}
110-
111-
object Program {
112-
113-
/** Define a sub-project that produces an executable program. It is necessary to also have used the [[Root]]
114-
* function because what that function sets up is necessary for publishing this module.
115-
* @param dirName
116-
* The name of the directory in which the plugin code and tests exist
117-
* @param appName
118-
* The name of the published artifact. If blank, the `dirName` will be used
119-
* @return
120-
* The configured sbt project that is ready to build an sbt plugin
121-
*/
122-
def apply(dirName: String, appName: String): Project = {
123-
Project
124-
.apply(dirName, file(dirName))
125-
.enablePlugins(OssumIncPlugin, JavaAppPackaging, UniversalDeployPlugin, GraalVMNativeImagePlugin)
126-
.settings(
127-
name := dirName,
128-
moduleName := { if (appName.isEmpty) dirName else appName }
129-
)
130-
}
131-
}
132-
10+
// The type of function that `Project.configure` takes as its argument
13311
private type ConfigFunc = Project => Project
13412

13+
// Major declarations
14+
val Root: com.ossuminc.sbt.Root.type = com.ossuminc.sbt.Root
15+
val Module: com.ossuminc.sbt.Module.type = com.ossuminc.sbt.Module
16+
val Plugin: com.ossuminc.sbt.Plugin.type = com.ossuminc.sbt.Plugin
17+
val Program: com.ossuminc.sbt.Program.type = com.ossuminc.sbt.Program
18+
val CrossModule: com.ossuminc.sbt.CrossModule.type = com.ossuminc.sbt.CrossModule
19+
val JVM: CrossModule.Target = CrossModule.JVMTarget
20+
val JS: CrossModule.Target = CrossModule.JSTarget
21+
val Native: CrossModule.Target = CrossModule.NativeTarget
22+
23+
// Clauses to customize the major declarations
13524
object With {
13625
val akka: ConfigFunc = helpers.Akka.configure
13726
val aliases: ConfigFunc = helpers.HandyAliases.configure
@@ -140,6 +29,7 @@ object OssumIncPlugin extends AutoPlugin {
14029
val git: ConfigFunc = helpers.Git.configure
14130
val header: ConfigFunc = helpers.Header.configure
14231
val java: ConfigFunc = helpers.Java.configure
32+
val javascript: ConfigFunc = helpers.Javascript.configure
14333
val misc: ConfigFunc = helpers.Miscellaneous.configure
14434
val native: ConfigFunc = helpers.Native.configure
14535
val publishing: ConfigFunc = helpers.SonatypePublishing.configure
@@ -188,6 +78,13 @@ object OssumIncPlugin extends AutoPlugin {
18878
these(java, misc, build_info, release)(project)
18979
}
19080

81+
def js(
82+
hasMain: Boolean = false,
83+
forProd: Boolean = false
84+
)(project: Project): Project = {
85+
helpers.Javascript.configure(hasMain, forProd)(project)
86+
}
87+
19188
def native(
19289
buildTarget: String = "static",
19390
targetTriple: String = "arm64-apple-macosx11.0.0",
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.ossuminc.sbt
2+
3+
import sbt.*
4+
import sbt.Keys.*
5+
6+
object Plugin {
7+
8+
/** Define a sub-project that produces an sbt plugin. It is necessary to also have used the [[Root]] function because
9+
* what that function sets up is necessary for publishing this module. scoverage doesn't work with sbt plugins so it
10+
* is disabled.
11+
* @param dirName
12+
* The name of the directory in which the plugin code and tests exist
13+
* @param modName
14+
* The name of the published artifact. If blank, the `dirName` will be used
15+
* @return
16+
* The configured sbt project that is ready to build an sbt plugin
17+
*/
18+
def apply(dirName: String, modName: String = ""): Project = {
19+
Project
20+
.apply(dirName, file(dirName))
21+
.enablePlugins(OssumIncPlugin)
22+
.configure(helpers.Plugin.configure)
23+
.settings(
24+
name := dirName,
25+
moduleName := { if (modName.isEmpty) dirName else modName }
26+
)
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.ossuminc.sbt
2+
3+
import com.typesafe.sbt.packager.archetypes.JavaAppPackaging
4+
import com.typesafe.sbt.packager.graalvmnativeimage.GraalVMNativeImagePlugin
5+
import com.typesafe.sbt.packager.universal.UniversalDeployPlugin
6+
import sbt.Keys.{moduleName, name}
7+
import sbt.{Project, file}
8+
9+
object Program {
10+
11+
/** Define a sub-project that produces an executable program. It is necessary to also have used the [[Root]]
12+
* function because what that function sets up is necessary for publishing this module.
13+
* @param dirName
14+
* The name of the directory in which the plugin code and tests exist
15+
* @param appName
16+
* The name of the published artifact. If blank, the `dirName` will be used
17+
* @return
18+
* The configured sbt project that is ready to build an sbt plugin
19+
*/
20+
def apply(dirName: String, appName: String): Project = {
21+
Project
22+
.apply(dirName, file(dirName))
23+
.enablePlugins(OssumIncPlugin, JavaAppPackaging, UniversalDeployPlugin, GraalVMNativeImagePlugin)
24+
.settings(
25+
name := dirName,
26+
moduleName := { if (appName.isEmpty) dirName else appName }
27+
)
28+
}
29+
}

0 commit comments

Comments
 (0)