Skip to content

Commit

Permalink
Merge branch 'main' into macro-time
Browse files Browse the repository at this point in the history
  • Loading branch information
danicheg committed Jul 13, 2024
2 parents 5af7f4b + b98d08e commit 662bba6
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 54 deletions.
53 changes: 49 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ on:

jobs:
scalafmt:
name: Formatting
name: Check formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java (temurin@8)
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
cache: sbt
- uses: coursier/cache-action@v6
- name: Check formatting
run: sbt -v "scalafmtSbtCheck" "scalafmtCheckAll"
Expand All @@ -20,27 +26,66 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java (temurin@8)
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
cache: sbt
- uses: coursier/cache-action@v6
- run: sbt docs/run
plugin-tests:
name: Compiler and SBT plugin tests
runs-on: ubuntu-latest
strategy:
matrix:
os: [ ubuntu-latest ]
scala:
- 2.12.13
- 2.12.14
- 2.12.15
- 2.12.16
- 2.12.17
- 2.12.18
- 2.12.19
- 2.13.5
- 2.13.6
- 2.13.7
- 2.13.8
- 2.13.9
- 2.13.10
- 2.13.11
- 2.13.12
- 2.13.13
- 2.13.14
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup Java (temurin@8)
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
cache: sbt
- uses: coursier/cache-action@v6
- name: Compiler plugin tests
run: sbt -v "+plugin/test"
run: sbt -v '++ ${{ matrix.scala }}' plugin/test
- name: SBT plugin tests
run: sbt -v "profilingSbtPlugin/scripted"
run: sbt -v '++ ${{ matrix.scala }}' profilingSbtPlugin/scripted
intergration-tests:
name: Integration tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup Java (temurin@8)
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
cache: sbt
- uses: coursier/cache-action@v6
- name: Running tests
run: sbt -v "showScalaInstances" "integrations/testOnly integration better-files wartremover"
2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "3.8.0"
version = "3.8.2"
runner.dialect = Scala213
maxColumn = 100
docstrings.style = Asterisk
Expand Down
22 changes: 17 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,20 @@ lazy val root = project
(integrations / watchSources).value
)

val bin212 = Seq("2.12.18", "2.12.17", "2.12.16", "2.12.15", "2.12.14", "2.12.13")
val bin213 = Seq("2.13.12", "2.13.11", "2.13.10", "2.13.9", "2.13.8", "2.13.7", "2.13.6", "2.13.5")
val bin212 = Seq("2.12.19", "2.12.18", "2.12.17", "2.12.16", "2.12.15", "2.12.14", "2.12.13")
val bin213 =
Seq(
"2.13.14",
"2.13.13",
"2.13.12",
"2.13.11",
"2.13.10",
"2.13.9",
"2.13.8",
"2.13.7",
"2.13.6",
"2.13.5"
)

// Copied from
// https://github.com/scalameta/scalameta/blob/370e304b0d10db1dd65fc79a5abc1f39004aeffd/build.sbt#L724-L737
Expand All @@ -36,7 +48,7 @@ lazy val fullCrossVersionSettings = Seq(
// NOTE: SBT 1.x provides cross-version support for Scala sources
// (https://www.scala-sbt.org/1.x/docs/Cross-Build.html#Scala-version+specific+source+directory).
// Unfortunately, it only includes directories like "scala_2.12" or "scala_2.13",
// not "scala_2.12.18" or "scala_2.13.12" that we need.
// not "scala_2.12.19" or "scala_2.13.14" that we need.
// That's why we have to work around here.
val base = (Compile / sourceDirectory).value
val versionDir = scalaVersion.value.replaceAll("-.*", "")
Expand All @@ -57,7 +69,7 @@ lazy val profiledb = project
libraryDependencies +=
"com.thesamet.scalapb" %% "scalapb-runtime" % scalapbVersion % "protobuf",
Compile / managedSourceDirectories += target.value / "protobuf-generated",
Compile / PB.targets in Compile := Seq(
Compile / PB.targets := Seq(
scalapb.gen() -> (target.value / "protobuf-generated")
),
buildInfoPackage := "scalac.profiling.internal.build",
Expand All @@ -77,7 +89,7 @@ lazy val plugin = project
fullCrossVersionSettings,
name := "scalac-profiling",
libraryDependencies ++= List(
"com.lihaoyi" %% "pprint" % "0.8.1",
"com.lihaoyi" %% "pprint" % "0.9.0",
scalaOrganization.value % "scala-compiler" % scalaVersion.value
),
libraryDependencies ++= List(
Expand Down
21 changes: 11 additions & 10 deletions docs/user-guide/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ lazy val myproject = project
There are several compiler plugin options to enable to enrichment of analysis capabilities.
All the following options are prepended by the `-P:scalac-profiling:`.

| Name | Description |
|:-----------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `generate-global-flamegraph` | Creates a global flamegraph of implicit searches for all compilation units. Use the `-P:scalac-profiling:sourceroot` option to manage the root directory, otherwise, a working directory (defined by the `user.dir` property) will be picked. |
| `generate-macro-flamegraph` | Generate a flamegraph for macro expansions. The flamegraph for implicit searches is enabled by default. |
| `generate-profiledb` | Generate profiledb. |
| `print-failed-implicit-macro-candidates` | Print trees of all failed implicit searches that triggered a macro expansion. |
| `print-search-result` | Print the result retrieved by an implicit search. Example: `-P:scalac-profiling:print-search-result:$MACRO_ID`. |
| `show-concrete-implicit-tparams` | Use more concrete type parameters in the implicit search flamegraph. Note that it may change the shape of the flamegraph. |
| `show-profiles` | Show implicit searches and macro expansions by type and call-site. |
| `sourceroot` | Tell the plugin what is the source directory of the project. Example: `-P:scalac-profiling:sourceroot:$PROJECT_BASE_DIR`. |
| Name | Description |
|:-----------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `generate-global-flamegraph` | Creates a global flamegraph of implicit searches for all compilation units. Use the `-P:scalac-profiling:cross-target` option to manage the target directory for the resulting flamegraph file, otherwise, the SBT target directory will be picked. |
| `generate-macro-flamegraph` | Generate a flamegraph for macro expansions. The flamegraph for implicit searches is enabled by default. |
| `generate-profiledb` | Generate profiledb. |
| `print-failed-implicit-macro-candidates` | Print trees of all failed implicit searches that triggered a macro expansion. |
| `print-search-result` | Print the result retrieved by an implicit search. Example: `-P:scalac-profiling:print-search-result:$MACRO_ID`. |
| `show-concrete-implicit-tparams` | Use more concrete type parameters in the implicit search flamegraph. Note that it may change the shape of the flamegraph. |
| `show-profiles` | Show implicit searches and macro expansions by type and call-site. |
| `sourceroot` | Tell the plugin what is the source directory of the project. Example: `-P:scalac-profiling:sourceroot:$PROJECT_BASE_DIR`. |
| `cross-target` | Tell the plugin what is the cross target directory of the project. Example: `-P:scalac-profiling:cross-target:$PROJECT_TARGET`. |
8 changes: 8 additions & 0 deletions plugin/src/main/scala-2.12.19/tools/SettingsOps.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ch.epfl.scala.profilers.tools

import scala.tools.nsc.Global

object SettingsOps {
def areStatisticsEnabled(g: Global): Boolean =
g.settings.areStatisticsEnabled
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ch.epfl.scala.profilers.tools

import scala.tools.nsc.Global

object SettingsOps {
def areStatisticsEnabled(g: Global): Boolean =
g.settings.areStatisticsEnabled
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ch.epfl.scala.profilers.tools

import scala.tools.nsc.Global

object SettingsOps {
def areStatisticsEnabled(g: Global): Boolean =
g.settings.areStatisticsEnabled
}
1 change: 1 addition & 0 deletions plugin/src/main/scala/ch/epfl/scala/PluginConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ final case class PluginConfig(
showProfiles: Boolean,
generateDb: Boolean,
sourceRoot: AbsolutePath,
crossTarget: AbsolutePath,
printSearchIds: Set[Int],
generateMacroFlamegraph: Boolean,
generateGlobalFlamegraph: Boolean,
Expand Down
63 changes: 38 additions & 25 deletions plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ProfilingPlugin(val global: Global) extends Plugin { self =>

private final lazy val ShowProfiles = "show-profiles"
private final lazy val SourceRoot = "sourceroot"
private final lazy val CrossTarget = "cross-target"
private final lazy val PrintSearchResult = "print-search-result"
private final lazy val GenerateMacroFlamegraph = "generate-macro-flamegraph"
private final lazy val GenerateGlobalFlamegraph = "generate-global-flamegraph"
Expand All @@ -40,6 +41,7 @@ class ProfilingPlugin(val global: Global) extends Plugin { self =>
private final lazy val ShowConcreteImplicitTparams = "show-concrete-implicit-tparams"
private final lazy val PrintSearchRegex = s"$PrintSearchResult:(.*)".r
private final lazy val SourceRootRegex = s"$SourceRoot:(.*)".r
private final lazy val CrossTargetRegex = s"$CrossTarget:(.*)".r

def findOption(name: String, pattern: Regex): Option[String] = {
super.options.find(_.startsWith(name)).flatMap {
Expand All @@ -55,18 +57,39 @@ class ProfilingPlugin(val global: Global) extends Plugin { self =>
}
}

private final lazy val config = PluginConfig(
showProfiles = super.options.contains(ShowProfiles),
generateDb = super.options.contains(GenerateProfileDb),
sourceRoot = findOption(SourceRoot, SourceRootRegex)
private final lazy val config = {
val sourceRoot = findOption(SourceRoot, SourceRootRegex)
.map(AbsolutePath.apply)
.getOrElse(AbsolutePath.workingDirectory),
printSearchIds = findSearchIds(findOption(PrintSearchResult, PrintSearchRegex)),
generateMacroFlamegraph = super.options.contains(GenerateMacroFlamegraph),
generateGlobalFlamegraph = super.options.contains(GenerateGlobalFlamegraph),
printFailedMacroImplicits = super.options.contains(PrintFailedMacroImplicits),
concreteTypeParamsInImplicits = super.options.contains(ShowConcreteImplicitTparams)
)
.getOrElse(AbsolutePath.workingDirectory)
val crossTarget = findOption(CrossTarget, CrossTargetRegex)
.map(AbsolutePath.apply)
.getOrElse {
val scalaDir =
if (ScalaSettingsOps.isScala212)
"scala-2.12"
else if (ScalaSettingsOps.isScala213)
"scala-2.13"
else
sys.error(
s"Currently, only Scala 2.12 and 2.13 are supported, " +
s"but [${global.settings.source.value}] has been spotted"
)

sourceRoot.resolve(RelativePath(s"target/$scalaDir"))
}

PluginConfig(
showProfiles = super.options.contains(ShowProfiles),
generateDb = super.options.contains(GenerateProfileDb),
sourceRoot = sourceRoot,
crossTarget = crossTarget,
printSearchIds = findSearchIds(findOption(PrintSearchResult, PrintSearchRegex)),
generateMacroFlamegraph = super.options.contains(GenerateMacroFlamegraph),
generateGlobalFlamegraph = super.options.contains(GenerateGlobalFlamegraph),
printFailedMacroImplicits = super.options.contains(PrintFailedMacroImplicits),
concreteTypeParamsInImplicits = super.options.contains(ShowConcreteImplicitTparams)
)
}

private lazy val logger = new Logger(global)

Expand All @@ -77,15 +100,16 @@ class ProfilingPlugin(val global: Global) extends Plugin { self =>
// format: off
override val optionsHelp: Option[String] = Some(
s"""
|-P:$name:${pad20(GenerateGlobalFlamegraph)} Creates a global flamegraph of implicit searches for all compilation units. Use the `-P:$name:$SourceRoot` option to manage the root directory, otherwise, a working directory (defined by the `user.dir` property) will be picked.
|-P:$name:${pad20(GenerateGlobalFlamegraph)} Creates a global flamegraph of implicit searches for all compilation units. Use the `-P:$name:$CrossTarget` option to manage the target directory for the resulting flamegraph file, otherwise, the SBT target directory will be picked.
|-P:$name:${pad20(GenerateMacroFlamegraph)} Generates a flamegraph for macro expansions. The flamegraph for implicit searches is enabled by default.
|-P:$name:${pad20(GenerateProfileDb)} Generates profiledb (will be removed later).
|-P:$name:${pad20(PrintFailedMacroImplicits)} Prints trees of all failed implicit searches that triggered a macro expansion.
|-P:$name:${pad20(PrintSearchResult)}:_ Print implicit search result trees for a list of search ids separated by a comma.
|-P:$name:${pad20(ShowConcreteImplicitTparams)} Shows types in flamegraphs of implicits with concrete type params.
|-P:$name:${pad20(ShowProfiles)} Logs profile information for every call-site.
|-P:$name:${pad20(SourceRoot)}:_ Sets the source root for this project.
""".stripMargin
|-P:$name:${pad20(CrossTarget)}:_ Sets the cross target for this project.
""".stripMargin
) // format: on

lazy val implementation = new ProfilingImpl(ProfilingPlugin.this.global, config, logger)
Expand All @@ -111,20 +135,9 @@ class ProfilingPlugin(val global: Global) extends Plugin { self =>
private def reportStatistics(graphsPath: AbsolutePath): Unit = {
val globalDir =
if (config.generateGlobalFlamegraph) {
val scalaDir =
if (ScalaSettingsOps.isScala212)
"scala-2.12"
else if (ScalaSettingsOps.isScala213)
"scala-2.13"
else
sys.error(
s"Currently, only Scala 2.12 and 2.13 are supported, " +
s"but [${global.settings.source.value}] has been spotted"
)

val globalDir =
ProfileDbPath.toGraphsProfilePath(
config.sourceRoot.resolve(RelativePath(s"target/$scalaDir/classes"))
config.crossTarget.resolve(RelativePath("classes"))
)

Some(globalDir)
Expand Down
6 changes: 3 additions & 3 deletions project/BuildPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ object BuildKeys {
val targetDir = (Compile / Keys.target).value
val compiledClassesDir = targetDir / s"scala-$scalaBinVersion/classes"
val testClassesDir = targetDir / s"scala-$scalaBinVersion/test-classes"
val libraryJar = Keys.scalaInstance.value.libraryJar.getAbsolutePath
val libraryJar = Keys.scalaInstance.value.libraryJars.head.getAbsolutePath
val deps = (Compile / Keys.libraryDependencies).value.mkString(":")
val classpath = s"$compiledClassesDir:$testClassesDir:$libraryJar:$deps"
val resourceDir = (Compile / Keys.resourceManaged).value
Expand Down Expand Up @@ -109,7 +109,7 @@ object BuildKeys {
////////////////////////////////////////////////////////////////////////////////

def inProject(ref: Reference)(ss: Seq[Setting[_]]): Seq[Setting[_]] =
sbt.inScope(sbt.ThisScope.in(project = ref))(ss)
sbt.inScope(sbt.ThisScope.copy(project = Select(ref)))(ss)

def inProjectRefs(refs: Seq[Reference])(ss: Setting[_]*): Seq[Setting[_]] =
refs.flatMap(inProject(_)(ss))
Expand Down Expand Up @@ -258,7 +258,7 @@ object BuildImplementation {
Keys.organization := "ch.epfl.scala",
Keys.resolvers += Resolver.jcenterRepo,
Keys.updateOptions := Keys.updateOptions.value.withCachedResolution(true),
Keys.scalaVersion := "2.12.18",
Keys.scalaVersion := "2.12.19",
sbt.nio.Keys.watchTriggeredMessage := Watch.clearScreenOnTrigger,
BuildKeys.enableStatistics := true,
BuildKeys.showScalaInstances := BuildDefaults.showScalaInstances.value
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.9.8
sbt.version=1.9.9
Loading

0 comments on commit 662bba6

Please sign in to comment.