mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
build scripts redesign: use groovy instead of gant, common code extracted, pass data between tasks explicitly, improved logging, allow to skip some build steps via system property
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# IDEA can copy library .jar files to prevent their locking.
|
||||
# By default this behavior is enabled on Windows and disabled on other platforms.
|
||||
|
||||
@@ -14,21 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.intellij.build
|
||||
|
||||
import groovy.transform.Immutable
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class ApplicationInfoProperties {
|
||||
final String majorVersion
|
||||
final String minorVersion
|
||||
final String shortProductName
|
||||
final String productName
|
||||
final String companyName
|
||||
final boolean isEAP
|
||||
|
||||
@SuppressWarnings("GrUnresolvedAccess")
|
||||
ApplicationInfoProperties(String appInfoXmlPath) {
|
||||
def root = new XmlParser().parse(new File(appInfoXmlPath))
|
||||
majorVersion = root.version.first().@major
|
||||
minorVersion = root.version.first().@minor
|
||||
shortProductName = root.names.first().@product
|
||||
productName = root.names.first().@fullname
|
||||
companyName = root.company.first().@name
|
||||
isEAP = Boolean.parseBoolean(root.version.first().@eap)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 org.codehaus.gant.GantBuilder
|
||||
import org.jetbrains.intellij.build.impl.BuildContextImpl
|
||||
import org.jetbrains.jps.gant.JpsGantProjectBuilder
|
||||
import org.jetbrains.jps.model.JpsGlobal
|
||||
import org.jetbrains.jps.model.JpsProject
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
abstract class BuildContext {
|
||||
GantBuilder ant
|
||||
BuildMessages messages
|
||||
BuildPaths paths
|
||||
JpsProject project
|
||||
ApplicationInfoProperties applicationInfo
|
||||
JpsGantProjectBuilder projectBuilder
|
||||
ProductProperties productProperties
|
||||
BuildOptions options
|
||||
|
||||
/**
|
||||
* Build number without product code (e.g. '162.500.10')
|
||||
*/
|
||||
String buildNumber
|
||||
|
||||
/**
|
||||
* Build number with product code (e.g. 'IC-162.500.10')
|
||||
*/
|
||||
String fullBuildNumber
|
||||
|
||||
/**
|
||||
* An identifier which will be used to form names for directories where configuration and caches will be stored, usually a product name
|
||||
* without spaces with added major version ('IntelliJIdea2016.1' for IntelliJ IDEA 2016.1)
|
||||
*/
|
||||
String systemSelector
|
||||
|
||||
/**
|
||||
* Base name for script files (*.bat, *.sh, *.exe), usually a shortened product name in lower case (e.g. 'idea' for IntelliJ IDEA, 'datagrip' for DataGrip)
|
||||
*/
|
||||
String fileNamePrefix
|
||||
|
||||
/**
|
||||
* Names of JARs inside IDE_HOME/lib directory which need to be added to bootclasspath to start the IDE
|
||||
*/
|
||||
List<String> bootClassPathJarNames
|
||||
|
||||
abstract void notifyArtifactBuilt(String artifactPath)
|
||||
|
||||
abstract File findApplicationInfoInSources()
|
||||
|
||||
abstract JpsModule findApplicationInfoModule()
|
||||
|
||||
abstract JpsModule findModule(String name)
|
||||
|
||||
abstract void executeStep(String stepMessage, String stepId, Closure step)
|
||||
|
||||
public static BuildContext createContext(GantBuilder ant, JpsGantProjectBuilder projectBuilder, JpsProject project, JpsGlobal global,
|
||||
String communityHome, String projectHome, String buildOutputRoot, ProductProperties productProperties,
|
||||
BuildOptions options = new BuildOptions()) {
|
||||
return new BuildContextImpl(ant, projectBuilder, project, global, communityHome, projectHome, buildOutputRoot, productProperties, options)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BuildPaths {
|
||||
/**
|
||||
* Path to a directory where idea/community Git repository is checked out
|
||||
*/
|
||||
String communityHome
|
||||
|
||||
/**
|
||||
* Path to a base directory of the project which will be compiled
|
||||
*/
|
||||
String projectHome
|
||||
|
||||
/**
|
||||
* Path to a directory where build script will store temporary and resulting files
|
||||
*/
|
||||
String buildOutputRoot
|
||||
|
||||
/**
|
||||
* Path to a directory where resulting artifacts will be placed
|
||||
*/
|
||||
String artifacts
|
||||
|
||||
/**
|
||||
* Path to a directory containing distribution files ('bin', 'lib', 'plugins' directories) common for all operating systems
|
||||
*/
|
||||
String distAll
|
||||
|
||||
/**
|
||||
* Path to a directory where temporary files required for a particular build steps can be stored
|
||||
*/
|
||||
String temp
|
||||
|
||||
/**
|
||||
* Path to a directory containing distribution of JRE for Windows which will be bundled with the product
|
||||
*/
|
||||
String winJre
|
||||
|
||||
/**
|
||||
* Path to a directory containing distribution of JRE for Linux which will be bundled with the product
|
||||
*/
|
||||
String linuxJre
|
||||
}
|
||||
|
||||
interface BuildMessages {
|
||||
void info(String message)
|
||||
void warning(String message)
|
||||
|
||||
/**
|
||||
* Report an error and stop the build process
|
||||
*/
|
||||
void error(String message)
|
||||
|
||||
void progress(String message)
|
||||
void block(String blockName, Closure body)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 com.intellij.util.SystemProperties
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class BuildOptions {
|
||||
/**
|
||||
* By default build scripts compile project classes to a special output directory (to not interfere with the default project output if
|
||||
* invoked on a developer machine). Pass 'true' to this system property to skip compilation step and use compiled classes from the project output instead.
|
||||
*/
|
||||
public static final String USE_COMPILED_CLASSES_PROPERTY = "intellij.build.useCompiledClasses"
|
||||
boolean useCompiledClassesFromProjectOutput = SystemProperties.getBooleanProperty(USE_COMPILED_CLASSES_PROPERTY, false)
|
||||
|
||||
/**
|
||||
* Pass comma-separated names of build steps (see below) to 'intellij.build.skipBuildSteps' system property to skip them when building locally.
|
||||
*/
|
||||
Set<String> buildStepsToSkip = System.getProperty("intellij.build.skipBuildSteps", "").split(",") as Set<String>
|
||||
static final SEARCHABLE_OPTIONS_INDEX_STEP = "search_index"
|
||||
static final SOURCES_ARCHIVE_STEP = "sources_archive"
|
||||
static final MAC_DISTRIBUTION_STEP = "mac_dist"
|
||||
static final LINUX_DISTRIBUTION_STEP = "linux_dist"
|
||||
static final WINDOWS_DISTRIBUTION_STEP = "windows_dist"
|
||||
static final CROSS_PLATFORM_DISTRIBUTION_STEP = "cross_platform_dist"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 org.jetbrains.intellij.build.impl.BuildTasksImpl
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
abstract class BuildTasks {
|
||||
/**
|
||||
* Build archive of the project source files keeping the original layout
|
||||
*/
|
||||
abstract void zipSources()
|
||||
|
||||
/**
|
||||
* Update search/searchableOptions.xml file in {@code targetModuleName} module output directory
|
||||
*/
|
||||
abstract void buildSearchableOptions(String targetModuleName, List<String> modulesToIndex, List<String> pathsToLicenses)
|
||||
|
||||
/**
|
||||
* Create a copy of *ApplicationInfo.xml file with substituted __BUILD_NUMBER__ and __BUILD_DATE__ placeholders
|
||||
* @return path to the copied file
|
||||
*/
|
||||
abstract File patchApplicationInfo()
|
||||
|
||||
/**
|
||||
* Create distribution for all operating system from JAR files located at {@link BuildPaths#distAll}
|
||||
*/
|
||||
abstract void buildDistributions()
|
||||
|
||||
abstract void cleanOutput()
|
||||
|
||||
abstract void compileProjectAndTests(List<String> includingTestsInModules = [])
|
||||
|
||||
public static BuildTasks create(BuildContext context) {
|
||||
return new BuildTasksImpl(context)
|
||||
}
|
||||
}
|
||||
@@ -22,43 +22,40 @@ public abstract class ProductProperties {
|
||||
String prefix
|
||||
String code
|
||||
String appInfoModule
|
||||
String appInfoModulePath
|
||||
String customInspectScriptName
|
||||
|
||||
abstract def String appInfoFile()
|
||||
|
||||
/**
|
||||
* @return build number with product code (e.g. IC-142.239 for IDEA Community)
|
||||
* Return {@code true} if tools.jar from JDK must be added to IDE's classpath
|
||||
*/
|
||||
abstract def String fullBuildNumber()
|
||||
boolean toolsJarRequired = false
|
||||
|
||||
abstract def String systemSelector()
|
||||
abstract def String systemSelector(ApplicationInfoProperties applicationInfo)
|
||||
|
||||
String additionalIDEPropertiesFilePath
|
||||
String exe_launcher_properties
|
||||
String exe64_launcher_properties
|
||||
String platformPrefix = null
|
||||
String bundleIdentifier
|
||||
|
||||
abstract def String macAppRoot()
|
||||
abstract def String macAppRoot(ApplicationInfoProperties applicationInfo, String buildNumber)
|
||||
|
||||
abstract def String winAppRoot()
|
||||
abstract def String winAppRoot(String buildNumber)
|
||||
|
||||
abstract def String linuxAppRoot()
|
||||
abstract def String linuxAppRoot(String buildNumber)
|
||||
|
||||
abstract def String archiveName()
|
||||
abstract def String archiveName(String buildNumber)
|
||||
|
||||
boolean setPluginAndIDEVersionInPluginXml = true
|
||||
|
||||
String ideJvmArgs = null
|
||||
String ideJvmArgs = ""
|
||||
boolean maySkipAndroidPlugin
|
||||
String relativeAndroidHome
|
||||
String relativeAndroidToolsBaseHome
|
||||
|
||||
boolean includeYourkitAgentInEAP = false
|
||||
boolean includeBatchLauncher = true
|
||||
boolean buildUpdater = false
|
||||
List<String> excludedPlugins = []
|
||||
List<String> extraMacBins = []
|
||||
List<String> extraLinuxBins = []
|
||||
|
||||
def customLayout(targetDirectory) {}
|
||||
|
||||
@@ -71,4 +68,28 @@ public abstract class ProductProperties {
|
||||
String icon128
|
||||
String ico
|
||||
String icns
|
||||
|
||||
WindowsProductProperties windows = new WindowsProductProperties()
|
||||
MacProductProperties mac = new MacProductProperties()
|
||||
LinuxProductProperties linux = new LinuxProductProperties()
|
||||
}
|
||||
|
||||
class WindowsProductProperties {
|
||||
boolean includeBatchLauncher = true
|
||||
boolean bundleJre = true
|
||||
}
|
||||
|
||||
class MacProductProperties {
|
||||
String minOSXVersion = "10.8"
|
||||
String helpId = ""
|
||||
String docTypes = null
|
||||
List<String> urlSchemes = []
|
||||
List<String> architectures = ["x86_64"]
|
||||
boolean includeYourkitAgentInEAP = true
|
||||
List<String> extraMacBins = []
|
||||
String bundleIdentifier
|
||||
}
|
||||
|
||||
class LinuxProductProperties {
|
||||
List<String> extraLinuxBins = []
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.util.SystemProperties
|
||||
import org.codehaus.gant.GantBuilder
|
||||
import org.jetbrains.intellij.build.ApplicationInfoProperties
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.BuildOptions
|
||||
import org.jetbrains.intellij.build.BuildPaths
|
||||
import org.jetbrains.intellij.build.ProductProperties
|
||||
import org.jetbrains.jps.gant.JpsGantProjectBuilder
|
||||
import org.jetbrains.jps.model.JpsGlobal
|
||||
import org.jetbrains.jps.model.JpsProject
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import org.jetbrains.jps.model.serialization.JpsModelSerializationDataService
|
||||
import org.jetbrains.jps.model.serialization.JpsProjectLoader
|
||||
import org.jetbrains.jps.util.JpsPathUtil
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class BuildContextImpl extends BuildContext {
|
||||
private final JpsGlobal global
|
||||
private final underTeamCity
|
||||
|
||||
BuildContextImpl(GantBuilder ant, JpsGantProjectBuilder projectBuilder, JpsProject project, JpsGlobal global,
|
||||
String communityHome, String projectHome, String buildOutputRoot, ProductProperties productProperties,
|
||||
BuildOptions options = new BuildOptions()) {
|
||||
this.projectBuilder = projectBuilder
|
||||
this.ant = ant
|
||||
this.project = project
|
||||
this.global = global
|
||||
this.productProperties = productProperties
|
||||
this.options = options
|
||||
underTeamCity = System.getProperty("teamcity.buildType.id") != null
|
||||
messages = new BuildMessagesImpl(projectBuilder, ant.project, underTeamCity)
|
||||
|
||||
paths = new BuildPathsImpl(communityHome, projectHome, buildOutputRoot)
|
||||
|
||||
loadProject()
|
||||
def appInfoFile = findApplicationInfoInSources()
|
||||
applicationInfo = new ApplicationInfoProperties(appInfoFile.absolutePath)
|
||||
|
||||
buildNumber = System.getProperty("build.number") ?: readSnapshotBuildNumber()
|
||||
fullBuildNumber = "$productProperties.code-$buildNumber"
|
||||
systemSelector = productProperties.systemSelector(applicationInfo)
|
||||
fileNamePrefix = productProperties.prefix
|
||||
|
||||
bootClassPathJarNames = ["bootstrap.jar", "extensions.jar", "util.jar", "jdom.jar", "log4j.jar", "trove4j.jar", "jna.jar"]
|
||||
}
|
||||
|
||||
private void loadProject() {
|
||||
def projectHome = paths.projectHome
|
||||
JdkUtils.defineJdk(global, "IDEA jdk", JdkUtils.computeJdkHome(messages, "jdkHome", "$projectHome/build/jdk/1.6", "JDK_16_x64"))
|
||||
JdkUtils.defineJdk(global, "1.8", JdkUtils.computeJdkHome(messages, "jdk8Home", "$projectHome/build/jdk/1.8", "JDK_18_x64"))
|
||||
def bundledKotlinPath = "$paths.communityHome/build/kotlinc"
|
||||
if (!new File(bundledKotlinPath, "lib/kotlin-runtime.jar").exists()) {
|
||||
messages.error("Could not find Kotlin runtime at $bundledKotlinPath/lib/kotlin-runtime.jar: run download_kotlin.gant script to download Kotlin JARs")
|
||||
}
|
||||
JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(global).addPathVariable("KOTLIN_BUNDLED", bundledKotlinPath)
|
||||
|
||||
projectBuilder.buildIncrementally = SystemProperties.getBooleanProperty("jps.build.incrementally", false)
|
||||
def dataDirName = projectBuilder.buildIncrementally ? ".jps-incremental-build" : ".jps-build-data"
|
||||
projectBuilder.dataStorageRoot = new File("$projectHome/$dataDirName")
|
||||
def tempDir = System.getProperty("teamcity.build.tempDir") ?: System.getProperty("java.io.tmpdir")
|
||||
projectBuilder.setupAdditionalLogging(new File("$tempDir/system/build-log/build.log"), System.getProperty("jps.build.debug.logging.categories", ""))
|
||||
|
||||
def pathVariables = JpsModelSerializationDataService.computeAllPathVariables(global)
|
||||
JpsProjectLoader.loadProject(project, pathVariables, projectHome)
|
||||
projectBuilder.exportModuleOutputProperties()
|
||||
messages.info("Loaded project $projectHome: ${project.modules.size()} modules, ${project.libraryCollection.libraries.size()} libraries")
|
||||
if (!options.useCompiledClassesFromProjectOutput) {
|
||||
projectBuilder.targetFolder = "$paths.buildOutputRoot/classes"
|
||||
}
|
||||
else {
|
||||
def outputDir = JpsPathUtil.urlToFile(JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(project).outputUrl)
|
||||
if (!outputDir.exists()) {
|
||||
messages.error("$BuildOptions.USE_COMPILED_CLASSES_PROPERTY is enabled, but the project output directory $outputDir.absolutePath doesn't exist")
|
||||
}
|
||||
}
|
||||
|
||||
suppressWarnings()
|
||||
}
|
||||
|
||||
private void suppressWarnings() {
|
||||
def compilerOptions = JpsJavaExtensionService.instance.getOrCreateCompilerConfiguration(project).currentCompilerOptions
|
||||
compilerOptions.GENERATE_NO_WARNINGS = true
|
||||
compilerOptions.DEPRECATION = false
|
||||
compilerOptions.ADDITIONAL_OPTIONS_STRING = compilerOptions.ADDITIONAL_OPTIONS_STRING.replace("-Xlint:unchecked", "")
|
||||
}
|
||||
|
||||
private String readSnapshotBuildNumber() {
|
||||
new File(paths.communityHome, "build.txt").text.trim()
|
||||
}
|
||||
|
||||
@Override
|
||||
File findApplicationInfoInSources() {
|
||||
JpsModule module = findApplicationInfoModule()
|
||||
def appInfoRelativePath = "idea/${productProperties.platformPrefix}ApplicationInfo.xml"
|
||||
def appInfoFile = module.sourceRoots.collect { new File(it.file, appInfoRelativePath) }.find { it.exists() }
|
||||
if (appInfoFile == null) {
|
||||
messages.error("Cannot find $appInfoRelativePath in '$module.name' module")
|
||||
}
|
||||
return appInfoFile
|
||||
}
|
||||
|
||||
@Override
|
||||
JpsModule findApplicationInfoModule() {
|
||||
def module = findModule(productProperties.appInfoModule)
|
||||
if (module == null) {
|
||||
messages.error("Cannot find module '$productProperties.appInfoModule' containing ApplicationInfo.xml file")
|
||||
}
|
||||
return module
|
||||
}
|
||||
|
||||
JpsModule findModule(String name) {
|
||||
project.modules.find { it.name == name }
|
||||
}
|
||||
|
||||
@Override
|
||||
void executeStep(String stepMessage, String stepId, Closure step) {
|
||||
if (options.buildStepsToSkip.contains(stepId)) {
|
||||
messages.info("Skipping '$stepMessage'")
|
||||
}
|
||||
else {
|
||||
messages.block(stepMessage, step)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void notifyArtifactBuilt(String artifactPath) {
|
||||
if (!underTeamCity) return
|
||||
|
||||
if (!FileUtil.startsWith(artifactPath, paths.projectHome)) {
|
||||
messages.warning("Artifact '$artifactPath' is not under '$paths.projectHome', it won't be reported")
|
||||
return
|
||||
}
|
||||
def relativePath = StringUtil.trimStart(artifactPath.substring(paths.projectHome.length()), "/")
|
||||
def file = new File(artifactPath)
|
||||
if (file.isDirectory()) {
|
||||
relativePath += "=>" + file.name
|
||||
}
|
||||
messages.info("##teamcity[publishArtifacts '$relativePath']")
|
||||
}
|
||||
}
|
||||
|
||||
class BuildPathsImpl extends BuildPaths {
|
||||
BuildPathsImpl(String communityHome, String projectHome, String buildOutputRoot) {
|
||||
this.communityHome = new File(communityHome).canonicalPath
|
||||
this.projectHome = new File(projectHome).canonicalPath
|
||||
this.buildOutputRoot = new File(buildOutputRoot).canonicalPath
|
||||
artifacts = "${this.buildOutputRoot}/artifacts"
|
||||
distAll = "$buildOutputRoot/dist.all"
|
||||
temp = "$buildOutputRoot/temp"
|
||||
winJre = "$buildOutputRoot/jdk.win"
|
||||
linuxJre = "$buildOutputRoot/jdk.linux"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.apache.tools.ant.BuildException
|
||||
import org.apache.tools.ant.Project
|
||||
import org.jetbrains.intellij.build.BuildMessages
|
||||
import org.jetbrains.jps.gant.BuildInfoPrinter
|
||||
import org.jetbrains.jps.gant.DefaultBuildInfoPrinter
|
||||
import org.jetbrains.jps.gant.JpsGantProjectBuilder
|
||||
import org.jetbrains.jps.gant.TeamCityBuildInfoPrinter
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class BuildMessagesImpl implements BuildMessages {
|
||||
private final JpsGantProjectBuilder builder
|
||||
private final BuildInfoPrinter buildInfoPrinter
|
||||
private final Project antProject
|
||||
private final boolean underTeamCity
|
||||
private int indent = 0
|
||||
|
||||
BuildMessagesImpl(JpsGantProjectBuilder builder, Project antProject, boolean underTeamCity) {
|
||||
this.underTeamCity = underTeamCity
|
||||
this.antProject = antProject
|
||||
this.builder = builder
|
||||
buildInfoPrinter = underTeamCity ? new TeamCityBuildInfoPrinter() : new DefaultBuildInfoPrinter()
|
||||
}
|
||||
|
||||
@Override
|
||||
void info(String message) {
|
||||
antProject.log(withIndent(message), Project.MSG_INFO)
|
||||
}
|
||||
|
||||
private String withIndent(String message) {
|
||||
StringUtil.repeat(" ", 2 * indent) + message
|
||||
}
|
||||
|
||||
@Override
|
||||
void warning(String message) {
|
||||
antProject.log(withIndent(message), Project.MSG_WARN)
|
||||
}
|
||||
|
||||
@Override
|
||||
void error(String message) {
|
||||
throw new BuildException(message)
|
||||
}
|
||||
|
||||
@Override
|
||||
void progress(String message) {
|
||||
if (underTeamCity) {
|
||||
buildInfoPrinter.printProgressMessage(builder, message)
|
||||
}
|
||||
else {
|
||||
info(message)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void block(String blockName, Closure body) {
|
||||
try {
|
||||
//todo[nik] move this logic into DefaultBuildInfoPrinter?
|
||||
if (underTeamCity) {
|
||||
buildInfoPrinter.printBlockOpenedMessage(builder, blockName)
|
||||
}
|
||||
else {
|
||||
info(blockName)
|
||||
indent++
|
||||
}
|
||||
body()
|
||||
}
|
||||
finally {
|
||||
if (underTeamCity) {
|
||||
buildInfoPrinter.printBlockClosedMessage(builder, blockName)
|
||||
}
|
||||
else {
|
||||
indent--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.BuildOptions
|
||||
import org.jetbrains.intellij.build.BuildTasks
|
||||
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class BuildTasksImpl extends BuildTasks {
|
||||
final BuildContext buildContext
|
||||
|
||||
BuildTasksImpl(BuildContext buildContext) {
|
||||
this.buildContext = buildContext
|
||||
}
|
||||
|
||||
@Override
|
||||
void zipSources() {
|
||||
buildContext.executeStep("Build sources zip archive", BuildOptions.SOURCES_ARCHIVE_STEP) {
|
||||
String targetFile = "$buildContext.paths.artifacts/sources.zip"
|
||||
buildContext.messages.progress("Building sources archive $targetFile")
|
||||
|
||||
buildContext.ant.mkdir(dir: buildContext.paths.artifacts)
|
||||
buildContext.ant.delete(file: targetFile)
|
||||
buildContext.ant.zip(destfile: targetFile) {
|
||||
fileset(dir: buildContext.paths.projectHome) {
|
||||
["java", "groovy", "ipr", "iml", "form", "xml", "properties", "kt"].each {
|
||||
include(name: "**/*.$it")
|
||||
}
|
||||
exclude(name: "**/testData/**")
|
||||
exclude(name: "out/**")
|
||||
}
|
||||
}
|
||||
buildContext.notifyArtifactBuilt(targetFile)
|
||||
}
|
||||
}
|
||||
|
||||
//todo[nik] do we need 'cp' and 'jvmArgs' parameters?
|
||||
@Override
|
||||
void buildSearchableOptions(String targetModuleName, List<String> modulesToIndex, List<String> pathsToLicenses) {
|
||||
//todo[nik] create searchableOptions.xml in a separate directory instead of modifying it in the module output
|
||||
buildContext.executeStep("Build searchable options index", BuildOptions.SEARCHABLE_OPTIONS_INDEX_STEP, {
|
||||
def javaRuntimeClasses = "${buildContext.projectBuilder.moduleOutput(buildContext.findModule("java-runtime"))}"
|
||||
if (!new File(javaRuntimeClasses).exists()) {
|
||||
buildContext.messages.
|
||||
error("Cannot build searchable options, 'java-runtime' module isn't compiled ($javaRuntimeClasses doesn't exist)")
|
||||
}
|
||||
|
||||
buildContext.messages.progress("Building searchable options for modules $modulesToIndex")
|
||||
|
||||
def targetModuleOutput = buildContext.projectBuilder.moduleOutput(buildContext.findModule(targetModuleName))
|
||||
String targetFile = "$targetModuleOutput/search/searchableOptions.xml"
|
||||
FileUtil.delete(new File(targetFile))
|
||||
|
||||
def tempDir = "$buildContext.paths.temp/searchableOptions"
|
||||
String systemPath = "$tempDir/system"
|
||||
String configPath = "$tempDir/config"
|
||||
buildContext.ant.mkdir(dir: tempDir)
|
||||
pathsToLicenses.each {
|
||||
//todo[nik] previously licenses were copied to systemPath
|
||||
buildContext.ant.copy(file: it, todir: configPath)
|
||||
}
|
||||
|
||||
def ideClasspath = new LinkedHashSet<String>()
|
||||
modulesToIndex.collectMany(ideClasspath) { buildContext.projectBuilder.moduleRuntimeClasspath(buildContext.findModule(it), false) }
|
||||
|
||||
String classpathFile = "$tempDir/classpath.txt"
|
||||
new File(classpathFile).text = ideClasspath.join("\n")
|
||||
|
||||
buildContext.ant.java(classname: "com.intellij.rt.execution.CommandLineWrapper", fork: true, failonerror: true) {
|
||||
jvmarg(line: "-ea -Xmx500m -XX:MaxPermSize=200m")
|
||||
jvmarg(value: "-Xbootclasspath/a:${buildContext.projectBuilder.moduleOutput(buildContext.findModule("boot"))}")
|
||||
sysproperty(key: "idea.home.path", value: buildContext.paths.projectHome)
|
||||
sysproperty(key: "idea.system.path", value: systemPath)
|
||||
sysproperty(key: "idea.config.path", value: configPath)
|
||||
arg(value: "$classpathFile")
|
||||
arg(line: "com.intellij.idea.Main traverseUI")
|
||||
arg(value: targetFile)
|
||||
|
||||
classpath() {
|
||||
pathelement(location: "$javaRuntimeClasses")
|
||||
}
|
||||
}
|
||||
|
||||
if (!new File(targetFile).exists()) {
|
||||
buildContext.messages.error("Failed to build searchable options index: $targetFile doesn't exist")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
File patchIdeaPropertiesFile() {
|
||||
File originalFile = new File("$buildContext.paths.communityHome/bin/idea.properties")
|
||||
|
||||
String text = originalFile.text
|
||||
if (buildContext.productProperties.additionalIDEPropertiesFilePath != null) {
|
||||
text += "\n" + new File(buildContext.productProperties.additionalIDEPropertiesFilePath).text
|
||||
}
|
||||
|
||||
//todo[nik] introduce special systemSelectorWithoutVersion instead?
|
||||
String settingsDir = buildContext.systemSelector.replaceFirst("\\d+(\\.\\d+)?", "")
|
||||
text = BuildUtils.replaceAll(text, ["settings_dir": settingsDir], "@@")
|
||||
|
||||
text += (buildContext.applicationInfo.isEAP ? """
|
||||
#-----------------------------------------------------------------------
|
||||
# Change to 'disabled' if you don't want to receive instant visual notifications
|
||||
# about fatal errors that happen to an IDE or plugins installed.
|
||||
#-----------------------------------------------------------------------
|
||||
idea.fatal.error.notification=enabled
|
||||
"""
|
||||
: """
|
||||
#-----------------------------------------------------------------------
|
||||
# Change to 'enabled' if you want to receive instant visual notifications
|
||||
# about fatal errors that happen to an IDE or plugins installed.
|
||||
#-----------------------------------------------------------------------
|
||||
idea.fatal.error.notification=disabled
|
||||
""")
|
||||
File propertiesFile = new File(buildContext.paths.temp, "idea.properties")
|
||||
propertiesFile.text = text
|
||||
return propertiesFile
|
||||
}
|
||||
|
||||
@Override
|
||||
File patchApplicationInfo() {
|
||||
def sourceFile = buildContext.findApplicationInfoInSources()
|
||||
def targetFile = new File(buildContext.paths.temp, sourceFile.name)
|
||||
def date = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
|
||||
BuildUtils.copyAndPatchFile(sourceFile.path, targetFile.path,
|
||||
["BUILD_NUMBER": buildContext.fullBuildNumber, "BUILD_DATE": date])
|
||||
return targetFile
|
||||
}
|
||||
|
||||
void layoutShared() {
|
||||
new File(buildContext.paths.distAll, "build.txt").text = buildContext.fullBuildNumber
|
||||
buildContext.ant.copy(todir: "$buildContext.paths.distAll/bin") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/bin") {
|
||||
include(name: "*.*")
|
||||
exclude(name: "idea.properties")
|
||||
}
|
||||
}
|
||||
buildContext.ant.copy(todir: "$buildContext.paths.distAll/license") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/license")
|
||||
}
|
||||
|
||||
//todo[nik] these seems to be required for IDEA CE only
|
||||
buildContext.ant.copy(todir: "$buildContext.paths.distAll") {
|
||||
fileset(file: "$buildContext.paths.communityHome/LICENSE.txt")
|
||||
fileset(file: "$buildContext.paths.communityHome/NOTICE.txt")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void buildDistributions() {
|
||||
layoutShared()
|
||||
def propertiesFile = patchIdeaPropertiesFile()
|
||||
|
||||
WindowsDistributionBuilder windowsBuilder = null
|
||||
buildContext.executeStep("Build Windows distribution", BuildOptions.WINDOWS_DISTRIBUTION_STEP, {
|
||||
windowsBuilder = new WindowsDistributionBuilder(buildContext)
|
||||
windowsBuilder.layoutWin(propertiesFile)
|
||||
})
|
||||
|
||||
LinuxDistributionBuilder linuxBuilder = null
|
||||
buildContext.executeStep("Build Linux distribution", BuildOptions.LINUX_DISTRIBUTION_STEP) {
|
||||
linuxBuilder = new LinuxDistributionBuilder(buildContext)
|
||||
linuxBuilder.layoutUnix(propertiesFile)
|
||||
}
|
||||
|
||||
MacDistributionBuilderImpl macBuilder = null
|
||||
buildContext.executeStep("Build Mac OS X distribution", BuildOptions.MAC_DISTRIBUTION_STEP) {
|
||||
macBuilder = new MacDistributionBuilderImpl(buildContext)
|
||||
macBuilder.layoutMac(propertiesFile)
|
||||
}
|
||||
|
||||
if (windowsBuilder != null && linuxBuilder != null && macBuilder != null) {
|
||||
buildContext.executeStep("Build cross-platform distribution", BuildOptions.CROSS_PLATFORM_DISTRIBUTION_STEP) {
|
||||
def crossPlatformBuilder = new CrossPlatformDistributionBuilder(buildContext)
|
||||
crossPlatformBuilder.buildCrossPlatformZip(windowsBuilder.winDistPath, linuxBuilder.unixDistPath, macBuilder.macDistPath)
|
||||
}
|
||||
}
|
||||
else {
|
||||
buildContext.messages.info("Skipping building cross-platform distribution because some OS-specific distributions was skipeed")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void cleanOutput() {
|
||||
buildContext.messages.block("Clean output") {
|
||||
def outputPath = buildContext.paths.buildOutputRoot
|
||||
buildContext.messages.progress("Cleaning output directory $outputPath")
|
||||
FileUtil.delete(new File(outputPath))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void compileProjectAndTests(List<String> includingTestsInModules = []) {
|
||||
if (buildContext.options.useCompiledClassesFromProjectOutput) {
|
||||
buildContext.messages.info("Compilation skipped, the compiled classes from the project output will be used")
|
||||
return
|
||||
}
|
||||
|
||||
buildContext.projectBuilder.cleanOutput()
|
||||
buildContext.projectBuilder.buildProduction()
|
||||
for (String moduleName : includingTestsInModules) {
|
||||
buildContext.projectBuilder.makeModuleTests(buildContext.findModule(moduleName))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class BuildUtils {
|
||||
static String replaceAll(String text, Map<String, String> replacements, String marker = "__") {
|
||||
replacements.each {
|
||||
text = StringUtil.replace(text, "$marker$it.key$marker", it.value)
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
static void copyAndPatchFile(String sourcePath, String targetPath, Map<String, String> replacements, String marker = "__") {
|
||||
FileUtil.createParentDirs(new File(targetPath))
|
||||
new File(targetPath).text = replaceAll(new File(sourcePath).text, replacements, marker)
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class CrossPlatformDistributionBuilder {
|
||||
private final BuildContext buildContext
|
||||
|
||||
CrossPlatformDistributionBuilder(BuildContext buildContext) {
|
||||
this.buildContext = buildContext
|
||||
}
|
||||
|
||||
void buildCrossPlatformZip(String winDistPath, String linuxDistPath, String macDistPath) {
|
||||
buildContext.messages.block("Building cross-platform zip") {
|
||||
def executableName = buildContext.fileNamePrefix
|
||||
def zipDir = "$buildContext.paths.temp/cross-platform-zip"
|
||||
buildContext.ant.copy(todir: "$zipDir/bin/win") {
|
||||
fileset(dir: "$linuxDistPath/bin") {
|
||||
include(name: "idea.properties")
|
||||
}
|
||||
}
|
||||
buildContext.ant.copy(todir: "$zipDir/bin/linux") {
|
||||
fileset(dir: "$linuxDistPath/bin") {
|
||||
include(name: "*.vmoptions")
|
||||
include(name: "idea.properties")
|
||||
}
|
||||
}
|
||||
buildContext.ant.copy(todir: "$zipDir/bin/mac") {
|
||||
fileset(dir: "$macDistPath/bin") {
|
||||
include(name: "${executableName}.vmoptions")
|
||||
include(name: "idea.properties")
|
||||
}
|
||||
}
|
||||
buildContext.ant.copy(file: "$macDistPath/bin/${executableName}.vmoptions", tofile: "$zipDir/bin/mac/${executableName}64.vmoptions")
|
||||
buildContext.ant.copy(todir: "$zipDir/bin") {
|
||||
fileset(dir: "$macDistPath/bin") {
|
||||
include(name: "*.jnilib")
|
||||
}
|
||||
mapper(type: "glob", from: "*.jnilib", to: "*.dylib")
|
||||
}
|
||||
|
||||
String targetPath = "$buildContext.paths.artifacts/$buildContext.fileNamePrefix${buildContext.fullBuildNumber}.zip"
|
||||
buildContext.ant.zip(zipfile: targetPath, duplicate: "fail") {
|
||||
fileset(dir: buildContext.paths.distAll) {
|
||||
exclude(name: "bin/idea.properties")
|
||||
}
|
||||
fileset(dir: zipDir)
|
||||
|
||||
fileset(dir: winDistPath) {
|
||||
exclude(name: "bin/fsnotifier*.exe")
|
||||
exclude(name: "bin/*.exe.vmoptions")
|
||||
exclude(name: "bin/${executableName}*.exe")
|
||||
exclude(name: "bin/idea.properties")
|
||||
}
|
||||
zipfileset(dir: "$winDistPath/bin", prefix: "bin/win") {
|
||||
include(name: "fsnotifier*.exe")
|
||||
include(name: "*.exe.vmoptions")
|
||||
}
|
||||
|
||||
fileset(dir: linuxDistPath) {
|
||||
exclude(name: "bin/fsnotifier*")
|
||||
exclude(name: "bin/*.vmoptions")
|
||||
exclude(name: "bin/*.sh")
|
||||
exclude(name: "bin/idea.properties")
|
||||
exclude(name: "help/**")
|
||||
}
|
||||
zipfileset(dir: "$linuxDistPath/bin", filemode: "775", prefix: "bin") {
|
||||
include(name: "*.sh")
|
||||
}
|
||||
zipfileset(dir: "$linuxDistPath/bin", prefix: "bin/linux", filemode: "775") {
|
||||
include(name: "fsnotifier*")
|
||||
}
|
||||
|
||||
fileset(dir: macDistPath) {
|
||||
exclude(name: "bin/fsnotifier*")
|
||||
exclude(name: "bin/restarter*")
|
||||
exclude(name: "bin/*.sh")
|
||||
exclude(name: "bin/*.py")
|
||||
exclude(name: "bin/*.jnilib")
|
||||
exclude(name: "bin/idea.properties")
|
||||
exclude(name: "bin/*.vmoptions")
|
||||
}
|
||||
zipfileset(dir: "$macDistPath/bin", filemode: "775", prefix: "bin") {
|
||||
include(name: "restarter*")
|
||||
include(name: "*.py")
|
||||
}
|
||||
zipfileset(dir: "$macDistPath/bin", prefix: "bin/mac", filemode: "775") {
|
||||
include(name: "fsnotifier*")
|
||||
}
|
||||
}
|
||||
buildContext.notifyArtifactBuilt(targetPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.util.SystemProperties
|
||||
import org.jetbrains.intellij.build.BuildMessages
|
||||
import org.jetbrains.jps.model.JpsGlobal
|
||||
import org.jetbrains.jps.model.java.JdkVersionDetector
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||
import org.jetbrains.jps.model.library.JpsOrderRootType
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class JdkUtils {
|
||||
public static void defineJdk(JpsGlobal global, String jdkName, String jdkHomePath) {
|
||||
def sdk = JpsJavaExtensionService.instance.addJavaSdk(global, jdkName, jdkHomePath)
|
||||
def toolsJar = new File(jdkHomePath, "lib/tools.jar")
|
||||
if (toolsJar.exists()) {
|
||||
sdk.addRoot(toolsJar, JpsOrderRootType.COMPILED)
|
||||
}
|
||||
}
|
||||
|
||||
public static String computeJdkHome(BuildMessages messages, String propertyName, String defaultDir, String envVarName) {
|
||||
def jdkDir = System.getProperty(propertyName)
|
||||
if (jdkDir != null) {
|
||||
return jdkDir
|
||||
}
|
||||
|
||||
jdkDir = SystemInfo.isMac ? "$defaultDir/Home" : defaultDir
|
||||
if (new File(jdkDir).exists()) {
|
||||
messages.info("$propertyName set to $jdkDir")
|
||||
}
|
||||
else {
|
||||
jdkDir = System.getenv(envVarName)
|
||||
if (jdkDir != null) {
|
||||
messages.info("'$defaultDir' doesn't exist, $propertyName set to '$envVarName' environment variable: $jdkDir")
|
||||
}
|
||||
else {
|
||||
jdkDir = getCurrentJdk()
|
||||
def version = JdkVersionDetector.instance.detectJdkVersion(jdkDir)
|
||||
if (propertyName.contains("8") && !version.contains("1.8.")) {
|
||||
messages.error("JDK 1.8 is required to compile the project, but '$propertyName' property and '$envVarName' environment variable aren't defined and default JDK $jdkDir ($version) cannot be used as JDK 1.8")
|
||||
return null
|
||||
}
|
||||
messages.info("'$envVarName' isn't defined and '$defaultDir' doesn't exist, $propertyName set to $jdkDir")
|
||||
}
|
||||
}
|
||||
return jdkDir
|
||||
}
|
||||
|
||||
private static String getCurrentJdk() {
|
||||
def javaHome = SystemProperties.javaHome
|
||||
if (new File(javaHome).name == "jre") {
|
||||
return new File(javaHome).getParent()
|
||||
}
|
||||
return javaHome
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
enum JvmArchitecture {
|
||||
x32(""), x64("64")
|
||||
|
||||
final String fileSuffix
|
||||
|
||||
JvmArchitecture(String fileSuffix) {
|
||||
this.fileSuffix = fileSuffix
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class LinuxDistributionBuilder {
|
||||
private final BuildContext buildContext
|
||||
final String unixDistPath
|
||||
|
||||
LinuxDistributionBuilder(BuildContext buildContext) {
|
||||
this.buildContext = buildContext
|
||||
unixDistPath = "$buildContext.paths.buildOutputRoot/dist.unix"
|
||||
}
|
||||
|
||||
//todo[nik] rename
|
||||
void layoutUnix(File ideaProperties) {
|
||||
buildContext.ant.copy(todir: "$unixDistPath/bin") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/bin/linux")
|
||||
}
|
||||
buildContext.ant.copy(file: ideaProperties.path, todir: "$unixDistPath/bin")
|
||||
//todo[nik] converting line separators to unix-style make sense only when building Linux distributions under Windows on a local machine;
|
||||
// for real installers we need to checkout all text files with 'lf' separators anyway
|
||||
buildContext.ant.fixcrlf(file: "$unixDistPath/bin/idea.properties", eol: "unix")
|
||||
buildContext.ant.copy(file: buildContext.productProperties.icon128, tofile: "$unixDistPath/bin/${buildContext.fileNamePrefix}.png")
|
||||
|
||||
unixScripts()
|
||||
unixVMOptions()
|
||||
unixReadme()
|
||||
buildContext.productProperties.customLinLayout(unixDistPath)
|
||||
buildTarGz(false)
|
||||
if (new File(buildContext.paths.linuxJre).exists()) {
|
||||
buildTarGz(true)
|
||||
}
|
||||
}
|
||||
|
||||
private void unixScripts() {
|
||||
String name = "${buildContext.fileNamePrefix}.sh"
|
||||
String fullName = buildContext.applicationInfo.productName
|
||||
String productUpperCase = buildContext.applicationInfo.shortProductName.toUpperCase()
|
||||
String vmOptionsFileName = buildContext.fileNamePrefix
|
||||
|
||||
String classPath = "CLASSPATH=\"\$IDE_HOME/lib/${buildContext.bootClassPathJarNames[0]}\"\n"
|
||||
classPath += buildContext.bootClassPathJarNames[1..-1].collect { "CLASSPATH=\"\$CLASSPATH:\$IDE_HOME/lib/${it}\"" }.join("\n")
|
||||
def jvmArgs = buildContext.productProperties.ideJvmArgs
|
||||
if (buildContext.productProperties.toolsJarRequired) {
|
||||
classPath += "\nCLASSPATH=\"\$CLASSPATH:\$JDK/lib/tools.jar\""
|
||||
jvmArgs = "$jvmArgs -Didea.jre.check=true".trim()
|
||||
}
|
||||
|
||||
buildContext.ant.copy(todir: "${unixDistPath}/bin") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/bin/scripts/unix")
|
||||
|
||||
filterset(begintoken: "@@", endtoken: "@@") {
|
||||
filter(token: "product_full", value: fullName)
|
||||
filter(token: "product_uc", value: productUpperCase)
|
||||
filter(token: "vm_options", value: vmOptionsFileName)
|
||||
filter(token: "isEap", value: buildContext.applicationInfo.isEAP)
|
||||
filter(token: "system_selector", value: buildContext.systemSelector)
|
||||
filter(token: "ide_jvm_args", value: jvmArgs)
|
||||
filter(token: "class_path", value: classPath)
|
||||
filter(token: "script_name", value: name)
|
||||
}
|
||||
}
|
||||
|
||||
if (name != "idea.sh") {
|
||||
//todo[nik] rename idea.sh in sources to something more generic
|
||||
buildContext.ant.move(file: "${unixDistPath}/bin/idea.sh", tofile: "${unixDistPath}/bin/$name")
|
||||
}
|
||||
String inspectScript = buildContext.productProperties.customInspectScriptName
|
||||
if (inspectScript != null && inspectScript != "inspect") {
|
||||
buildContext.ant.move(file: "${unixDistPath}/bin/inspect.sh", tofile: "${unixDistPath}/bin/${inspectScript}.sh")
|
||||
}
|
||||
|
||||
buildContext.ant.fixcrlf(srcdir: "${unixDistPath}/bin", includes: "*.sh", eol: "unix")
|
||||
}
|
||||
|
||||
private void unixVMOptions() {
|
||||
JvmArchitecture.values().each {
|
||||
def fileName = "${buildContext.fileNamePrefix}${it.fileSuffix}.vmoptions"
|
||||
//todo[nik] why we don't add yourkit agent on unix?
|
||||
def options = VmOptionsGenerator.computeVmOptions(it, buildContext.applicationInfo.isEAP, null) + " -Dawt.useSystemAAFontSettings=lcd"
|
||||
new File(unixDistPath, "bin/$fileName").text = options.replace(' ', '\n')
|
||||
}
|
||||
}
|
||||
|
||||
private void unixReadme() {
|
||||
String fullName = buildContext.applicationInfo.productName
|
||||
BuildUtils.copyAndPatchFile("$buildContext.paths.communityHome/build/Install-Linux-tar.txt", "$unixDistPath/Install-Linux-tar.txt",
|
||||
["product_full" : fullName,
|
||||
"product" : buildContext.fileNamePrefix,
|
||||
"system_selector": buildContext.systemSelector], "@@")
|
||||
buildContext.ant.fixcrlf(file: "$unixDistPath/bin/Install-Linux-tar.txt", eol: "unix")
|
||||
}
|
||||
|
||||
private void buildTarGz(boolean bundleJre) {
|
||||
def tarRoot = buildContext.productProperties.linuxAppRoot(buildContext.buildNumber)
|
||||
def suffix = bundleJre ? "" : "-no-jdk"
|
||||
def tarPath = "$buildContext.paths.artifacts/${buildContext.productProperties.archiveName(buildContext.buildNumber)}${suffix}.tar"
|
||||
def extraBins = buildContext.productProperties.linux.extraLinuxBins
|
||||
def paths = [buildContext.paths.distAll, unixDistPath]
|
||||
if (bundleJre) {
|
||||
paths += buildContext.paths.linuxJre
|
||||
extraBins += "jre/jre/bin/*"
|
||||
}
|
||||
buildContext.messages.block("Build Linux tar.gz archive${bundleJre ? "" : " (without JRE)"}") {
|
||||
buildContext.ant.tar(tarfile: tarPath, longfile: "gnu") {
|
||||
paths.each {
|
||||
tarfileset(dir: it, prefix: tarRoot) {
|
||||
exclude(name: "bin/*.sh")
|
||||
exclude(name: "bin/fsnotifier*")
|
||||
extraBins.each {
|
||||
exclude(name: it)
|
||||
}
|
||||
type(type: "file")
|
||||
}
|
||||
}
|
||||
|
||||
paths.each {
|
||||
tarfileset(dir: it, filemode: "755", prefix: tarRoot) {
|
||||
include(name: "bin/*.sh")
|
||||
include(name: "bin/fsnotifier*")
|
||||
extraBins.each {
|
||||
include(name: it)
|
||||
}
|
||||
type(type: "file")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String gzPath = "${tarPath}.gz"
|
||||
buildContext.ant.gzip(src: tarPath, zipfile: gzPath)
|
||||
buildContext.ant.delete(file: tarPath)
|
||||
buildContext.notifyArtifactBuilt(gzPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
|
||||
import java.time.LocalDate
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class MacDistributionBuilderImpl {
|
||||
private final BuildContext buildContext
|
||||
final String macDistPath
|
||||
|
||||
MacDistributionBuilderImpl(BuildContext buildContext) {
|
||||
this.buildContext = buildContext
|
||||
macDistPath = "$buildContext.paths.buildOutputRoot/dist.mac"
|
||||
}
|
||||
|
||||
public layoutMac(File ideaPropertiesFile) {
|
||||
def docTypes = buildContext.productProperties.mac.docTypes ?: """
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>ipr</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>${buildContext.fileNamePrefix}.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>${buildContext.applicationInfo.productName} Project File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
"""
|
||||
Map<String, String> customIdeaProperties = ["idea.jre.check": "$buildContext.productProperties.toolsJarRequired"];
|
||||
layoutMacApp(ideaPropertiesFile, customIdeaProperties, docTypes)
|
||||
buildContext.productProperties.customMacLayout(macDistPath)
|
||||
buildMacZip()
|
||||
}
|
||||
|
||||
private void layoutMacApp(File ideaPropertiesFile, Map<String, String> customIdeaProperties, String docTypes) {
|
||||
String target = macDistPath
|
||||
def macProductProperties = buildContext.productProperties.mac
|
||||
buildContext.ant.copy(todir: "$target/bin") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/bin/mac")
|
||||
}
|
||||
|
||||
buildContext.ant.copy(todir: target) {
|
||||
fileset(dir: "$buildContext.paths.communityHome/build/conf/mac/Contents")
|
||||
}
|
||||
|
||||
String executable = buildContext.fileNamePrefix
|
||||
String icns = "idea.icns" //todo[nik] rename to more generic name?
|
||||
String helpId = macProductProperties.helpId
|
||||
String helpIcns = "$target/Resources/${helpId}.help/Contents/Resources/Shared/product.icns"
|
||||
String customIcns = buildContext.productProperties.icns
|
||||
if (customIcns != null) {
|
||||
buildContext.ant.delete(file: "$target/Resources/idea.icns")
|
||||
buildContext.ant.copy(file: customIcns, todir: "$target/Resources")
|
||||
buildContext.ant.copy(file: customIcns, tofile: helpIcns)
|
||||
icns = new File(customIcns).name
|
||||
}
|
||||
else {
|
||||
buildContext.ant.copy(file: "$target/Resources/idea.icns", tofile: helpIcns)
|
||||
}
|
||||
|
||||
String fullName = buildContext.applicationInfo.productName
|
||||
|
||||
//todo[nik] why do we put vm options to separate places (some into Info.plist, some into vmoptions file)?
|
||||
String vmOptions = "-Dfile.encoding=UTF-8 ${VmOptionsGenerator.computeCommonVmOptions(buildContext.applicationInfo.isEAP)} -Xverify:none"
|
||||
|
||||
//todo[nik] improve
|
||||
String minor = buildContext.applicationInfo.minorVersion
|
||||
boolean isNotRelease = buildContext.applicationInfo.isEAP && !minor.contains("RC") && !minor.contains("Beta")
|
||||
String version = isNotRelease ? "EAP $buildContext.fullBuildNumber" : "${buildContext.applicationInfo.majorVersion}.${minor}"
|
||||
String EAP = isNotRelease ? "-EAP" : ""
|
||||
|
||||
//todo[nik] don't mix properties for idea.properties file with properties for Info.plist
|
||||
Map<String, String> properties = readIdeaProperties(ideaPropertiesFile, customIdeaProperties)
|
||||
|
||||
def coreKeys = ["idea.platform.prefix", "idea.paths.selector", "idea.executable"]
|
||||
|
||||
String coreProperties = submapToXml(properties, coreKeys);
|
||||
|
||||
StringBuilder effectiveProperties = new StringBuilder()
|
||||
properties.each { k, v ->
|
||||
if (!coreKeys.contains(k)) {
|
||||
effectiveProperties.append("$k=$v\n");
|
||||
}
|
||||
}
|
||||
|
||||
new File("$target/bin/idea.properties").text = effectiveProperties.toString()
|
||||
String ideaVmOptions = "${VmOptionsGenerator.vmOptionsForArch(JvmArchitecture.x64)} -XX:+UseCompressedOops"
|
||||
if (buildContext.applicationInfo.isEAP && buildContext.productProperties.includeYourkitAgentInEAP && macProductProperties.includeYourkitAgentInEAP) {
|
||||
ideaVmOptions += VmOptionsGenerator.yourkitOptions(buildContext.systemSelector, "")
|
||||
}
|
||||
new File("$target/bin/${executable}.vmoptions").text = ideaVmOptions.split(" ").join("\n")
|
||||
|
||||
String classPath = buildContext.bootClassPathJarNames.collect { "\$APP_PACKAGE/Contents/lib/${it}" }.join(":")
|
||||
|
||||
String archsString = """
|
||||
<key>LSArchitecturePriority</key>
|
||||
<array>"""
|
||||
macProductProperties.architectures.each {
|
||||
archsString += "<string>$it</string>"
|
||||
}
|
||||
archsString += "</array>\n"
|
||||
|
||||
List<String> urlSchemes = macProductProperties.urlSchemes
|
||||
String urlSchemesString = ""
|
||||
if (urlSchemes.size() > 0) {
|
||||
urlSchemesString += """
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Stacktrace</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
"""
|
||||
urlSchemes.each { scheme ->
|
||||
urlSchemesString += " <string>${scheme}</string>"
|
||||
}
|
||||
urlSchemesString += """
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
"""
|
||||
}
|
||||
|
||||
String todayYear = LocalDate.now().year
|
||||
buildContext.ant.replace(file: "$target/Info.plist") {
|
||||
replacefilter(token: "@@build@@", value: buildContext.fullBuildNumber)
|
||||
replacefilter(token: "@@doc_types@@", value: docTypes ?: "")
|
||||
replacefilter(token: "@@executable@@", value: executable)
|
||||
replacefilter(token: "@@icns@@", value: icns)
|
||||
replacefilter(token: "@@bundle_name@@", value: fullName)
|
||||
replacefilter(token: "@@product_state@@", value: EAP)
|
||||
replacefilter(token: "@@bundle_identifier@@", value: macProductProperties.bundleIdentifier)
|
||||
replacefilter(token: "@@year@@", value: "$todayYear")
|
||||
replacefilter(token: "@@company_name@@", value: buildContext.applicationInfo.companyName)
|
||||
replacefilter(token: "@@min_year@@", value: "2000")
|
||||
replacefilter(token: "@@max_year@@", value: "$todayYear")
|
||||
replacefilter(token: "@@version@@", value: version)
|
||||
replacefilter(token: "@@vmoptions@@", value: vmOptions)
|
||||
replacefilter(token: "@@idea_properties@@", value: coreProperties)
|
||||
replacefilter(token: "@@class_path@@", value: classPath)
|
||||
replacefilter(token: "@@help_id@@", value: helpId)
|
||||
replacefilter(token: "@@url_schemes@@", value: urlSchemesString)
|
||||
replacefilter(token: "@@archs@@", value: archsString)
|
||||
replacefilter(token: "@@min_osx@@", value: macProductProperties.minOSXVersion)
|
||||
}
|
||||
|
||||
if (executable != "idea") {
|
||||
buildContext.ant.move(file: "$target/MacOS/idea", tofile: "$target/MacOS/$executable")
|
||||
}
|
||||
|
||||
buildContext.ant.replace(file: "$target/bin/inspect.sh") {
|
||||
replacefilter(token: "@@product_full@@", value: fullName)
|
||||
replacefilter(token: "@@script_name@@", value: executable)
|
||||
}
|
||||
String inspectScript = buildContext.productProperties.customInspectScriptName
|
||||
if (inspectScript != null && inspectScript != "inspect") {
|
||||
buildContext.ant.move(file: "$target/bin/inspect.sh", tofile: "$target/bin/${inspectScript}.sh")
|
||||
}
|
||||
|
||||
buildContext.ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix")
|
||||
buildContext.ant.fixcrlf(srcdir: "$target/bin", includes: "*.py", eol: "unix")
|
||||
}
|
||||
|
||||
void buildMacZip() {
|
||||
buildContext.messages.block("Build zip archive for Mac OS") {
|
||||
def extraBins = buildContext.productProperties.mac.extraMacBins
|
||||
def allPaths = [buildContext.paths.distAll, macDistPath]
|
||||
def zipRoot = buildContext.productProperties.macAppRoot(buildContext.applicationInfo, buildContext.buildNumber)
|
||||
def targetPath = "$buildContext.paths.artifacts/${buildContext.productProperties.archiveName(buildContext.buildNumber)}.mac.zip"
|
||||
buildContext.ant.zip(zipfile: targetPath) {
|
||||
allPaths.each {
|
||||
zipfileset(dir: it, prefix: zipRoot) {
|
||||
exclude(name: "bin/*.sh")
|
||||
exclude(name: "bin/*.py")
|
||||
exclude(name: "bin/fsnotifier")
|
||||
exclude(name: "bin/restarter")
|
||||
exclude(name: "MacOS/*")
|
||||
exclude(name: "build.txt")
|
||||
exclude(name: "NOTICE.txt")
|
||||
extraBins.each {
|
||||
exclude(name: it)
|
||||
}
|
||||
exclude(name: "bin/idea.properties")
|
||||
}
|
||||
}
|
||||
|
||||
allPaths.each {
|
||||
zipfileset(dir: it, filemode: "755", prefix: zipRoot) {
|
||||
include(name: "bin/*.sh")
|
||||
include(name: "bin/*.py")
|
||||
include(name: "bin/fsnotifier")
|
||||
include(name: "bin/restarter")
|
||||
include(name: "MacOS/*")
|
||||
extraBins.each {
|
||||
include(name: it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allPaths.each {
|
||||
zipfileset(dir: it, prefix: "$zipRoot/Resources") {
|
||||
include(name: "build.txt")
|
||||
include(name: "NOTICE.txt")
|
||||
}
|
||||
}
|
||||
|
||||
zipfileset(file: "$macDistPath/bin/idea.properties", prefix: "$zipRoot/bin")
|
||||
}
|
||||
buildContext.notifyArtifactBuilt(targetPath)
|
||||
}
|
||||
}
|
||||
|
||||
private static String submapToXml(Map<String, String> properties, List<String> keys) {
|
||||
// generate properties description for Info.plist
|
||||
StringBuilder buff = new StringBuilder()
|
||||
|
||||
keys.each { key ->
|
||||
String value = properties[key]
|
||||
if (value != null) {
|
||||
String string =
|
||||
"""
|
||||
<key>$key</key>
|
||||
<string>$value</string>
|
||||
"""
|
||||
buff.append(string)
|
||||
}
|
||||
}
|
||||
return buff.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* E.g.
|
||||
*
|
||||
* Load all properties from file:
|
||||
* readIdeaProperties(buildContext, "$home/ruby/build/idea.properties")
|
||||
*
|
||||
* Load all properties except "idea.cycle.buffer.size", change "idea.max.intellisense.filesize" to 3000
|
||||
* and enable "idea.is.internal" mode:
|
||||
* readIdeaProperties(buildContext, "$home/ruby/build/idea.properties",
|
||||
* "idea.properties" : ["idea.max.intellisense.filesize" : 3000,
|
||||
* "idea.cycle.buffer.size" : null,
|
||||
* "idea.is.internal" : true ])
|
||||
* @param args
|
||||
* @return text xml properties description in xml
|
||||
*/
|
||||
private Map<String, String> readIdeaProperties(File propertiesFile, Map<String, String> customProperties = [:]) {
|
||||
Map<String, String> ideaProperties = [:]
|
||||
propertiesFile.withReader {
|
||||
Properties loadedProperties = new Properties();
|
||||
loadedProperties.load(it)
|
||||
ideaProperties.putAll(loadedProperties as Map<String, String>)
|
||||
}
|
||||
|
||||
Map<String, String> properties =
|
||||
["CVS_PASSFILE" : "~/.cvspass",
|
||||
"com.apple.mrj.application.live-resize" : "false",
|
||||
"idea.paths.selector" : buildContext.systemSelector,
|
||||
"idea.executable" : buildContext.fileNamePrefix,
|
||||
"java.endorsed.dirs" : "",
|
||||
"idea.smooth.progress" : "false",
|
||||
"apple.laf.useScreenMenuBar" : "true",
|
||||
"apple.awt.graphics.UseQuartz" : "true",
|
||||
"apple.awt.fullscreencapturealldisplays": "false"]
|
||||
if (buildContext.productProperties.platformPrefix != null) {
|
||||
properties["idea.platform.prefix"] = buildContext.productProperties.platformPrefix
|
||||
}
|
||||
|
||||
properties += customProperties
|
||||
|
||||
properties.each { k, v ->
|
||||
if (v == null) {
|
||||
// if overridden with null - ignore property
|
||||
ideaProperties.remove(k)
|
||||
}
|
||||
else {
|
||||
// if property is overridden in args map - use new value
|
||||
ideaProperties[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return ideaProperties
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class VmOptionsGenerator {
|
||||
private static final String COMMON_VM_OPTIONS = "-XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea " +
|
||||
"-Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
|
||||
"-XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow"
|
||||
|
||||
static String computeVmOptions(JvmArchitecture arch, boolean isEAP, String yourkitSessionName = null) {
|
||||
String options = vmOptionsForArch(arch) + " " + computeCommonVmOptions(isEAP)
|
||||
if (yourkitSessionName != null) {
|
||||
options += " " + yourkitOptions(yourkitSessionName, arch.fileSuffix)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
static String computeCommonVmOptions(boolean isEAP) {
|
||||
String options = COMMON_VM_OPTIONS
|
||||
if (isEAP) {
|
||||
options += " -XX:MaxJavaStackTraceDepth=-1"
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
static String vmOptionsForArch(JvmArchitecture arch) {
|
||||
switch (arch) {
|
||||
case JvmArchitecture.x32: return "-server -Xms128m -Xmx512m -XX:ReservedCodeCacheSize=240m"
|
||||
case JvmArchitecture.x64: return "-Xms128m -Xmx750m -XX:ReservedCodeCacheSize=240m"
|
||||
}
|
||||
throw new AssertionError(arch)
|
||||
}
|
||||
|
||||
static String yourkitOptions(String sessionName, String fileSuffix) {
|
||||
"-agentlib:yjpagent$fileSuffix=probe_disable=*,disablealloc,disabletracing,onlylocal,disableexceptiontelemetry,delay=10000,sessionname=$sessionName".trim()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.impl
|
||||
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.jps.model.module.JpsModuleSourceRoot
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class WindowsDistributionBuilder {
|
||||
private final BuildContext buildContext
|
||||
final String winDistPath
|
||||
|
||||
WindowsDistributionBuilder(BuildContext buildContext) {
|
||||
this.buildContext = buildContext
|
||||
winDistPath = "$buildContext.paths.buildOutputRoot/dist.win"
|
||||
}
|
||||
|
||||
//todo[nik] rename
|
||||
void layoutWin(File ideaProperties) {
|
||||
buildContext.ant.copy(todir: "$winDistPath/bin") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/bin/win")
|
||||
}
|
||||
buildContext.ant.copy(file: ideaProperties.path, todir: "$winDistPath/bin")
|
||||
buildContext.ant.fixcrlf(file: "$winDistPath/bin/idea.properties", eol: "dos")
|
||||
|
||||
buildContext.ant.copy(file: buildContext.productProperties.ico, tofile: "$winDistPath/bin/${buildContext.fileNamePrefix}.ico")
|
||||
if (buildContext.productProperties.windows.includeBatchLauncher) {
|
||||
winScripts()
|
||||
}
|
||||
winVMOptions()
|
||||
buildWinLauncher(JvmArchitecture.x32)
|
||||
buildWinLauncher(JvmArchitecture.x64)
|
||||
buildContext.productProperties.customWinLayout(winDistPath)
|
||||
buildWinZip()
|
||||
}
|
||||
|
||||
//todo[nik] rename
|
||||
private void winScripts() {
|
||||
String fullName = buildContext.applicationInfo.productName
|
||||
String productUpperCase = buildContext.applicationInfo.shortProductName.toUpperCase()
|
||||
//todo[nik] looks like names without .exe were also supported, do we need this?
|
||||
String vmOptionsFileName = "${buildContext.fileNamePrefix}%BITS%.exe"
|
||||
|
||||
String classPath = "SET CLASS_PATH=%IDE_HOME%\\lib\\${buildContext.bootClassPathJarNames[0]}\n"
|
||||
classPath += buildContext.bootClassPathJarNames[1..-1].collect { "SET CLASS_PATH=%CLASS_PATH%;%IDE_HOME%\\lib\\$it" }.join("\n")
|
||||
def jvmArgs = buildContext.productProperties.ideJvmArgs
|
||||
if (buildContext.productProperties.toolsJarRequired) {
|
||||
classPath += "\nSET CLASS_PATH=%CLASS_PATH%;%JDK%\\lib\\tools.jar"
|
||||
jvmArgs = "$jvmArgs -Didea.jre.check=true".trim()
|
||||
}
|
||||
|
||||
def batName = "${buildContext.fileNamePrefix}.bat"
|
||||
buildContext.ant.copy(todir: "$winDistPath/bin") {
|
||||
fileset(dir: "$buildContext.paths.communityHome/bin/scripts/win")
|
||||
|
||||
filterset(begintoken: "@@", endtoken: "@@") {
|
||||
filter(token: "product_full", value: fullName)
|
||||
filter(token: "product_uc", value: productUpperCase)
|
||||
filter(token: "vm_options", value: vmOptionsFileName)
|
||||
filter(token: "isEap", value: buildContext.applicationInfo.isEAP)
|
||||
filter(token: "system_selector", value: buildContext.systemSelector)
|
||||
filter(token: "ide_jvm_args", value: jvmArgs)
|
||||
filter(token: "class_path", value: classPath)
|
||||
filter(token: "script_name", value: batName)
|
||||
}
|
||||
}
|
||||
|
||||
if (batName != "idea.bat") {
|
||||
//todo[nik] rename idea.bat in sources to something more generic
|
||||
buildContext.ant.move(file: "$winDistPath/bin/idea.bat", tofile: "$winDistPath/bin/$batName")
|
||||
}
|
||||
String inspectScript = buildContext.productProperties.customInspectScriptName
|
||||
if (inspectScript != null && inspectScript != "inspect") {
|
||||
buildContext.ant.move(file: "$winDistPath/bin/inspect.bat", tofile: "$winDistPath/bin/${inspectScript}.bat")
|
||||
}
|
||||
|
||||
|
||||
buildContext.ant.fixcrlf(srcdir: "$winDistPath/bin", includes: "*.bat", eol: "dos")
|
||||
}
|
||||
|
||||
//todo[nik] rename
|
||||
private void winVMOptions() {
|
||||
JvmArchitecture.values().each {
|
||||
def yourkitSessionName = buildContext.applicationInfo.isEAP && buildContext.productProperties.includeYourkitAgentInEAP ? buildContext.systemSelector : null
|
||||
def fileName = "${buildContext.fileNamePrefix}${it.fileSuffix}.exe.vmoptions"
|
||||
new File(winDistPath, "bin/$fileName").text = VmOptionsGenerator.computeVmOptions(it, buildContext.applicationInfo.isEAP, yourkitSessionName).replace(' ', '\n')
|
||||
}
|
||||
|
||||
buildContext.ant.fixcrlf(srcdir: "$winDistPath/bin", includes: "*.vmoptions", eol: "dos")
|
||||
}
|
||||
|
||||
private void buildWinLauncher(JvmArchitecture arch) {
|
||||
buildContext.messages.block("Build Windows executable ${arch.name()}") {
|
||||
String exeFileName = "$buildContext.fileNamePrefix${arch.fileSuffix}.exe"
|
||||
def launcherPropertiesPath = "${buildContext.paths.temp}/launcher.properties"
|
||||
//todo[nik] generate launcher.properties file automatically
|
||||
def launcherPropertiesTemplatePath = arch == JvmArchitecture.x32 ? buildContext.productProperties.exe_launcher_properties
|
||||
: buildContext.productProperties.exe64_launcher_properties
|
||||
|
||||
BuildUtils.copyAndPatchFile(launcherPropertiesTemplatePath, launcherPropertiesPath,
|
||||
["PRODUCT_PATHS_SELECTOR": buildContext.systemSelector,
|
||||
"IDE-NAME": buildContext.applicationInfo.shortProductName.toUpperCase()])
|
||||
|
||||
def communityHome = "$buildContext.paths.communityHome"
|
||||
String inputPath = "$communityHome/bin/WinLauncher/WinLauncher${arch.fileSuffix}.exe"
|
||||
buildContext.ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true", failonerror: "true") {
|
||||
sysproperty(key: "java.awt.headless", value: "true")
|
||||
arg(value: inputPath)
|
||||
arg(value: buildContext.findApplicationInfoInSources().absolutePath)
|
||||
arg(value: "$communityHome/native/WinLauncher/WinLauncher/resource.h")
|
||||
arg(value: launcherPropertiesPath)
|
||||
arg(value: "$winDistPath/bin/$exeFileName")
|
||||
classpath {
|
||||
pathelement(location: "$communityHome/build/lib/launcher-generator.jar")
|
||||
fileset(dir: "$communityHome/lib") {
|
||||
include(name: "guava*.jar")
|
||||
include(name: "jdom.jar")
|
||||
include(name: "sanselan*.jar")
|
||||
}
|
||||
[buildContext.findApplicationInfoModule(), buildContext.findModule("icons")].collectMany { it.sourceRoots }.each { JpsModuleSourceRoot root ->
|
||||
pathelement(location: root.file.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildWinZip() {
|
||||
buildContext.messages.block("Build Windows .zip distribution") {
|
||||
def targetPath = "$buildContext.paths.artifacts/${buildContext.productProperties.archiveName(buildContext.buildNumber)}.win.zip"
|
||||
def zipPrefix = buildContext.productProperties.winAppRoot(buildContext.buildNumber)
|
||||
def dirs = [buildContext.paths.distAll, winDistPath]
|
||||
if (buildContext.productProperties.windows.bundleJre && new File(buildContext.paths.winJre).exists()) {
|
||||
dirs += buildContext.paths.winJre
|
||||
}
|
||||
buildContext.ant.zip(zipfile: targetPath) {
|
||||
dirs.each {
|
||||
zipfileset(dir: it, prefix: zipPrefix)
|
||||
}
|
||||
}
|
||||
buildContext.notifyArtifactBuilt(targetPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
-239
@@ -13,10 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.apache.tools.ant.BuildException
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.BuildOptions
|
||||
import org.jetbrains.intellij.build.BuildTasks
|
||||
import org.jetbrains.jps.gant.LayoutInfo
|
||||
|
||||
import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
|
||||
@@ -27,40 +27,12 @@ requireProperty("out", "$home/out")
|
||||
|
||||
// "out" has to be canonical, otherwise the ant build fails
|
||||
// with mysterious errors
|
||||
out = new File(out).getCanonicalPath()
|
||||
setProperty("out", out)
|
||||
String out = new File(out).getCanonicalPath()
|
||||
|
||||
class Paths {
|
||||
final sandbox
|
||||
final distWin
|
||||
final distAll
|
||||
final distUnix
|
||||
final distMac
|
||||
final artifacts
|
||||
final artifacts_core
|
||||
final artifacts_jps
|
||||
final ideaSystem
|
||||
final ideaConfig
|
||||
loadProductProperties(home)
|
||||
|
||||
def Paths(String out) {
|
||||
sandbox = out
|
||||
distWin = "$sandbox/dist.win.ce"
|
||||
distAll = "$sandbox/dist.all.ce"
|
||||
distUnix = "$sandbox/dist.unix.ce"
|
||||
distMac = "$sandbox/dist.mac.ce"
|
||||
artifacts = "$sandbox/artifacts"
|
||||
artifacts_core = "$artifacts/core"
|
||||
artifacts_jps = "$artifacts/jps"
|
||||
ideaSystem = "$sandbox/system"
|
||||
ideaConfig = "$sandbox/config"
|
||||
}
|
||||
}
|
||||
|
||||
def paths = new Paths(out)
|
||||
setProperty("paths", paths)
|
||||
loadProductProperties(home, snapshot)
|
||||
|
||||
def loadProductProperties(String home, String buildNumber) {
|
||||
def loadProductProperties(String home) {
|
||||
//todo[nik] improve (load implementation class from groovy resources root directly?)
|
||||
requireProperty("product", "idea")
|
||||
requireProperty("productPropertiesPath", "")
|
||||
if (productPropertiesPath.isEmpty()) {
|
||||
@@ -69,231 +41,75 @@ def loadProductProperties(String home, String buildNumber) {
|
||||
if (!new File(productPropertiesPath).exists()) {
|
||||
throw new BuildException("No product specific properties file found at: " + productPropertiesPath)
|
||||
}
|
||||
setProperty("productProperties", includeFile(productPropertiesPath).getProperties(home, buildNumber))
|
||||
productProperties.ideJvmArgs = productProperties.ideJvmArgs != null ?
|
||||
productProperties.ideJvmArgs + " -Didea.jre.check=true" :
|
||||
"-Didea.jre.check=true"
|
||||
setProperty("productProperties", includeFile(productPropertiesPath).getProperties(home))
|
||||
}
|
||||
|
||||
private BuildContext createBuildContext(String out, BuildOptions options = new BuildOptions()) {
|
||||
//todo[nik] construct buildOutputRoot automatically based on product name
|
||||
BuildContext.createContext(ant, projectBuilder, project, global, home, home, "$out/release", productProperties, options)
|
||||
}
|
||||
|
||||
private static void compileModules(BuildContext buildContext) {
|
||||
BuildTasks.create(buildContext).compileProjectAndTests(["jps-builders"])
|
||||
}
|
||||
|
||||
target(compile: "Compile project") {
|
||||
projectBuilder.stage("Cleaning up sandbox folder")
|
||||
forceDelete(paths.sandbox)
|
||||
|
||||
loadProject()
|
||||
|
||||
[paths.sandbox, paths.distWin, paths.distAll, paths.distUnix, paths.distMac, paths.artifacts, paths.artifacts_core, paths.artifacts_jps].each {
|
||||
ant.mkdir(dir: it)
|
||||
}
|
||||
|
||||
projectBuilder.targetFolder = "$out/classes"
|
||||
clearBuildCaches()
|
||||
projectBuilder.cleanOutput()
|
||||
projectBuilder.buildProduction()
|
||||
projectBuilder.makeModuleTests(findModule("jps-builders"))
|
||||
}
|
||||
|
||||
private String appInfoFile() {
|
||||
return productProperties.appInfoFile()
|
||||
compileModules(createBuildContext(out))
|
||||
}
|
||||
|
||||
target('default': 'The default target') {
|
||||
depends([compile])
|
||||
|
||||
// load ApplicationInfo.xml properties
|
||||
ant.xmlproperty(file: appInfoFile(), collapseAttributes: "true")
|
||||
|
||||
zipSources(home, paths.artifacts)
|
||||
|
||||
indexSearchableOptions()
|
||||
|
||||
layoutAll([buildNumber: productProperties.fullBuildNumber(),
|
||||
system_selector: productProperties.systemSelector(),
|
||||
platform_prefix: productProperties.platformPrefix,
|
||||
ide_jvm_args: productProperties.ideJvmArgs,
|
||||
tools_jar: true],
|
||||
home, null, paths, true)
|
||||
String archiveName = productProperties.archiveName()
|
||||
String macZip = "$paths.artifacts/${archiveName}.mac.zip"
|
||||
notifyArtifactBuilt(macZip)
|
||||
def buildContext = createBuildContext(out)
|
||||
compileModules(buildContext)
|
||||
def tasks = BuildTasks.create(buildContext)
|
||||
tasks.cleanOutput()
|
||||
tasks.buildSearchableOptions("resources-en", ["community-main"], [])
|
||||
|
||||
layoutAll(buildContext, true)
|
||||
if (productProperties.buildUpdater) {
|
||||
// Generate updater.jar from the updater module (patch updater)
|
||||
layoutUpdater(out)
|
||||
}
|
||||
tasks.zipSources()
|
||||
}
|
||||
|
||||
//todo[nik] do we really need this target? updates.xml calls layout.gant directly
|
||||
target('build-dist-jars' : 'Target to build jars from locally compiled classes') {
|
||||
loadProject()
|
||||
|
||||
// load ApplicationInfo.xml properties
|
||||
ant.xmlproperty(file: appInfoFile(), collapseAttributes: "true")
|
||||
|
||||
indexSearchableOptions()
|
||||
|
||||
layoutAll([buildNumber: productProperties.fullBuildNumber(),
|
||||
system_selector: productProperties.systemSelector(),
|
||||
platform_prefix: productProperties.platformPrefix,
|
||||
ide_jvm_args: productProperties.ideJvmArgs,
|
||||
tools_jar: true],
|
||||
home, null, paths)
|
||||
String macZipPrefix = productProperties.prefix + productProperties.fullBuildNumber()
|
||||
String macZip = "$paths.artifacts/${macZipPrefix}.mac.zip"
|
||||
notifyArtifactBuilt(macZip)
|
||||
def options = new BuildOptions()
|
||||
options.useCompiledClassesFromProjectOutput = true
|
||||
def buildContext = createBuildContext(out, options)
|
||||
compileModules(buildContext)
|
||||
def tasks = BuildTasks.create(buildContext)
|
||||
tasks.cleanOutput()
|
||||
tasks.buildSearchableOptions("resources-en", ["community-main"], [])
|
||||
layoutAll(buildContext)
|
||||
}
|
||||
|
||||
private void indexSearchableOptions() {
|
||||
buildSearchableOptions("${projectBuilder.moduleOutput(findModule("resources-en"))}/search", [], {
|
||||
ant.pathelement(location: "$jdkHome/lib/tools.jar")
|
||||
ant.pathelement(location: "$home/lib/junit.jar")
|
||||
projectBuilder.moduleRuntimeClasspath(findModule("community-main"), false).each {
|
||||
ant.pathelement(location: it)
|
||||
def layoutAll(BuildContext buildContext, buildJps = false) {
|
||||
def layouts = includeFile("$buildContext.paths.communityHome/build/scripts/layouts.gant")
|
||||
def tasks = BuildTasks.create(buildContext)
|
||||
def applicationInfo = tasks.patchApplicationInfo()
|
||||
LayoutInfo info = layouts.layoutFull(buildContext.paths.projectHome, buildContext.paths.distAll, applicationInfo)
|
||||
|
||||
buildContext.messages.block("Build intellij-core") {
|
||||
String coreArtifactDir = "$buildContext.paths.artifacts/core"
|
||||
buildContext.ant.mkdir(dir: coreArtifactDir)
|
||||
layouts.layout_core(buildContext.paths.projectHome, coreArtifactDir)
|
||||
buildContext.notifyArtifactBuilt(coreArtifactDir)
|
||||
|
||||
def intellijCoreZip = "${buildContext.paths.artifacts}/intellij-core-${buildContext.buildNumber}.zip"
|
||||
ant.zip(destfile: intellijCoreZip) {
|
||||
fileset(dir: coreArtifactDir)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) {
|
||||
Paths paths = _paths != null ? _paths : new Paths(out)
|
||||
|
||||
wireBuildDate(args.buildNumber, appInfoFile())
|
||||
ant.echo(message: args.buildNumber, file: "$paths.distAll/build.txt")
|
||||
|
||||
def layouts = includeFile("$home/build/scripts/layouts.gant")
|
||||
LayoutInfo info = layouts.layoutFull(home, paths.distAll, null)
|
||||
layouts.layout_core(home, paths.artifacts_core)
|
||||
ant.zip(destfile: "${paths.artifacts}/intellij-core-${StringUtil.trimStart(args.buildNumber, "IC-")}.zip") {
|
||||
fileset(dir: paths.artifacts_core)
|
||||
buildContext.notifyArtifactBuilt(intellijCoreZip)
|
||||
}
|
||||
|
||||
notifyArtifactBuilt(paths.artifacts_core)
|
||||
if (buildJps) {
|
||||
layouts.layoutJps(home, paths.artifacts_jps, args.buildNumber, {})
|
||||
notifyArtifactBuilt(paths.artifacts_jps)
|
||||
}
|
||||
|
||||
layout(paths.distAll) {
|
||||
dir("bin") {
|
||||
fileset(dir: "${home}/bin") {
|
||||
include(name: "*.*")
|
||||
}
|
||||
buildContext.messages.block("Build standalone JPS") {
|
||||
String jpsArtifactDir = "$buildContext.paths.artifacts/jps"
|
||||
layouts.layoutJps(buildContext.paths.communityHome, jpsArtifactDir, buildContext.fullBuildNumber, {})
|
||||
buildContext.notifyArtifactBuilt(jpsArtifactDir)
|
||||
}
|
||||
|
||||
dir("license") {
|
||||
fileset(dir: "${home}/license") {
|
||||
exclude(name: "placeholder.txt")
|
||||
}
|
||||
}
|
||||
fileset(file: "${home}/LICENSE.txt")
|
||||
fileset(file: "${home}/NOTICE.txt")
|
||||
}
|
||||
patchPropertiesFile(paths.distAll, args + [appendices: ["$home/build/conf/ideaCE.properties"]])
|
||||
|
||||
layoutWin(args, home, paths)
|
||||
layoutMac(args, home, paths)
|
||||
layoutUnix(args, home, paths)
|
||||
|
||||
def macAppRoot = productProperties.macAppRoot()
|
||||
def winAppRoot = productProperties.winAppRoot()
|
||||
def linuxAppRoot = productProperties.linuxAppRoot()
|
||||
def archiveName = productProperties.archiveName()
|
||||
|
||||
List pathsDist = new File("${paths.sandbox}/jdk.win/jre").exists() ? [paths.distAll, paths.distWin, "${paths.sandbox}/jdk.win"] : [paths.distAll, paths.distWin]
|
||||
buildWinZip("$paths.artifacts/${archiveName}.win.zip", pathsDist, winAppRoot)
|
||||
//win oracle jdk
|
||||
if (new File("${paths.sandbox}/jdk.oracle.win/jre").exists()) {
|
||||
buildWinZip("$paths.artifacts/${archiveName}-oracle-win.zip",
|
||||
[paths.distAll, paths.distWin, "${paths.sandbox}/jdk.oracle.win"])
|
||||
}
|
||||
|
||||
|
||||
buildCrossPlatformZip("$paths.artifacts/idea${args.buildNumber}.zip", "${paths.sandbox}/sandbox-ce", [paths.distAll],
|
||||
paths.distWin, paths.distUnix, paths.distMac)
|
||||
|
||||
String macZip = "$paths.artifacts/${archiveName}.mac.zip"
|
||||
buildMacZip(macAppRoot, macZip, [paths.distAll], paths.distMac, productProperties.extraMacBins)
|
||||
|
||||
buildTarGz(linuxAppRoot, "$paths.artifacts/${archiveName}-no-jdk.tar", [paths.distAll, paths.distUnix], productProperties.extraLinuxBins)
|
||||
requireProperty("jdk.linux", "false")
|
||||
if (p("jdk.linux") != "false") {
|
||||
buildTarGz(linuxAppRoot, "$paths.artifacts/${archiveName}.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/jdk.linux"], ["jre/jre/bin/*"] + productProperties.extraLinuxBins)
|
||||
}
|
||||
tasks.buildDistributions()
|
||||
return info
|
||||
}
|
||||
|
||||
private layoutWin(Map args, String home, Paths paths) {
|
||||
String target = paths.distWin
|
||||
|
||||
layout(target) {
|
||||
dir("bin") {
|
||||
fileset(dir: "$home/bin/win")
|
||||
}
|
||||
}
|
||||
|
||||
def name = productProperties.prefix
|
||||
def ico = productProperties.ico
|
||||
|
||||
ant.copy(file: ico, tofile: "$target/bin/${name}.ico")
|
||||
|
||||
if (productProperties.includeBatchLauncher) {
|
||||
winScripts(target, home, "${name}.bat", args)
|
||||
}
|
||||
winVMOptions(target, productProperties.includeYourkitAgentInEAP ? args.system_selector : null, "${name}.exe", "${name}64.exe")
|
||||
def appInfoModulePath = productProperties.appInfoModulePath
|
||||
|
||||
List resourcePaths = ["$home/${appInfoModulePath}/src", "$home/platform/icons/src"]
|
||||
buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher.exe", "$target/bin/${name}.exe", appInfoFile(),
|
||||
productProperties.exe_launcher_properties, args.system_selector, resourcePaths)
|
||||
buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher64.exe", "$target/bin/${name}64.exe", appInfoFile(),
|
||||
productProperties.exe64_launcher_properties, args.system_selector, resourcePaths)
|
||||
|
||||
productProperties.customWinLayout(target)
|
||||
}
|
||||
|
||||
private layoutMac(Map _args, String home, Paths paths) {
|
||||
String target = paths.distMac
|
||||
def prefix = productProperties.prefix
|
||||
|
||||
Map args = new HashMap(_args)
|
||||
args.bundleIdentifier = productProperties.bundleIdentifier
|
||||
args.doc_types = """
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>ipr</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>${prefix}.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>IntelliJ IDEA Project File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
"""
|
||||
args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
|
||||
args."idea.properties" = ["idea.jre.check": true];
|
||||
args.urlSchemes = ["idea"]
|
||||
args.mac_no_yjp = true
|
||||
args.executable = prefix
|
||||
args.icns = productProperties.icns
|
||||
layoutMacApp(target, home, args)
|
||||
productProperties.customMacLayout(target)
|
||||
}
|
||||
|
||||
private layoutUnix(Map args, String home, Paths paths) {
|
||||
String target = paths.distUnix
|
||||
|
||||
layout(target) {
|
||||
dir("bin") {
|
||||
fileset(dir: "$home/bin/linux")
|
||||
}
|
||||
}
|
||||
|
||||
def name = productProperties.prefix
|
||||
def icon128 = productProperties.icon128
|
||||
|
||||
ant.copy(file: icon128, tofile: "$target/bin/${name}.png")
|
||||
|
||||
unixScripts(target, home, "${name}.sh", args)
|
||||
unixVMOptions(target, "${name}")
|
||||
unixReadme(target, home, args)
|
||||
productProperties.customLinLayout(target)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import org.jetbrains.intellij.build.ApplicationInfoProperties
|
||||
import org.jetbrains.intellij.build.ProductProperties
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
@@ -17,41 +17,47 @@ import org.jetbrains.intellij.build.ProductProperties
|
||||
*/
|
||||
|
||||
|
||||
def getProperties(String home, String buildNumber) {
|
||||
def getProperties(String home) {
|
||||
return new ProductProperties() {
|
||||
{
|
||||
prefix = "idea"
|
||||
platformPrefix = "Idea"
|
||||
code = "IC"
|
||||
appInfoModule = "community-resources"
|
||||
appInfoModulePath = "community-resources"
|
||||
additionalIDEPropertiesFilePath = "$home/build/conf/ideaCE.properties"
|
||||
exe_launcher_properties = "$home/build/conf/ideaCE-launcher.properties"
|
||||
exe64_launcher_properties = "$home/build/conf/ideaCE64-launcher.properties"
|
||||
bundleIdentifier = "com.jetbrains.intellij.ce"
|
||||
maySkipAndroidPlugin = true
|
||||
relativeAndroidHome = "android"
|
||||
relativeAndroidToolsBaseHome = "android/tools-base"
|
||||
toolsJarRequired = true
|
||||
|
||||
icon128 = "$home/platform/icons/src/icon_CE_128.png"
|
||||
ico = "$home/platform/icons/src/idea_CE.ico"
|
||||
|
||||
windows.bundleJre = true
|
||||
|
||||
mac.helpId = "IJ"
|
||||
mac.urlSchemes = ["idea"]
|
||||
mac.includeYourkitAgentInEAP = false
|
||||
mac.bundleIdentifier = "com.jetbrains.intellij.ce"
|
||||
}
|
||||
|
||||
def String appInfoFile() {
|
||||
"${projectBuilder.moduleOutput(findModule("community-resources"))}/idea/IdeaApplicationInfo.xml"
|
||||
}
|
||||
|
||||
def String fullBuildNumber() { "IC-$buildNumber" }
|
||||
def String systemSelector(ApplicationInfoProperties applicationInfo) { "IdeaIC$applicationInfo.majorVersion" }
|
||||
|
||||
def String systemSelector() { "IdeaIC${p("component.version.major")}" }
|
||||
|
||||
def String macAppRoot() {
|
||||
isEap() ? "IntelliJ IDEA ${p("component.version.major")}.${p("component.version.minor")} CE EAP.app/Contents"
|
||||
def String macAppRoot(ApplicationInfoProperties applicationInfo, String buildNumber) {
|
||||
applicationInfo.isEAP ? "IntelliJ IDEA ${applicationInfo.majorVersion}.${applicationInfo.minorVersion} CE EAP.app/Contents"
|
||||
: "IntelliJ IDEA CE.app/Contents"
|
||||
}
|
||||
|
||||
def String winAppRoot() { "" }
|
||||
def String winAppRoot(String buildNumber) { "" }
|
||||
|
||||
def String linuxAppRoot() { "idea-IC-$buildNumber" }
|
||||
def String linuxAppRoot(String buildNumber) { "idea-IC-$buildNumber" }
|
||||
|
||||
def String archiveName() { "ideaIC-$buildNumber" }
|
||||
def String archiveName(String buildNumber) { "ideaIC-$buildNumber" }
|
||||
}
|
||||
}
|
||||
+15
-15
@@ -21,9 +21,9 @@ target('default': "Developers update") {
|
||||
//when IDEA CE is updated from IDEA UE sources project should be loaded from IDEA UE directory
|
||||
String projectHome = isDefined("devIdeaHome") ? devIdeaHome : home
|
||||
loadProjectFromPath(projectHome)
|
||||
def patchedDescriptorDir = patchAppDescriptor(deploy)
|
||||
layoutFull(home, deploy, patchedDescriptorDir)
|
||||
ant.delete(dir: patchedDescriptorDir)
|
||||
def patchedAppInfo = patchApplicationInfo(deploy)
|
||||
layoutFull(home, deploy, patchedAppInfo)
|
||||
ant.delete(dir: patchedAppInfo)
|
||||
}
|
||||
|
||||
String appInfoFileName() {
|
||||
@@ -64,7 +64,7 @@ List<String> getExcludedPlugins() {
|
||||
return isDefined("productProperties") ? productProperties.excludedPlugins : []
|
||||
}
|
||||
|
||||
String patchAppDescriptor(String targetDirectory) {
|
||||
File patchApplicationInfo(String targetDirectory) {
|
||||
def patchedDirectory = "${targetDirectory}/../patched"
|
||||
|
||||
ant.delete(dir: patchedDirectory)
|
||||
@@ -79,10 +79,10 @@ String patchAppDescriptor(String targetDirectory) {
|
||||
ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "${code}-$snapshot")
|
||||
ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_DATE__", value: new Date().format("yyyyMMddHHmm"))
|
||||
|
||||
return patchedDirectory
|
||||
return new File(patchedDirectory, "idea/${appInfoFileName()}")
|
||||
}
|
||||
|
||||
def layoutFull(String home, String targetDirectory, String patchedDescriptorDir = null) {
|
||||
def layoutFull(String home, String targetDirectory, File patchedApplicationInfo = null) {
|
||||
projectBuilder.stage("layout to $targetDirectory")
|
||||
|
||||
List<String> jpsCommonModules = ["jps-model-impl", "jps-model-serialization"]
|
||||
@@ -197,24 +197,24 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
|
||||
module("platform-resources")
|
||||
|
||||
def appInfoModule = appInfoModule()
|
||||
def appInfoInCommunity = "community-resources".equals(appInfoModule)
|
||||
|
||||
if (appInfoInCommunity) {
|
||||
if ("community-resources" == appInfoModule) {
|
||||
module("community-resources") {
|
||||
if (patchedDescriptorDir != null) {
|
||||
exclude(name: appInfoFileName())
|
||||
if (patchedApplicationInfo != null) {
|
||||
exclude(name: "idea/$patchedApplicationInfo.name")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
module("community-resources")
|
||||
module(appInfoModule) {
|
||||
if (patchedDescriptorDir != null) {
|
||||
exclude(name: appInfoFileName())
|
||||
if (patchedApplicationInfo != null) {
|
||||
exclude(name: "idea/$patchedApplicationInfo.name")
|
||||
}
|
||||
}
|
||||
}
|
||||
if (patchedDescriptorDir != null) {
|
||||
fileset(dir: patchedDescriptorDir)
|
||||
if (patchedApplicationInfo != null) {
|
||||
dir("idea") {
|
||||
fileset(file: patchedApplicationInfo.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user