217c9cbe26c776c9adc134a620f3112ea019c33e
[idea/community.git] / python / edu / build / pycharm_edu_build.gant
1 /*
2  * Copyright 2000-2014 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
17 import org.jetbrains.jps.LayoutInfo
18
19 setProperty("home", getHome())
20 includeTargets << new File("$home/community/build/scripts/utils.gant")
21 includeTargets << new File("$home/community/build/scripts/libLicenses.gant")
22 includeTargets << new File("$home/build/scripts/ultimate_utils.gant")
23
24 requireProperty("buildNumber", requireProperty("build.number", snapshot))
25 setProperty("buildName", "PE-$buildNumber")
26 setProperty("ch", "$home/community")
27 setProperty("pythonCommunityHome", "$ch/python")
28 setProperty("pythonEduHome", "$ch/python/edu")
29 requireProperty("jdk_bundled_mac", "1.7")
30 def jdk_bundled_version = p("jdk_bundled_mac") == "1.8" ? "jdk8_mac_redist.tar" : "jdk_mac_redist.tar"
31 ant.copy(file: "${home}/build/jdk/${jdk_bundled_version}", tofile: "${home}/build/jdk/jdk_mac_redist_for_${buildNumber}.tar")
32
33 // load ApplicationInfo.xml properties
34 ant.xmlproperty(file: "$pythonEduHome/resources/idea/PyCharmEduApplicationInfo.xml", collapseAttributes: "true")
35 setProperty("system_selector", "PyCharm${p("component.version.major")}0")
36 setProperty("dryRun", false)
37 setProperty("jdk16", guessJdk())
38
39 //modules to compile
40 setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
41
42 private String getHome(){
43   // current file is supposed to be at build/scripts/*.gant path
44   String uri = this["gant.file"]
45   return new File(new URI(uri).getSchemeSpecificPart()).getParentFile().getParentFile().getParentFile().getParentFile().getParentFile()
46 }
47
48 private List<String> pycharmPlatformApiModules() {
49   return [platformApiModules, "dom-openapi"].flatten()
50 }
51
52
53 private List pycharmImplementationModules() {   //modules to put into pycharm.jar
54   return [platformImplementationModules, "dom-impl", "python-community", "python-ide-community", "python-educational", "python-openapi", "python-psi-api",
55     "platform-main"].flatten()
56 }
57
58 private List modules() {
59   return [
60     "python-pydev", "colorSchemes", pycharmPlatformApiModules(), pycharmImplementationModules(), pluginFilter
61   ].flatten()
62 }
63
64 private List approvedJars() {
65   def normalizedHome = ch.replace('\\', '/')
66   def normalizedPythonHome = pythonCommunityHome.replace('\\', '/')
67   return ["$normalizedHome/lib/", "$normalizedPythonHome/lib/", "$normalizedHome/xml/relaxng/lib/"]
68 }
69
70 class Paths {
71   final sandbox
72   final distAll
73   final distWin
74   final distMac
75   final distUnix
76   final artifacts
77   final ideaSystem
78   final ideaConfig
79
80   def Paths(String home) {
81     sandbox = "$home/out/pycharmEDU"
82
83     distAll = "$sandbox/layout"
84     distWin = "$sandbox/win"
85     distMac = "$sandbox/mac"
86     distUnix = "$sandbox/unix"
87     artifacts = "$sandbox/artifacts"
88
89     ideaSystem = "$sandbox/system"
90     ideaConfig = "$sandbox/config"
91   }
92 }
93
94 setProperty("paths", new Paths(home))
95 setProperty("buildName", "PE-$buildNumber")
96
97 target('default': "Build artifacts") {
98
99   loadProject()
100
101   List resourcePaths = ["$ch/community-resources/src",
102                         "$ch/platform/icons/src",
103                         "$pythonEduHome/resources"]
104
105   projectBuilder.stage("Cleaning up sandbox folder")
106
107   projectBuilder.targetFolder = "${paths.sandbox}/classes"
108   projectBuilder.dryRun = dryRun
109
110   if (!dryRun) {
111     forceDelete(paths.sandbox)
112     ant.mkdir(dir: paths.sandbox)
113   }
114
115   ant.tstamp() {
116     format(property: "todayYear", pattern: "yyyy")
117   }
118
119   ant.patternset(id: "resources.included") {
120     include(name: "**/*.properties")
121     include(name: "fileTemplates/**/*")
122     include(name: "inspectionDescriptions/**/*")
123     include(name: "intentionDescriptions/**/*")
124     include(name: "tips/**/*")
125     include(name: "search/**/*")
126   }
127
128   ant.patternset(id: "resources.excluded") {
129     exclude(name: "**/*.properties")
130     exclude(name: "fileTemplates/**/*")
131     exclude(name: "fileTemplates")
132     exclude(name: "inspectionDescriptions/**/*")
133     exclude(name: "inspectionDescriptions")
134     exclude(name: "intentionDescriptions/**/*")
135     exclude(name: "intentionDescriptions")
136     exclude(name: "tips/**/*")
137     exclude(name: "tips")
138     exclude(name: "courses")
139     exclude(name: "courses/*")
140   }
141
142   zipSources(home, paths.artifacts)
143
144   def usedJars = buildModulesAndCollectUsedJars(modules(), approvedJars(), ["/ant/"])
145
146   layoutEducational("${paths.sandbox}/classes/production", usedJars)
147
148
149   def extraArgs = ["build.code": "pycharm${buildName}", "build.number": "PE-$buildNumber", "artifacts.path": "${paths.artifacts}"]
150   signMacZip("pycharm", extraArgs + ["sitFileName": "pycharm${buildName}-jdk-bundled", "jdk_archive_name": "jdk_mac_redist_for_${buildNumber}.tar"])
151   buildDmg("pycharm", "${pythonEduHome}/build/DMG_background.png", extraArgs + ["sitFileName": "pycharm${buildName}-jdk-bundled", "jdk_archive_name": "jdk_mac_redist_for_${buildNumber}.tar"])
152
153 }
154
155 public layoutEducational(String classesPath, Set usedJars) {
156   setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
157
158   if (usedJars == null) {
159     usedJars = collectUsedJars(modules(), approvedJars(), ["/ant/"], null)
160   }
161
162   def appInfo = appInfoFile()
163   def paths = new Paths(home)
164   buildSearchableOptions("${projectBuilder.moduleOutput(findModule("platform-resources"))}/search", [], {
165     projectBuilder.moduleRuntimeClasspath(findModule("main_pycharm_edu"), false).each {
166       ant.pathelement(location: it)
167     }
168   }, "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true")
169
170   if (!dryRun) {
171     wireBuildDate("PE-${buildNumber}", appInfo)
172   }
173
174   Map args = [
175     buildNumber: "PE-${buildNumber}",
176     system_selector: system_selector,
177     ide_jvm_args: "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true"]
178
179   LayoutInfo layoutInfo = layoutFull(args, paths.distAll, usedJars)
180   generateLicensesTable("$paths.artifacts/third-party-libraries.txt", layoutInfo.usedModules);
181
182   layoutWin(args, paths.distWin)
183   layoutUnix(args, paths.distUnix)
184   layoutMac(args, paths.distMac)
185
186   ant.echo(message: "PE-${buildNumber}", file: "${paths.distAll}/build.txt")
187
188   def launcher = "${paths.distWin}/bin/pycharm.exe"
189   List resourcePaths = ["$ch/community-resources/src",
190     "$ch/platform/icons/src",
191     "$pythonCommunityHome/resources",
192     "$pythonEduHome/resources"]
193   buildWinLauncher(ch, "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
194                    appInfo, "$pythonEduHome/build/pycharm_edu_launcher.properties", system_selector, resourcePaths)
195   //signExe(launcher)
196   executeExternalAnt(["dirName": "${paths.distWin}/bin", "fileName": "pycharm.exe"], "$home/build/signBuild.xml")
197
198   buildWinZip("${paths.artifacts}/pycharm${buildName}.zip", [paths.distAll, paths.distWin])
199
200   buildNSIS([paths.distAll, paths.distWin],
201             "$pythonEduHome/build/strings.nsi", "$pythonEduHome/build/paths.nsi",
202             "pycharmPE-", false, true, ".py", system_selector)
203
204   String tarRoot = isEap() ? "pycharm-pe-$buildNumber" : "pycharm-pe-${p("component.version.major")}.${p("component.version.minor")}"
205   buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix])
206
207   String macAppRoot = isEap() ? "PyCharm PE ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm PE.app/Contents"
208   buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac)
209   ant.copy(file: "${paths.artifacts}/pycharm${buildName}.sit", tofile: "${paths.artifacts}/pycharm${buildName}-jdk-bundled.sit")
210   ant.delete(file: "${paths.artifacts}/pycharm${buildName}.sit")
211 }
212
213 private layoutPlugins(layouts) {
214   dir("plugins") {
215     layouts.layoutPlugin("learn-python") {
216       dir("courses") {
217         fileset(dir: "$pythonEduHome/learn-python/resources/courses")
218       }
219     }
220   }
221
222   layouts.layoutCommunityPlugins(ch)
223 }
224
225 private String appInfoFile() {
226   return "$pythonEduHome/resources/idea/PyCharmEduApplicationInfo.xml"
227 }
228
229 private layoutFull(Map args, String target, Set usedJars) {
230   def openapiModules = pycharmPlatformApiModules()
231   def superLayouts = includeFile("$ch/build/scripts/layouts.gant")
232
233   reassignAltClickToMultipleCarets("$ch")
234   
235   def result = layout(target) {
236     dir("lib") {
237       jar("util.jar") {
238         module("util")
239         module("util-rt")
240       }
241
242       jar("openapi.jar") {
243         openapiModules.each { module it }
244       }
245
246       jar("annotations.jar") { module("annotations") }
247       jar("extensions.jar") { module("extensions") }
248
249       jar("pycharm.jar") {
250         pycharmImplementationModules().each {
251           module(it) {
252             exclude(name: "**/tips/**")
253           }
254         }
255       }
256
257       jar("pycharm-pydev.jar") {
258         module("python-pydev")
259       }
260
261       jar("bootstrap.jar") { module("bootstrap") }
262       jar("resources.jar") {
263         module("platform-resources")
264         module("colorSchemes")
265       }
266
267       jar("forms_rt.jar") {
268         module("forms_rt")
269       }
270
271       //noinspection GroovyAssignabilityCheck
272       jar([name: "resources_en.jar", duplicate: "preserve"]) {
273         // custom resources should go first
274         fileset(dir: "$pythonCommunityHome/resources") {
275           include(name: "**/tips/**")
276         }
277         module("platform-resources-en") {
278           ant.patternset {
279             exclude(name: "tips/images/switcher.png")
280             exclude(name: "tips/images/navigateToFilePath.gif")
281           }
282         }
283       }
284
285       jar("icons.jar") { module("icons") }
286       jar("boot.jar") { module("boot") }
287
288       usedJars.each {
289         fileset(file: it)
290       }
291
292       dir("libpty") {
293         fileset(dir: "$ch/lib/libpty") {
294           exclude(name: "*.txt")
295         }
296       }
297
298       dir("ext") {
299         fileset(dir: "$ch/lib") {
300           include(name: "cglib*.jar")
301         }
302       }
303
304       dir("src") {
305         fileset(dir: "$ch/lib/src") {
306           include(name: "trove4j_changes.txt")
307           include(name: "trove4j_src.jar")
308         }
309
310         jar("pycharm-pydev-src.zip") {
311           fileset(dir: "$pythonCommunityHome/pydevSrc")
312         }
313         jar("pycharm-openapi-src.zip") {
314           fileset(dir: "$pythonCommunityHome/openapi/src")
315           fileset(dir: "$pythonCommunityHome/psi-api/src")
316         }
317       }
318     }
319
320     dir("help") {
321       fileset(dir: "$home/python/help") {
322         include(name: "*.pdf")
323       }
324     }
325
326     dir("helpers") {
327       fileset(dir: "$pythonCommunityHome/helpers")
328     }
329
330     dir("license") {
331       fileset(dir: "$ch/license")
332       fileset(dir: "$ch") {
333         include(name: "LICENSE.txt")
334         include(name: "NOTICE.txt")
335       }
336     }
337
338     layoutPlugins(superLayouts)
339
340     dir("bin") {
341       fileset(dir: "$ch/bin") {
342         exclude(name: "appletviewer.policy")
343         include(name: "*.*")
344       }
345     }
346   }
347   patchPropertiesFile(target, args + [appendices: ["$home/build/conf/ideaJNC.properties"]])
348   return result
349 }
350
351 private layoutWin(Map args, String target) {
352   layout(target) {
353     dir("bin") {
354       fileset(dir: "$ch/bin/win") {
355         exclude(name: "breakgen*")
356       }
357     }
358
359     dir("skeletons") {
360       fileset(dir: "$pythonCommunityHome/skeletons") {
361         include(name: "skeletons-win*.zip")
362       }
363     }
364   }
365
366   winScripts(target, ch, "pycharm.bat", args)
367   winVMOptions(target, null, "pycharm.exe")
368
369   ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
370 }
371
372 private layoutUnix(Map args, String target) {
373   layout(target) {
374     dir("bin") {
375       fileset(dir: "$ch/bin/linux") {
376         exclude(name: "libbreakgen*")
377       }
378     }
379   }
380
381   ant.copy(file: "$pythonCommunityHome/resources/PyCharmCore128.png", tofile: "$target/bin/pycharm.png")
382
383   unixScripts(target, ch, "pycharm.sh", args)
384   unixVMOptions(target, "pycharm")
385
386   ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
387 }
388
389 private layoutMac(Map _args, String target) {
390   layout(target) {
391     dir("bin") {
392       fileset(dir: "$home/bin") {
393         include(name: "*.jnilib")
394       }
395     }
396
397     dir("skeletons") {
398       fileset(dir: "$pythonCommunityHome/skeletons") {
399         include(name: "skeletons-mac*.zip")
400       }
401     }
402   }
403
404   Map args = new HashMap(_args)
405   args.icns = "$pythonCommunityHome/resources/PyCharmCore.icns"
406   args.bundleIdentifier = "com.jetbrains.pycharm"
407   args.platform_prefix = "PyCharmEdu"
408   args.help_id = "PY"
409   args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
410   args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"];
411   layoutMacApp(target, ch, args)
412 }