comparison mxtool/mx.py @ 12639:50aca0c0dff4

Merge.
author Christian Humer <christian.humer@gmail.com>
date Wed, 30 Oct 2013 11:08:00 +0100
parents 2303d9e199e3
children 6860d5528902
comparison
equal deleted inserted replaced
12638:02f844c76626 12639:50aca0c0dff4
324 if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true': 324 if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true':
325 ap.add(p.name) 325 ap.add(p.name)
326 self._annotationProcessors = list(ap) 326 self._annotationProcessors = list(ap)
327 return self._annotationProcessors 327 return self._annotationProcessors
328 328
329 def update_current_annotation_processors_file(self):
330 aps = self.annotation_processors()
331 outOfDate = False
332 currentApsFile = join(self.dir, '.currentAnnotationProcessors')
333 if exists(currentApsFile):
334 with open(currentApsFile) as fp:
335 currentAps = [l.strip() for l in fp.readlines()]
336 if currentAps != aps:
337 outOfDate = True
338 else:
339 outOfDate = True
340 if outOfDate:
341 with open(currentApsFile, 'w') as fp:
342 for ap in aps:
343 print >> fp, ap
344 return outOfDate
345
346
329 class Library(Dependency): 347 class Library(Dependency):
330 def __init__(self, suite, name, path, mustExist, urls, sourcePath, sourceUrls): 348 def __init__(self, suite, name, path, mustExist, urls, sourcePath, sourceUrls):
331 Dependency.__init__(self, suite, name) 349 Dependency.__init__(self, suite, name)
332 self.path = path.replace('/', os.sep) 350 self.path = path.replace('/', os.sep)
333 self.urls = urls 351 self.urls = urls
767 785
768 if self.name is None: 786 if self.name is None:
769 abort('Missing "suite=<name>" in ' + projectsFile) 787 abort('Missing "suite=<name>" in ' + projectsFile)
770 788
771 def _commands_name(self): 789 def _commands_name(self):
772 return 'mx_' + self.name.replace('-', '_') 790 return 'mx_' + self.name.replace('-','_')
773 791
774 def _find_commands(self, name): 792 def _find_commands(self, name):
775 commandsPath = join(self.mxDir, name + '.py') 793 commandsPath = join(self.mxDir, name + '.py')
776 if exists(commandsPath): 794 if exists(commandsPath):
777 return name 795 return name
801 if hasattr(mod, 'mx_post_parse_cmd_line'): 819 if hasattr(mod, 'mx_post_parse_cmd_line'):
802 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line 820 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line
803 821
804 mod.mx_init(self) 822 mod.mx_init(self)
805 self.commands = mod 823 self.commands = mod
824
825 def _imports_file(self):
826 return join(self.mxDir, 'imports')
827
828 def import_timestamp(self):
829 return TimeStampFile(self._imports_file())
806 830
807 def visit_imports(self, visitor, **extra_args): 831 def visit_imports(self, visitor, **extra_args):
808 """ 832 """
809 Visitor support for the imports file. 833 Visitor support for the imports file.
810 For each line of the imports file that specifies an import, the visitor function is 834 For each line of the imports file that specifies an import, the visitor function is
815 all imports are processed. 839 all imports are processed.
816 N.B. There is no built-in support for avoiding visiting the same suite multiple times, 840 N.B. There is no built-in support for avoiding visiting the same suite multiple times,
817 as this function only visits the imports of a single suite. If a (recursive) visitor function 841 as this function only visits the imports of a single suite. If a (recursive) visitor function
818 wishes to visit a suite exactly once, it must manage that through extra_args. 842 wishes to visit a suite exactly once, it must manage that through extra_args.
819 """ 843 """
820 importsFile = join(self.mxDir, 'imports') 844 importsFile = self._imports_file()
821 if exists(importsFile): 845 if exists(importsFile):
822 update_versions = extra_args.has_key('update_versions') and extra_args['update_versions'] 846 update_versions = extra_args.has_key('update_versions') and extra_args['update_versions']
823 out = StringIO.StringIO() if update_versions else None 847 out = StringIO.StringIO() if update_versions else None
824 extra_args['updated_imports'] = out 848 extra_args['updated_imports'] = out
825 with open(importsFile) as f: 849 with open(importsFile) as f:
1845 sortedProjects = sorted_project_deps(projects, includeAnnotationProcessors=True) 1869 sortedProjects = sorted_project_deps(projects, includeAnnotationProcessors=True)
1846 1870
1847 if args.java: 1871 if args.java:
1848 ideinit([], refreshOnly=True, buildProcessorJars=False) 1872 ideinit([], refreshOnly=True, buildProcessorJars=False)
1849 1873
1874 def prepareOutputDirs(p, clean):
1875 outputDir = p.output_dir()
1876 if exists(outputDir):
1877 if clean:
1878 log('Cleaning {0}...'.format(outputDir))
1879 shutil.rmtree(outputDir)
1880 os.mkdir(outputDir)
1881 else:
1882 os.mkdir(outputDir)
1883 genDir = p.source_gen_dir()
1884 if genDir != '' and exists(genDir) and clean:
1885 log('Cleaning {0}...'.format(genDir))
1886 for f in os.listdir(genDir):
1887 shutil.rmtree(join(genDir, f))
1888 return outputDir
1889
1850 for p in sortedProjects: 1890 for p in sortedProjects:
1851 if p.native: 1891 if p.native:
1852 if args.native: 1892 if args.native:
1853 log('Calling GNU make {0}...'.format(p.dir)) 1893 log('Calling GNU make {0}...'.format(p.dir))
1854 1894
1867 # skip building this Java project if its Java compliance level is "higher" than the configured JDK 1907 # skip building this Java project if its Java compliance level is "higher" than the configured JDK
1868 if javaCompliance < p.javaCompliance: 1908 if javaCompliance < p.javaCompliance:
1869 log('Excluding {0} from build (Java compliance level {1} required)'.format(p.name, p.javaCompliance)) 1909 log('Excluding {0} from build (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
1870 continue 1910 continue
1871 1911
1872 outputDir = p.output_dir() 1912 outputDir = prepareOutputDirs(p, args.clean)
1873 if exists(outputDir):
1874 if args.clean:
1875 log('Cleaning {0}...'.format(outputDir))
1876 shutil.rmtree(outputDir)
1877 os.mkdir(outputDir)
1878 else:
1879 os.mkdir(outputDir)
1880 1913
1881 cp = classpath(p.name, includeSelf=True) 1914 cp = classpath(p.name, includeSelf=True)
1882 sourceDirs = p.source_dirs() 1915 sourceDirs = p.source_dirs()
1883 mustBuild = args.force 1916 mustBuild = args.force
1884 if not mustBuild: 1917 if not mustBuild:
1885 for dep in p.all_deps([], False): 1918 for dep in p.all_deps([], False):
1886 if dep.name in built: 1919 if dep.name in built:
1887 mustBuild = True 1920 mustBuild = True
1921
1888 1922
1889 jasminAvailable = None 1923 jasminAvailable = None
1890 javafilelist = [] 1924 javafilelist = []
1891 for sourceDir in sourceDirs: 1925 for sourceDir in sourceDirs:
1892 for root, _, files in os.walk(sourceDir): 1926 for root, _, files in os.walk(sourceDir):
1933 if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)): 1967 if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)):
1934 shutil.copyfile(src, dst) 1968 shutil.copyfile(src, dst)
1935 1969
1936 if not mustBuild: 1970 if not mustBuild:
1937 for javafile in javafiles: 1971 for javafile in javafiles:
1938 classfile = outputDir + javafile[len(sourceDir):-len('java')] + 'class' 1972 classfile = TimeStampFile(outputDir + javafile[len(sourceDir):-len('java')] + 'class')
1939 if not exists(classfile) or os.path.getmtime(javafile) > os.path.getmtime(classfile): 1973 if not classfile.exists() or classfile.isOlderThan(javafile):
1940 mustBuild = True 1974 mustBuild = True
1941 break 1975 break
1976
1977 aps = p.annotation_processors()
1978 apsOutOfDate = p.update_current_annotation_processors_file()
1979 if apsOutOfDate:
1980 logv('[annotation processors for {0} changed]'.format(p.name))
1981 mustBuild = True
1942 1982
1943 if not mustBuild: 1983 if not mustBuild:
1944 logv('[all class files for {0} are up to date - skipping]'.format(p.name)) 1984 logv('[all class files for {0} are up to date - skipping]'.format(p.name))
1945 continue 1985 continue
1946 1986
1947 if len(javafilelist) == 0: 1987 if len(javafilelist) == 0:
1948 logv('[no Java sources for {0} - skipping]'.format(p.name)) 1988 logv('[no Java sources for {0} - skipping]'.format(p.name))
1949 continue 1989 continue
1990
1991 # Ensure that the output directories are clean
1992 prepareOutputDirs(p, True)
1950 1993
1951 built.add(p.name) 1994 built.add(p.name)
1952 1995
1953 argfileName = join(p.dir, 'javafilelist.txt') 1996 argfileName = join(p.dir, 'javafilelist.txt')
1954 argfile = open(argfileName, 'wb') 1997 argfile = open(argfileName, 'wb')
1955 argfile.write('\n'.join(javafilelist)) 1998 argfile.write('\n'.join(javafilelist))
1956 argfile.close() 1999 argfile.close()
1957 2000
1958 processorArgs = [] 2001 processorArgs = []
1959 2002
1960 ap = p.annotation_processors() 2003 if len(aps) > 0:
1961 if len(ap) > 0: 2004 processorPath = classpath(aps, resolve=True)
1962 processorPath = classpath(ap, resolve=True)
1963 genDir = p.source_gen_dir() 2005 genDir = p.source_gen_dir()
1964 if exists(genDir): 2006 if exists(genDir):
1965 shutil.rmtree(genDir) 2007 shutil.rmtree(genDir)
1966 os.mkdir(genDir) 2008 os.mkdir(genDir)
1967 processorArgs += ['-processorpath', join(processorPath), '-s', genDir] 2009 processorArgs += ['-processorpath', join(processorPath), '-s', genDir]
2130 log('Wrote backup of {0} modified files to {1}'.format(len(modified), backup)) 2172 log('Wrote backup of {0} modified files to {1}'.format(len(modified), backup))
2131 return 1 2173 return 1
2132 return 0 2174 return 0
2133 2175
2134 def processorjars(): 2176 def processorjars():
2135 2177 for s in suites(True):
2178 _processorjars_suite(s)
2179
2180 def _processorjars_suite(s):
2136 projs = set() 2181 projs = set()
2137 for p in sorted_deps(): 2182 candidates = sorted_project_deps(s.projects)
2183 for p in candidates:
2138 if _isAnnotationProcessorDependency(p): 2184 if _isAnnotationProcessorDependency(p):
2139 projs.add(p) 2185 projs.add(p)
2140 2186
2141 if len(projs) < 0: 2187 if len(projs) <= 0:
2142 return 2188 return
2143 2189
2144 pnames = [p.name for p in projs] 2190 pnames = [p.name for p in projs]
2145 build(['--projects', ",".join(pnames)]) 2191 build(['--projects', ",".join(pnames)])
2146 archive(pnames) 2192 archive(pnames)
2376 self.timestamp = os.path.getmtime(path) if exists(path) else None 2422 self.timestamp = os.path.getmtime(path) if exists(path) else None
2377 2423
2378 def isOlderThan(self, arg): 2424 def isOlderThan(self, arg):
2379 if not self.timestamp: 2425 if not self.timestamp:
2380 return True 2426 return True
2381 if isinstance(arg, types.ListType): 2427 if isinstance(arg, TimeStampFile):
2428 if arg.timestamp is None:
2429 return False
2430 else:
2431 return arg.timestamp > self.timestamp
2432 elif isinstance(arg, types.ListType):
2382 files = arg 2433 files = arg
2383 else: 2434 else:
2384 files = [arg] 2435 files = [arg]
2385 for f in files: 2436 for f in files:
2386 if os.path.getmtime(f) > self.timestamp: 2437 if os.path.getmtime(f) > self.timestamp:
2639 fromIndex = fromIndex + 1 2690 fromIndex = fromIndex + 1
2640 igv.close('edges') 2691 igv.close('edges')
2641 igv.close('graph') 2692 igv.close('graph')
2642 igv.close('group') 2693 igv.close('group')
2643 igv.close('graphDocument') 2694 igv.close('graphDocument')
2644 2695
2645 if args.igv: 2696 if args.igv:
2646 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 2697 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2647 s.connect(('127.0.0.1', 4444)) 2698 s.connect(('127.0.0.1', 4444))
2648 s.send(igv.xml()) 2699 s.send(igv.xml())
2649 else: 2700 else:
2650 print igv.xml(indent=' ', newl='\n'); 2701 print igv.xml(indent=' ', newl='\n')
2651 return 2702 return
2652 2703
2653
2654 print 'digraph projects {' 2704 print 'digraph projects {'
2655 print 'rankdir=BT;' 2705 print 'rankdir=BT;'
2656 print 'node [shape=rect];' 2706 print 'node [shape=rect];'
2657 for p in projects(): 2707 for p in projects():
2658 for dep in p.canonical_deps(): 2708 for dep in p.canonical_deps():
2785 for s in suites(True): 2835 for s in suites(True):
2786 _eclipseinit_suite(args, s, buildProcessorJars, refreshOnly) 2836 _eclipseinit_suite(args, s, buildProcessorJars, refreshOnly)
2787 2837
2788 generate_eclipse_workingsets() 2838 generate_eclipse_workingsets()
2789 2839
2840 def _check_ide_timestamp(suite, timestamp):
2841 """return True if and only if the projects file, imports file, and mx itself are all older than timestamp"""
2842 projectsFile = join(suite.mxDir, 'projects')
2843 projectsFileOlder = not timestamp.isOlderThan(projectsFile)
2844 importsFileOlder = not timestamp.isOlderThan(suite.import_timestamp())
2845 # Assume that any mx change might imply changes to the generated IDE files
2846 mxOlder = not timestamp.isOlderThan(__file__)
2847 return projectsFileOlder and importsFileOlder and mxOlder
2790 2848
2791 def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False): 2849 def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False):
2792 projectsFile = join(suite.mxDir, 'projects')
2793 timestamp = TimeStampFile(join(suite.mxDir, 'eclipseinit.timestamp')) 2850 timestamp = TimeStampFile(join(suite.mxDir, 'eclipseinit.timestamp'))
2794 if refreshOnly and not timestamp.exists(): 2851 if refreshOnly and not timestamp.exists():
2795 return 2852 return
2796 2853
2797 if not timestamp.isOlderThan(projectsFile) and not TimeStampFile(projectsFile).isOlderThan(__file__): 2854 if _check_ide_timestamp(suite, timestamp):
2798 logv('[Eclipse configurations are up to date - skipping]') 2855 logv('[Eclipse configurations are up to date - skipping]')
2799 return 2856 return
2800 2857
2801 if buildProcessorJars: 2858 if buildProcessorJars:
2802 # todo suite specific 2859 _processorjars_suite(suite)
2803 processorjars()
2804 2860
2805 projToDist = dict() 2861 projToDist = dict()
2806 for dist in _dists.values(): 2862 for dist in _dists.values():
2807 distDeps = sorted_deps(dist.deps) 2863 distDeps = sorted_deps(dist.deps)
2808 for p in distDeps: 2864 for p in distDeps:
3197 3253
3198 for suite in suites(True): 3254 for suite in suites(True):
3199 _netbeansinit_suite(args, suite, refreshOnly, buildProcessorJars) 3255 _netbeansinit_suite(args, suite, refreshOnly, buildProcessorJars)
3200 3256
3201 def _netbeansinit_suite(args, suite, refreshOnly=False, buildProcessorJars=True): 3257 def _netbeansinit_suite(args, suite, refreshOnly=False, buildProcessorJars=True):
3202 projectsFile = join(suite.mxDir, 'projects')
3203 timestamp = TimeStampFile(join(suite.mxDir, 'netbeansinit.timestamp')) 3258 timestamp = TimeStampFile(join(suite.mxDir, 'netbeansinit.timestamp'))
3204 if refreshOnly and not timestamp.exists(): 3259 if refreshOnly and not timestamp.exists():
3205 return 3260 return
3206 3261
3207 if not timestamp.isOlderThan(projectsFile) and not TimeStampFile(projectsFile).isOlderThan(__file__): 3262 if _check_ide_timestamp(suite, timestamp):
3208 logv('[NetBeans configurations are up to date - skipping]') 3263 logv('[NetBeans configurations are up to date - skipping]')
3209 return 3264 return
3210 3265
3211 updated = False 3266 updated = False
3212 for p in suite.projects: 3267 for p in suite.projects: