Skip to content

Commit

Permalink
Merge pull request #127 from danicheg/issue-#55
Browse files Browse the repository at this point in the history
Add `cross-target` compiler plugin option
  • Loading branch information
danicheg authored Jul 7, 2024
2 parents 9e79ca5 + 7f64e8f commit 7c27b7d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 35 deletions.
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`. |
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

0 comments on commit 7c27b7d

Please sign in to comment.