build scripts: support dynamic generation of resource files for plugins

This way we can have statically defined PluginLayout even if some resources for the plugin are need to be generated during build, and it allows us to reuse PluginLayout for such plugins in different IDEs.
This commit is contained in:
nik
2017-05-16 08:55:31 +03:00
parent fac9e45379
commit 2d0229936a
4 changed files with 68 additions and 3 deletions
@@ -0,0 +1,31 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.intellij.build
import groovy.transform.CompileStatic
/**
* @see org.jetbrains.intellij.build.impl.PluginLayout.PluginLayoutSpec#withGeneratedResources
* @author nik
*/
@CompileStatic
interface ResourcesGenerator {
/**
* Generate files which need to be included into the product distribution somewhere under {@code context.paths.temp} directory.
* @return path to the generated file or directory or {@code null} if nothing was generated
*/
File generateResources(BuildContext context)
}
@@ -16,6 +16,9 @@
package org.jetbrains.intellij.build.impl
import com.intellij.openapi.util.MultiValuesMap
import com.intellij.openapi.util.Pair
import org.jetbrains.intellij.build.ResourcesGenerator
/**
* Describes layout of a plugin or the platform JARs in the product distribution
*
@@ -33,6 +36,7 @@ abstract class BaseLayout {
final MultiValuesMap<String, String> projectLibrariesToUnpack = new MultiValuesMap<>()
protected final Set<String> modulesWithLocalizableResourcesInCommonJar = new LinkedHashSet<>()
final List<String> modulesWithExcludedModuleLibraries = []
final List<Pair<ResourcesGenerator, String>> resourceGenerators = []
boolean packLocalizableResourcesInCommonJar(String moduleName) {
return modulesWithLocalizableResourcesInCommonJar.contains(moduleName)
@@ -16,6 +16,7 @@
package org.jetbrains.intellij.build.impl
import com.intellij.openapi.util.MultiValuesMap
import com.intellij.openapi.util.Pair
import com.intellij.openapi.util.io.FileUtil
import org.apache.tools.ant.types.FileSet
import org.apache.tools.ant.types.resources.FileProvider
@@ -225,7 +226,7 @@ class DistributionJARsBuilder {
layoutBuilder.patchModuleOutput("platform-resources", FileUtil.toSystemIndependentName(patchedKeyMapDir.absolutePath))
}
buildByLayout(layoutBuilder, platform, buildContext.paths.distAll, platform.moduleJars)
buildByLayout(layoutBuilder, platform, buildContext.paths.distAll, platform.moduleJars, [])
if (buildContext.proprietaryBuildTools.scrambleTool != null) {
def forbiddenJarNames = buildContext.proprietaryBuildTools.scrambleTool.namesOfJarsRequiredToBeScrambled
@@ -301,7 +302,11 @@ class DistributionJARsBuilder {
pluginsToInclude.each { plugin ->
def actualModuleJars = plugin.getActualModules(enabledModulesSet)
checkOutputOfPluginModules(plugin.mainModule, actualModuleJars.values(), plugin.moduleExcludes)
buildByLayout(layoutBuilder, plugin, "$targetDirectory/$plugin.directoryName", actualModuleJars)
List<Pair<File, String>> generatedResources = plugin.resourceGenerators.collectMany {
File resourceFile = it.first.generateResources(buildContext)
resourceFile != null ? [Pair.create(resourceFile, it.second)] : []
}
buildByLayout(layoutBuilder, plugin, "$targetDirectory/$plugin.directoryName", actualModuleJars, generatedResources)
}
}
@@ -327,7 +332,12 @@ class DistributionJARsBuilder {
})
}
private void buildByLayout(LayoutBuilder layoutBuilder, BaseLayout layout, String targetDirectory, MultiValuesMap<String, String> moduleJars) {
/**
* @param moduleJars mapping from JAR path relative to 'lib' directory to names of modules
* @param additionalResources pairs of resources files and corresponding relative output paths
*/
private void buildByLayout(LayoutBuilder layoutBuilder, BaseLayout layout, String targetDirectory, MultiValuesMap<String, String> moduleJars,
List<Pair<File, String>> additionalResources) {
def ant = buildContext.ant
def resourceExcluded = RESOURCES_EXCLUDED
def resourcesIncluded = RESOURCES_INCLUDED
@@ -423,6 +433,17 @@ class DistributionJARsBuilder {
}
}
}
additionalResources.each {
File resource = it.first
dir(it.second) {
if (resource.isFile()) {
ant.fileset(file: resource.absolutePath)
}
else {
ant.fileset(dir: resource.absolutePath)
}
}
}
}
}
@@ -16,7 +16,9 @@
package org.jetbrains.intellij.build.impl
import com.intellij.openapi.util.MultiValuesMap
import com.intellij.openapi.util.Pair
import org.jetbrains.intellij.build.BuildContext
import org.jetbrains.intellij.build.ResourcesGenerator
import java.util.function.Function
@@ -126,6 +128,13 @@ class PluginLayout extends BaseLayout {
layout.resourcePaths << new ModuleResourceData(layout.mainModule, resourcePath, relativeOutputFile, true)
}
/**
* Copy output produced by {@code generator} to the directory specified by {@code relativeOutputPath} under the plugin directory.
*/
void withGeneratedResources(ResourcesGenerator generator, String relativeOutputPath) {
layout.resourceGenerators << Pair.create(generator, relativeOutputPath)
}
/**
* Register an optional module which may be excluded from the plugin distribution in some products. These modules are included in plugin
* distribution only if they are added to {@link org.jetbrains.intellij.build.ProductModulesLayout#bundledPluginModules} list.