diff --git a/main/Defaults.scala b/main/Defaults.scala index 9664a4c48..ddddead42 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -55,7 +55,6 @@ object Defaults javaOptions :== Nil, sbtPlugin :== false, crossPaths :== true, - generatedResources :== Nil, classpathTypes := Set("jar", "bundle"), aggregate :== Aggregation.Enabled, maxErrors :== 100, @@ -85,28 +84,41 @@ object Defaults historyPath <<= target(t => Some(t / ".history")), sourceDirectory <<= baseDirectory / "src", sourceFilter in GlobalScope :== ("*.java" | "*.scala"), - sourceManaged <<= baseDirectory / "src_managed", + sourceManaged <<= crossTarget / "src_managed", cacheDirectory <<= target / "cache" ) - lazy val configPaths = Seq( + lazy val configPaths = sourceConfigPaths ++ resourceConfigPaths ++ outputConfigPaths + lazy val sourceConfigPaths = Seq( sourceDirectory <<= configSrcSub( sourceDirectory in Scope(This,Global,This,This) ), sourceManaged <<= configSrcSub(sourceManaged), - cacheDirectory <<= (cacheDirectory, configuration) { _ / _.name }, - classDirectory <<= (crossTarget, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "classes") }, - docDirectory <<= (crossTarget, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "api") }, - sources <<= (sourceDirectories, sourceFilter, defaultExcludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles }, scalaSource <<= sourceDirectory / "scala", javaSource <<= sourceDirectory / "java", + unmanagedSourceDirectories <<= Seq(scalaSource, javaSource).join, + unmanagedSources <<= collectFiles(unmanagedSourceDirectories, sourceFilter, defaultExcludes), + managedSourceDirectories :== Nil, + managedSources <<= collectFiles(managedSourceDirectories, sourceFilter, defaultExcludes), + sources <<= Classpaths.concat(unmanagedSources, managedSources) + ) + lazy val resourceConfigPaths = Seq( resourceDirectory <<= sourceDirectory / "resources", - generatedResourceDirectory <<= crossTarget / "res_managed", - sourceDirectories <<= Seq(scalaSource, javaSource).join, - resourceDirectories <<= Seq(resourceDirectory, generatedResourceDirectory).join, - resources <<= (resourceDirectories, defaultExcludes, generatedResources, generatedResourceDirectory) map resourcesTask, - generatedResources <<= (definedSbtPlugins, generatedResourceDirectory) map writePluginsDescriptor + resourceManaged <<= sourceManaged / "res_managed", + unmanagedResourceDirectories <<= Seq(resourceDirectory).join, + managedResourceDirectories <<= Seq(resourceManaged).join, + resourceDirectories <<= Classpaths.concatSettings(unmanagedResourceDirectories, managedResourceDirectories), + unmanagedResources <<= (unmanagedResourceDirectories, defaultExcludes) map unmanagedResourcesTask, + managedResources <<= (definedSbtPlugins, resourceManaged) map writePluginsDescriptor, + resources <<= Classpaths.concat(managedResources, unmanagedResources) + ) + lazy val outputConfigPaths = Seq( + cacheDirectory <<= (cacheDirectory, configuration) { _ / _.name }, + classDirectory <<= (crossTarget, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "classes") }, + docDirectory <<= (crossTarget, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "api") } ) def addBaseSources = Seq( - sources <<= (sources, baseDirectory, sourceFilter, defaultExcludes) map { (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles } + unmanagedSources <<= (unmanagedSources, baseDirectory, sourceFilter, defaultExcludes) map { + (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles + } ) def compileBase = Seq( @@ -142,7 +154,7 @@ object Defaults ) lazy val projectTasks: Seq[Setting[_]] = Seq( - cleanFiles <<= Seq(managedDirectory, target, sourceManaged).join, + cleanFiles <<= Seq(managedDirectory, target).join, cleanKeepFiles <<= historyPath(_.toList), clean <<= (cleanFiles, cleanKeepFiles) map doClean, consoleProject <<= consoleProjectTask, @@ -162,14 +174,19 @@ object Defaults (state, thisProjectRef) flatMap { (s, base) => inAllDependencies(base, watchSources.task, Project structure s).join.map(_.flatten) } - def watchSourcesTask: Initialize[Task[Seq[File]]] = Seq(sources, resources).map(inAllConfigurations).join { _.join.map(_.flatten.flatten) } + def watchSourcesTask: Initialize[Task[Seq[File]]] = + Seq(unmanagedSources, unmanagedResources).map(inAllConfigurations).join { _.join.map(_.flatten.flatten.distinct) } def watchSetting: Initialize[Watched] = (pollInterval, thisProjectRef) { (interval, base) => new Watched { val scoped = watchTransitiveSources in base val key = ScopedKey(scoped.scope, scoped.key) override def pollInterval = interval - override def watchPaths(s: State) = EvaluateTask.evaluateTask(Project structure s, key, s, base) match { case Some(Value(ps)) => ps; case _ => Nil } + override def watchPaths(s: State) = EvaluateTask.evaluateTask(Project structure s, key, s, base) match { + case Some(Value(ps)) => ps + case Some(Inc(i)) => throw i + case None => error("key not found: " + Project.display(key)) + } } } def scalaInstanceSetting = (appConfiguration, scalaVersion, scalaHome){ (app, version, home) => @@ -179,7 +196,8 @@ object Defaults case Some(h) => ScalaInstance(h, launcher) } } - def resourcesTask(dirs: Seq[File], excl: FileFilter, gen: Seq[File], genDir: File) = gen ++ (dirs --- genDir).descendentsExcept("*",excl).getFiles + def unmanagedResourcesTask(dirs: Seq[File], excl: FileFilter) = + dirs.descendentsExcept("*",excl).getFiles lazy val testTasks = testTaskOptions(test) ++ testTaskOptions(testOnly) ++ Seq( testLoader <<= (fullClasspath, scalaInstance) map { (cp, si) => TestFramework.createTestLoader(data(cp), si) }, @@ -238,19 +256,22 @@ object Defaults def packageBinTask = classMappings def packageDocTask = doc map allSubpaths - def packageSrcTask = concat(resourceMappings, sourceMappings) + def packageSrcTask = concatMappings(resourceMappings, sourceMappings) private type Mappings = Initialize[Task[Seq[(File, String)]]] - def concat(as: Mappings, bs: Mappings) = (as zipWith bs)( (a,b) => (a :^: b :^: KNil) map { case a :+: b :+: HNil => a ++ b } ) + def concatMappings(as: Mappings, bs: Mappings) = (as zipWith bs)( (a,b) => (a :^: b :^: KNil) map { case a :+: b :+: HNil => a ++ b } ) def classMappings = (compileInputs, products) map { (in, _) => allSubpaths(in.config.classesDirectory) } // drop base directories, since there are no valid mappings for these - def sourceMappings = (sources, sourceDirectories, baseDirectory) map { (srcs, sdirs, base) => + def sourceMappings = (unmanagedSources, unmanagedSourceDirectories, baseDirectory) map { (srcs, sdirs, base) => ( (srcs --- sdirs --- base) x (relativeTo(sdirs)|relativeTo(base)|flat)) toSeq } - def resourceMappings = (resources, resourceDirectories) map { (rs, rdirs) => + def resourceMappings = (unmanagedResources, unmanagedResourceDirectories) map { (rs, rdirs) => (rs --- rdirs) x (relativeTo(rdirs)|flat) toSeq } + def collectFiles(dirs: ScopedTaskable[Seq[File]], filter: ScopedTaskable[FileFilter], excludes: ScopedTaskable[FileFilter]): Initialize[Task[Seq[File]]] = + (dirs, filter, excludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles } + def artifactPathSetting(art: ScopedSetting[Artifact]) = (crossTarget, projectID, art, scalaVersion, artifactName) { (t, module, a, sv, toString) => t / toString(sv, module, a) asFile } def pairID[A,B] = (a: A, b: B) => (a,b) @@ -443,6 +464,7 @@ object Classpaths import Attributed.{blank, blankSeq} def concat[T](a: ScopedTaskable[Seq[T]], b: ScopedTaskable[Seq[T]]): Initialize[Task[Seq[T]]] = (a,b) map (_ ++ _) + def concatSettings[T](a: ScopedSetting[Seq[T]], b: ScopedSetting[Seq[T]]): Initialize[Seq[T]] = (a,b)(_ ++ _) lazy val configSettings: Seq[Setting[_]] = Seq( externalDependencyClasspath <<= concat(unmanagedClasspath, managedClasspath), diff --git a/main/Keys.scala b/main/Keys.scala index 697f3e60e..6c31c3ec3 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -54,19 +54,37 @@ object Keys val baseDirectory = SettingKey[File]("base-directory", "The base directory. Depending on the scope, this is the base directory for the build, project, configuration, or task.") val target = SettingKey[File]("target", "Main directory for files generated by the build.") val crossTarget = SettingKey[File]("cross-target", "Main directory for files generated by the build that are cross-built.") + + // Source paths val sourceDirectory = SettingKey[File]("source-directory", "Default directory containing sources.") - val sourceManaged = SettingKey[File]("source-managed", "Default directory for generated sources.") + val sourceManaged = SettingKey[File]("source-managed", "Default directory for sources generated by the build.") val scalaSource = SettingKey[File]("scala-source", "Default Scala source directory.") val javaSource = SettingKey[File]("java-source", "Default Java source directory.") - val resourceDirectory = SettingKey[File]("resource-directory", "Default resource directory.") - val sourceDirectories = SettingKey[Seq[File]]("source-directories", "List of source directories.") - val resourceDirectories = SettingKey[Seq[File]]("resource-directories", "List of resource directories.") + val sourceDirectories = SettingKey[Seq[File]]("source-directories", "List of all source directories, both managed and unmanaged.") + val unmanagedSourceDirectories = SettingKey[Seq[File]]("unmanaged-source-directories", "Unmanaged source directories, which contain manually created sources.") + val unmanagedSources = TaskKey[Seq[File]]("unmanaged-sources", "Unmanaged sources, which are manually created.") + val managedSourceDirectories = SettingKey[Seq[File]]("managed-source-directories", "Managed source directories, which contain sources generated by the build.") + val managedSources = TaskKey[Seq[File]]("managed-sources", "Sources generated by the build.") + val sources = TaskKey[Seq[File]]("sources", "All sources, both managed and unmanaged.") + + // Filters + val sourceFilter = SettingKey[FileFilter]("source-filter", "Filter for selecting sources from default directories.") + val defaultExcludes = SettingKey[FileFilter]("default-excludes", "Filter for excluding files, such as sources and resources, by default.") + + // Resource paths + val resourceDirectory = SettingKey[File]("resource-directory", "Default unmanaged resource directory, used for user-defined resources.") + val resourceManaged = SettingKey[File]("resource-managed", "Default managed resource directory, used when generating resources.") + val unmanagedResourceDirectories = SettingKey[Seq[File]]("unmanaged-resource-directories", "Unmanaged resource directories, containing resources manually created by the user.") + val unmanagedResources = TaskKey[Seq[File]]("unmanaged-resources", "Unmanaged resources, which are manually created.") + val managedResourceDirectories = SettingKey[Seq[File]]("managed-resource-directories", "List of managed resource directories.") + val managedResources = TaskKey[Seq[File]]("managed-resources", "Resources generated by the build.") + val resourceDirectories = SettingKey[Seq[File]]("resource-directories", "List of all resource directories, both managed and unmanaged.") + val resources = TaskKey[Seq[File]]("resources", "All resource files, both managed and unmanaged.") + + // Output paths val classDirectory = SettingKey[File]("class-directory", "Directory for compiled classes and copied resources.") val docDirectory = SettingKey[File]("doc-directory", "Directory for generated documentation.") val cacheDirectory = SettingKey[File]("cache-directory", "Directory used for caching task data.") - val sourceFilter = SettingKey[FileFilter]("source-filter", "Filter for selecting sources from default directories.") - val defaultExcludes = SettingKey[FileFilter]("default-excludes", "Filter for excluding files, such as sources and resources, by default.") - val sources = TaskKey[Seq[File]]("sources", "Defines sources, such as for compilation.") val cleanFiles = SettingKey[Seq[File]]("clean-files", "The files to recursively delete during a clean.") val cleanKeepFiles = SettingKey[Seq[File]]("clean-keep-files", "Files to keep during a clean.") val crossPaths = SettingKey[Boolean]("cross-paths", "If true, enables cross paths, which distinguish output directories for cross-building.") @@ -96,11 +114,7 @@ object Keys val compilers = TaskKey[Compiler.Compilers]("compilers", "Defines the Scala and Java compilers to use for compilation.") val doc = TaskKey[File]("doc", "Generates API documentation.") val copyResources = TaskKey[Seq[(File,File)]]("copy-resources", "Copies resources to the output directory.") - val resources = TaskKey[Seq[File]]("resources", "Defines resource files.") val aggregate = SettingKey[Aggregation]("aggregate", "Configures task aggregation.") - val generatedResources = TaskKey[Seq[File]]("generated-resources", "Resources generated by the build.") - val generatedResourceDirectory = SettingKey[File]("generated-resource-directory", "Default target directory used when generating resources.") - // package keys val packageBin = TaskKey[File]("package", "Produces the main artifact, such as a binary jar.")