diff --git a/plugin/src/main/scala/com/github/sbt/avro/SbtAvro.scala b/plugin/src/main/scala/com/github/sbt/avro/SbtAvro.scala index c2d960a..abb7d97 100644 --- a/plugin/src/main/scala/com/github/sbt/avro/SbtAvro.scala +++ b/plugin/src/main/scala/com/github/sbt/avro/SbtAvro.scala @@ -98,7 +98,10 @@ object SbtAvro extends AutoPlugin { // source generation avroGenerate / target := configSrcSub(avroGenerate / target).value, managedSourceDirectories += (avroGenerate / target).value, - avroGenerate := sourceGeneratorTask(avroGenerate).dependsOn(avroUnpackDependencies).value, + avroGenerate := sourceGeneratorTask(avroGenerate) + .dependsOn(avroUnpackDependencies) + .dependsOn(avroUnpackDependencies.?.all(filterDependsOn)) + .value, sourceGenerators += avroGenerate.taskValue, compile := compile.dependsOn(avroGenerate).value, // packaging @@ -126,6 +129,13 @@ object SbtAvro extends AutoPlugin { inConfig(Avro)(Defaults.configSettings) ++ Seq(Compile, Test).flatMap(c => inConfig(c)(configScopedSettings)) + // This filter is meant evaluate for all dependant submodules + // eg. source files / unpack dependencies + private val filterDependsOn = ScopeFilter( + inDependencies(ThisProject, transitive = false), + inConfigurations(Compile) + ) + private def unpack( cacheBaseDirectory: File, deps: Seq[File], @@ -196,7 +206,11 @@ object SbtAvro extends AutoPlugin { private def sourceGeneratorTask(key: TaskKey[Seq[File]]) = Def.task { val out = (key / streams).value val externalSrcDir = (avroUnpackDependencies / target).value - val srcDirs = avroUnmanagedSourceDirectories.value :+ externalSrcDir + val unmanagedSrcDirs = avroUnmanagedSourceDirectories.value + val dependsOnDirs = (avroUnpackDependencies / target).?.all(filterDependsOn).value.flatten ++ + avroUnmanagedSourceDirectories.?.all(filterDependsOn).value.flatten.flatten + val srcDirs = Seq(externalSrcDir) ++ unmanagedSrcDirs ++ dependsOnDirs + val outDir = (key / target).value implicit val conv: xsbti.FileConverter = fileConverter.value // used by PluginCompat diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/build.sbt b/plugin/src/sbt-test/sbt-avro/local-dependency/build.sbt new file mode 100644 index 0000000..d05e3c5 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/build.sbt @@ -0,0 +1,76 @@ +val checkUnpacked = TaskKey[Unit]("checkUnpacked") +val checkGenerated = TaskKey[Unit]("checkGenerated") + +def exists(f: File): Unit = assert(f.exists(), s"$f does not exist") +def absent(f: File): Unit = assert(!f.exists(), s"$f does exists") + +lazy val commonSettings = Seq( + organization := "com.github.sbt", + scalaVersion := "2.13.15" +) + +lazy val avroOnlySettings = Seq( + crossScalaVersions := Seq.empty, + crossPaths := false, + autoScalaLibrary := false, + // only create avro jar + Compile / packageAvro / publishArtifact := true, + Compile / packageBin / publishArtifact := false, + Compile / packageSrc / publishArtifact := false, + Compile / packageDoc / publishArtifact := false, +) + +lazy val `external`: Project = project + .in(file("external")) + .enablePlugins(SbtAvro) + .settings(commonSettings) + .settings(avroOnlySettings) + .settings( + name := "external", + version := "0.0.1-SNAPSHOT", + ) + +lazy val `transitive`: Project = project + .in(file("transitive")) + .enablePlugins(SbtAvro) + .settings(commonSettings) + .settings(avroOnlySettings) + .settings( + name := "transitive", + version := "0.0.1-SNAPSHOT", + libraryDependencies ++= Seq( + // when using avro scope, it won't be part of the pom dependencies -> intransitive + // to declare transitive dependency use the compile scope + "com.github.sbt" % "external" % "0.0.1-SNAPSHOT" classifier "avro" + ), + Compile / avroDependencyIncludeFilter := artifactFilter(classifier = "avro"), + // create a test jar with a schema as resource + Test / packageBin / publishArtifact := true, + ) + +lazy val root: Project = project + .in(file(".")) + .enablePlugins(SbtAvro) + .dependsOn(`transitive` % "avro->avro") + .settings(commonSettings) + .settings( + name := "local-dependency", + crossScalaVersions := Seq("2.13.15", "2.12.20"), + libraryDependencies ++= Seq( + "org.specs2" %% "specs2-core" % "4.20.9" % Test + ), + // add additional avro source test jar + Test / avroDependencyIncludeFilter := artifactFilter(name = "transitive", classifier = "tests"), + + Compile / checkUnpacked := { + exists((`transitive` / crossTarget).value / "src_managed" / "avro" / "main" / "external-avro" / "avdl.avdl") + exists((`transitive` / crossTarget).value / "src_managed" / "avro" / "main" / "external-avro" / "avpr.avpr") + exists((`transitive` / crossTarget).value / "src_managed" / "avro" / "main" / "external-avro" / "avsc.avsc") + }, + Compile / checkGenerated := { + exists(crossTarget.value / "src_managed" / "compiled_avro" / "main" / "com" / "github" / "sbt" / "avro" / "test" / "external" / "Avdl.java") + exists(crossTarget.value / "src_managed" / "compiled_avro" / "main" / "com" / "github" / "sbt" / "avro" / "test" / "external" / "Avpr.java") + exists(crossTarget.value / "src_managed" / "compiled_avro" / "main" / "com" / "github" / "sbt" / "avro" / "test" / "external" / "Avsc.java") + exists(crossTarget.value / "src_managed" / "compiled_avro" / "main" / "com" / "github" / "sbt" / "avro" / "test" / "transitive" / "Avsc.java") + } + ) diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avdl.avdl b/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avdl.avdl new file mode 100644 index 0000000..a6b8de7 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avdl.avdl @@ -0,0 +1,6 @@ +@namespace("com.github.sbt.avro.test.external") +protocol ProtocolAvdl { + record Avdl { + string stringField; + } +} diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avpr.avpr b/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avpr.avpr new file mode 100644 index 0000000..2d08ca9 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avpr.avpr @@ -0,0 +1,16 @@ +{ + "namespace": "com.github.sbt.avro.test.external", + "protocol": "ProtocolAvpr", + "types": [ + { + "name": "Avpr", + "type": "record", + "fields": [ + { + "name": "stringField", + "type": "string" + } + ] + } + ] +} diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avsc.avsc b/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avsc.avsc new file mode 100644 index 0000000..ba309c7 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/external/src/main/avro/avsc.avsc @@ -0,0 +1,11 @@ +{ + "name": "Avsc", + "namespace": "com.github.sbt.avro.test.external", + "type": "record", + "fields": [ + { + "name": "stringField", + "type": "string" + } + ] +} diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/project/plugins.sbt b/plugin/src/sbt-test/sbt-avro/local-dependency/project/plugins.sbt new file mode 100644 index 0000000..c52f4d5 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/project/plugins.sbt @@ -0,0 +1,5 @@ +sys.props.get("plugin.version") match { + case Some(x) => addSbtPlugin("com.github.sbt" % "sbt-avro" % x) + case _ => sys.error("""|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) +} diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/src/main/scala/com/github/sbt/avro/test/Main.scala b/plugin/src/sbt-test/sbt-avro/local-dependency/src/main/scala/com/github/sbt/avro/test/Main.scala new file mode 100644 index 0000000..52bd9cb --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/src/main/scala/com/github/sbt/avro/test/Main.scala @@ -0,0 +1,11 @@ +package com.github.sbt.avro.test + +object Main extends App { + + external.Avsc.newBuilder().setStringField("external").build() + external.Avpr.newBuilder().setStringField("external").build() + external.Avdl.newBuilder().setStringField("external").build() + transitive.Avsc.newBuilder().setStringField("transitive").build() + + println("success") +} \ No newline at end of file diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/src/test/scala/com/github/sbt/avro/test/AvroTest.scala b/plugin/src/sbt-test/sbt-avro/local-dependency/src/test/scala/com/github/sbt/avro/test/AvroTest.scala new file mode 100644 index 0000000..c22c138 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/src/test/scala/com/github/sbt/avro/test/AvroTest.scala @@ -0,0 +1,10 @@ +package com.github.sbt.avro.test + +import com.github.sbt.avro.test.transitive.Test + +object AvroTest extends App { + + Test.newBuilder().setStringField("external").build() + + println("success") +} \ No newline at end of file diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/test b/plugin/src/sbt-test/sbt-avro/local-dependency/test new file mode 100644 index 0000000..c31a267 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/test @@ -0,0 +1,7 @@ +> external/publishLocal + +> avroGenerate +> checkUnpacked +> checkGenerated + +> +compile diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/transitive/src/main/avro/com/github/sbt/avro/test/transitive/avsc.avsc b/plugin/src/sbt-test/sbt-avro/local-dependency/transitive/src/main/avro/com/github/sbt/avro/test/transitive/avsc.avsc new file mode 100644 index 0000000..d4d504e --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/transitive/src/main/avro/com/github/sbt/avro/test/transitive/avsc.avsc @@ -0,0 +1,15 @@ +{ + "name": "Avsc", + "namespace": "com.github.sbt.avro.test.transitive", + "type": "record", + "fields": [ + { + "name": "stringField", + "type": "string" + }, + { + "name": "referencedTypeField", + "type": "com.github.sbt.avro.test.external.Avsc" + } + ] +} \ No newline at end of file diff --git a/plugin/src/sbt-test/sbt-avro/local-dependency/transitive/src/test/resources/test.avsc b/plugin/src/sbt-test/sbt-avro/local-dependency/transitive/src/test/resources/test.avsc new file mode 100644 index 0000000..1a87638 --- /dev/null +++ b/plugin/src/sbt-test/sbt-avro/local-dependency/transitive/src/test/resources/test.avsc @@ -0,0 +1,15 @@ +{ + "name": "Test", + "namespace": "com.github.sbt.avro.test.transitive", + "type": "record", + "fields": [ + { + "name": "stringField", + "type": "string" + }, + { + "name": "referencedTypeField", + "type": "com.github.sbt.avro.test.external.Avsc" + } + ] +} diff --git a/plugin/src/sbt-test/sbt-avro/publishing/build.sbt b/plugin/src/sbt-test/sbt-avro/publishing/build.sbt index f2f6ed7..f5a788f 100644 --- a/plugin/src/sbt-test/sbt-avro/publishing/build.sbt +++ b/plugin/src/sbt-test/sbt-avro/publishing/build.sbt @@ -43,7 +43,6 @@ lazy val `transitive`: Project = project // to declare transitive dependency use the compile scope "com.github.sbt" % "external" % "0.0.1-SNAPSHOT" classifier "avro" ), - transitiveClassifiers += "avro", Compile / avroDependencyIncludeFilter := artifactFilter(classifier = "avro"), // create a test jar with a schema as resource Test / packageBin / publishArtifact := true, @@ -62,9 +61,7 @@ lazy val root: Project = project "org.specs2" %% "specs2-core" % "4.20.9" % Test ), // add additional avro source test jar - // we unfortunatelly must recompile schemas from compile scope when test schema depends on it. - Test / avroDependencyIncludeFilter := (Compile / avroDependencyIncludeFilter).value || - artifactFilter(name = "transitive", classifier = "tests"), + Test / avroDependencyIncludeFilter := artifactFilter(name = "transitive", classifier = "tests"), // exclude specific avsc file Compile / avroUnpackDependencies / excludeFilter := (Compile / avroUnpackDependencies / excludeFilter).value || "exclude.avsc",