blob: d1e90c1bd5d4ae3afc3f6a7065eccfe41441036c [file] [log] [blame]
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -08001/*
2 * Copyright 2000-2013 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tor Norbye6739a8f2013-08-07 11:11:08 -070017import org.jetbrains.jps.gant.JpsGantTool
18import org.jetbrains.jps.gant.TeamCityBuildInfoPrinter
19import org.jetbrains.jps.model.java.JavaSourceRootType
20import org.jetbrains.jps.model.module.JpsModule
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080021
Tor Norbye6739a8f2013-08-07 11:11:08 -070022includeTool << JpsGantTool
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080023
24binding.setVariable("p", {String key ->
25 return getProperty(key) as String
26})
27
28binding.setVariable("guessJdk", {
29 String javaHome = p("java.home")
30
31 if (new File(javaHome).getName() == "jre") {
32 javaHome = new File(javaHome).getParent()
33 }
34
35 return javaHome
36})
37
38binding.setVariable("includeFile", {String filePath ->
39 Script s = groovyShell.parse(new File(filePath))
40 s.setBinding(binding)
41 s
42})
43
44binding.setVariable("isMac", {
45 return System.getProperty("os.name").toLowerCase().startsWith("mac")
46})
47
48binding.setVariable("isWin", {
49 return System.getProperty("os.name").toLowerCase().startsWith("windows")
50})
51
52binding.setVariable("isEap", {
53 return "true" == p("component.version.eap")
54})
55
Tor Norbyec1ace1f2013-07-08 11:26:24 -070056binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m")
57binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=96m")
58binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
59 "-XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080060
61binding.setVariable("vmOptions", { "$common_vmoptions ${isEap() ? '-XX:+HeapDumpOnOutOfMemoryError' : ''}".trim() })
62binding.setVariable("vmOptions32", { "$mem32 ${vmOptions()}".trim() })
63binding.setVariable("vmOptions64", { "$mem64 ${vmOptions()}".trim() })
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070064
65binding.setVariable("yjpOptions", { String systemSelector, String platformSuffix = "" ->
Tor Norbyec1ace1f2013-07-08 11:26:24 -070066 "-agentlib:yjpagent$platformSuffix=disablej2ee,disablealloc,disabletracing,onlylocal,builtinprobes=none,disableexceptiontelemetry,delay=10000,sessionname=$systemSelector".trim()
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070067})
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080068binding.setVariable("vmOptions32yjp", { String systemSelector ->
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070069 "${vmOptions32()} ${yjpOptions(systemSelector)}".trim()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080070})
71binding.setVariable("vmOptions64yjp", { String systemSelector ->
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070072 "${vmOptions64()} ${yjpOptions(systemSelector, "64")}".trim()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080073})
74
75binding.setVariable("isDefined", {String key ->
76 try {
77 this[key]
78 return true
79 }
80 catch (MissingPropertyException ignored) {
81 return false
82 }
83})
84
85private String require(String key) {
86 try {
87 this[key]
88 }
89 catch (MissingPropertyException ignored) {
90 projectBuilder.error("Property $key is required")
91 }
92}
93
94private String require(String key, String defaultValue) {
95 try {
96 this[key]
97 }
98 catch (MissingPropertyException ignored) {
99 projectBuilder.info("$key is not defined. Defaulting to $defaultValue")
100 this[key] = defaultValue
101 }
102}
103
104binding.setVariable("requireProperty", {String key, String defaultValue = null ->
105 if (defaultValue == null) {
106 require(key)
107 }
108 else {
109 require(key, defaultValue)
110 }
111})
112
113binding.setVariable("guessHome", {
114 // Current file is supposed to be at build/scripts/release.gant path
115 new File(requireProperty("gant.file").substring("file:".length())).getParentFile().getParentFile().getParent()
116})
117
118binding.setVariable("loadProject", {
119 requireProperty("jdkHome", guessJdk())
120 def mac = isMac()
121 jdk("IDEA jdk", jdkHome) {
122 if (!mac) {
123 classpath "$jdkHome/lib/tools.jar"
124 }
125 }
Tor Norbye6739a8f2013-08-07 11:11:08 -0700126 projectBuilder.dataStorageRoot = new File("$home/.jps-build-data")
127 loadProjectFromPath(home)
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800128})
129
Tor Norbye6739a8f2013-08-07 11:11:08 -0700130boolean hasSourceRoots(JpsModule module) {
131 return module.getSourceRoots(JavaSourceRootType.SOURCE).iterator().hasNext()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800132}
133
134binding.setVariable("findModule", {String name ->
Tor Norbye6739a8f2013-08-07 11:11:08 -0700135 project.modules.find { it.name == name }
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800136})
137
138binding.setVariable("allModules", {
Tor Norbye6739a8f2013-08-07 11:11:08 -0700139 return project.modules
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800140})
141
142binding.setVariable("printUnusedModules", {Set<String> usedModules ->
Tor Norbye6739a8f2013-08-07 11:11:08 -0700143 allModules().each {JpsModule m ->
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800144 if (!usedModules.contains(m.name) && hasSourceRoots(m)) {
145 projectBuilder.warning("Module $m.name is not used in project layout")
146 }
147 }
148})
149
150requireProperty("home", guessHome())
151
152String readSnapshotBuild() {
153 def file = new File("$home/community/build.txt")
154 if (!file.exists()) {
155 file = new File("$home/build.txt")
156 }
157
158 return file.readLines().get(0)
159}
160
161binding.setVariable("snapshot", readSnapshotBuild())
162
Tor Norbye6739a8f2013-08-07 11:11:08 -0700163projectBuilder.buildInfoPrinter = new TeamCityBuildInfoPrinter()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800164projectBuilder.compressJars = false
165
166binding.setVariable("notifyArtifactBuilt", { String artifactPath ->
167 if (!artifactPath.startsWith(home)) {
168 projectBuilder.error("Artifact path $artifactPath should start with $home")
169 }
170 def relativePath = artifactPath.substring(home.length())
171 if (relativePath.startsWith("/")) {
172 relativePath = relativePath.substring(1)
173 }
174 def file = new File(artifactPath)
175 if (file.isDirectory()) {
176 relativePath += "=>" + file.name
177 }
178 projectBuilder.info("##teamcity[publishArtifacts '$relativePath']")
179})
180
181def suspendUntilDebuggerConnect = System.getProperty("debug.suspend") ?: "n"
182def debugPort = System.getProperty("debug.port") ?: 5555
183if (suspendUntilDebuggerConnect == 'y') {
184 println """\
185------------->----------- This process is suspended until remote debugger connects to the port $debugPort ----<----
Tor Norbye8fb00212013-05-01 12:55:43 -0700186-------------------------------------------^------^------^------^------^------^------^-----------------------
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800187"""
188}
189
190binding.setVariable("patchFiles", { List files, Map args, String marker = "__" ->
191 files.each { file ->
192 args.each { arg ->
193 ant.replace(file: file, token: "${marker}${arg.key}${marker}", value: arg.value)
194 }
195 }
196})
197
198binding.setVariable("copyAndPatchFile", { String file, String target, Map args, String marker = "__" ->
199 ant.copy(file: file, tofile: target, overwrite: "true") {
200 filterset(begintoken: marker, endtoken: marker) {
201 args.each {
202 filter(token: it.key, value: it.value)
203 }
204 }
205 }
206})
207
208binding.setVariable("copyAndPatchFiles", { Closure files, String target, Map args, String marker = "__" ->
209 ant.copy(todir: target, overwrite: "true") {
210 files()
211
212 filterset(begintoken: marker, endtoken: marker) {
213 args.each {
214 filter(token: it.key, value: it.value)
215 }
216 }
217 }
218})
219
220binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile ->
221 ant.tstamp()
222 patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP])
223})
224
225binding.setVariable("commonJvmArgs", {
226 return [
227 "-ea",
228 "-Didea.home.path=$home",
229 "-Xbootclasspath/p:${projectBuilder.moduleOutput(findModule("boot"))}",
230 "-XX:+HeapDumpOnOutOfMemoryError",
231 "-Didea.system.path=${p("teamcity.build.tempDir")}/system",
232 "-Didea.config.path=${p("teamcity.build.tempDir")}/config",
233 "-Xdebug",
234 "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
235})
236
237binding.setVariable("classPathLibs", [
238 "bootstrap.jar",
239 "extensions.jar",
240 "util.jar",
241 "jdom.jar",
242 "log4j.jar",
243 "trove4j.jar",
244 "jna.jar"
245])
246
247binding.setVariable("platformApiModules", [
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700248 "analysis-api",
249 "core-api",
Tor Norbyec7f983b2013-09-05 16:07:26 -0700250 "editor-ui-api",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700251 "external-system-api",
252 "indexing-api",
253 "jps-model-api",
254 "lang-api",
255 "lvcs-api",
256 "projectModel-api",
257 "platform-api",
258 "usageView",
259 "vcs-api",
260 "xdebugger-api",
261 "xml-openapi",
262 "xml-psi-api",
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800263])
264
265
266binding.setVariable("platformImplementationModules", [
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700267 "analysis-impl",
268 "core-impl",
269 "dvcs",
Tor Norbyea28de542013-09-11 15:53:32 -0700270 "editor-ui-ex",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700271 "images",
272 "indexing-impl",
273 "jps-model-impl",
274 "jps-model-serialization",
275 "lang-impl",
276 "lvcs-impl",
277 "projectModel-impl",
278 "platform-impl",
279 "vcs-impl",
280 "testRunner",
281 "smRunner",
282 "relaxng",
283 "RegExpSupport",
284 "spellchecker",
285 "xdebugger-impl",
286 "xml",
287 "xml-psi-impl",
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800288])
289
290binding.setVariable("layoutMacApp", { String path, String ch, Map args ->
291 ant.copy(todir: "$path/bin") {
292 fileset(dir: "$ch/bin/mac")
293 }
294
295 ant.copy(todir: path) {
296 fileset(dir: "$ch/build/conf/mac")
297 }
298
299 ant.tstamp() {
300 format(property: "todayYear", pattern: "yyyy")
301 }
302
303 String executable = args.executable != null ? args.executable : p("component.names.product").toLowerCase()
304 String helpId = args.help_id != null ? args.help_id : "IJ"
305 String icns = "idea.icns"
306 String helpIcns = "$path/Contents/Resources/${helpId}.help/Contents/Resources/Shared/product.icns"
307 if (args.icns != null) {
308 ant.delete(file: "$path/Contents/Resources/idea.icns")
309 ant.copy(file: args.icns, todir: "$path/Contents/Resources")
310 ant.copy(file: args.icns, tofile: helpIcns)
311 icns = new File((String)args.icns).getName();
312 } else {
313 ant.copy(file: "$path/Contents/Resources/idea.icns", tofile: helpIcns)
314 }
315
316 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
317
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700318 String vmOptions = "-Dfile.encoding=UTF-8 ${vmOptions()} -Xverify:none"
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800319 if (isEap() && !args.mac_no_yjp) {
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700320 vmOptions += " ${yjpOptions(args.system_selector)}"
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800321 }
322
323 String minor = p("component.version.minor")
324 String version = isEap() && !minor.contains("RC") && !minor.contains("Beta") ? "EAP $args.buildNumber" : "${p("component.version.major")}.${minor}"
325
326 Map properties = readIdeaProperties(args)
327
328 def coreKeys = ["idea.platform.prefix", "idea.paths.selector"]
329
330 String coreProperties = submapToXml(properties, coreKeys);
331
332 StringBuilder effectiveProperties = new StringBuilder()
333 properties.each { k, v ->
334 if (!coreKeys.contains(k)) {
335 effectiveProperties.append("$k=$v\n");
336 }
337 }
338
339 new File("$path/bin/idea.properties").text = effectiveProperties.toString()
340 new File("$path/bin/idea.vmoptions").text = "$mem64 -XX:+UseCompressedOops".split(" ").join("\n")
341
342 String classPath = classPathLibs.collect {"\$APP_PACKAGE/lib/${it}" }.join(":")
343
Jean-Baptiste Queru1d526b12013-02-27 09:41:48 -0800344 String urlSchemes = ""
345 if (args.urlSchemes != null) {
346 urlSchemes += """
347 <key>CFBundleURLTypes</key>
348 <array>
349 <dict>
350 <key>CFBundleTypeRole</key>
351 <string>Editor</string>
352 <key>CFBundleURLName</key>
353 <string>Stacktrace</string>
354 <key>CFBundleURLSchemes</key>
355 <array>
356"""
357 args.urlSchemes.each { scheme ->
358 urlSchemes += " <string>${scheme}</string>"
359 }
360 urlSchemes += """
361 </array>
362 </dict>
363 </array>
364"""
365 }
366
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800367 ant.replace(file: "$path/Contents/Info.plist") {
368 replacefilter(token: "@@build@@", value: args.buildNumber)
369 replacefilter(token: "@@doc_types@@", value: ifNull(args.doc_types, ""))
370 replacefilter(token: "@@executable@@", value: executable)
371 replacefilter(token: "@@icns@@", value: icns)
372 replacefilter(token: "@@bundle_name@@", value: fullName)
373 replacefilter(token: "@@bundle_identifier@@", value: args.bundleIdentifier)
374 replacefilter(token: "@@year@@", value: "$todayYear")
375 replacefilter(token: "@@version@@", value: version)
376 replacefilter(token: "@@vmoptions@@", value: vmOptions)
377 replacefilter(token: "@@idea_properties@@", value: coreProperties)
378 replacefilter(token: "@@class_path@@", value: classPath)
379 replacefilter(token: "@@help_id@@", value: helpId)
Jean-Baptiste Queru1d526b12013-02-27 09:41:48 -0800380 replacefilter(token: "@@url_schemes@@", value: urlSchemes)
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800381 }
382
383 if (executable != "idea") {
384 ant.move(file: "$path/Contents/MacOS/idea", tofile: "$path/Contents/MacOS/$executable")
385 }
386
387 ant.replace(file: "$path/bin/inspect.sh") {
388 replacefilter(token: "@@product_full@@", value: fullName)
389 replacefilter(token: "@@script_name@@", value: executable)
390 }
391 if (args.inspect_script != null && args.inspect_script != "inspect") {
392 ant.move(file: "$path/bin/inspect.sh", tofile: "$path/bin/${args.inspect_script}.sh")
393 }
394})
395
396binding.setVariable("winScripts", { String target, String home, String name, Map args ->
397 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
398 String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
399 String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase()}.exe"
400 if (vm_options.endsWith(".exe")) {
401 vm_options = vm_options.replace(".exe", "%BITS%.exe")
402 }
403 else {
404 vm_options = vm_options + "%BITS%"
405 }
406
407 String classPath = "SET CLASS_PATH=%IDE_HOME%\\lib\\${classPathLibs[0]}\n"
408 classPath += classPathLibs[1..-1].collect {"SET CLASS_PATH=%CLASS_PATH%;%IDE_HOME%\\lib\\${it}"}.join("\n")
409 if (args.tools_jar) classPath += "\nSET CLASS_PATH=%CLASS_PATH%;%JDK%\\lib\\tools.jar"
410
411 ant.copy(todir: "$target/bin") {
412 fileset(dir: "$home/bin/scripts/win")
413
414 filterset(begintoken: "@@", endtoken: "@@") {
415 filter(token: "product_full", value: fullName)
416 filter(token: "product_uc", value: product_uc)
417 filter(token: "vm_options", value: vm_options)
418 filter(token: "isEap", value: isEap())
419 filter(token: "system_selector", value: args.system_selector)
420 filter(token: "ide_jvm_args", value: ifNull(args.ide_jvm_args, ""))
421 filter(token: "class_path", value: classPath)
422 filter(token: "script_name", value: name)
423 }
424 }
425
426 if (name != "idea.bat") {
427 ant.move(file: "$target/bin/idea.bat", tofile: "$target/bin/$name")
428 }
429 if (args.inspect_script != null && args.inspect_script != "inspect") {
430 ant.move(file: "$target/bin/inspect.bat", tofile: "$target/bin/${args.inspect_script}.bat")
431 }
432
433 ant.fixcrlf(srcdir: "$target/bin", includes: "*.bat", eol: "dos")
434})
435
436private ifNull(v, defVal) { v != null ? v : defVal }
437
438binding.setVariable("unixScripts", { String target, String home, String name, Map args ->
439 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
440 String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
441 String vm_options = args.vm_options != null ? args.vm_options : p("component.names.product").toLowerCase()
442
443 String classPath = "CLASSPATH=\"\$IDE_HOME/lib/${classPathLibs[0]}\"\n"
444 classPath += classPathLibs[1..-1].collect {"CLASSPATH=\"\$CLASSPATH:\$IDE_HOME/lib/${it}\""}.join("\n")
445 if (args.tools_jar) classPath += "\nCLASSPATH=\"\$CLASSPATH:\$JDK/lib/tools.jar\""
446
447 ant.copy(todir: "$target/bin") {
448 fileset(dir: "$home/bin/scripts/unix")
449
450 filterset(begintoken: "@@", endtoken: "@@") {
451 filter(token: "product_full", value: fullName)
452 filter(token: "product_uc", value: product_uc)
453 filter(token: "vm_options", value: vm_options)
454 filter(token: "isEap", value: isEap())
455 filter(token: "system_selector", value: args.system_selector)
456 filter(token: "ide_jvm_args", value: ifNull(args.ide_jvm_args, ""))
457 filter(token: "class_path", value: classPath)
458 filter(token: "script_name", value: name)
459 }
460 }
461
462 if (name != "idea.sh") {
463 ant.move(file: "$target/bin/idea.sh", tofile: "$target/bin/$name")
464 }
465 if (args.inspect_script != null && args.inspect_script != "inspect") {
466 ant.move(file: "$target/bin/inspect.sh", tofile: "$target/bin/${args.inspect_script}.sh")
467 }
468
469 ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix")
470})
471
472binding.setVariable("winVMOptions", { String target, String system_selector, String name, String name64 = null ->
473 def options = isEap() && system_selector != null ? vmOptions32yjp(system_selector) : vmOptions32()
474 ant.echo(file: "$target/bin/${name}.vmoptions", message: options.replace(' ', '\n'))
475
476 if (name64 != null) {
477 options = isEap() && system_selector != null ? vmOptions64yjp(system_selector) : vmOptions64()
478 ant.echo(file: "$target/bin/${name64}.vmoptions", message: options.replace(' ', '\n'))
479 }
480
481 ant.fixcrlf(srcdir: "$target/bin", includes: "*.vmoptions", eol: "dos")
482})
483
484binding.setVariable("unixVMOptions", { String target, String name ->
Tor Norbyec1ace1f2013-07-08 11:26:24 -0700485 ant.echo(file: "$target/bin/${name}.vmoptions", message: "${vmOptions32()} -Dawt.useSystemAAFontSettings=lcd".trim().replace(' ', '\n'))
486 ant.echo(file: "$target/bin/${name}64.vmoptions", message: "${vmOptions64()} -Dawt.useSystemAAFontSettings=lcd".trim().replace(' ', '\n'))
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800487 ant.fixcrlf(srcdir: "$target/bin", includes: "*.vmoptions", eol: "unix")
488})
489
490binding.setVariable("unixReadme", { String target, String home, Map args ->
491 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
492 String settings_dir = args.system_selector.replaceFirst("\\d+", "")
493 copyAndPatchFile("$home/build/Install-Linux-tar.txt", "$target/Install-Linux-tar.txt",
494 ["product_full": fullName,
495 "product": p("component.names.product").toLowerCase(),
496 "system_selector": args.system_selector,
497 "settings_dir": settings_dir], "@@")
498 ant.fixcrlf(file: "$target/bin/Install-Linux-tar.txt", eol: "unix")
499})
500
501binding.setVariable("forceDelete", { String dirPath ->
502 // if wasn't deleted - retry several times
503 attempt = 1
504 while (attempt < 21 && (new File(dirPath).exists())) {
505 if (attempt > 1) {
506 ant.echo "Deleting $dirPath ... (attempt=$attempt)"
507
508 // let's wait a bit and try again - may be help
509 // in some cases on our windows 7 agents
510 sleep(2000)
511 }
512
513 ant.delete(failonerror: false, dir: dirPath)
514
515 attempt++
516 }
517
518 if (new File(dirPath).exists()) {
519 ant.project.log ("Cannot delete directory: $dirPath" )
520 System.exit (1)
521 }
522})
523
524binding.setVariable("patchPropertiesFile", { String target, Map args = [:] ->
525 String file = "$target/bin/idea.properties"
526
527 if (args.appendices != null) {
528 ant.concat(destfile: file, append: true) {
529 args.appendices.each {
530 fileset(file: it)
531 }
532 }
533 }
534
535 String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
536 String settings_dir = args.system_selector.replaceFirst("\\d+", "")
537 ant.replace(file: file) {
538 replacefilter(token: "@@product_uc@@", value: product_uc)
539 replacefilter(token: "@@settings_dir@@", value: settings_dir)
540 }
541
542 String message = (isEap() ? """
543#-----------------------------------------------------------------------
544# Change to 'disabled' if you don't want to receive instant visual notifications
545# about fatal errors that happen to an IDE or plugins installed.
546#-----------------------------------------------------------------------
547idea.fatal.error.notification=enabled
548"""
549 : """
550#-----------------------------------------------------------------------
551# Change to 'enabled' if you want to receive instant visual notifications
552# about fatal errors that happen to an IDE or plugins installed.
553#-----------------------------------------------------------------------
554idea.fatal.error.notification=disabled
555""")
556 ant.echo(file: file, append: true, message: message)
557})
558
559binding.setVariable("zipSources", { String home, String targetDir ->
560 String sources = "$targetDir/sources.zip"
561 projectBuilder.stage("zip sources to $sources")
562
563 ant.mkdir(dir: targetDir)
564 ant.delete(file: sources)
565 ant.zip(destfile: sources) {
566 fileset(dir: home) {
567 ["java", "groovy", "ipr", "iml", "form", "xml", "properties"].each {
568 include(name: "**/*.$it")
569 }
570 exclude(name: "**/testData/**")
571 }
572 }
573
574 notifyArtifactBuilt(sources)
575})
576
577/**
578 * E.g.
579 *
580 * Load all properties from file:
581 * readIdeaProperties("idea.properties.path" : "$home/ruby/build/idea.properties")
582 *
583 * Load all properties except "idea.cycle.buffer.size", change "idea.max.intellisense.filesize" to 3000
584 * and enable "idea.is.internal" mode:
585 * readIdeaProperties("idea.properties.path" : "$home/ruby/build/idea.properties",
586 * "idea.properties" : ["idea.max.intellisense.filesize" : 3000,
587 * "idea.cycle.buffer.size" : null,
588 * "idea.is.internal" : true ])
589 * @param args
590 * @return text xml properties description in xml
591 */
592private Map readIdeaProperties(Map args) {
593 String ideaPropertiesPath = args == null ? null : args.get("idea.properties.path")
594 if (ideaPropertiesPath == null) {
595 return [:]
596 }
597
598 // read idea.properties file
599 Properties ideaProperties = new Properties();
600 FileInputStream ideaPropertiesFile = new FileInputStream(ideaPropertiesPath);
601 ideaProperties.load(ideaPropertiesFile);
602 ideaPropertiesFile.close();
603
604 def defaultProperties = ["CVS_PASSFILE": "~/.cvspass",
605 "com.apple.mrj.application.live-resize": "false",
606 "idea.paths.selector": args.system_selector,
607 "java.endorsed.dirs": "",
608 "idea.smooth.progress": "false",
609 "apple.laf.useScreenMenuBar": "true",
610 "apple.awt.graphics.UseQuartz": "true",
611 "apple.awt.fullscreencapturealldisplays": "false"]
612 if (args.platform_prefix != null) {
613 defaultProperties.put("idea.platform.prefix", args.platform_prefix)
614 }
615
616 Map properties = defaultProperties
617 def customProperties = args.get("idea.properties")
618 if (customProperties != null) {
619 properties += customProperties
620 }
621
622 properties.each {k, v ->
623 if (v == null) {
624 // if overridden with null - ignore property
625 ideaProperties.remove(k)
626 } else {
627 // if property is overridden in args map - use new value
628 ideaProperties.put(k, v)
629 }
630 }
631
632 return ideaProperties;
633}
634
635private String submapToXml(Map properties, List keys) {
636// generate properties description for Info.plist
637 StringBuilder buff = new StringBuilder()
638
639 keys.each { key ->
640 String value = properties[key]
641 if (value != null) {
642 String string =
643 """
644 <key>$key</key>
645 <string>$value</string>
646"""
647 buff.append(string)
648 }
649 }
650 return buff.toString()
651}
652
653binding.setVariable("buildWinZip", { String zipPath, List paths ->
654 projectBuilder.stage(".win.zip")
655
656 fixIdeaPropertiesEol(paths, "dos")
657
658 ant.zip(zipfile: zipPath) {
659 paths.each {
660 fileset(dir: it)
661 }
662 }
663
664 notifyArtifactBuilt(zipPath)
665})
666
667binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, String macPath, List extraBins = [] ->
668 projectBuilder.stage(".mac.zip")
669
670 allPaths = paths + [macPath]
671 ant.zip(zipfile: zipPath) {
672 allPaths.each {
673 zipfileset(dir: it, prefix: zipRoot) {
674 exclude(name: "bin/*.sh")
675 exclude(name: "bin/fsnotifier")
Jean-Baptiste Queru9edc8f62013-02-08 15:14:04 -0800676 exclude(name: "bin/restarter")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800677 exclude(name: "Contents/MacOS/*")
678 extraBins.each {
679 exclude(name: it)
680 }
681 exclude(name: "bin/idea.properties")
682 }
683 }
684
685 allPaths.each {
686 zipfileset(dir: it, filemode: "755", prefix: zipRoot) {
687 include(name: "bin/*.sh")
688 include(name: "bin/fsnotifier")
Jean-Baptiste Queru9edc8f62013-02-08 15:14:04 -0800689 include(name: "bin/restarter")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800690 include(name: "Contents/MacOS/*")
691 extraBins.each {
692 include(name: it)
693 }
694 }
695 }
696
697 zipfileset(file: "$macPath/bin/idea.properties", prefix: "$zipRoot/bin")
698 }
699})
700
701binding.setVariable("buildTarGz", { String tarRoot, String tarPath, List paths ->
702 projectBuilder.stage(".tar.gz")
703
704 fixIdeaPropertiesEol(paths, "unix")
705
706 ant.tar(tarfile: tarPath, longfile: "gnu") {
707 paths.each {
708 tarfileset(dir: it, prefix: tarRoot) {
709 exclude(name: "bin/*.sh")
710 exclude(name: "bin/fsnotifier*")
711 type(type: "file")
712 }
713 }
714
715 paths.each {
716 tarfileset(dir: it, filemode: "755", prefix: tarRoot) {
717 include(name: "bin/*.sh")
718 include(name: "bin/fsnotifier*")
719 type(type: "file")
720 }
721 }
722 }
723
724 String gzPath = "${tarPath}.gz"
725 ant.gzip(src: tarPath, zipfile: gzPath)
726 ant.delete(file: tarPath)
727 notifyArtifactBuilt(gzPath)
728})
729
730private void fixIdeaPropertiesEol(List paths, String eol) {
731 paths.each {
732 String file = "$it/bin/idea.properties"
733 if (new File(file).exists()) {
734 ant.fixcrlf(file: file, eol: eol)
735 }
736 }
737}
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700738
Tor Norbyec1ace1f2013-07-08 11:26:24 -0700739binding.setVariable("buildWinLauncher", { String ch, String inputPath, String outputPath, String appInfo,
740 String launcherProperties, String pathsSelector, List resourcePaths ->
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700741 projectBuilder.stage("winLauncher")
742
Tor Norbyed1a59a02013-04-03 16:27:26 -0700743 File launcherPropertiesTempFile = null;
744 if (pathsSelector != null) {
745 String propertiesContent = new File(launcherProperties).text
746 if (propertiesContent.contains("__PRODUCT_PATHS_SELECTOR__")) {
747 propertiesContent = propertiesContent.replace("__PRODUCT_PATHS_SELECTOR__", pathsSelector)
748 launcherPropertiesTempFile = File.createTempFile("launcher", ".properties")
749 launcherPropertiesTempFile.write(propertiesContent)
750 launcherProperties = launcherPropertiesTempFile.getAbsolutePath()
751 }
752 }
753
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700754 ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true") {
755 arg(value: inputPath)
756 arg(value: appInfo)
757 arg(value: "$ch/native/WinLauncher/WinLauncher/resource.h")
758 arg(value: launcherProperties)
759 arg(value: outputPath)
760 classpath {
761 pathelement(location: "$ch/build/lib/launcher-generator.jar")
762 fileset(dir: "$ch/lib") {
763 include(name: "guava*.jar")
764 include(name: "jdom.jar")
765 include(name: "sanselan*.jar")
766 }
767 resourcePaths.each {
768 pathelement(location: it)
769 }
770 }
771 }
Tor Norbyed1a59a02013-04-03 16:27:26 -0700772
773 if (launcherPropertiesTempFile != null) {
774 launcherPropertiesTempFile.delete()
775 }
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700776})
Tor Norbyebeca9832013-09-19 12:39:22 -0700777
Tor Norbyef7998d02013-09-27 10:19:19 -0700778binding.setVariable("collectUsedJars", { List modules, List approvedJars, List forbiddenJars, List modulesToBuild ->
Tor Norbyebeca9832013-09-19 12:39:22 -0700779 def usedJars = new HashSet();
780
Tor Norbyebeca9832013-09-19 12:39:22 -0700781 modules.each {
782 def module = findModule(it)
783 if (module != null) {
784 projectBuilder.moduleRuntimeClasspath(module, false).each {
785 File file = new File(it)
786 if (file.exists()) {
787 String path = file.canonicalPath.replace('\\', '/')
788 if (path.endsWith(".jar") && approvedJars.any { path.startsWith(it) } && !forbiddenJars.any { path.contains(it) }) {
789 if (usedJars.add(path)) {
790 projectBuilder.info("\tADDED: $path for ${module.getName()}")
791 }
792 }
793 }
794 }
Tor Norbyef7998d02013-09-27 10:19:19 -0700795 if (modulesToBuild != null) {
796 modulesToBuild << module
797 }
Tor Norbyebeca9832013-09-19 12:39:22 -0700798 }
799 else {
800 projectBuilder.warning("$it is not a module")
801 }
802 }
Tor Norbyef7998d02013-09-27 10:19:19 -0700803
804 return usedJars
805})
806
807binding.setVariable("buildModulesAndCollectUsedJars", { List modules, List approvedJars, List forbiddenJars ->
808 def modulesToBuild = []
809 def usedJars = collectUsedJars(modules, approvedJars, forbiddenJars, modulesToBuild)
810 projectBuilder.cleanOutput()
Tor Norbyebeca9832013-09-19 12:39:22 -0700811 projectBuilder.buildModules(modulesToBuild)
812
813 return usedJars
814})
815
816binding.setVariable("buildSearchableOptions", { String target, List licenses, Closure cp, String jvmArgs = null,
817 def paths = getProperty("paths") ->
818 projectBuilder.stage("Building searchable options")
819
820 String targetFile = "${target}/searchableOptions.xml"
821 ant.delete(file: targetFile)
822
823 licenses.each {
824 ant.copy(file: it, todir: paths.ideaSystem)
825 }
826
827 ant.path(id: "searchable.options.classpath") { cp() }
828 String classpathFile = "${paths.sandbox}/classpath.txt"
829 ant.echo(file: classpathFile, append: false, message: "\${toString:searchable.options.classpath}")
830 ant.replace(file: classpathFile, token: File.pathSeparator, value: "\n")
831
832 ant.java(classname: "com.intellij.rt.execution.CommandLineWrapper", fork: true, failonerror: true) {
833 jvmarg(line: "-Xbootclasspath/a:${projectBuilder.moduleOutput(findModule("boot"))} -ea -Xmx500m -XX:MaxPermSize=200m")
834 jvmarg(line: "-Didea.home.path=$home -Didea.system.path=${paths.ideaSystem} -Didea.config.path=${paths.ideaConfig}")
835 if (jvmArgs != null) {
836 jvmarg(line: jvmArgs)
837 }
838
839 arg(line: "${classpathFile} com.intellij.idea.Main traverseUI ${target}/searchableOptions.xml")
840
841 classpath() {
842 pathelement(location: "${projectBuilder.moduleOutput(findModule("java-runtime"))}")
843 }
844 }
845
846 ant.available(file: targetFile, property: "searchable.options.exists");
847 ant.fail(unless: "searchable.options.exists", message: "Searchable options were not built.")
848})