comparison mxtool/mx.py @ 11756:78e6109ee411

mx refactoring for split-repo suites; should have no effect on existing repos
author Mick Jordan <mick.jordan@oracle.com>
date Mon, 23 Sep 2013 21:30:35 -0700
parents e29743466d00
children 8bcd76c3f23b
comparison
equal deleted inserted replaced
11755:bbcb72443066 11756:78e6109ee411
37 containing one or more projects. It's not coincidental that this closely 37 containing one or more projects. It's not coincidental that this closely
38 matches the layout of one or more projects in a Mercurial repository. 38 matches the layout of one or more projects in a Mercurial repository.
39 The configuration information for a suite lives in an 'mx' sub-directory 39 The configuration information for a suite lives in an 'mx' sub-directory
40 at the top level of the suite. A suite is given a name by a 'suite=name' 40 at the top level of the suite. A suite is given a name by a 'suite=name'
41 property in the 'mx/projects' file (if omitted the name is suite directory). 41 property in the 'mx/projects' file (if omitted the name is suite directory).
42 An 'mx' subdirectory can be named as plain 'mx' or 'mxbasename', where 42 An 'mx' subdirectory can be named as plain 'mx' or 'mx.name', where
43 'basename' is the os.path.basename of the suite directory. 43 'name' is typically the name as the suite name.
44 The latter is useful to avoid clashes in IDE project names. 44 The latter is useful to avoid clashes in IDE project names.
45 45
46 When launched, mx treats the current working directory as a suite. 46 When launched, mx treats the current working directory as a suite.
47 This is the primary suite. All other suites are called included suites. 47 This is the primary suite. All other suites are called included suites.
48 48
156 _suites = dict() 156 _suites = dict()
157 _annotationProcessors = None 157 _annotationProcessors = None
158 _mainSuite = None 158 _mainSuite = None
159 _opts = None 159 _opts = None
160 _java = None 160 _java = None
161 _check_global_structures = True # can be set False to allow suites with duplicate definitions to load without aborting
162
161 163
162 """ 164 """
163 A distribution is a jar or zip file containing the output from one or more Java projects. 165 A distribution is a jar or zip file containing the output from one or more Java projects.
164 """ 166 """
165 class Distribution: 167 class Distribution:
514 projsMap = dict() 516 projsMap = dict()
515 distsMap = dict() 517 distsMap = dict()
516 projectsFile = join(mxDir, 'projects') 518 projectsFile = join(mxDir, 'projects')
517 if not exists(projectsFile): 519 if not exists(projectsFile):
518 return 520 return
521
522 def _find_suite_key():
523 for items in _suites.items():
524 if items[1].dir == self.dir:
525 return items[0]
526 raise KeyError
527
519 with open(projectsFile) as f: 528 with open(projectsFile) as f:
520 for line in f: 529 for line in f:
521 line = line.strip() 530 line = line.strip()
522 if len(line) != 0 and line[0] != '#': 531 if len(line) != 0 and line[0] != '#':
523 key, value = line.split('=', 1) 532 key, value = line.split('=', 1)
525 parts = key.split('@') 534 parts = key.split('@')
526 535
527 if len(parts) == 1: 536 if len(parts) == 1:
528 if parts[0] != 'suite': 537 if parts[0] != 'suite':
529 abort('Single part property must be "suite": ' + key) 538 abort('Single part property must be "suite": ' + key)
530 self.name = value 539 if self.name != value:
540 currentKey = _find_suite_key()
541 _suites.pop(currentKey)
542 self.name = value
543 _suites[value] = self
531 continue 544 continue
532 if len(parts) != 3: 545 if len(parts) != 3:
533 abort('Property name does not have 3 parts separated by "@": ' + key) 546 abort('Property name does not have 3 parts separated by "@": ' + key)
534 kind, name, attr = parts 547 kind, name, attr = parts
535 if kind == 'project': 548 if kind == 'project':
637 if len(line) != 0 and line[0] != '#': 650 if len(line) != 0 and line[0] != '#':
638 if not '=' in line: 651 if not '=' in line:
639 abort(e + ':' + str(lineNum) + ': line does not match pattern "key=value"') 652 abort(e + ':' + str(lineNum) + ': line does not match pattern "key=value"')
640 key, value = line.split('=', 1) 653 key, value = line.split('=', 1)
641 os.environ[key.strip()] = expandvars_in_property(value.strip()) 654 os.environ[key.strip()] = expandvars_in_property(value.strip())
655
642 def _post_init(self, opts): 656 def _post_init(self, opts):
643 self._load_projects(self.mxDir) 657 self._load_projects(self.mxDir)
658 # set the global data structures, checking for conflicts unless _global_structures is False
644 for p in self.projects: 659 for p in self.projects:
645 existing = _projects.get(p.name) 660 existing = _projects.get(p.name)
646 if existing is not None: 661 if existing is not None and _check_global_structures:
647 abort('cannot override project ' + p.name + ' in ' + p.dir + " with project of the same name in " + existing.dir) 662 abort('cannot override project ' + p.name + ' in ' + p.dir + " with project of the same name in " + existing.dir)
648 if not p.name in _opts.ignored_projects: 663 if not p.name in _opts.ignored_projects:
649 _projects[p.name] = p 664 _projects[p.name] = p
650 for l in self.libs: 665 for l in self.libs:
651 existing = _libs.get(l.name) 666 existing = _libs.get(l.name)
652 # Check that suites that define same library are consistent 667 # Check that suites that define same library are consistent
653 if existing is not None and existing != l: 668 if existing is not None and existing != l and _check_global_structures:
654 abort('inconsistent library redefinition of ' + l.name + ' in ' + existing.suite.dir + ' and ' + l.suite.dir) 669 abort('inconsistent library redefinition of ' + l.name + ' in ' + existing.suite.dir + ' and ' + l.suite.dir)
655 _libs[l.name] = l 670 _libs[l.name] = l
656 for d in self.dists: 671 for d in self.dists:
657 existing = _dists.get(d.name) 672 existing = _dists.get(d.name)
658 if existing is not None: 673 if existing is not None and _check_global_structures:
659 abort('cannot redefine distribution ' + d.name) 674 # allow redefinition, so use path from existing
675 # abort('cannot redefine distribution ' + d.name)
676 print('WARNING: distribution ' + d.name + ' redefined')
677 d.path = existing.path
660 _dists[d.name] = d 678 _dists[d.name] = d
661 if hasattr(self, 'mx_post_parse_cmd_line'): 679 if hasattr(self, 'mx_post_parse_cmd_line'):
662 self.mx_post_parse_cmd_line(opts) 680 self.mx_post_parse_cmd_line(opts)
663 681
664 class XMLElement(xml.dom.minidom.Element): 682 class XMLElement(xml.dom.minidom.Element):
749 return 'solaris' 767 return 'solaris'
750 elif sys.platform.startswith('win32') or sys.platform.startswith('cygwin'): 768 elif sys.platform.startswith('win32') or sys.platform.startswith('cygwin'):
751 return 'windows' 769 return 'windows'
752 else: 770 else:
753 abort('Unknown operating system ' + sys.platform) 771 abort('Unknown operating system ' + sys.platform)
754 772
755 def _loadSuite(d, primary=False): 773 def _loadSuite(d, primary=False):
756 """ 774 """
757 Load a suite from the 'mx' or 'mxbbb' subdirectory of d, where 'bbb' is basename of d 775 Load a suite from the 'mx' or 'mx.bbb' subdirectory of d, where 'bbb' is basename of d
758 """ 776 """
759 mxDefaultDir = join(d, 'mx') 777 mxDefaultDir = join(d, 'mx')
760 name = os.path.basename(d) 778 name = os.path.basename(d)
761 mxTaggedDir = mxDefaultDir + name 779 mxTaggedDir = mxDefaultDir + '.' + name
762 mxDir = None 780 mxDir = None
763 if exists(mxTaggedDir) and isdir(mxTaggedDir): 781 if exists(mxTaggedDir) and isdir(mxTaggedDir):
764 mxDir = mxTaggedDir 782 mxDir = mxTaggedDir
765 else: 783 else:
766 if exists(mxDefaultDir) and isdir(mxDefaultDir): 784 if exists(mxDefaultDir) and isdir(mxDefaultDir):
769 787
770 if mxDir is None: 788 if mxDir is None:
771 return None 789 return None
772 if len([s for s in _suites.itervalues() if s.dir == d]) == 0: 790 if len([s for s in _suites.itervalues() if s.dir == d]) == 0:
773 s = Suite(d, mxDir, primary) 791 s = Suite(d, mxDir, primary)
792 # N.B. this will be updated once the projects file has been read
774 _suites[name] = s 793 _suites[name] = s
775 return s 794 return s
776 795
777 def suites(): 796 def suites(opt_limit_to_suite=False):
778 """ 797 """
779 Get the list of all loaded suites. 798 Get the list of all loaded suites.
780 """ 799 """
781 return _suites.values() 800 if opt_limit_to_suite and _opts.specific_suites:
801 result = []
802 for s in _suites:
803 if s.name in _opts.specific_suites:
804 result.append(s)
805 return result
806 else:
807 return _suites.values()
782 808
783 def suite(name, fatalIfMissing=True): 809 def suite(name, fatalIfMissing=True):
784 """ 810 """
785 Get the suite for a given name. 811 Get the suite for a given name.
786 """ 812 """
787 s = _suites.get(name) 813 s = _suites.get(name)
788 if s is None and fatalIfMissing: 814 if s is None and fatalIfMissing:
789 abort('suite named ' + name + ' not found') 815 abort('suite named ' + name + ' not found')
790 return s 816 return s
791 817
792 def projects(): 818 def projects_from_names(projectNames):
793 """ 819 """
794 Get the list of all loaded projects. 820 Get the list of projects corresponding to projectNames; all projects if None
795 """ 821 """
796 return _projects.values() 822 if projectNames is None:
823 return projects()
824 else:
825 return [project(name) for name in projectNames]
826
827 def projects(opt_limit_to_suite=False):
828 """
829 Get the list of all loaded projects limited by --suite option if opt_limit_to_suite == True
830 """
831
832 if opt_limit_to_suite:
833 return _projects_opt_limit_to_suites(_projects.values())
834 else:
835 return _projects.values()
836
837 def projects_opt_limit_to_suites():
838 """
839 Get the list of all loaded projects optionally limited by --suite option
840 """
841 return projects(True)
842
843 def _projects_opt_limit_to_suites(projects):
844 if not _opts.specific_suites:
845 return projects
846 else:
847 result = []
848 for p in projects:
849 s = p.suite
850 if s.name in _opts.specific_suites:
851 result.append(p)
852 return result
797 853
798 def annotation_processors(): 854 def annotation_processors():
799 """ 855 """
800 Get the list of all loaded projects that define an annotation processor. 856 Get the list of all loaded projects that define an annotation processor.
801 """ 857 """
912 """ 968 """
913 Gets projects and libraries sorted such that dependencies 969 Gets projects and libraries sorted such that dependencies
914 are before the projects that depend on them. Unless 'includeLibs' is 970 are before the projects that depend on them. Unless 'includeLibs' is
915 true, libraries are omitted from the result. 971 true, libraries are omitted from the result.
916 """ 972 """
973 projects = projects_from_names(projectNames)
974
975 return sorted_project_deps(projects, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
976
977 def sorted_project_deps(projects, includeLibs=False, includeAnnotationProcessors=False):
917 deps = [] 978 deps = []
918 if projectNames is None:
919 projects = opt_limit_to_suite(_projects.values())
920 else:
921 projects = [project(name) for name in projectNames]
922
923 for p in projects: 979 for p in projects:
924 p.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors) 980 p.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
925 return deps 981 return deps
926
927 def opt_limit_to_suite(projects):
928 if _opts.specific_suite is None:
929 return projects
930 else:
931 result = []
932 for p in projects:
933 s = p.suite
934 if s.name == _opts.specific_suite:
935 result.append(p)
936 return result
937 982
938 def _handle_missing_java_home(): 983 def _handle_missing_java_home():
939 if not sys.stdout.isatty(): 984 if not sys.stdout.isatty():
940 abort('Could not find bootstrap JDK. Use --java-home option or ensure JAVA_HOME environment variable is set.') 985 abort('Could not find bootstrap JDK. Use --java-home option or ensure JAVA_HOME environment variable is set.')
941 986
997 self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[]) 1042 self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
998 self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[]) 1043 self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
999 self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~')) 1044 self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
1000 self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='<path>') 1045 self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='<path>')
1001 self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[]) 1046 self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
1002 self.add_argument('--suite', dest='specific_suite', help='limit command to given suite', default=None) 1047 self.add_argument('--suite', action='append', dest='specific_suites', help='limit command to given suite', default=[])
1003 if get_os() != 'windows': 1048 if get_os() != 'windows':
1004 # Time outs are (currently) implemented with Unix specific functionality 1049 # Time outs are (currently) implemented with Unix specific functionality
1005 self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>') 1050 self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
1006 self.add_argument('--ptimeout', help='timeout (in seconds) for subprocesses', type=int, default=0, metavar='<secs>') 1051 self.add_argument('--ptimeout', help='timeout (in seconds) for subprocesses', type=int, default=0, metavar='<secs>')
1007 1052
1551 # Silently ignore JDT if default location is used but not ecj.jar exists there 1596 # Silently ignore JDT if default location is used but not ecj.jar exists there
1552 jdtJar = None 1597 jdtJar = None
1553 1598
1554 built = set() 1599 built = set()
1555 1600
1556 projects = None
1557 if args.projects is not None:
1558 projects = args.projects.split(',')
1559
1560 if args.only is not None: 1601 if args.only is not None:
1602 # N.B. This build will not include dependencies including annotation processor dependencies
1561 sortedProjects = [project(name) for name in args.only.split(',')] 1603 sortedProjects = [project(name) for name in args.only.split(',')]
1562 else: 1604 else:
1563 sortedProjects = sorted_deps(projects, includeAnnotationProcessors=True) 1605 if args.projects is not None:
1606 projectNames = args.projects.split(',')
1607 else:
1608 projectNames = None
1609
1610 projects = _projects_opt_limit_to_suites(projects_from_names(projectNames))
1611 # N.B. Limiting to a suite only affects the starting set of projects. Dependencies in other suites will still be compiled
1612 sortedProjects = sorted_project_deps(projects, includeAnnotationProcessors=True)
1564 1613
1565 if args.java: 1614 if args.java:
1566 ideinit([], refreshOnly=True, buildProcessorJars=False) 1615 ideinit([], refreshOnly=True, buildProcessorJars=False)
1567 1616
1568 for p in sortedProjects: 1617 for p in sortedProjects:
2058 2107
2059 parser.add_argument('-f', action='store_true', dest='force', help='force checking (disables timestamp checking)') 2108 parser.add_argument('-f', action='store_true', dest='force', help='force checking (disables timestamp checking)')
2060 args = parser.parse_args(args) 2109 args = parser.parse_args(args)
2061 2110
2062 totalErrors = 0 2111 totalErrors = 0
2063 for p in sorted_deps(): 2112 for p in projects_opt_limit_to_suites():
2064 if p.native: 2113 if p.native:
2065 continue 2114 continue
2066 sourceDirs = p.source_dirs() 2115 sourceDirs = p.source_dirs()
2067 dotCheckstyle = join(p.dir, '.checkstyle') 2116 dotCheckstyle = join(p.dir, '.checkstyle')
2068 2117
2189 parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects') 2238 parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects')
2190 parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects') 2239 parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects')
2191 2240
2192 args = parser.parse_args(args) 2241 args = parser.parse_args(args)
2193 2242
2194 for p in projects(): 2243 for p in projects_opt_limit_to_suites():
2195 if p.native: 2244 if p.native:
2196 if args.native: 2245 if args.native:
2197 run([gmake_cmd(), '-C', p.dir, 'clean']) 2246 run([gmake_cmd(), '-C', p.dir, 'clean'])
2198 else: 2247 else:
2199 if args.java: 2248 if args.java:
2281 2330
2282 slm.close('sourceContainers') 2331 slm.close('sourceContainers')
2283 slm.close('sourceLookupDirector') 2332 slm.close('sourceLookupDirector')
2284 return slm 2333 return slm
2285 2334
2286 def make_eclipse_attach(hostname, port, name=None, deps=None): 2335 def make_eclipse_attach(suite, hostname, port, name=None, deps=None):
2287 """ 2336 """
2288 Creates an Eclipse launch configuration file for attaching to a Java process. 2337 Creates an Eclipse launch configuration file for attaching to a Java process.
2289 """ 2338 """
2290 if deps is None: 2339 if deps is None:
2291 deps = [] 2340 deps = []
2303 launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.VM_CONNECTOR_ID', 'value' : 'org.eclipse.jdt.launching.socketAttachConnector'}) 2352 launch.element('stringAttribute', {'key' : 'org.eclipse.jdt.launching.VM_CONNECTOR_ID', 'value' : 'org.eclipse.jdt.launching.socketAttachConnector'})
2304 launch.close('launchConfiguration') 2353 launch.close('launchConfiguration')
2305 launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no') 2354 launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no')
2306 2355
2307 if name is None: 2356 if name is None:
2308 name = 'attach-' + hostname + '-' + port 2357 if len(suites()) == 1:
2309 eclipseLaunches = join('mx', 'eclipse-launches') 2358 suitePrefix =''
2359 else:
2360 suitePrefix = suite.name + '-'
2361 name = suitePrefix + 'attach-' + hostname + '-' + port
2362 eclipseLaunches = join(suite.mxDir, 'eclipse-launches')
2310 if not exists(eclipseLaunches): 2363 if not exists(eclipseLaunches):
2311 os.makedirs(eclipseLaunches) 2364 os.makedirs(eclipseLaunches)
2312 return update_file(join(eclipseLaunches, name + '.launch'), launch) 2365 return update_file(join(eclipseLaunches, name + '.launch'), launch)
2313 2366
2314 def make_eclipse_launch(javaArgs, jre, name=None, deps=None): 2367 def make_eclipse_launch(javaArgs, jre, name=None, deps=None):
2376 eclipseLaunches = join('mx', 'eclipse-launches') 2429 eclipseLaunches = join('mx', 'eclipse-launches')
2377 if not exists(eclipseLaunches): 2430 if not exists(eclipseLaunches):
2378 os.makedirs(eclipseLaunches) 2431 os.makedirs(eclipseLaunches)
2379 return update_file(join(eclipseLaunches, name + '.launch'), launch) 2432 return update_file(join(eclipseLaunches, name + '.launch'), launch)
2380 2433
2381 def eclipseinit(args, suite=None, buildProcessorJars=True, refreshOnly=False): 2434 def eclipseinit(args, buildProcessorJars=True, refreshOnly=False):
2382 """(re)generate Eclipse project configurations and working sets""" 2435 """(re)generate Eclipse project configurations and working sets"""
2383 2436 for s in suites(True):
2384 if suite is None: 2437 _eclipseinit_suite(args, s, buildProcessorJars, refreshOnly)
2385 suite = _mainSuite 2438
2386 2439 generate_eclipse_workingsets()
2440
2441
2442 def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False):
2387 projectsFile = join(suite.mxDir, 'projects') 2443 projectsFile = join(suite.mxDir, 'projects')
2388 timestamp = TimeStampFile(join(suite.mxDir, 'eclipseinit.timestamp')) 2444 timestamp = TimeStampFile(join(suite.mxDir, 'eclipseinit.timestamp'))
2389 if refreshOnly and not timestamp.exists(): 2445 if refreshOnly and not timestamp.exists():
2390 return 2446 return
2391 2447
2392 if not timestamp.outOfDate(projectsFile): 2448 if not timestamp.outOfDate(projectsFile):
2393 logv('[Eclipse configurations are up to date - skipping]') 2449 logv('[Eclipse configurations are up to date - skipping]')
2394 return 2450 return
2395 2451
2396 if buildProcessorJars: 2452 if buildProcessorJars:
2453 ## todo suite specific
2397 processorjars() 2454 processorjars()
2398 2455
2399 projToDist = dict() 2456 projToDist = dict()
2400 for dist in _dists.values(): 2457 for dist in _dists.values():
2401 distDeps = sorted_deps(dist.deps) 2458 distDeps = sorted_deps(dist.deps)
2402 for p in distDeps: 2459 for p in distDeps:
2403 projToDist[p.name] = (dist, [dep.name for dep in distDeps]) 2460 projToDist[p.name] = (dist, [dep.name for dep in distDeps])
2404 2461
2405 for p in projects(): 2462 for p in suite.projects:
2406 if p.native: 2463 if p.native:
2407 continue 2464 continue
2408 2465
2409 if not exists(p.dir): 2466 if not exists(p.dir):
2410 os.makedirs(p.dir) 2467 os.makedirs(p.dir)
2575 else: 2632 else:
2576 out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) 2633 out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
2577 out.close('factorypath') 2634 out.close('factorypath')
2578 update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n')) 2635 update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
2579 2636
2580 make_eclipse_attach('localhost', '8000', deps=projects()) 2637 make_eclipse_attach(suite, 'localhost', '8000', deps=projects())
2581 generate_eclipse_workingsets(suite)
2582 timestamp.touch() 2638 timestamp.touch()
2583 2639
2584 def _isAnnotationProcessorDependency(p): 2640 def _isAnnotationProcessorDependency(p):
2585 """ 2641 """
2586 Determines if a given project is part of an annotation processor. 2642 Determines if a given project is part of an annotation processor.
2587 """ 2643 """
2588 return p in sorted_deps(annotation_processors()) 2644 return p in sorted_deps(annotation_processors())
2634 dotProjectDoc.element('value', data='true') 2690 dotProjectDoc.element('value', data='true')
2635 dotProjectDoc.close('dictionary') 2691 dotProjectDoc.close('dictionary')
2636 dotProjectDoc.close('arguments') 2692 dotProjectDoc.close('arguments')
2637 dotProjectDoc.close('buildCommand') 2693 dotProjectDoc.close('buildCommand')
2638 2694
2639 def generate_eclipse_workingsets(suite): 2695 def generate_eclipse_workingsets():
2640 """ 2696 """
2641 Populate the workspace's working set configuration with working sets generated from project data. 2697 Populate the workspace's working set configuration with working sets generated from project data for the primary suite
2642 If the workspace already contains working set definitions, the existing ones will be retained and extended. 2698 If the workspace already contains working set definitions, the existing ones will be retained and extended.
2643 In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, the Graal project root directory will be assumed. 2699 In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, a parent search from the primary suite directory is performed.
2644 If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand. 2700 If no workspace root directory can be identified, the primary suite directory is used and the user has to place the workingsets.xml file by hand.
2645 """ 2701 """
2646 2702
2647 # identify the location where to look for workingsets.xml 2703 # identify the location where to look for workingsets.xml
2648 wsfilename = 'workingsets.xml' 2704 wsfilename = 'workingsets.xml'
2649 wsloc = '.metadata/.plugins/org.eclipse.ui.workbench' 2705 wsloc = '.metadata/.plugins/org.eclipse.ui.workbench'
2650 wsroot = suite.dir
2651 if os.environ.has_key('WORKSPACE'): 2706 if os.environ.has_key('WORKSPACE'):
2652 wsroot = os.environ['WORKSPACE'] 2707 expected_wsroot = os.environ['WORKSPACE']
2708 else:
2709 expected_wsroot = _mainSuite.dir
2710
2711 wsroot =_find_eclipse_wsroot(expected_wsroot)
2712 if wsroot is None:
2713 # failed to find it
2714 wsroot = expected_wsroot
2715
2653 wsdir = join(wsroot, wsloc) 2716 wsdir = join(wsroot, wsloc)
2654 if not exists(wsdir): 2717 if not exists(wsdir):
2655 wsdir = wsroot 2718 wsdir = wsroot
2656 log('Could not find Eclipse metadata directory. Please place ' + wsfilename + ' in ' + wsloc + ' manually.') 2719 log('Could not find Eclipse metadata directory. Please place ' + wsfilename + ' in ' + wsloc + ' manually.')
2657 wspath = join(wsdir, wsfilename) 2720 wspath = join(wsdir, wsfilename)
2671 wsdoc = _copy_workingset_xml(wspath, workingSets) 2734 wsdoc = _copy_workingset_xml(wspath, workingSets)
2672 else: 2735 else:
2673 wsdoc = _make_workingset_xml(workingSets) 2736 wsdoc = _make_workingset_xml(workingSets)
2674 2737
2675 update_file(wspath, wsdoc.xml(newl='\n')) 2738 update_file(wspath, wsdoc.xml(newl='\n'))
2739
2740 def _find_eclipse_wsroot(wsdir):
2741 md = join(wsdir, '.metadata')
2742 if exists(md):
2743 return wsdir
2744 split = os.path.split(wsdir)
2745 # How to do this for Windows?
2746 if split[0] == '/':
2747 return None
2748 else:
2749 return _find_eclipse_wsroot(split[0])
2750
2751 def _foobar(val):
2752 print(val)
2676 2753
2677 def _make_workingset_xml(workingSets): 2754 def _make_workingset_xml(workingSets):
2678 wsdoc = XMLDoc() 2755 wsdoc = XMLDoc()
2679 wsdoc.open('workingSetManager') 2756 wsdoc.open('workingSetManager')
2680 2757
2754 wsdoc.open('workingSet', {'editPageID': 'org.eclipse.jdt.ui.JavaWorkingSetPage', 'factoryID': 'org.eclipse.ui.internal.WorkingSetFactory', 'id': 'wsid_' + ws, 'label': ws, 'name': ws}) 2831 wsdoc.open('workingSet', {'editPageID': 'org.eclipse.jdt.ui.JavaWorkingSetPage', 'factoryID': 'org.eclipse.ui.internal.WorkingSetFactory', 'id': 'wsid_' + ws, 'label': ws, 'name': ws})
2755 2832
2756 def _workingset_element(wsdoc, p): 2833 def _workingset_element(wsdoc, p):
2757 wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'}) 2834 wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'})
2758 2835
2759 def netbeansinit(args, suite=None, refreshOnly=False, buildProcessorJars=True): 2836 def netbeansinit(args, refreshOnly=False, buildProcessorJars=True):
2760 """(re)generate NetBeans project configurations""" 2837 """(re)generate NetBeans project configurations"""
2761 2838
2762 if suite is None: 2839 for suite in suites(True):
2763 suite = _mainSuite 2840 _netbeansinit_suite(args, suite, refreshOnly, buildProcessorJars)
2764 2841
2842 def _netbeansinit_suite(args, suite, refreshOnly=False, buildProcessorJars=True):
2765 projectsFile = join(suite.mxDir, 'projects') 2843 projectsFile = join(suite.mxDir, 'projects')
2766 timestamp = TimeStampFile(join(suite.mxDir, 'netbeansinit.timestamp')) 2844 timestamp = TimeStampFile(join(suite.mxDir, 'netbeansinit.timestamp'))
2767 if refreshOnly and not timestamp.exists(): 2845 if refreshOnly and not timestamp.exists():
2768 return 2846 return
2769 2847
2770 if not timestamp.outOfDate(projectsFile): 2848 if not timestamp.outOfDate(projectsFile):
2771 logv('[NetBeans configurations are up to date - skipping]') 2849 logv('[NetBeans configurations are up to date - skipping]')
2772 return 2850 return
2773 2851
2774 updated = False 2852 updated = False
2775 for p in projects(): 2853 for p in suite.projects:
2776 if p.native: 2854 if p.native:
2777 continue 2855 continue
2778 2856
2779 if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project 2857 if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
2780 continue 2858 continue
2986 log(' 1. Ensure that a platform named "JDK_' + str(java().version) + '" is defined (Tools -> Java Platforms)') 3064 log(' 1. Ensure that a platform named "JDK_' + str(java().version) + '" is defined (Tools -> Java Platforms)')
2987 log(' 2. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)') 3065 log(' 2. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)')
2988 3066
2989 timestamp.touch() 3067 timestamp.touch()
2990 3068
2991 def ideclean(args, suite=None): 3069 def ideclean(args):
2992 """remove all Eclipse and NetBeans project configurations""" 3070 """remove all Eclipse and NetBeans project configurations"""
2993 def rm(path): 3071 def rm(path):
2994 if exists(path): 3072 if exists(path):
2995 os.remove(path) 3073 os.remove(path)
2996 3074
3014 rm(join(p.dir, p.name + '.jar')) 3092 rm(join(p.dir, p.name + '.jar'))
3015 except: 3093 except:
3016 log("Error removing {0}".format(p.name + '.jar')) 3094 log("Error removing {0}".format(p.name + '.jar'))
3017 3095
3018 3096
3019 def ideinit(args, suite=None, refreshOnly=False, buildProcessorJars=True): 3097 def ideinit(args, refreshOnly=False, buildProcessorJars=True):
3020 """(re)generate Eclipse and NetBeans project configurations""" 3098 """(re)generate Eclipse and NetBeans project configurations"""
3021 eclipseinit(args, suite, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) 3099 eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
3022 netbeansinit(args, suite, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) 3100 netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
3023 if not refreshOnly: 3101 if not refreshOnly:
3024 fsckprojects([]) 3102 fsckprojects([])
3025 3103
3026 def fsckprojects(args): 3104 def fsckprojects(args):
3027 """find directories corresponding to deleted Java projects and delete them""" 3105 """find directories corresponding to deleted Java projects and delete them"""
3028 for suite in suites(): 3106 for suite in suites(True):
3029 projectDirs = [p.dir for p in suite.projects] 3107 projectDirs = [p.dir for p in suite.projects]
3030 for root, dirnames, files in os.walk(suite.dir): 3108 for root, dirnames, files in os.walk(suite.dir):
3031 currentDir = join(suite.dir, root) 3109 currentDir = join(suite.dir, root)
3032 if currentDir in projectDirs: 3110 if currentDir in projectDirs:
3033 # don't traverse subdirs of an existing project 3111 # don't traverse subdirs of an existing project
3056 parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude') 3134 parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude')
3057 3135
3058 args = parser.parse_args(args) 3136 args = parser.parse_args(args)
3059 3137
3060 # build list of projects to be processed 3138 # build list of projects to be processed
3061 candidates = sorted_deps()
3062 if args.projects is not None: 3139 if args.projects is not None:
3063 candidates = [project(name) for name in args.projects.split(',')] 3140 candidates = [project(name) for name in args.projects.split(',')]
3141 else:
3142 candidates = projects_opt_limit_to_suites()
3064 3143
3065 # optionally restrict packages within a project 3144 # optionally restrict packages within a project
3066 packages = [] 3145 packages = []
3067 if args.packages is not None: 3146 if args.packages is not None:
3068 packages = [name for name in args.packages.split(',')] 3147 packages = [name for name in args.packages.split(',')]
3522 projectsFile = join(s.mxDir, 'projects') 3601 projectsFile = join(s.mxDir, 'projects')
3523 if exists(projectsFile): 3602 if exists(projectsFile):
3524 log(projectsFile) 3603 log(projectsFile)
3525 for p in s.projects: 3604 for p in s.projects:
3526 log('\t' + p.name) 3605 log('\t' + p.name)
3527 3606
3528 def ask_yes_no(question, default=None): 3607 def ask_yes_no(question, default=None):
3529 """""" 3608 """"""
3530 assert not default or default == 'y' or default == 'n' 3609 assert not default or default == 'y' or default == 'n'
3531 if not sys.stdout.isatty(): 3610 if not sys.stdout.isatty():
3532 if default: 3611 if default:
3586 _argParser = ArgParser() 3665 _argParser = ArgParser()
3587 3666
3588 def _findPrimarySuite(): 3667 def _findPrimarySuite():
3589 def is_suite_dir(d): 3668 def is_suite_dir(d):
3590 for f in os.listdir(d): 3669 for f in os.listdir(d):
3591 if fnmatch.fnmatch(f, 'mx*'): 3670 if f == 'mx' or fnmatch.fnmatch(f, 'mx.*'):
3592 mxDir = join(d, f) 3671 mxDir = join(d, f)
3593 if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')): 3672 if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')):
3594 return dirname(mxDir) 3673 return dirname(mxDir)
3595 3674
3596 3675