Fix community plugin build
authorDmitry Trofimov <dmitry.trofimov@jetbrains.com>
Fri, 18 Nov 2016 11:02:57 +0000 (12:02 +0100)
committerDmitry Trofimov <dmitry.trofimov@jetbrains.com>
Tue, 22 Nov 2016 11:57:44 +0000 (12:57 +0100)
(cherry picked from commit 995599749569bd0d1c4050bc9858d356fd5e827b)
(cherry picked from commit fd2c6ee29dadc1adf1caebdd70f31c175dd96366)

python/build/python_plugin_build.gant

index 96c4bca4fe5d5c49ca2f53acfff42d44ba7dd0e1..85e61bec42ef56f41b5757541ba0dc6d9d9856a1 100644 (file)
+import org.jetbrains.intellij.build.impl.BuildUtils
+import org.jetbrains.jps.model.library.JpsOrderRootType
+
 import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
 
 setProperty("projectHome", guessHome(this as Script))
-setProperty("home", projectHome)
 
 includeTargets << new File("${projectHome}/build/scripts/utils.gant")
 
-setProperty("outDir", "${projectHome}/out/python")
-setProperty("ideaDir", "${outDir}/ideaCE")
-requireProperty("ideaPath", ideaDir)
-
-setProperty("pluginHelp", "${outDir}/help")
-
-setProperty("buildNumber", requireProperty("build.number", snapshot))
-setProperty("ideaBuildNumber", requireProperty("idea.build.number"))
-
-setProperty("ideaSinceBuildNumber", ("${ideaBuildNumber}" =~ /(\d+\.[A-Z0-9]+)/)[0][1])
-
-setProperty("ideaHomePacked", "${ideaDir}/jdk16") //compiled idea
-setProperty("ideaHome", "${ideaDir}/jdk16/idea-IC-${ideaBuildNumber}") //compiled idea
-
-setProperty("pluginHome", "${projectHome}/python")
-setProperty("pluginRevision", "${buildNumber}")
+setProperty("dryRun", false)
 
-setProperty("ideaLib", "${ideaHome}/lib")
-setProperty("ideaPlugins", "${ideaHome}/plugins") //compiled plugins
+setProperty("communityHome", "${projectHome}/python")
 
+setProperty("pythonPluginVersion", requireProperty("build.number", snapshot))
 
-setProperty("output", "${projectHome}/python/distCE")
+def buildModules(List modules, List libDirs) {
+  def forbiddenJars = [
+    "/dev/", "/rt/", "/ant/",
+    "ls-client-api", "/ideaLicenseDecoder", "jcip-annotations",
+    "/eawtstub.jar", "/y.jar", "/ysvg.jar"
+  ]
 
-setProperty("zipdir", "${output}/zip")
-setProperty("plugindir", "${zipdir}/python")
-setProperty("zipname", "python-community-${pluginRevision}.zip")
+  def normalizedHome = home.replace('\\', '/')
+  def approvedJars = ["$normalizedHome/lib/", "$normalizedHome/xml/relaxng/lib/"]
+  libDirs.each { approvedJars.add("$normalizedHome/$it/") }
 
-setProperty("srcDir", "${pluginHome}/src")
+  buildModulesAndCollectUsedJars(modules, approvedJars, forbiddenJars)
+}
 
-setProperty("classesRootDir", "${outDir}/classes")
-setProperty("classesDir", "${classesRootDir}/python")
 
-//Compiler options
-setProperty("compilerDebug", "on")
-setProperty("compilerGenerateNoWarnings", "off")
-setProperty("compilerArgs", "")
-setProperty("compilerMaxMemory", "256m")
+target('default': "Build Python Plugin") {
+  def pythonHome = "$home/python"
+  ant.property(file: "$pythonHome/build/build-plugin.properties")
+  BuildUtils.addToClassPath("$home/python/build/groovy", ant)
 
-ant.patternset(id: "resources.pt") {
-  include(name: "**/?*.properties")
-  include(name: "**/?*.template")
-  include(name: "**/?*.xml")
-  include(name: "**/?*.gif")
-  include(name: "**/?*.png")
-  include(name: "**/?*.txt")
-  include(name: "**/?*.jpeg")
-  include(name: "**/?*.jpg")
-  include(name: "**/?*.html")
-  include(name: "**/?*.dtd")
-  include(name: "**/?*.tld")
-  include(name: "**/?*.py")
-  include(name: "**/?*.ft")
-  include(name: "**/?*.dic")
-  exclude(name: "**/plugin.xml")
-}
+  def communityModules = [
+    "IntelliLang-python",
+    "ipnb",
+    "python-openapi",
+    "python-community-plugin-core",
+    "python-community-plugin-java",
+    "python-psi-api",
+    "python-pydev",
+    "python-community-ide-resources",
+    "python-community"
+  ]
 
-target(name: "clean", description: "Cleanup output") {
-  ant.echo("Cleaning ${output}")
-  ant.delete(dir: "${output}", failonerror: "false")
-  ant.echo("Cleaning ${classesRootDir}")
-  ant.delete(dir: "${classesRootDir}", failonerror: "false")
-  ant.echo("Cleaning ${ideaHome}")
-  ant.delete(dir: "${ideaHome}", failonerror: "false")          // out/python/idea/
-}
 
-target(name: "unzip") {
-  ant.mkdir(dir: "${ideaHomePacked}")
-  ant.gunzip(src: "${ideaPath}/ideaIC-${ideaBuildNumber}.tar.gz")
-  ant.untar(src: "${ideaPath}/ideaIC-${ideaBuildNumber}.tar", dest: "${ideaHomePacked}")
-}
+  def modules = communityModules
 
-target(name: "compile", description: "Compile module python") {
-  depends("unzip")
+  def outDir = "$home/out/python"
+  def ideaDistDir = "$outDir/idea"
+  def helpDir = "$outDir/help"
+  loadProject()
 
-  ant.path(id: "classpath.lib") {
-    fileset(dir: "${ideaLib}") {
-      include(name: "?*.jar")
-    }
-    fileset(dir: "${ideaPlugins}/terminal/lib") {
-      include(name: "*.jar")
-    }
-    fileset(dir: "${ideaPlugins}/IntelliLang/lib") {
-      include(name: "*.jar")
-    }
-    fileset(dir: "${pluginHome}/ipnb/lib") {
-      include(name: "*.jar")
-    }
+  if (dryRun) {
+    projectBuilder.targetFolder = "$home/out/classes"
   }
-
-  ant.path(id: "sourcepath") {
-    dirset(dir: "${pluginHome}") {
-      include(name: "src")
-      include(name: "gen")
-      include(name: "pluginCore")
-      include(name: "pluginJava")
-      include(name: "pydevSrc")
-      include(name: "openapi/src")
-      include(name: "psi-api/src")
-      include(name: "IntelliLang-python/src")
-      include(name: "ipnb/src")
-    }
-  }
-  //The task requires the following libraries from IntelliJ IDEA distribution:
-  //javac2.jar; jdom.jar; asm.jar; asm-commons.jar
-  ant.taskdef(name: "javac2", classname: "com.intellij.ant.Javac2") {
-    classpath {
-      fileset(dir: "${ideaLib}") {
-        include(name: "?*.jar")
-      }
-    }
+  else {
+    projectBuilder.targetFolder = "$outDir/classes"
   }
+  projectBuilder.dryRun = dryRun
 
-  ant.mkdir(dir: "${classesDir}")
-
-  //compile
-  ant.javac2(destdir: "${classesDir}",
-             debug: "${compilerDebug}",
-             nowarn: "${compilerGenerateNoWarnings}",
-             memorymaximumsize: "${compilerMaxMemory}",
-             fork: "true") {
-    compilerarg(line: "${compilerArgs}")
-    classpath(refid: "classpath.lib")
-    src(refid: "sourcepath")
+  projectBuilder.stage("Cleaning up sandbox folder")
+  if (!dryRun) {
+    forceDelete("$outDir/classes")
   }
 
-  //copy resources
-  ant.copy(todir: "${classesDir}") {
-    fileset(dir: "${pluginHome}/resources") {
-      patternset(refid: "resources.pt")
-      type(type: "file")
-    }
-    fileset(dir: "${pluginHome}/python-community-ide-resources/resources") {
-      patternset(refid: "resources.pt")
-      type(type: "file")
-    }
-    fileset(dir: "${pluginHome}/src") {
-      patternset(refid: "resources.pt")
-      type(type: "file")
-    }
-    fileset(dir: "${pluginHome}/psi-api/resources") {
-      patternset(refid: "resources.pt")
-      type(type: "file")
-    }
-    fileset(dir: "${pluginHome}/IntelliLang-python/resources") {
-      patternset(refid: "resources.pt")
-      type(type: "file")
-    }
-    fileset(dir: "${pluginHome}/IntelliLang-python/src") {
-      include(name: "resources/*.xml")
-    }
-    fileset(dir: "${home}/colorSchemes/src")
-    fileset(dir: "${pluginHome}/ipnb/resources") {
-      patternset(refid: "resources.pt")
-      type(type: "file")
-    }
+  buildModules(modules, [])
+
+  def ideaBuildTxt = new File(ideaDistDir, "build.txt")
+  def currentIdeaBranch
+  def currentIdeaBuild
+  if (ideaBuildTxt.exists()) {
+    def matcher = (ideaBuildTxt.text =~ /IU-(\d+)\.(\d+).*/)
+    currentIdeaBranch = matcher[0][1]
+    currentIdeaBuild = matcher[0][2]
+  }
+  else {
+    currentIdeaBranch = null
+    currentIdeaBuild = null
   }
 
-  //copy plugin.xml
-  ant.mkdir(dir: "${classesDir}/META-INF")
-  ant.copy(todir: "${classesDir}/META-INF") {
-    fileset(file: "${pluginHome}/pluginCore/META-INF/python-community-plugin-core.xml")
-    fileset(file: "${pluginHome}/pluginJava/META-INF/python-community-plugin-java.xml")
-    fileset(file: "${pluginHome}/pluginResources/META-INF/plugin.xml")
-    fileset(file: "${pluginHome}/build/python-plugin-dependencies.xml")
+  def sinceBuild
+  def untilBuild
+  if (currentIdeaBranch != null && currentIdeaBuild != null) {
+    sinceBuild = "${currentIdeaBranch}.${currentIdeaBuild}"
+    untilBuildNum = (currentIdeaBranch.toInteger() + 1).toString()
+    untilBuild = "$untilBuildNum.0"
+  } else {
+    sinceBuild = null
+    untilBuild = null
   }
 
+  //  def pluginVersion = "$pythonPluginVersion.${new SimpleDateFormat("yyyyMMdd").format(new Date())}"
+  def pluginVersion = "$pythonPluginVersion"
+
   // set version to PyCharm current version from ApplicationInfo.xml
-  ant.loadfile(property: "appInfo", srcFile: "${pluginHome}/python-community-ide-resources/resources/idea/PyCharmCoreApplicationInfo.xml") {
+  ant.loadfile(property: "appInfo", srcFile: "${communityHome}/python-community-ide-resources/resources/idea/PyCharmCoreApplicationInfo.xml") {
   }
 
-  major = ("${appInfo}" =~ /major\s*=\s*\"([^"])\"/)[0][1]
-  minor = ("${appInfo}" =~ /minor\s*=\s*\"([^"])\"/)[0][1]
+  ant.xmlproperty(file: "${communityHome}/python-community-ide-resources/resources/idea/PyCharmCoreApplicationInfo.xml", collapseAttributes: "true")
 
+  def pythonPluginVersionString = "${versionSelector()}.${pluginVersion}"
 
-  ant.replaceregexp(file: "${classesDir}/META-INF/plugin.xml",
-                    match: "@@PYCHARM_VERSION@@",
-                    replace: "${major}.${minor}")
 
-  // set since-build to the current idea build number
-  ant.replace(file: "${classesDir}/META-INF/plugin.xml") {
-    replacefilter(token: "@@BUILD_NUMBER@@", value: "${buildNumber}")
+  ant.mkdir(dir: "$outDir/plugins/python-ce")
+  ant.copy(file: "$communityHome/pluginResources/META-INF/plugin.xml", todir: "$outDir/plugins/python-ce")
+  ant.replace(file: "$outDir/plugins/python-ce/plugin.xml") {
+    replacefilter(token: "@@PYCHARM_VERSION@@", value: "$pythonPluginVersionString")
   }
 
-  ant.replaceregexp(file: "${classesDir}/META-INF/plugin.xml",
-                    match: "since-build=\"\\d+\\.\\d+\"",
-                    replace: "since-build=\"${ideaSinceBuildNumber}\"")
-}
-
-target(name: "jar", description: "Generate jar file") {
-  depends("compile")
-  ant.mkdir(dir: "${output}")
-  ant.jar(destfile: "${output}/python-community.jar", basedir: "${classesDir}") {
-    manifest() {
-      attribute(name: "Revision", value: "${pluginRevision}")
-      //<!--<attribute name="Build" value="${plugin.version}"/>-->
-    }
+  if (sinceBuild != null && untilBuild != null) {
+    ant.replaceregexp(file: "$outDir/plugins/python-ce/plugin.xml",
+                      match: "since-build=\"[^\"]+\"",
+                      replace: "since-build=\"${sinceBuild}\"")
   }
-}
-
-target(name: "zip", description: "Generate zip plugin file") {
-  depends("jar")
-
-  ant.mkdir(dir: "${zipdir}")
 
-  // copy plugin jar
-  ant.mkdir(dir: "${plugindir}/lib")
-  ant.move(file: "${output}/python-community.jar", todir: "${plugindir}/lib")
-
-  ant.copy(todir: "${plugindir}/lib") {
-    fileset(dir: "${pluginHome}/ipnb/lib") {
-      include(name: "*.jar")
+  layout("$outDir/layout-ce") {
+    dir("python") {
+      dir("lib") {
+        jar("python.jar") {
+          communityModules.each {
+            module(it) {
+              exclude(name: "**/plugin.xml")
+              exclude(name: "**/python-plugin-dependencies.xml")
+            }
+          }
+          dir("META-INF") {
+            fileset(file: "$outDir/plugins/python-ce/plugin.xml")
+            fileset(file: "$communityHome/build/python-plugin-dependencies.xml")
+          }
+        }
+        fileset(dir: "${communityHome}/ipnb/lib") {
+          include(name: "*.jar")
+        }
+      }
+      dir("help") {
+        fileset(dir: "${helpDir}") {
+          include(name: "pytonpluginhelp.jar")
+          include(name: "pytonpluginhelp_mac.jar")
+        }
+      }
+      dir("helpers") {
+        fileset(dir: "${communityHome}/helpers") {
+          include(name: "**/*")
+        }
+      }
     }
   }
 
-  ant.mkdir(dir: "${plugindir}/helpers")
-  ant.copy(todir: "${plugindir}/helpers") {
-    fileset(dir: "${pluginHome}/helpers") {
-      include(name: "**/*")
-    }
+  def zipFilePathCE = "$outDir/python-community-${pluginVersion}.zip"
+  ant.delete(file: zipFilePathCE)
+  ant.zip(destfile: zipFilePathCE) {
+    fileset(dir: "$outDir/layout-ce")
   }
+  notifyArtifactBuilt(zipFilePathCE)
 
-  ant.mkdir(dir: "${plugindir}/help")
-  ant.copy(file: "${pluginHelp}/pytonpluginhelp.jar", tofile: "${plugindir}/help/pythonpluginhelp.jar", failonerror: false)
-  ant.copy(file: "${pluginHelp}/pytonpluginhelp_mac.jar", tofile: "${plugindir}/help/pythonpluginhelp_mac.jar", failonerror: false)
+  def pluginsPaths = []
+  pluginsPaths << zipFilePathCE
 
-  ant.zip(basedir: "${zipdir}", destfile: "${output}/${zipname}")
-}
 
-target(name: "build") {
-  depends("unzip")
-  depends("compile")
-}
-
-target(name: "dist", description: "main target") {
-  depends("clean")
-  depends("build")
-  depends("zip")
-}
-
-target('default': "Build artifacts") {
-  depends("dist")
-}
+  new File(outDir, "plugins-paths.txt").text = pluginsPaths.join("\n")
+}
\ No newline at end of file