diff --git a/build/src/org/jetbrains/intellij/build/IdeaCommunityProperties.kt b/build/src/org/jetbrains/intellij/build/IdeaCommunityProperties.kt index 08819f24f64f..0911aaa6a8b8 100644 --- a/build/src/org/jetbrains/intellij/build/IdeaCommunityProperties.kt +++ b/build/src/org/jetbrains/intellij/build/IdeaCommunityProperties.kt @@ -142,9 +142,9 @@ open class IdeaCommunityProperties(private val communityHomeDir: Path) : JetBrai protected open inner class CommunityWindowsDistributionCustomizer : WindowsDistributionCustomizer() { init { - icoPath = "${communityHomeDir}/build/conf/ideaCE/win/images/idea_CE.ico" - icoPathForEAP = "${communityHomeDir}/build/conf/ideaCE/win/images/idea_CE_EAP.ico" - installerImagesPath = "${communityHomeDir}/build/conf/ideaCE/win/images" + icoPath = communityHomeDir.resolve("build/conf/ideaCE/win/images/idea_CE.ico") + icoPathForEAP = communityHomeDir.resolve("build/conf/ideaCE/win/images/idea_CE_EAP.ico") + installerImagesPath = communityHomeDir.resolve("build/conf/ideaCE/win/images") } override val fileAssociations: List diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/WindowsDistributionCustomizer.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/WindowsDistributionCustomizer.kt index 394bccc246ea..77163e241906 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/WindowsDistributionCustomizer.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/WindowsDistributionCustomizer.kt @@ -8,12 +8,12 @@ abstract class WindowsDistributionCustomizer { /** * Path to 256x256 *.ico file for Windows distribution. */ - var icoPath: String? = null + var icoPath: Path? = null /** * Path to an ico file for EAP builds (if `null` [icoPath] will be used). */ - var icoPathForEAP: String? = null + var icoPathForEAP: Path? = null /** * If `true`, *.bat files (productName.bat and inspect.bat) will be included in the distribution. @@ -42,7 +42,7 @@ abstract class WindowsDistributionCustomizer { /** * Path to a directory containing images for installer: `logo.bmp`, `headerlogo.bmp`, `install.ico`, `uninstall.ico`. */ - var installerImagesPath: String? = null + var installerImagesPath: Path? = null /** * Set to `false` for products that are not updated with patches. diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt index 2012c235e2a6..5e126c94bad0 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt @@ -611,22 +611,22 @@ private suspend fun checkProductProperties(context: BuildContext) { } context.linuxDistributionCustomizer?.let { linuxDistributionCustomizer -> - checkPaths(listOfNotNull(linuxDistributionCustomizer.iconPngPath), "productProperties.linuxCustomizer.iconPngPath") - checkPaths(listOfNotNull(linuxDistributionCustomizer.iconPngPathForEAP), "productProperties.linuxCustomizer.iconPngPathForEAP") + checkStringPaths(listOfNotNull(linuxDistributionCustomizer.iconPngPath), "productProperties.linuxCustomizer.iconPngPath") + checkStringPaths(listOfNotNull(linuxDistributionCustomizer.iconPngPathForEAP), "productProperties.linuxCustomizer.iconPngPathForEAP") } context.macDistributionCustomizer?.let { macCustomizer -> checkMandatoryField(macCustomizer.bundleIdentifier, "productProperties.macCustomizer.bundleIdentifier") checkMandatoryPath(macCustomizer.icnsPath, "productProperties.macCustomizer.icnsPath") - checkPaths(listOfNotNull(macCustomizer.icnsPathForEAP), "productProperties.macCustomizer.icnsPathForEAP") - checkPaths(listOfNotNull(macCustomizer.icnsPathForAlternativeIcon), "productProperties.macCustomizer.icnsPathForAlternativeIcon") - checkPaths( + checkStringPaths(listOfNotNull(macCustomizer.icnsPathForEAP), "productProperties.macCustomizer.icnsPathForEAP") + checkStringPaths(listOfNotNull(macCustomizer.icnsPathForAlternativeIcon), "productProperties.macCustomizer.icnsPathForAlternativeIcon") + checkStringPaths( listOfNotNull(macCustomizer.icnsPathForAlternativeIconForEAP), "productProperties.macCustomizer.icnsPathForAlternativeIconForEAP" ) context.executeStep(spanBuilder("check .dmg images"), BuildOptions.MAC_DMG_STEP) { checkMandatoryPath(macCustomizer.dmgImagePath, "productProperties.macCustomizer.dmgImagePath") - checkPaths(listOfNotNull(macCustomizer.dmgImagePathForEAP), "productProperties.macCustomizer.dmgImagePathForEAP") + checkStringPaths(listOfNotNull(macCustomizer.dmgImagePathForEAP), "productProperties.macCustomizer.dmgImagePathForEAP") } } @@ -767,7 +767,14 @@ private fun checkPluginModules(pluginModules: Collection?, fieldName: St } } -private fun checkPaths(paths: Collection, propertyName: String) { +private fun checkPaths(paths: Collection, propertyName: String) { + val nonExistingFiles = paths.filter { Files.notExists(it) } + check(nonExistingFiles.isEmpty()) { + "$propertyName contains non-existing files: ${nonExistingFiles.joinToString()}" + } +} + +private fun checkStringPaths(paths: Collection, propertyName: String) { val nonExistingFiles = paths.filter { Files.notExists(Path.of(it)) } check(nonExistingFiles.isEmpty()) { "$propertyName contains non-existing files: ${nonExistingFiles.joinToString()}" @@ -789,7 +796,7 @@ private fun checkMandatoryField(value: String?, fieldName: String) { private fun checkMandatoryPath(path: String, fieldName: String) { checkMandatoryField(path, fieldName) - checkPaths(listOf(path), fieldName) + checkPaths(listOf(Path.of(path)), fieldName) } private fun logFreeDiskSpace(phase: String, context: CompilationContext) { diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt index 276e13083501..052f698e1beb 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt @@ -122,7 +122,7 @@ class LinuxDistributionBuilder( span.addEvent("skip") } else { - buildTarGz(arch, runtimeDir = null, osAndArchSpecificDistPath, NO_RUNTIME_SUFFIX + suffix(arch, targetLibcImpl)) + buildTarGz(arch = arch, runtimeDir = null, unixDistPath = osAndArchSpecificDistPath, suffix = NO_RUNTIME_SUFFIX + suffix(arch, targetLibcImpl)) } } } @@ -138,12 +138,12 @@ class LinuxDistributionBuilder( "linux_tar_gz_${arch.name}" ) { _ -> val suffix = suffix(arch, targetLibcImpl) - buildTarGz(arch, runtimeDir, osAndArchSpecificDistPath, suffix) + buildTarGz(arch = arch, runtimeDir = runtimeDir, unixDistPath = osAndArchSpecificDistPath, suffix = suffix) } if (targetLibcImpl != LinuxLibcImpl.MUSL) { launch(Dispatchers.IO + CoroutineName("build Snap package")) { - buildSnapPackage(runtimeDir, osAndArchSpecificDistPath, arch, targetLibcImpl) + buildSnapPackage(runtimeDir = runtimeDir, unixDistPath = osAndArchSpecificDistPath, arch = arch, targetLibcImpl = targetLibcImpl) } } @@ -180,8 +180,9 @@ class LinuxDistributionBuilder( ) } - override fun generateExecutableFilesPatterns(includeRuntime: Boolean, arch: JvmArchitecture, libc: LibcImpl): Sequence = - customizer.generateExecutableFilesPatterns(includeRuntime, arch, libc, context) + override fun generateExecutableFilesPatterns(includeRuntime: Boolean, arch: JvmArchitecture, libc: LibcImpl): Sequence { + return customizer.generateExecutableFilesPatterns(includeRuntime = includeRuntime, arch = arch, targetLibcImpl = libc, context = context) + } private val rootDirectoryName: String get() = customizer.getRootDirectoryName(context.applicationInfo, context.buildNumber) @@ -203,20 +204,27 @@ class LinuxDistributionBuilder( } val productJsonDir = context.paths.tempDir.resolve("linux.dist.product-info.json${suffix}") - val productJsonFile = writeProductJsonFile(productJsonDir, arch, withRuntime = runtimeDir != null) + val productJsonFile = writeProductJsonFile(targetDir = productJsonDir, arch = arch, withRuntime = runtimeDir != null) dirs.add(productJsonDir) spanBuilder("build Linux tar.gz") .setAttribute("runtimeDir", runtimeDir?.toString() ?: "") .setAttribute("targetLibcImpl", targetLibcImpl.name) .use(Dispatchers.IO) { - val executableFileMatchers = generateExecutableFilesMatchers(includeRuntime = runtimeDir != null, arch, targetLibcImpl).keys + val executableFileMatchers = generateExecutableFilesMatchers(includeRuntime = runtimeDir != null, arch, this@LinuxDistributionBuilder.targetLibcImpl).keys tar(tarPath, tarRoot, dirs, executableFileMatchers, context.options.buildDateInSeconds) validateProductJson(tarPath, tarRoot, context) copyFile(productJsonFile, tarProductInfoJsonPath) context.notifyArtifactBuilt(tarProductInfoJsonPath) + context.notifyArtifactBuilt(tarPath) - checkExecutablePermissions(tarPath, rootDirectoryName, includeRuntime = runtimeDir != null, arch, targetLibcImpl) + checkExecutablePermissions( + distribution = tarPath, + root = rootDirectoryName, + includeRuntime = runtimeDir != null, + arch = arch, + libc = this@LinuxDistributionBuilder.targetLibcImpl, + ) } tarPath } @@ -239,7 +247,7 @@ class LinuxDistributionBuilder( } buildSnapPackage(snapName, runtimeDir, unixDistPath, arch, targetLibcImpl) customizer.snapLegacyAliases.forEach { - buildSnapPackage(snapName = it, runtimeDir, unixDistPath, arch, targetLibcImpl) + buildSnapPackage(snapName = it, runtimeDir = runtimeDir, unixDistPath = unixDistPath, arch = arch, targetLibcImpl = targetLibcImpl) } } @@ -299,7 +307,7 @@ class LinuxDistributionBuilder( val productJsonDir = context.paths.tempDir.resolve("linux.dist.snap.$snapName.product-info.json.$architecture") val productJsonFile = writeProductJsonFile(productJsonDir, arch) val installationDirectories = listOf(context.paths.distAllDir, unixDistPath, runtimeDir) - validateProductJson(jsonText = productJsonFile.readText(), installationDirectories, installationArchives = emptyList(), context) + validateProductJson(jsonText = productJsonFile.readText(), installationDirectories = installationDirectories, installationArchives = emptyList(), context = context) val resultDir = snapDir.resolve("result") Files.createDirectories(resultDir) @@ -328,7 +336,7 @@ class LinuxDistributionBuilder( val snapArtifactPath = moveFileToDir(resultDir.resolve(snapArtifactName), context.paths.artifactDir) context.notifyArtifactBuilt(snapArtifactPath) - checkExecutablePermissions(snapArtifactPath, root = "", includeRuntime = true, arch, targetLibcImpl) + checkExecutablePermissions(distribution = snapArtifactPath, root = "", includeRuntime = true, arch = arch, libc = targetLibcImpl) val snapProductInfoJsonPath = snapArtifactPath.resolveProductInfoJsonSibling() copyFile(productJsonFile, snapProductInfoJsonPath) @@ -379,107 +387,112 @@ class LinuxDistributionBuilder( writeProductInfoJson(file, json, context) return file } +} - private fun generateVersionMarker(unixDistPath: Path, context: BuildContext) { - val targetDir = unixDistPath.resolve("lib") - Files.createDirectories(targetDir) - Files.writeString(targetDir.resolve("build-marker-${context.fullBuildNumber}"), context.fullBuildNumber) - } +private fun generateVersionMarker(unixDistPath: Path, context: BuildContext) { + val targetDir = unixDistPath.resolve("lib") + Files.createDirectories(targetDir) + Files.writeString(targetDir.resolve("build-marker-${context.fullBuildNumber}"), context.fullBuildNumber) +} - private fun generateScripts(distBinDir: Path, arch: JvmArchitecture, targetLibcImpl: LinuxLibcImpl, context: BuildContext) { - Files.createDirectories(distBinDir) +private fun generateScripts(distBinDir: Path, arch: JvmArchitecture, targetLibcImpl: LinuxLibcImpl, context: BuildContext) { + Files.createDirectories(distBinDir) - val sourceScriptDir = context.paths.communityHomeDir.resolve("platform/build-scripts/resources/linux/scripts") - Files.newDirectoryStream(sourceScriptDir).use { - for (file in it) { - val fileName = file.fileName.toString() - if (fileName != EXECUTABLE_TEMPLATE_NAME) { - copyScript(file, distBinDir.resolve(fileName), additionalTemplateValues = emptyList(), context) - } + val sourceScriptDir = context.paths.communityHomeDir.resolve("platform/build-scripts/resources/linux/scripts") + Files.newDirectoryStream(sourceScriptDir).use { + for (file in it) { + val fileName = file.fileName.toString() + if (fileName != EXECUTABLE_TEMPLATE_NAME) { + copyScript(sourceFile = file, targetFile = distBinDir.resolve(fileName), additionalTemplateValues = emptyList(), context = context) } } - - copyInspectScript(context, distBinDir) - - generateLauncherScript(distBinDir, arch, nonCustomizableJvmArgs = emptyList(), targetLibcImpl, context) } - private suspend fun addNativeLauncher(distBinDir: Path, targetPath: Path, arch: JvmArchitecture, context: BuildContext) { - val (execPath, licensePath) = NativeBinaryDownloader.getLauncher(context, OsFamily.LINUX, arch) - copyFile(execPath, distBinDir.resolve(context.productProperties.baseFileName)) - copyFile(licensePath, targetPath.resolve("license/launcher-third-party-libraries.html")) - } + copyInspectScript(context, distBinDir) - private fun generateLauncherScript(distBinDir: Path, arch: JvmArchitecture, nonCustomizableJvmArgs: List, targetLibcImpl: LinuxLibcImpl, context: BuildContext) { - val vmOptionsPath = distBinDir.resolve("${context.productProperties.baseFileName}64.vmoptions") + generateLauncherScript(distBinDir = distBinDir, arch = arch, nonCustomizableJvmArgs = emptyList(), targetLibcImpl = targetLibcImpl, context = context) +} - val defaultXmxParameter = try { - Files.readAllLines(vmOptionsPath).firstOrNull { it.startsWith("-Xmx") } - ?: throw IllegalStateException("-Xmx was not found in '$vmOptionsPath'") - } - catch (e: NoSuchFileException) { - throw IllegalStateException("File '$vmOptionsPath' should be already generated at this point", e) - } +private suspend fun addNativeLauncher(distBinDir: Path, targetPath: Path, arch: JvmArchitecture, context: BuildContext) { + val (execPath, licensePath) = NativeBinaryDownloader.getLauncher(context, OsFamily.LINUX, arch) + copyFile(execPath, distBinDir.resolve(context.productProperties.baseFileName)) + copyFile(licensePath, targetPath.resolve("license/launcher-third-party-libraries.html")) +} - val classPathJars = context.bootClassPathJarNames - var classPath = $$"CLASS_PATH=\"$IDE_HOME/lib/$${classPathJars[0]}\"" - for (i in 1 until classPathJars.size) { - classPath += $$"\nCLASS_PATH=\"$CLASS_PATH:$IDE_HOME/lib/$${classPathJars[i]}\"" - } +private fun generateLauncherScript(distBinDir: Path, arch: JvmArchitecture, nonCustomizableJvmArgs: List, targetLibcImpl: LinuxLibcImpl, context: BuildContext) { + val vmOptionsPath = distBinDir.resolve("${context.productProperties.baseFileName}64.vmoptions") - val additionalJvmArguments = mutableListOf() - // https://youtrack.jetbrains.com/issue/IDEA-304440 - // "-Djdk.lang.Process.launchMechanism=vfork" - if (targetLibcImpl == LinuxLibcImpl.MUSL) { - additionalJvmArguments.add("-Djdk.lang.Process.launchMechanism=vfork") - } - additionalJvmArguments.addAll(context.getAdditionalJvmArguments(OsFamily.LINUX, arch, isScript = true) + nonCustomizableJvmArgs) + val defaultXmxParameter = try { + Files.readAllLines(vmOptionsPath).firstOrNull { it.startsWith("-Xmx") } + ?: throw IllegalStateException("-Xmx was not found in '$vmOptionsPath'") + } + catch (e: NoSuchFileException) { + throw IllegalStateException("File '$vmOptionsPath' should be already generated at this point", e) + } - val additionalTemplateValues = listOf( - Pair("vm_options", context.productProperties.baseFileName), - Pair("system_selector", context.systemSelector), - Pair("ide_jvm_args", additionalJvmArguments.joinToString(separator = " ")), - Pair("ide_default_xmx", defaultXmxParameter.trim()), - Pair("class_path", classPath), - Pair("main_class_name", context.ideMainClassName), - ) + val classPathJars = context.bootClassPathJarNames + var classPath = $$"CLASS_PATH=\"$IDE_HOME/lib/$${classPathJars[0]}\"" + for (i in 1 until classPathJars.size) { + classPath += $$"\nCLASS_PATH=\"$CLASS_PATH:$IDE_HOME/lib/$${classPathJars[i]}\"" + } - val template = context.paths.communityHomeDir.resolve("platform/build-scripts/resources/linux/scripts/${EXECUTABLE_TEMPLATE_NAME}") - val targetFile = distBinDir.resolve("${context.productProperties.baseFileName}.sh") - copyScript(template, targetFile, additionalTemplateValues, context) + val additionalJvmArguments = mutableListOf() + // https://youtrack.jetbrains.com/issue/IDEA-304440 + // "-Djdk.lang.Process.launchMechanism=vfork" + if (targetLibcImpl == LinuxLibcImpl.MUSL) { + additionalJvmArguments.add("-Djdk.lang.Process.launchMechanism=vfork") } + additionalJvmArguments.addAll(context.getAdditionalJvmArguments(os = OsFamily.LINUX, arch = arch, isScript = true) + nonCustomizableJvmArgs) + + val additionalTemplateValues = listOf( + Pair("vm_options", context.productProperties.baseFileName), + Pair("system_selector", context.systemSelector), + Pair("ide_jvm_args", additionalJvmArguments.joinToString(separator = " ")), + Pair("ide_default_xmx", defaultXmxParameter.trim()), + Pair("class_path", classPath), + Pair("main_class_name", context.ideMainClassName), + ) - private fun copyScript(sourceFile: Path, targetFile: Path, additionalTemplateValues: List>, context: BuildContext) { - // Until CR (\r) will be removed from the repository checkout, we need to filter it out from Unix-style scripts - // https://youtrack.jetbrains.com/issue/IJI-526/Force-git-to-use-LF-line-endings-in-working-copy-of-via-gitattri - substituteTemplatePlaceholders( - inputFile = sourceFile, - outputFile = targetFile, - placeholder = "__", - values = listOf( - Pair("product_full", context.applicationInfo.fullProductName), - Pair("product_uc", context.productProperties.getEnvironmentVariableBaseName(context.applicationInfo)), - Pair("product_vendor", context.applicationInfo.shortCompanyName), - Pair("product_code", context.applicationInfo.productCode), - Pair("script_name", "${context.productProperties.baseFileName}.sh"), - ) + additionalTemplateValues, - mustUseAllPlaceholders = false, - convertToUnixLineEndings = true, - ) - } + val template = context.paths.communityHomeDir.resolve("platform/build-scripts/resources/linux/scripts/${EXECUTABLE_TEMPLATE_NAME}") + copyScript( + sourceFile = template, + targetFile = distBinDir.resolve("${context.productProperties.baseFileName}.sh"), + additionalTemplateValues = additionalTemplateValues, + context = context, + ) +} + +private fun copyScript(sourceFile: Path, targetFile: Path, additionalTemplateValues: List>, context: BuildContext) { + // Until CR (\r) will be removed from the repository checkout, we need to filter it out from Unix-style scripts + // https://youtrack.jetbrains.com/issue/IJI-526/Force-git-to-use-LF-line-endings-in-working-copy-of-via-gitattri + substituteTemplatePlaceholders( + inputFile = sourceFile, + outputFile = targetFile, + placeholder = "__", + values = listOf( + Pair("product_full", context.applicationInfo.fullProductName), + Pair("product_uc", context.productProperties.getEnvironmentVariableBaseName(context.applicationInfo)), + Pair("product_vendor", context.applicationInfo.shortCompanyName), + Pair("product_code", context.applicationInfo.productCode), + Pair("script_name", "${context.productProperties.baseFileName}.sh"), + ) + additionalTemplateValues, + mustUseAllPlaceholders = false, + convertToUnixLineEndings = true, + ) +} - private fun writeLinuxVmOptions(distBinDir: Path, context: BuildContext): Path { - val vmOptionsPath = distBinDir.resolve("${context.productProperties.baseFileName}64.vmoptions") - val vmOptions = VmOptionsGenerator.generate(context).asSequence() + sequenceOf("-Dsun.tools.attach.tmp.only=true", "-Dawt.lock.fair=true") - VmOptionsGenerator.writeVmOptions(vmOptionsPath, vmOptions, separator = "\n") - return vmOptionsPath - } +private fun writeLinuxVmOptions(distBinDir: Path, context: BuildContext): Path { + val vmOptionsPath = distBinDir.resolve("${context.productProperties.baseFileName}64.vmoptions") + val vmOptions = generateVmOptions(context).asSequence() + sequenceOf("-Dsun.tools.attach.tmp.only=true", "-Dawt.lock.fair=true") + writeVmOptions(file = vmOptionsPath, vmOptions = vmOptions, separator = "\n") + return vmOptionsPath +} - private fun suffix(arch: JvmArchitecture, targetLibcImpl: LinuxLibcImpl): String = - suffix(arch) + if (targetLibcImpl == LinuxLibcImpl.MUSL) "-musl" else "" +private fun suffix(arch: JvmArchitecture, targetLibcImpl: LinuxLibcImpl): String { + return suffix(arch) + if (targetLibcImpl == LinuxLibcImpl.MUSL) "-musl" else "" +} - private fun getSnapArchName(arch: JvmArchitecture) = when (arch) { - JvmArchitecture.x64 -> "amd64" - JvmArchitecture.aarch64 -> "arm64" - } +private fun getSnapArchName(arch: JvmArchitecture) = when (arch) { + JvmArchitecture.x64 -> "amd64" + JvmArchitecture.aarch64 -> "arm64" } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt index 08b553c915d3..4b1d6b8ff0ae 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt @@ -119,7 +119,7 @@ class MacDistributionBuilder( override suspend fun copyFilesForOsDistribution(targetPath: Path, arch: JvmArchitecture) { withContext(Dispatchers.IO) { - doCopyExtraFiles(targetPath, arch, copyDistFiles = true) + doCopyExtraFiles(macDistDir = targetPath, arch = arch, copyDistFiles = true) } } @@ -231,7 +231,7 @@ class MacDistributionBuilder( signMacBinaries(binariesToSign, context) for (dir in listOf(osAndArchSpecificDistPath, runtimeDist)) { launch(CoroutineName("recursively signing macOS binaries in $dir")) { - recursivelySignMacBinaries(coroutineScope = this, dir, context, matchers) + recursivelySignMacBinaries(coroutineScope = this, root = dir, context = context, executableFileMatchers = matchers) } } } @@ -492,15 +492,15 @@ class MacDistributionBuilder( } } - validateProductJson(targetFile, pathInArchive = "${zipRoot}/Resources", macDistributionBuilder.context) + validateProductJson(archiveFile = targetFile, pathInArchive = "${zipRoot}/Resources", context = macDistributionBuilder.context) } } private fun writeMacOsVmOptions(distBinDir: Path, context: BuildContext): Path { val executable = context.productProperties.baseFileName - val vmOptions = VmOptionsGenerator.generate(context).asSequence() + sequenceOf("-Dapple.awt.application.appearance=system") + val vmOptions = generateVmOptions(context).asSequence() + sequenceOf("-Dapple.awt.application.appearance=system") val vmOptionsPath = distBinDir.resolve("${executable}.vmoptions") - VmOptionsGenerator.writeVmOptions(vmOptionsPath, vmOptions, separator = "\n") + writeVmOptions(vmOptionsPath, vmOptions, separator = "\n") return vmOptionsPath } @@ -569,8 +569,9 @@ class MacDistributionBuilder( } } - private fun getMacZipRoot(customizer: MacDistributionCustomizer, context: BuildContext): String = - "${customizer.getRootDirectoryName(context.applicationInfo, context.buildNumber)}/Contents" + private fun getMacZipRoot(customizer: MacDistributionCustomizer, context: BuildContext): String { + return "${customizer.getRootDirectoryName(context.applicationInfo, context.buildNumber)}/Contents" + } private val publishSitArchive: Boolean get() = !context.isStepSkipped(BuildOptions.MAC_SIT_PUBLICATION_STEP) @@ -638,75 +639,75 @@ class MacDistributionBuilder( NioFiles.deleteRecursively(tempDir) } } +} - private fun prepareDmgBuildScripts(tempDir: Path, staple: Boolean, customizer: MacDistributionCustomizer, context: BuildContext): Path { - NioFiles.deleteRecursively(tempDir) - Files.createDirectories(tempDir) - val dmgImageCopy = tempDir.resolve("${context.fullBuildNumber}.png") - Files.copy(Path.of((if (context.applicationInfo.isEAP) customizer.dmgImagePathForEAP else null) ?: customizer.dmgImagePath), dmgImageCopy) - val scriptsDir = context.paths.communityHomeDir.resolve("platform/build-scripts/tools/mac/scripts") - Files.copy(scriptsDir.resolve("makedmg.sh"), tempDir.resolve("makedmg.sh"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) - NioFiles.setExecutable(tempDir.resolve("makedmg.sh")) - Files.copy(scriptsDir.resolve("makedmg.py"), tempDir.resolve("makedmg.py"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) - Files.copy(scriptsDir.resolve("staple.sh"), tempDir.resolve("staple.sh"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) - val entrypoint = tempDir.resolve("build.sh") - Files.writeString( - entrypoint, - Files.readString(scriptsDir.resolve("build-template.sh")) - .resolveTemplateVar("staple", "$staple") - .resolveTemplateVar("appName", context.fullBuildNumber) - .resolveTemplateVar("contentSigned", "${context.isMacCodeSignEnabled}") - .resolveTemplateVar("buildDateInSeconds", "${context.options.buildDateInSeconds}") - ) - NioFiles.setExecutable(entrypoint) - return entrypoint - } +private fun prepareDmgBuildScripts(tempDir: Path, staple: Boolean, customizer: MacDistributionCustomizer, context: BuildContext): Path { + NioFiles.deleteRecursively(tempDir) + Files.createDirectories(tempDir) + val dmgImageCopy = tempDir.resolve("${context.fullBuildNumber}.png") + Files.copy(Path.of((if (context.applicationInfo.isEAP) customizer.dmgImagePathForEAP else null) ?: customizer.dmgImagePath), dmgImageCopy) + val scriptsDir = context.paths.communityHomeDir.resolve("platform/build-scripts/tools/mac/scripts") + Files.copy(scriptsDir.resolve("makedmg.sh"), tempDir.resolve("makedmg.sh"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) + NioFiles.setExecutable(tempDir.resolve("makedmg.sh")) + Files.copy(scriptsDir.resolve("makedmg.py"), tempDir.resolve("makedmg.py"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) + Files.copy(scriptsDir.resolve("staple.sh"), tempDir.resolve("staple.sh"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) + val entrypoint = tempDir.resolve("build.sh") + Files.writeString( + entrypoint, + Files.readString(scriptsDir.resolve("build-template.sh")) + .resolveTemplateVar("staple", "$staple") + .resolveTemplateVar("appName", context.fullBuildNumber) + .resolveTemplateVar("contentSigned", "${context.isMacCodeSignEnabled}") + .resolveTemplateVar("buildDateInSeconds", "${context.options.buildDateInSeconds}") + ) + NioFiles.setExecutable(entrypoint) + return entrypoint +} - private fun String.resolveTemplateVar(variable: String, value: String): String { - val reference = "%$variable%" - check(contains(reference)) { "No $reference is found in:\n'$this'" } - return replace(reference, value) - } +private fun String.resolveTemplateVar(variable: String, value: String): String { + val reference = "%$variable%" + check(contains(reference)) { "No $reference is found in:\n'$this'" } + return replace(reference, value) +} - private fun publishDmgBuildScripts(entrypoint: Path, tempDir: Path, context: BuildContext) { - val artifactDir = context.paths.artifactDir.resolve("macos-dmg-build") - artifactDir.createDirectories() - synchronized("$artifactDir".intern()) { - tempDir.listDirectoryEntries().forEach { - Files.copy(it, artifactDir.resolve(it.name), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) - } - val message = """ +private fun publishDmgBuildScripts(entrypoint: Path, tempDir: Path, context: BuildContext) { + val artifactDir = context.paths.artifactDir.resolve("macos-dmg-build") + artifactDir.createDirectories() + synchronized("$artifactDir".intern()) { + tempDir.listDirectoryEntries().forEach { + Files.copy(it, artifactDir.resolve(it.name), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES) + } + val message = """ To build .dmg(s): 1. transfer .sit(s) to macOS host; 2. transfer ${artifactDir.name}/ content to the same folder; 3. execute ${entrypoint.name} from Terminal. .dmg(s) will be built in the same folder. """.trimIndent() - artifactDir.resolve("README.txt").writeText(message) - context.messages.info(message) - context.notifyArtifactBuilt(artifactDir) - } + artifactDir.resolve("README.txt").writeText(message) + context.messages.info(message) + context.notifyArtifactBuilt(artifactDir) + } +} + +private suspend fun generateIntegrityManifest(sitFile: Path, sitRoot: String, arch: JvmArchitecture, context: BuildContext) { + if (context.options.buildStepsToSkip.contains(BuildOptions.REPAIR_UTILITY_BUNDLE_STEP)) { + return } - private suspend fun generateIntegrityManifest(sitFile: Path, sitRoot: String, arch: JvmArchitecture, context: BuildContext) { - if (context.options.buildStepsToSkip.contains(BuildOptions.REPAIR_UTILITY_BUNDLE_STEP)) { - return + val tempSit = Files.createTempDirectory(context.paths.tempDir, "sit-") + try { + spanBuilder("extracting ${sitFile.name}").use(Dispatchers.IO) { + Decompressor.Zip(sitFile) + .withZipExtensions() + .extract(tempSit) } - - val tempSit = Files.createTempDirectory(context.paths.tempDir, "sit-") - try { - spanBuilder("extracting ${sitFile.name}").use(Dispatchers.IO) { - Decompressor.Zip(sitFile) - .withZipExtensions() - .extract(tempSit) - } - RepairUtilityBuilder.generateManifest(context, tempSit.resolve(sitRoot), OsFamily.MACOS, arch) - } - finally { - withContext(Dispatchers.IO + NonCancellable) { - @OptIn(ExperimentalPathApi::class) - tempSit.deleteRecursively() - } + RepairUtilityBuilder.generateManifest(context, tempSit.resolve(sitRoot), OsFamily.MACOS, arch) + } + finally { + withContext(Dispatchers.IO + NonCancellable) { + @OptIn(ExperimentalPathApi::class) + tempSit.deleteRecursively() } } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt index 1c192cc06739..3d654232dbc2 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/TestingTasksImpl.kt @@ -633,7 +633,7 @@ internal class TestingTasksImpl(context: CompilationContext, private val options val customMemoryOptions = options.jvmMemoryOptions?.trim()?.split(Regex("\\s+"))?.takeIf { it.isNotEmpty() } jvmArgs.addAll( index = 0, - elements = VmOptionsGenerator.generate( + elements = generateVmOptions( isEAP = true, customVmMemoryOptions = if (customMemoryOptions == null) mapOf("-Xms" to "750m", "-Xmx" to "1024m") else emptyMap(), additionalVmOptions = customMemoryOptions ?: emptyList(), diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/VmOptionsGenerator.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/VmOptionsGenerator.kt index a0829ef7d9a1..3fa198442512 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/VmOptionsGenerator.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/VmOptionsGenerator.kt @@ -9,92 +9,90 @@ import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.name -object VmOptionsGenerator { - private const val DEFAULT_MIN_HEAP = "128m" - private const val DEFAULT_MAX_HEAP = "2048m" +private const val DEFAULT_MIN_HEAP = "128m" +private const val DEFAULT_MAX_HEAP = "2048m" - private val COMMON_VM_OPTIONS: List = listOf( - "-XX:JbrShrinkingGcMaxHeapFreeRatio=40", // IJPL-181469. Used in a couple with AppIdleMemoryCleaner.runGc() - "-XX:ReservedCodeCacheSize=512m", - "-XX:+HeapDumpOnOutOfMemoryError", - "-XX:-OmitStackTraceInFastThrow", - "-XX:CICompilerCount=2", - "-XX:+IgnoreUnrecognizedVMOptions", // allowing the JVM to start even with outdated options stuck in user configs - "-XX:+UnlockDiagnosticVMOptions", - "-XX:TieredOldPercentage=100000", - "-ea", - "-Dsun.io.useCanonCaches=false", - "-Dsun.java2d.metal=true", - "-Djbr.catch.SIGABRT=true", - "-Djdk.http.auth.tunneling.disabledSchemes=\"\"", - "-Djdk.attach.allowAttachSelf=true", - "-Djdk.module.illegalAccess.silent=true", - "-Djdk.nio.maxCachedBufferSize=2097152", - "-Djava.util.zip.use.nio.for.zip.file.access=true", // IJPL-149160 - "-Dkotlinx.coroutines.debug=off", - ) +private val COMMON_VM_OPTIONS: List = listOf( + "-XX:JbrShrinkingGcMaxHeapFreeRatio=40", // IJPL-181469. Used in a couple with AppIdleMemoryCleaner.runGc() + "-XX:ReservedCodeCacheSize=512m", + "-XX:+HeapDumpOnOutOfMemoryError", + "-XX:-OmitStackTraceInFastThrow", + "-XX:CICompilerCount=2", + "-XX:+IgnoreUnrecognizedVMOptions", // allowing the JVM to start even with outdated options stuck in user configs + "-XX:+UnlockDiagnosticVMOptions", + "-XX:TieredOldPercentage=100000", + "-ea", + "-Dsun.io.useCanonCaches=false", + "-Dsun.java2d.metal=true", + "-Djbr.catch.SIGABRT=true", + "-Djdk.http.auth.tunneling.disabledSchemes=\"\"", + "-Djdk.attach.allowAttachSelf=true", + "-Djdk.module.illegalAccess.silent=true", + "-Djdk.nio.maxCachedBufferSize=2097152", + "-Djava.util.zip.use.nio.for.zip.file.access=true", // IJPL-149160 + "-Dkotlinx.coroutines.debug=off", +) - /** duplicates RepositoryHelper.CUSTOM_BUILT_IN_PLUGIN_REPOSITORY_PROPERTY */ - private const val CUSTOM_BUILT_IN_PLUGIN_REPOSITORY_PROPERTY = "intellij.plugins.custom.built.in.repository.url" +/** duplicates RepositoryHelper.CUSTOM_BUILT_IN_PLUGIN_REPOSITORY_PROPERTY */ +private const val CUSTOM_BUILT_IN_PLUGIN_REPOSITORY_PROPERTY = "intellij.plugins.custom.built.in.repository.url" - fun generate(context: BuildContext): List = generate( - context.applicationInfo.isEAP, - context.productProperties.customJvmMemoryOptions, - context.productProperties.additionalVmOptions.let { - val url = computeCustomPluginRepositoryUrl(context) - if (url == null) it else it + "-D${CUSTOM_BUILT_IN_PLUGIN_REPOSITORY_PROPERTY}=${url}" - }, - context.productProperties.platformPrefix, - ) +fun generateVmOptions(context: BuildContext): List = generateVmOptions( + context.applicationInfo.isEAP, + context.productProperties.customJvmMemoryOptions, + context.productProperties.additionalVmOptions.let { + val url = computeCustomPluginRepositoryUrl(context) + if (url == null) it else it + "-D${CUSTOM_BUILT_IN_PLUGIN_REPOSITORY_PROPERTY}=${url}" + }, + context.productProperties.platformPrefix, +) - internal fun generate( - isEAP: Boolean, - customVmMemoryOptions: Map, - additionalVmOptions: List, - platformPrefix: String?, - ): List { - val result = ArrayList() +internal fun generateVmOptions( + isEAP: Boolean, + customVmMemoryOptions: Map, + additionalVmOptions: List, + platformPrefix: String?, +): List { + val result = ArrayList() - val memory = LinkedHashMap(customVmMemoryOptions) - memory.putIfAbsent("-Xms", DEFAULT_MIN_HEAP) - memory.putIfAbsent("-Xmx", DEFAULT_MAX_HEAP) - for ((k, v) in memory) { - result += k + v - } - - result += COMMON_VM_OPTIONS - - if (isMultiRoutingFileSystemEnabledForProduct(platformPrefix)) { - result.addAll(MULTI_ROUTING_FILE_SYSTEM_VMOPTIONS) - } - - result += additionalVmOptions - - if (isEAP) { - var index = result.indexOf("-ea") - if (index < 0) index = result.indexOfFirst { it.startsWith("-D") } - if (index < 0) index = result.size - result.add(index, "-XX:MaxJavaStackTraceDepth=10000") // must be consistent with `ConfigImportHelper#updateVMOptions` - } - - return result + val memory = LinkedHashMap(customVmMemoryOptions) + memory.putIfAbsent("-Xms", DEFAULT_MIN_HEAP) + memory.putIfAbsent("-Xmx", DEFAULT_MAX_HEAP) + for ((k, v) in memory) { + result += k + v } - private fun computeCustomPluginRepositoryUrl(context: BuildContext): String? { - val artifactsServer = context.proprietaryBuildTools.artifactsServer - if (artifactsServer != null && context.productProperties.productLayout.prepareCustomPluginRepositoryForPublishedPlugins) { - val builtinPluginsRepoUrl = artifactsServer.urlToArtifact(context, "${context.nonBundledPlugins.name}/plugins.xml") - if (builtinPluginsRepoUrl != null) { - if (builtinPluginsRepoUrl.startsWith("http:")) { - context.messages.logErrorAndThrow("Insecure artifact server: ${builtinPluginsRepoUrl}") - } - return builtinPluginsRepoUrl - } - } - return null + result += COMMON_VM_OPTIONS + + if (isMultiRoutingFileSystemEnabledForProduct(platformPrefix)) { + result.addAll(MULTI_ROUTING_FILE_SYSTEM_VMOPTIONS) } - internal fun writeVmOptions(file: Path, vmOptions: Sequence, separator: String) { - Files.writeString(file, vmOptions.joinToString(separator, postfix = separator), StandardCharsets.US_ASCII) + result += additionalVmOptions + + if (isEAP) { + var index = result.indexOf("-ea") + if (index < 0) index = result.indexOfFirst { it.startsWith("-D") } + if (index < 0) index = result.size + result.add(index, "-XX:MaxJavaStackTraceDepth=10000") // must be consistent with `ConfigImportHelper#updateVMOptions` } + + return result +} + +private fun computeCustomPluginRepositoryUrl(context: BuildContext): String? { + val artifactsServer = context.proprietaryBuildTools.artifactsServer + if (artifactsServer != null && context.productProperties.productLayout.prepareCustomPluginRepositoryForPublishedPlugins) { + val builtinPluginsRepoUrl = artifactsServer.urlToArtifact(context, "${context.nonBundledPlugins.name}/plugins.xml") + if (builtinPluginsRepoUrl != null) { + if (builtinPluginsRepoUrl.startsWith("http:")) { + context.messages.logErrorAndThrow("Insecure artifact server: ${builtinPluginsRepoUrl}") + } + return builtinPluginsRepoUrl + } + } + return null +} + +internal fun writeVmOptions(file: Path, vmOptions: Sequence, separator: String) { + Files.writeString(file, vmOptions.joinToString(separator, postfix = separator), StandardCharsets.US_ASCII) } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.kt index c44e61dbce7b..dd3cb3b45a7e 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.kt @@ -196,7 +196,7 @@ private suspend fun prepareConfigurationFiles(nsiConfDir: Path, uninstallerFileN Files.writeString(nsiConfDir.resolve("config.nsi"), $$""" !define INSTALLER_ARCH $${expectedArch} - !define IMAGES_LOCATION "$${Path.of(customizer.installerImagesPath!!)}" + !define IMAGES_LOCATION "$${customizer.installerImagesPath!!}" !define MANUFACTURER "$${appInfo.shortCompanyName}" !define MUI_PRODUCT "$${customizer.getFullNameIncludingEdition(appInfo)}" diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt index fb35e306f42e..40565824f8cf 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt @@ -468,13 +468,13 @@ internal class WindowsDistributionBuilder( val customizer = context.windowsDistributionCustomizer!! val icoPath = (if (context.applicationInfo.isEAP) customizer.icoPathForEAP else null) ?: customizer.icoPath requireNotNull(icoPath) { "`WindowsDistributionCustomizer#icoPath` must be set" } - return Path.of(icoPath) + return icoPath } private fun writeWindowsVmOptions(distBinDir: Path, context: BuildContext): Path { val vmOptionsFile = distBinDir.resolve("${context.productProperties.baseFileName}64.exe.vmoptions") - val vmOptions = VmOptionsGenerator.generate(context).asSequence() - VmOptionsGenerator.writeVmOptions(vmOptionsFile, vmOptions, separator = "\r\n") + val vmOptions = generateVmOptions(context).asSequence() + writeVmOptions(vmOptionsFile, vmOptions, separator = "\r\n") return vmOptionsFile } diff --git a/python/build/src/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.kt b/python/build/src/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.kt index 193a5ac29b6e..fb0260e7c123 100644 --- a/python/build/src/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.kt +++ b/python/build/src/org/jetbrains/intellij/build/pycharm/PyCharmCommunityProperties.kt @@ -90,9 +90,9 @@ open class PyCharmCommunityProperties(protected val communityHome: Path) : PyCha override fun createWindowsCustomizer(projectHome: Path): WindowsDistributionCustomizer = object : WindowsDistributionCustomizer() { init { - icoPath = "${communityHome}/python/build/resources/PyCharmCore.ico" - icoPathForEAP = "${communityHome}/python/build/resources/PyCharmCore_EAP.ico" - installerImagesPath = "${communityHome}/python/build/resources" + icoPath = communityHome.resolve("python/build/resources/PyCharmCore.ico") + icoPathForEAP = communityHome.resolve("python/build/resources/PyCharmCore_EAP.ico") + installerImagesPath = communityHome.resolve("python/build/resources") } override val fileAssociations: List