# HG changeset patch # User Doug Simon # Date 1340794910 -7200 # Node ID 6517d36e6905ec9c715581d1dc41dcb7431f4df9 # Parent d0a6e25de770c179240dd5d7fa6513900cf6e242# Parent 764db9ada24f52cb60fd5efb02f59f504f2f70fd Merge. diff -r 764db9ada24f -r 6517d36e6905 graal/overview.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/overview.html Wed Jun 27 13:01:50 2012 +0200 @@ -0,0 +1,42 @@ + + + + + + + + + + + +

+This document is the unified Javadoc for the Graal code base. +The module dependency graph is shown above. +Each node in the diagram is a link to the standalone Javadoc for the denoted module. + + + diff -r 764db9ada24f -r 6517d36e6905 mx/commands.py --- a/mx/commands.py Wed Jun 27 11:51:18 2012 +0200 +++ b/mx/commands.py Wed Jun 27 13:01:50 2012 +0200 @@ -1001,6 +1001,68 @@ mx.abort('jacocoreport takes only one argument : an output directory') mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) +def site(args): + """creates a website containing javadoc and the project dependency graph""" + + parser = ArgumentParser(prog='site') + parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='

') + parser.add_argument('-c', '--clean', action='store_true', help='remove existing site in ') + + args = parser.parse_args(args) + + args.base = os.path.abspath(args.base) + + if not exists(args.base): + os.mkdir(args.base) + elif args.clean: + shutil.rmtree(args.base) + os.mkdir(args.base) + + mx.javadoc(['--base', args.base]) + + unified = join(args.base, 'all') + if exists(unified): + shutil.rmtree(unified) + mx.javadoc(['--base', args.base, '--unified', '--arg', '@-overview', '--arg', '@' + join(_graal_home, 'graal', 'overview.html')]) + os.rename(join(args.base, 'javadoc'), unified) + + _, tmp = tempfile.mkstemp() + try: + svg = join(args.base, 'all', 'modules.svg') + with open(tmp, 'w') as fp: + print >> fp, 'digraph projects {' + print >> fp, 'rankdir=BT;' + print >> fp, 'size = "13,13";' + print >> fp, 'node [shape=rect, fontcolor="blue"];' + print >> fp, 'edge [color="green"];' + for p in mx.projects(): + print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]' + for dep in p.canonical_deps(): + if mx.project(dep, False): + print >> fp, '"' + p.name + '" -> "' + dep + '"' + depths = dict() + for p in mx.projects(): + d = p.max_depth() + depths.setdefault(d, list()).append(p.name) + for d, names in depths.iteritems(): + print >> fp, '{ rank = same; "' + '"; "'.join(names) + '"; }' + print >> fp, '}' + + mx.run(['dot', '-Tsvg', '-o' + svg, tmp]) + + # Post-process generated SVG to remove unified title elements which most browsers + # render as redundant (and annoying) tooltips. + with open(svg, 'r') as fp: + content = fp.read() + content = re.sub('.*', '', content) + content = re.sub('xlink:title="[^"]*"', '', content) + with open(svg, 'w') as fp: + fp.write(content) + + print 'Created website - root is ' + join(unified, 'index.html') + finally: + os.remove(tmp) + def mx_init(): _vmbuild = 'product' commands = { @@ -1022,6 +1084,7 @@ 'unittest' : [unittest, '[filters...]'], 'jtt' : [jtt, '[filters...]'], 'jacocoreport' : [jacocoreport, '[output directory]'], + 'site' : [site, '[-options]'], 'vm': [vm, '[-options] class [args...]'], 'vmg': [vmg, '[-options] class [args...]'], 'vmfg': [vmfg, '[-options] class [args...]'] diff -r 764db9ada24f -r 6517d36e6905 mxtool/mx.py --- a/mxtool/mx.py Wed Jun 27 11:51:18 2012 +0200 +++ b/mxtool/mx.py Wed Jun 27 13:01:50 2012 +0200 @@ -50,10 +50,10 @@ commands.py Suite specific extensions to the commands available to mx. - This is only processed for the primary suite. includes - Other suites to be loaded. This is recursive. + Other suites to be loaded. This is recursive. Each + line in an includes file is a path to a suite directory. env A set of environment variable definitions. These override any @@ -223,11 +223,17 @@ if d == 1: result.add(n) - if len(result) == len(self.deps) and frozenset(self.deps) == result: return self.deps return result; + def max_depth(self): + """ + Get the maximum canonical distance between this project and its most distant dependency. + """ + distances = dict() + self._compute_max_dep_distances(self.name, distances, 0) + return max(distances.values()) def source_dirs(self): """ @@ -288,8 +294,8 @@ self.primary = primary mxDir = join(dir, 'mx') self._load_env(mxDir) - if primary: - self._load_commands(mxDir) + self._load_commands(mxDir) + self._load_includes(mxDir) def _load_projects(self, mxDir): libsMap = dict() @@ -360,8 +366,9 @@ if exists(commands): # temporarily extend the Python path sys.path.insert(0, mxDir) - mod = __import__('commands') + + sys.modules[join(mxDir, 'commands')] = sys.modules.pop('commands') # revert the Python path del sys.path[0] @@ -379,7 +386,9 @@ if exists(includes): with open(includes) as f: for line in f: - self.includes.append(expandvars_in_property(line.strip())) + include = expandvars_in_property(line.strip()) + self.includes.append(include) + _loadSuite(include, False) def _load_env(self, mxDir): e = join(mxDir, 'env') @@ -393,9 +402,8 @@ def _post_init(self, opts): mxDir = join(self.dir, 'mx') - self._load_includes(mxDir) self._load_projects(mxDir) - if self.mx_post_parse_cmd_line is not None: + if hasattr(self, 'mx_post_parse_cmd_line'): self.mx_post_parse_cmd_line(opts) for p in self.projects: existing = _projects.get(p.name) @@ -1499,7 +1507,6 @@ print '"' + p.name + '"->"' + dep + '"' print '}' - def _source_locator_memento(deps): slm = XMLDoc() slm.open('sourceLookupDirector') @@ -1950,16 +1957,17 @@ eclipseinit(args, suite) netbeansinit(args, suite) -def javadoc(args): +def javadoc(args, parser=None, docDir='javadoc', includeDeps=True): """generate javadoc for some/all Java projects""" - parser = ArgumentParser(prog='mx javadoc') + parser = ArgumentParser(prog='mx javadoc') if parser is None else parser + parser.add_argument('-d', '--base', action='store', help='base directory for output') parser.add_argument('--unified', action='store_true', help='put javadoc in a single directory instead of one per project') parser.add_argument('--force', action='store_true', help='(re)generate javadoc even if package-list file exists') parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') parser.add_argument('--argfile', action='store', help='name of file containing extra javadoc options') + parser.add_argument('--arg', action='append', dest='extra_args', help='extra Javadoc arguments (e.g. --arg @-use)', metavar='@', default=[]) parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM') - parser.add_argument('--wiki', action='store_true', help='generate Confluence Wiki format for package-info.java files') parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)') args = parser.parse_args(args) @@ -1969,32 +1977,18 @@ if args.projects is not None: candidates = [project(name) for name in args.projects.split(',')] - # optionally restrict packages within a project (most useful for wiki) + # optionally restrict packages within a project packages = [] if args.packages is not None: packages = [name for name in args.packages.split(',')] - # the WikiDoclet cannot see the -classpath argument passed to javadoc so we pass the - # full list of projects as an explicit argument, thereby enabling it to map classes - # to projects, which is needed to generate Wiki links to the source code. - # There is no virtue in running the doclet on dependent projects as there are - # no generated links between Wiki pages - docletArgs = [] - if args.wiki: - docDir = 'wikidoc' - toolsDir = project('com.oracle.max.tools').output_dir() - baseDir = project('com.oracle.max.base').output_dir() - dp = os.pathsep.join([toolsDir, baseDir]) - project_list = ','.join(p.name for p in sorted_deps()) - docletArgs = ['-docletpath', dp, '-doclet', 'com.oracle.max.tools.javadoc.wiki.WikiDoclet', '-projects', project_list] - else: - docDir = 'javadoc' + def outDir(p): + if args.base is None: + return join(p.dir, docDir) + return join(args.base, p.name, docDir) def check_package_list(p): - if args.wiki: - return True - else: - return not exists(join(p.dir, docDir, 'package-list')) + return not exists(join(outDir(p), 'package-list')) def assess_candidate(p, projects): if p in projects: @@ -2007,7 +2001,7 @@ projects = [] for p in candidates: if not p.native: - if not args.wiki: + if includeDeps: deps = p.all_deps([], includeLibs=False, includeSelf=False) for d in deps: assess_candidate(d, projects) @@ -2024,7 +2018,7 @@ pkgs.add(pkg) return pkgs - extraArgs = [] + extraArgs = [a.lstrip('@') for a in args.extra_args] if args.argfile is not None: extraArgs += ['@' + args.argfile] memory = '2g' @@ -2037,15 +2031,15 @@ pkgs = find_packages(p.source_dirs(), set()) deps = p.all_deps([], includeLibs=False, includeSelf=False) links = ['-link', 'http://docs.oracle.com/javase/' + str(p.javaCompliance.value) + '/docs/api/'] - out = join(p.dir, docDir) + out = outDir(p) for d in deps: - depOut = join(d.dir, docDir) + depOut = outDir(d) links.append('-link') links.append(os.path.relpath(depOut, out)) cp = classpath(p.name, includeSelf=True) sp = os.pathsep.join(p.source_dirs()) log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) - run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + docletArgs + links + extraArgs + list(pkgs)) + run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + links + extraArgs + list(pkgs)) log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) else: pkgs = set() @@ -2058,10 +2052,12 @@ links = ['-link', 'http://docs.oracle.com/javase/' + str(_java.javaCompliance.value) + '/docs/api/'] out = join(_mainSuite.dir, docDir) + if args.base is not None: + out = join(args.base, docDir) cp = classpath() sp = os.pathsep.join(sp) log('Generating {2} for {0} in {1}'.format(', '.join(names), out, docDir)) - run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + docletArgs + links + extraArgs + list(pkgs)) + run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + links + extraArgs + list(pkgs)) log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir)) def findclass(args): @@ -2132,11 +2128,27 @@ _argParser = ArgParser() +def _findPrimarySuite(): + # try current working directory first + mxDir = join(os.getcwd(), 'mx') + if exists(mxDir) and isdir(mxDir): + return dirname(mxDir) + + # now search path of my executable + me = sys.argv[0] + parent = dirname(me) + while parent: + mxDir = join(parent, 'mx') + if exists(mxDir) and isdir(mxDir): + return parent + parent = dirname(parent) + return None + def main(): - cwdMxDir = join(os.getcwd(), 'mx') - if exists(cwdMxDir) and isdir(cwdMxDir): + primarySuiteDir = _findPrimarySuite() + if primarySuiteDir: global _mainSuite - _mainSuite = _loadSuite(os.getcwd(), True) + _mainSuite = _loadSuite(primarySuiteDir, True) opts, commandAndArgs = _argParser._parse_cmd_line()