comparison mxtool/mx.py @ 4145:9aee7df31417

Removed 'tests' command. Folded 'make' command into 'build' command. Renamed 'eclipseprojects' command to 'ideinit'
author Doug Simon <doug.simon@oracle.com>
date Mon, 19 Dec 2011 20:56:59 +0100
parents 34527a24bcf8
children 55376d8953a6
comparison
equal deleted inserted replaced
4144:34527a24bcf8 4145:9aee7df31417
29 # and hg (http://mercurial.selenic.com/). It includes a mechanism for 29 # and hg (http://mercurial.selenic.com/). It includes a mechanism for
30 # managing the dependencies between a set of projects (like Maven) 30 # managing the dependencies between a set of projects (like Maven)
31 # as well as making it simple to run commands 31 # as well as making it simple to run commands
32 # (like hg is the interface to the Mercurial commands). 32 # (like hg is the interface to the Mercurial commands).
33 # 33 #
34 # When launched, mx looks for a mx configuration (i.e. a directory named 'mx') 34 # The organizing principle of mx is a project suite. A suite is a directory
35 # in the current working directory. This is the primary mx configuration. Any 35 # containing one or more projects. It's not coincidental that this closely
36 # other mx configurations are included mx configurations. 36 # matches the layout of one or more projects in a Mercurial repository.
37 # 37 # The configuration information for a suite lives in an 'mx' sub-directory
38 # If an mx configuration exists, then the following files in the configuration 38 # at the top level of the suite.
39 # are processed (if they exist): 39 #
40 # 40 # When launched, mx treats the current working directory as a suite.
41 # projects - Lists projects, libraries and dependencies between them 41 # This is the primary suite. All other suites are called included suites.
42 # commands.py - Extensions to the commands launchable by mx. This is only processed 42 #
43 # for the primary mx configuration. 43 # The configuration files (i.e. in the 'mx' sub-directory) of a suite are:
44 # includes - Other directories containing mx configurations to be loaded. 44 #
45 # This is a recursive action. 45 # projects - Defines the projects and libraries in the suite and the dependencies between them
46 # commands.py - Suite specific extensions to the commands available to mx. This is only processed
47 # for the primary suite.
48 # includes - Other suites to be loaded. This is a recursive.
46 # env - A set of environment variable definitions. 49 # env - A set of environment variable definitions.
47 # 50 #
48 # The MX_INCLUDES environment variable can also be used to specify 51 # The MX_INCLUDES environment variable can also be used to specify other suites.
49 # other directories containing mx configurations.
50 # This value of this variable has the same format as a Java class path. 52 # This value of this variable has the same format as a Java class path.
51 # 53 #
52 # The includes and env files are typically not put under version control 54 # The includes and env files are typically not put under version control
53 # as they usually contain local filesystem paths. 55 # as they usually contain local file-system paths.
54 # 56 #
55 # The projects file is like the pom.xml file from Maven except that 57 # The projects file is like the pom.xml file from Maven except that
56 # it is in a properties file format instead of XML. Each non-comment line 58 # it is a properties file (not XML). Each non-comment line
57 # in the file specifies an attribute of a project or library. The main 59 # in the file specifies an attribute of a project or library. The main
58 # difference between a project and a library is that the former contains 60 # difference between a project and a library is that the former contains
59 # source code built by the mx tool where as the latter is an external 61 # source code built by the mx tool where as the latter is an external
60 # dependency. The format of the projects file is 62 # dependency. The format of the projects file is
61 # 63 #
103 DEFAULT_JAVA_ARGS = '-ea -Xss2m -Xmx1g' 105 DEFAULT_JAVA_ARGS = '-ea -Xss2m -Xmx1g'
104 106
105 _projects = dict() 107 _projects = dict()
106 _libs = dict() 108 _libs = dict()
107 _suites = dict() 109 _suites = dict()
108
109 """ Options parsed from the command line. """
110 _opts = None 110 _opts = None
111
112 """ Prefix for a Java command. """
113 _java = None 111 _java = None
114 112
115 """ 113 """
116 A dependency is a library or project specified in a suite. 114 A dependency is a library or project specified in a suite.
117 """ 115 """
143 self.checkstyleProj = name 141 self.checkstyleProj = name
144 self.native = False 142 self.native = False
145 self.dir = dir 143 self.dir = dir
146 144
147 def all_deps(self, deps, includeLibs): 145 def all_deps(self, deps, includeLibs):
146 """
147 Add the transitive set of dependencies for this project, including
148 libraries if 'includeLibs' is true, to the 'deps' list.
149 """
148 if self in deps: 150 if self in deps:
149 return deps 151 return deps
150 for name in self.deps: 152 for name in self.deps:
151 assert name != self.name 153 assert name != self.name
152 dep = _libs.get(name, None) 154 dep = _libs.get(name, None)
189 return result; 191 return result;
190 192
191 193
192 def source_dirs(self): 194 def source_dirs(self):
193 """ 195 """
194 Get the directories in whihc the sources of this project are found. 196 Get the directories in which the sources of this project are found.
195 """ 197 """
196 return [join(self.dir, s) for s in self.srcDirs] 198 return [join(self.dir, s) for s in self.srcDirs]
197 199
198 def output_dir(self): 200 def output_dir(self):
199 """ 201 """
200 Get the directory in which the class files of this project are found. 202 Get the directory in which the class files of this project are found/placed.
201 """ 203 """
202 if self.native: 204 if self.native:
203 return None 205 return None
204 return join(self.dir, 'bin') 206 return join(self.dir, 'bin')
205 207
338 self._load_env(mxDir) 340 self._load_env(mxDir)
339 if primary: 341 if primary:
340 self._load_commands(mxDir) 342 self._load_commands(mxDir)
341 343
342 def get_os(): 344 def get_os():
345 """
346 Get a canonical form of sys.platform.
347 """
343 if sys.platform.startswith('darwin'): 348 if sys.platform.startswith('darwin'):
344 return 'darwin' 349 return 'darwin'
345 elif sys.platform.startswith('linux'): 350 elif sys.platform.startswith('linux'):
346 return 'linux' 351 return 'linux'
347 elif sys.platform.startswith('sunos'): 352 elif sys.platform.startswith('sunos'):
496 if doc is None: 501 if doc is None:
497 doc = '' 502 doc = ''
498 msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0]) 503 msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0])
499 return msg + '\n' 504 return msg + '\n'
500 505
501 def java_home(): 506 def java():
502 return _opts.java_home 507 """
503 508 Get a JavaConfig object containing Java commands launch details.
504 def java_exe(): 509 """
505 return exe_suffix(_opts.java) 510 assert _java is not None
506 511 return _java
507 def java_args(): 512
508 init_java()
509 return _opts.java_args
510
511 def format_java_cmd(args):
512 init_java()
513 return _java + args
514
515 def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None): 513 def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None):
516 return run(format_java_cmd(args), nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd) 514 return run(_java.format_cmd(args), nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd)
517 515
518 def run(args, nonZeroIsFatal=True, out=None, err=None, cwd=None): 516 def run(args, nonZeroIsFatal=True, out=None, err=None, cwd=None):
519 """ 517 """
520 Run a command in a subprocess, wait for it to complete and return the exit status of the process. 518 Run a command in a subprocess, wait for it to complete and return the exit status of the process.
521 If the exit status is non-zero and `nonZeroIsFatal` is true, then the program is exited with 519 If the exit status is non-zero and `nonZeroIsFatal` is true, then the program is exited with
569 """ 567 """
570 if os == 'windows': 568 if os == 'windows':
571 return name + '.exe' 569 return name + '.exe'
572 return name 570 return name
573 571
574 def init_java(): 572 """
575 """ 573 A JavaConfig object encapsulates info on how Java commands are run.
576 Lazy initialization and preprocessing of this object's fields before running a Java command. 574 """
577 """ 575 class JavaConfig:
578 global _java 576 def __init__(self, opts):
579 if _java is not None: 577 self.jdk = opts.java_home
580 return 578 self.debug = opts.java_dbg
581 579 self.java = exe_suffix(join(self.jdk, 'bin', 'java'))
582 def delAtAndSplit(s): 580 self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
583 return shlex.split(s.lstrip('@')) 581 self.javap = exe_suffix(join(self.jdk, 'bin', 'javap'))
584 582
585 _opts.java_args = delAtAndSplit(_opts.java_args) 583 def delAtAndSplit(s):
586 _opts.java_args_pfx = sum(map(delAtAndSplit, _opts.java_args_pfx), []) 584 return shlex.split(s.lstrip('@'))
587 _opts.java_args_sfx = sum(map(delAtAndSplit, _opts.java_args_sfx), []) 585
588 586 self.java_args = delAtAndSplit(_opts.java_args)
589 # Prepend the -d64 VM option only if the java command supports it 587 self.java_args_pfx = sum(map(delAtAndSplit, _opts.java_args_pfx), [])
590 output = '' 588 self.java_args_sfx = sum(map(delAtAndSplit, _opts.java_args_sfx), [])
591 java = _opts.java 589
592 try: 590 # Prepend the -d64 VM option only if the java command supports it
593
594 output = subprocess.check_output([java, '-d64', '-version'], stderr=subprocess.STDOUT)
595 _opts.java_args = ['-d64'] + _opts.java_args
596 except subprocess.CalledProcessError as e:
597 try: 591 try:
598 output = subprocess.check_output([java, '-version'], stderr=subprocess.STDOUT) 592 subprocess.check_output([self.java, '-d64', '-version'], stderr=subprocess.STDOUT)
593 self.java_args = ['-d64'] + self.java_args
599 except subprocess.CalledProcessError as e: 594 except subprocess.CalledProcessError as e:
600 print e.output 595 try:
601 abort(e.returncode) 596 subprocess.check_output([self.java, '-version'], stderr=subprocess.STDOUT)
602 597 except subprocess.CalledProcessError as e:
603 output = output.split() 598 print e.output
604 assert output[0] == 'java' or output[0] == 'openjdk' 599 abort(e.returncode)
605 assert output[1] == 'version' 600
606 version = output[2] 601 if self.debug:
607 if not version.startswith('"1.6') and not version.startswith('"1.7'): 602 self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000']
608 abort('Requires Java version 1.6 or 1.7, got version ' + version) 603
609 604 def format_cmd(self, args):
610 if _opts.java_dbg: 605 return [self.java] + self.java_args_pfx + self.java_args + self.java_args_sfx + args
611 _opts.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000']
612
613 _java = [java] + _opts.java_args_pfx + _opts.java_args + _opts.java_args_sfx
614 606
615 def _default_java_home(): 607 def _default_java_home():
616 javaHome = os.getenv('JAVA_HOME') 608 javaHome = os.getenv('JAVA_HOME')
617 if javaHome is None: 609 if javaHome is None:
618 if exists('/usr/lib/java/java-6-sun'): 610 if exists('/usr/lib/java/java-6-sun'):
1133 cwdMxDir = join(os.getcwd(), 'mx') 1125 cwdMxDir = join(os.getcwd(), 'mx')
1134 if exists(cwdMxDir) and isdir(cwdMxDir): 1126 if exists(cwdMxDir) and isdir(cwdMxDir):
1135 _loadSuite(os.getcwd(), True) 1127 _loadSuite(os.getcwd(), True)
1136 1128
1137 opts, commandAndArgs = _argParser._parse_cmd_line() 1129 opts, commandAndArgs = _argParser._parse_cmd_line()
1138 global _opts 1130 global _opts, _java
1139 _opts = opts 1131 _opts = opts
1132 _java = JavaConfig(opts)
1140 1133
1141 if len(commandAndArgs) == 0: 1134 if len(commandAndArgs) == 0:
1142 _argParser.print_help() 1135 _argParser.print_help()
1143 return 1136 return
1144 1137