changeset 17224:a02c295218aa

mx: add support for cygwin * use `cygpath' to translate paths * pay attention when passing paths from unix world to windows world (e.g., when calling out to `javac') * adapt _runInDebugShell to avoid quoting issues
author Bernhard Urban <bernhard.urban@jku.at>
date Fri, 26 Sep 2014 04:53:13 -0700
parents 5b8f316bdb9e
children fd0f5f9abb79
files mx/mx_graal.py mxtool/mx.py
diffstat 2 files changed, 109 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/mx/mx_graal.py	Thu Sep 25 20:57:00 2014 -0700
+++ b/mx/mx_graal.py	Fri Sep 26 04:53:13 2014 -0700
@@ -154,6 +154,9 @@
         _vmbuild = self.previousBuild
 
 def chmodRecursive(dirname, chmodFlagsDir):
+    if mx.get_os() == 'windows':
+        return
+
     def _chmodDir(chmodFlags, dirname, fnames):
         os.chmod(dirname, chmodFlagsDir)
 
@@ -351,9 +354,10 @@
     Get the directory within a JDK where the server and client
     subdirectories are located.
     """
-    if platform.system() == 'Darwin':
+    mxos = mx.get_os()
+    if mxos == 'darwin':
         return join(jdk, 'jre', 'lib')
-    if platform.system() == 'Windows':
+    if mxos == 'windows' or mxos == 'cygwin':
         return join(jdk, 'jre', 'bin')
     return join(jdk, 'jre', 'lib', mx.get_arch())
 
@@ -361,9 +365,10 @@
     """
     Get the directories within a JDK where the jli library designates to.
     """
-    if platform.system() == 'Darwin':
+    mxos = mx.get_os()
+    if mxos == 'darwin':
         return [join(jdk, 'jre', 'lib', 'jli')]
-    if platform.system() == 'Windows':
+    if mxos == 'windows' or mxos == 'cygwin':
         return [join(jdk, 'jre', 'bin'), join(jdk, 'bin')]
     return [join(jdk, 'jre', 'lib', mx.get_arch(), 'jli'), join(jdk, 'lib', mx.get_arch(), 'jli')]
 
@@ -371,7 +376,8 @@
     """
     Get the jvm.cfg file.
     """
-    if platform.system() == 'Windows':
+    mxos = mx.get_os()
+    if mxos == "windows" or mxos == "cygwin":
         return join(jdk, 'jre', 'lib', mx.get_arch(), jvmCfgFile)
     return join(_vmLibDirInJdk(jdk), jvmCfgFile)
 
@@ -426,11 +432,9 @@
                         jvmCfgLines += [line]
 
             assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
-            if mx.get_os() != 'windows':
-                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
+            chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
             shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
 
-
             with open(jvmCfg, 'w') as fp:
                 for line in jvmCfgLines:
                     fp.write(line)
@@ -525,7 +529,7 @@
         graalRuntime_inline_hpp = join(genSrcDir, 'graalRuntime.inline.hpp')
         cp = os.pathsep.join([mx.distribution(d).path for d in dist.distDependencies] + [dist.path, p.output_dir()])
         tmp = StringIO.StringIO()
-        mx.run_java(['-cp', cp, mainClass], out=tmp.write)
+        mx.run_java(['-cp', mx._tspU2W(cp), mainClass], out=tmp.write)
 
         # Compute SHA1 for currently generated graalRuntime.inline.hpp content
         # and all other generated sources in genSrcDir
@@ -548,7 +552,7 @@
         javaClass = join(_graal_home, 'GeneratedSourcesSha1.class')
         with open(javaSource, 'w') as fp:
             print >> fp, 'class GeneratedSourcesSha1 { private static final String value = "' + sha1 + '"; }'
-        subprocess.check_call([mx.java().javac, '-d', _graal_home, javaSource], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+        subprocess.check_call([mx.java().javac, '-d', mx._tpU2W(_graal_home), mx._tpU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
         zf = zipfile.ZipFile(dist.path, 'a')
         with open(javaClass, 'rb') as fp:
             zf.writestr(os.path.basename(javaClass), fp.read())
@@ -607,21 +611,26 @@
 
     winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
 
-    if not exists(winSDK):
+    if not exists(mx._tpW2U(winSDK)):
         mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist")
 
-    if not exists(join(winSDK, 'Bin', 'SetEnv.cmd')):
+    winSDKSetEnv = mx._tpW2U(join(winSDK, 'Bin', 'SetEnv.cmd'))
+    if not exists(winSDKSetEnv):
         mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)")
 
-    p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + startToken + '"', \
-            shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
+    wincmd = 'cmd.exe /E:ON /V:ON /K "' + mx._tpU2W(winSDKSetEnv) + '"'
+    p = subprocess.Popen(wincmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     stdout = p.stdout
     stdin = p.stdin
     if logFile:
         log = open(logFile, 'w')
     ret = False
+
+    def _writeProcess(s):
+        stdin.write(s + newLine)
+
+    _writeProcess("echo " + startToken)
     while True:
-
         # encoding may be None on windows plattforms
         if sys.stdout.encoding is None:
             encoding = 'utf-8'
@@ -634,25 +643,25 @@
         line = line.strip()
         mx.log(line)
         if line == startToken:
-            stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken + newLine)
+            _writeProcess('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken)
         for regex in respondTo.keys():
             match = regex.search(line)
             if match:
-                stdin.write(respondTo[regex] + newLine)
+                _writeProcess(respondTo[regex])
         if findInOutput:
             match = findInOutput.search(line)
             if match:
                 ret = True
         if line == endToken:
             if not findInOutput:
-                stdin.write('echo ERRXXX%errorlevel%' + newLine)
+                _writeProcess('echo ERRXXX%errorlevel%')
             else:
                 break
         if line.startswith('ERRXXX'):
             if line == 'ERRXXX0':
                 ret = True
             break
-    stdin.write('exit' + newLine)
+    _writeProcess("exit")
     if logFile:
         log.close()
     return ret
@@ -806,8 +815,7 @@
 
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
-            if mx.get_os() != 'windows':
-                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
+            chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
             mx.log('Creating VM directory in JDK: ' + vmDir)
             os.makedirs(vmDir)
 
@@ -838,21 +846,22 @@
             mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]')
             continue
 
-        if platform.system() == 'Windows':
-            compilelogfile = _graal_home + '/graalCompile.log'
+        if platform.system() == 'Windows' or "CYGWIN" in platform.system():
+            t_compilelogfile = mx._tpU2W(os.path.join(_graal_home, "graalCompile.log"))
             mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin')
 
             variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm)
             project_config = variant + '_' + build
-            _runInDebugShell('msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', _graal_home)
-            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + _graal_home + r'\make\windows"& call create.bat ' + _graal_home
+            t_graal_home = mx._tpU2W(_graal_home)
+            _runInDebugShell('msbuild ' + t_graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', t_graal_home)
+            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + mx._tpU2W(jdk) + r'& set JAVA_HOME=' + mx._tpU2W(jdk) + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + t_graal_home + r'\make\windows"& call create.bat ' + t_graal_home
             print winCompileCmd
             winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
-            if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess):
+            if not _runInDebugShell(winCompileCmd, t_graal_home, t_compilelogfile, winCompileSuccess):
                 mx.log('Error executing create command')
                 return
-            winBuildCmd = 'msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64'
-            if not _runInDebugShell(winBuildCmd, _graal_home, compilelogfile):
+            winBuildCmd = 'msbuild ' + t_graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64'
+            if not _runInDebugShell(winBuildCmd, t_graal_home, t_compilelogfile):
                 mx.log('Error building project')
                 return
         else:
@@ -1442,7 +1451,8 @@
     _jacoco = 'off'
 
     t = Task('CleanAndBuildIdealGraphVisualizer')
-    mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-q', 'clean', 'build'])
+    buildxml = mx._tpU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'))
+    mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'])
     tasks.append(t.stop())
 
     # Prevent Graal modifications from breaking the standard builds
@@ -2235,13 +2245,13 @@
         findbugsJar = join(findbugsLib, 'findbugs.jar')
     assert exists(findbugsJar)
     nonTestProjects = [p for p in mx.projects() if not p.name.endswith('.test') and not p.name.endswith('.jtt')]
-    outputDirs = [p.output_dir() for p in nonTestProjects]
+    outputDirs = map(mx._tpU2W, [p.output_dir() for p in nonTestProjects])
     findbugsResults = join(_graal_home, 'findbugs.results')
 
-    cmd = ['-jar', findbugsJar, '-textui', '-low', '-maxRank', '15']
+    cmd = ['-jar', mx._tpU2W(findbugsJar), '-textui', '-low', '-maxRank', '15']
     if sys.stdout.isatty():
         cmd.append('-progress')
-    cmd = cmd + ['-auxclasspath', mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects]), '-output', findbugsResults, '-exitcode'] + args + outputDirs
+    cmd = cmd + ['-auxclasspath', mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects]), '-output', mx._tpU2W(findbugsResults), '-exitcode'] + args + outputDirs
     exitcode = mx.run_java(cmd, nonZeroIsFatal=False)
     if exitcode != 0:
         with open(findbugsResults) as fp:
--- a/mxtool/mx.py	Thu Sep 25 20:57:00 2014 -0700
+++ b/mxtool/mx.py	Fri Sep 26 04:53:13 2014 -0700
@@ -639,16 +639,7 @@
             return NotImplemented
 
     def is_present_in_jdk(self, jdk):
-        for e in jdk.bootclasspath().split(os.pathsep):
-            if basename(e) == self.jar:
-                return True
-        for d in jdk.extdirs().split(os.pathsep):
-            if len(d) and self.jar in os.listdir(d):
-                return True
-        for d in jdk.endorseddirs().split(os.pathsep):
-            if len(d) and self.jar in os.listdir(d):
-                return True
-        return False
+        return jdk.containsJar(self.jar)
 
     def all_deps(self, deps, includeLibs, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=False):
         """
@@ -1337,11 +1328,47 @@
         return 'linux'
     elif sys.platform.startswith('sunos'):
         return 'solaris'
-    elif sys.platform.startswith('win32') or sys.platform.startswith('cygwin'):
+    elif sys.platform.startswith('win32'):
         return 'windows'
+    elif sys.platform.startswith('cygwin'):
+        return 'cygwin'
     else:
         abort('Unknown operating system ' + sys.platform)
 
+def _tpU2W(p):
+    """
+    Translate a path from unix-style to windows-style
+    """
+    if p is None or get_os() != "cygwin":
+        return p
+    return subprocess.check_output(['cygpath', '-w', p]).strip()
+
+def _tpW2U(p):
+    """
+    Translate a path from windows-style to unix-style
+    """
+    if p is None or get_os() != "cygwin":
+        return p
+    return subprocess.check_output(['cygpath', '-u', p]).strip()
+
+def _tspU2W(p):
+    """
+    Translate a group of paths, seperated by a path seperator.
+    unix-style to windows-style.
+    """
+    if p is None or p == "" or get_os() != "cygwin":
+        return p
+    return ';'.join(map(_tpU2W, p.split(os.pathsep)))
+
+def _tspW2U(p):
+    """
+    Translate a group of paths, seperated by a path seperator.
+    windows-style to unix-style.
+    """
+    if p is None or p == "" or get_os() != "cygwin":
+        return p
+    return os.pathsep.join(map(_tpW2U, p.split(';')))
+
 def get_arch():
     machine = platform.uname()[4]
     if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
@@ -1530,7 +1557,8 @@
 
     if includeBootClasspath:
         result = os.pathsep.join([java().bootclasspath(), result])
-    return result
+
+    return _tspU2W(result)
 
 def classpath_walk(names=None, resolve=True, includeSelf=True, includeBootClasspath=False):
     """
@@ -1998,7 +2026,7 @@
         return cmp(self.parts, other.parts)
 
 def _filter_non_existant_paths(paths):
-    return os.pathsep.join([path for path in paths.split(os.pathsep) if exists(path)])
+    return os.pathsep.join([path for path in _tspW2U(paths).split(os.pathsep) if exists(path)])
 
 """
 A JavaConfig object encapsulates info on how Java commands are run.
@@ -2063,8 +2091,8 @@
             os.makedirs(outDir)
         javaSource = join(myDir, 'ClasspathDump.java')
         if not exists(join(outDir, 'ClasspathDump.class')):
-            subprocess.check_call([self.javac, '-d', outDir, javaSource], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
-        self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', outDir, 'ClasspathDump'], stderr=subprocess.PIPE).split('|')]
+            subprocess.check_call([self.javac, '-d', _tpU2W(outDir), _tpU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+        self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', _tspU2W(outDir), 'ClasspathDump'], stderr=subprocess.PIPE).split('|')]
         if not self._bootclasspath or not self._extdirs or not self._endorseddirs:
             warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'")
         self._bootclasspath = _filter_non_existant_paths(self._bootclasspath)
@@ -2091,17 +2119,32 @@
     def bootclasspath(self):
         if self._bootclasspath is None:
             self._init_classpaths()
-        return self._bootclasspath
+        return _tspU2W(self._bootclasspath)
 
     def extdirs(self):
         if self._extdirs is None:
             self._init_classpaths()
-        return self._extdirs
+        return _tspU2W(self._extdirs)
 
     def endorseddirs(self):
         if self._endorseddirs is None:
             self._init_classpaths()
-        return self._endorseddirs
+        return _tspU2W(self._endorseddirs)
+
+    def containsJar(self, jar):
+        if self._bootclasspath is None:
+            self._init_classpaths()
+
+        for e in self._bootclasspath.split(os.pathsep):
+            if basename(e) == self.jar:
+                return True
+        for d in self._extdirs.split(os.pathsep):
+            if len(d) and self.jar in os.listdir(d):
+                return True
+        for d in self._endorseddirs.split(os.pathsep):
+            if len(d) and self.jar in os.listdir(d):
+                return True
+        return False
 
 def check_get_env(key):
     """
@@ -2232,11 +2275,11 @@
     javaSource = join(myDir, 'URLConnectionDownload.java')
     javaClass = join(myDir, 'URLConnectionDownload.class')
     if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
-        subprocess.check_call([java().javac, '-d', myDir, javaSource])
+        subprocess.check_call([java().javac, '-d', _tpU2W(myDir), _tpU2W(javaSource)])
     verbose = []
     if sys.stderr.isatty():
         verbose.append("-v")
-    if run([java().java, '-cp', myDir, 'URLConnectionDownload', path] + verbose + urls, nonZeroIsFatal=False) == 0:
+    if run([java().java, '-cp', _tpU2W(myDir), 'URLConnectionDownload', _tpU2W(path)] + verbose + urls, nonZeroIsFatal=False) == 0:
         return
 
     abort('Could not download to ' + path + ' from any of the following URLs:\n\n    ' +
@@ -2291,24 +2334,23 @@
     def execute(self):
         argfileName = join(self.proj.dir, 'javafilelist.txt')
         argfile = open(argfileName, 'wb')
-        argfile.write('\n'.join(self.javafilelist))
+        argfile.write('\n'.join(map(_tpU2W, self.javafilelist)))
         argfile.close()
 
         processorArgs = []
-
         processorPath = self.proj.annotation_processors_path()
         if processorPath:
             genDir = self.proj.source_gen_dir()
             if exists(genDir):
                 shutil.rmtree(genDir)
             os.mkdir(genDir)
-            processorArgs += ['-processorpath', join(processorPath), '-s', genDir]
+            processorArgs += ['-processorpath', _tspU2W(join(processorPath)), '-s', _tpU2W(genDir)]
         else:
             processorArgs += ['-proc:none']
 
         args = self.args
         jdk = self.jdk
-        outputDir = self.outputDir
+        outputDir = _tpU2W(self.outputDir)
         compliance = str(jdk.javaCompliance)
         cp = classpath(self.proj.name, includeSelf=True)
         toBeDeleted = [argfileName]
@@ -2323,7 +2365,7 @@
                     if jdk.debug_port is not None:
                         javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)]
                     javacCmd += processorArgs
-                    javacCmd += ['@' + argfile.name]
+                    javacCmd += ['@' + _tpU2W(argfile.name)]
 
                     if not args.warnAPI:
                         javacCmd.append('-XDignore.symbol.file')