From 6bdb3338170aa4a6885ccc334a01d8ba6ef5c5e7 Mon Sep 17 00:00:00 2001 From: danicheg Date: Sat, 6 Jul 2024 18:08:24 +0400 Subject: [PATCH 1/3] Add cross-target compiler plugin option --- .../scala/ch/epfl/scala/PluginConfig.scala | 1 + .../scala/ch/epfl/scala/ProfilingPlugin.scala | 58 +++++++++++-------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/plugin/src/main/scala/ch/epfl/scala/PluginConfig.scala b/plugin/src/main/scala/ch/epfl/scala/PluginConfig.scala index cc0d824..d17511a 100644 --- a/plugin/src/main/scala/ch/epfl/scala/PluginConfig.scala +++ b/plugin/src/main/scala/ch/epfl/scala/PluginConfig.scala @@ -6,6 +6,7 @@ final case class PluginConfig( showProfiles: Boolean, generateDb: Boolean, sourceRoot: AbsolutePath, + crossTarget: AbsolutePath, printSearchIds: Set[Int], generateMacroFlamegraph: Boolean, generateGlobalFlamegraph: Boolean, diff --git a/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala b/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala index e2ef32d..5221550 100644 --- a/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala +++ b/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala @@ -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" @@ -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 { @@ -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) @@ -111,20 +134,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) From 18dc0fc6285fdf15c6db2aaa4daa3e88589fac29 Mon Sep 17 00:00:00 2001 From: danicheg Date: Sat, 6 Jul 2024 18:13:27 +0400 Subject: [PATCH 2/3] Add a new option to the optionsHelp --- plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala b/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala index 5221550..17ef20f 100644 --- a/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala +++ b/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala @@ -100,7 +100,7 @@ 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. @@ -108,7 +108,8 @@ class ProfilingPlugin(val global: Global) extends Plugin { self => |-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) From 7f64e8fdb53b9d487857a376796f7ae40abdf0af Mon Sep 17 00:00:00 2001 From: danicheg Date: Sat, 6 Jul 2024 18:35:24 +0400 Subject: [PATCH 3/3] Enhance docs --- docs/user-guide/installation.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/user-guide/installation.md b/docs/user-guide/installation.md index e15d22b..88726a7 100644 --- a/docs/user-guide/installation.md +++ b/docs/user-guide/installation.md @@ -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`. |