Mercurial > hg > graal-jvmci-8
comparison mxtool/mx.py @ 17163:30dda118ef3d
mx: added support for extending distributions; require list literals for list attributes in projects.py
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Fri, 19 Sep 2014 17:46:35 +0200 |
parents | ef5212ce8091 |
children | a8c0553cb2e4 |
comparison
equal
deleted
inserted
replaced
17162:4a955509b98a | 17163:30dda118ef3d |
---|---|
869 def inc(self): | 869 def inc(self): |
870 self.prefix = ''.rjust(len(self.prefix) + self.indent) | 870 self.prefix = ''.rjust(len(self.prefix) + self.indent) |
871 def dec(self): | 871 def dec(self): |
872 self.prefix = ''.rjust(len(self.prefix) - self.indent) | 872 self.prefix = ''.rjust(len(self.prefix) - self.indent) |
873 | 873 |
874 list_attrs = ['urls', 'dependencies', 'sourceUrls', 'sourceDirs', 'annotationProcessors', 'exclude', 'distDependencies'] | |
875 | |
874 for projectsFile in args: | 876 for projectsFile in args: |
875 suite = _read_projects_file(projectsFile) | 877 suite = _read_projects_file(projectsFile) |
876 def print_attrs(p, name, attrs, listKeys, is_last=False): | 878 def print_attrs(p, name, attrs, is_last=False): |
877 p.println('"' + name + '" : {') | 879 p.println('"' + name + '" : {') |
878 p.inc() | 880 p.inc() |
879 for n, v in attrs.iteritems(): | 881 for n, v in attrs.iteritems(): |
880 if n in listKeys: | 882 if n in list_attrs: |
881 if len(v) == 0: | 883 if len(v) == 0: |
882 p.println('"{}" : [],'.format(n)) | 884 p.println('"{}" : [],'.format(n)) |
883 else: | 885 else: |
884 p.println('"{}" : ['.format(n)) | 886 v = [e.strip() for e in v.split(',')] |
885 p.inc() | 887 if len(v) == 1: |
886 for e in v.split(','): | 888 p.println('"{}" : ["{}"],'.format(n, v[0])) |
887 p.println('"' + e.strip() + '",') | 889 else: |
888 p.dec() | 890 p.println('"{}" : ['.format(n)) |
889 p.println('],') | 891 p.inc() |
892 for e in v: | |
893 p.println('"' + e + '",') | |
894 p.dec() | |
895 p.println('],') | |
890 else: | 896 else: |
891 p.println('"{}" : "{}",'.format(n, v)) | 897 p.println('"{}" : "{}",'.format(n, v)) |
892 p.dec() | 898 p.dec() |
893 if is_last: | 899 if is_last: |
894 p.println('}') | 900 p.println('}') |
902 p.println('"' + sname + '" : {') | 908 p.println('"' + sname + '" : {') |
903 p.inc() | 909 p.inc() |
904 i = 0 | 910 i = 0 |
905 for name, attrs in section.iteritems(): | 911 for name, attrs in section.iteritems(): |
906 i = i + 1 | 912 i = i + 1 |
907 print_attrs(p, name, attrs, ['urls', 'dependencies', 'sourceUrls'], i == len(section)) | 913 print_attrs(p, name, attrs, i == len(section)) |
908 | 914 |
909 p.dec() | 915 p.dec() |
910 if is_last: | 916 if is_last: |
911 p.println('}') | 917 p.println('}') |
912 else: | 918 else: |
916 existing, projectsPyFile = _load_suite_dict(dirname(projectsFile)) | 922 existing, projectsPyFile = _load_suite_dict(dirname(projectsFile)) |
917 if existing: | 923 if existing: |
918 assert existing['name'] == suite.pop('name') | 924 assert existing['name'] == suite.pop('name') |
919 assert existing['mxversion'] == suite.pop('mxversion') | 925 assert existing['mxversion'] == suite.pop('mxversion') |
920 for s in ['projects', 'libraries', 'jrelibraries', 'distributions']: | 926 for s in ['projects', 'libraries', 'jrelibraries', 'distributions']: |
927 section = suite[s] | |
921 for k in existing[s].iterkeys(): | 928 for k in existing[s].iterkeys(): |
922 suite[s].pop(k) | 929 duplicate = section.pop(k) |
923 if len(suite[s]) == 0: | 930 if duplicate and s == 'distributions': |
931 original = existing[s][k] | |
932 extensions = [d for d in duplicate['dependencies'].split(',') if d not in original['dependencies']] | |
933 if len(extensions): | |
934 extensions = ','.join(extensions) | |
935 suite.setdefault('distribution_extensions', {})[k] = {'dependencies' : extensions} | |
936 if len(section) == 0: | |
924 suite.pop(s) | 937 suite.pop(s) |
925 | 938 |
926 if len(suite): | 939 if len(suite): |
927 out = StringIO.StringIO() | 940 out = StringIO.StringIO() |
928 p = Printer(out, 2) | 941 p = Printer(out, 2) |
932 p.println('"mxversion" : "' + suite['mxversion'] + '",') | 945 p.println('"mxversion" : "' + suite['mxversion'] + '",') |
933 p.println('"name" : "' + suite['name'] + '",') | 946 p.println('"name" : "' + suite['name'] + '",') |
934 print_section(p, 'libraries', suite) | 947 print_section(p, 'libraries', suite) |
935 print_section(p, 'jrelibraries', suite) | 948 print_section(p, 'jrelibraries', suite) |
936 print_section(p, 'projects', suite) | 949 print_section(p, 'projects', suite) |
937 print_section(p, 'distributions', suite, is_last=True) | 950 print_section(p, 'distributions', suite) |
951 if existing and suite.has_key('distribution_extensions'): | |
952 print_section(p, 'distribution_extensions', suite, is_last=True) | |
953 | |
938 p.dec() | 954 p.dec() |
939 p.println('}') | 955 p.println('}') |
940 | 956 |
941 with open(projectsPyFile, 'w') as fp: | 957 with open(projectsPyFile, 'w') as fp: |
942 fp.write(out.getvalue()) | 958 fp.write(out.getvalue()) |
979 del sys.path[0] | 995 del sys.path[0] |
980 | 996 |
981 if not hasattr(module, dictName): | 997 if not hasattr(module, dictName): |
982 abort(modulePath + ' must define a variable named "' + dictName + '"') | 998 abort(modulePath + ' must define a variable named "' + dictName + '"') |
983 d = getattr(module, dictName) | 999 d = getattr(module, dictName) |
984 sections = ['projects', 'libraries', 'jrelibraries', 'distributions'] + ([] if suite else ['name', 'mxversion']) | 1000 sections = ['projects', 'libraries', 'jrelibraries', 'distributions'] + (['distribution_extensions'] if suite else ['name', 'mxversion']) |
985 unknown = d.viewkeys() - sections | 1001 unknown = d.viewkeys() - sections |
986 if unknown: | 1002 if unknown: |
987 abort(modulePath + ' defines unsupported suite sections: ' + ', '.join(unknown)) | 1003 abort(modulePath + ' defines unsupported suite sections: ' + ', '.join(unknown)) |
988 | 1004 |
989 if suite is None: | 1005 if suite is None: |
998 else: | 1014 else: |
999 conflicting = additional.viewkeys() & existing.viewkeys() | 1015 conflicting = additional.viewkeys() & existing.viewkeys() |
1000 if conflicting: | 1016 if conflicting: |
1001 abort(modulePath + ' redefines: ' + ', '.join(conflicting)) | 1017 abort(modulePath + ' redefines: ' + ', '.join(conflicting)) |
1002 existing.update(additional) | 1018 existing.update(additional) |
1019 distExtensions = d.get('distribution_extensions') | |
1020 if distExtensions: | |
1021 existing = suite['distributions'] | |
1022 for n, attrs in distExtensions.iteritems(): | |
1023 original = existing.get(n) | |
1024 if not original: | |
1025 abort('cannot extend non-existing distribution ' + n) | |
1026 for k, v in attrs.iteritems(): | |
1027 if k != 'dependencies': | |
1028 abort('Only the dependencies of distribution ' + n + ' can be extended') | |
1029 if not isinstance(v, types.ListType): | |
1030 abort('distribution_extensions.' + n + '.dependencies must be a list') | |
1031 original['dependencies'] += v | |
1003 | 1032 |
1004 dictName = 'extra' | 1033 dictName = 'extra' |
1005 moduleName = 'projects' + str(suffix) | 1034 moduleName = 'projects' + str(suffix) |
1006 modulePath = join(mxDir, moduleName + '.py') | 1035 modulePath = join(mxDir, moduleName + '.py') |
1007 suffix = suffix + 1 | 1036 suffix = suffix + 1 |
1054 libsMap = suiteDict['libraries'] | 1083 libsMap = suiteDict['libraries'] |
1055 jreLibsMap = suiteDict['jrelibraries'] | 1084 jreLibsMap = suiteDict['jrelibraries'] |
1056 projsMap = suiteDict['projects'] | 1085 projsMap = suiteDict['projects'] |
1057 distsMap = suiteDict['distributions'] | 1086 distsMap = suiteDict['distributions'] |
1058 | 1087 |
1059 def pop_list(attrs, name): | 1088 def pop_list(attrs, name, context): |
1060 v = attrs.pop(name, None) | 1089 v = attrs.pop(name, None) |
1061 if isinstance(v, list): | 1090 if not v: |
1062 return v | |
1063 if v is None or len(v.strip()) == 0: | |
1064 return [] | 1091 return [] |
1065 return [n.strip() for n in v.split(',')] | 1092 if not isinstance(v, list): |
1093 abort('Attribute "' + name + '" for ' + context + ' must be a list') | |
1094 return v | |
1066 | 1095 |
1067 for name, attrs in projsMap.iteritems(): | 1096 for name, attrs in projsMap.iteritems(): |
1068 srcDirs = pop_list(attrs, 'sourceDirs') | 1097 context = 'project ' + name |
1069 deps = pop_list(attrs, 'dependencies') | 1098 srcDirs = pop_list(attrs, 'sourceDirs', context) |
1070 ap = pop_list(attrs, 'annotationProcessors') | 1099 deps = pop_list(attrs, 'dependencies', context) |
1100 ap = pop_list(attrs, 'annotationProcessors', context) | |
1071 javaCompliance = attrs.pop('javaCompliance', None) | 1101 javaCompliance = attrs.pop('javaCompliance', None) |
1072 subDir = attrs.pop('subDir', None) | 1102 subDir = attrs.pop('subDir', None) |
1073 if subDir is None: | 1103 if subDir is None: |
1074 d = join(self.dir, name) | 1104 d = join(self.dir, name) |
1075 else: | 1105 else: |
1091 optional = attrs.pop('optional', 'true') != 'false' | 1121 optional = attrs.pop('optional', 'true') != 'false' |
1092 l = JreLibrary(self, name, jar, optional) | 1122 l = JreLibrary(self, name, jar, optional) |
1093 self.jreLibs.append(l) | 1123 self.jreLibs.append(l) |
1094 | 1124 |
1095 for name, attrs in libsMap.iteritems(): | 1125 for name, attrs in libsMap.iteritems(): |
1126 context = 'library ' + name | |
1096 if "|" in name: | 1127 if "|" in name: |
1097 if name.count('|') != 2: | 1128 if name.count('|') != 2: |
1098 abort("Format error in library name: " + name + "\nsyntax: libname|os-platform|architecture") | 1129 abort("Format error in library name: " + name + "\nsyntax: libname|os-platform|architecture") |
1099 name, platform, architecture = name.split("|") | 1130 name, platform, architecture = name.split("|") |
1100 if platform != get_os() or architecture != get_arch(): | 1131 if platform != get_os() or architecture != get_arch(): |
1101 continue | 1132 continue |
1102 path = attrs.pop('path') | 1133 path = attrs.pop('path') |
1103 urls = pop_list(attrs, 'urls') | 1134 urls = pop_list(attrs, 'urls', context) |
1104 sha1 = attrs.pop('sha1', None) | 1135 sha1 = attrs.pop('sha1', None) |
1105 sourcePath = attrs.pop('sourcePath', None) | 1136 sourcePath = attrs.pop('sourcePath', None) |
1106 sourceUrls = pop_list(attrs, 'sourceUrls') | 1137 sourceUrls = pop_list(attrs, 'sourceUrls', context) |
1107 sourceSha1 = attrs.pop('sourceSha1', None) | 1138 sourceSha1 = attrs.pop('sourceSha1', None) |
1108 deps = pop_list(attrs, 'dependencies') | 1139 deps = pop_list(attrs, 'dependencies', context) |
1109 # Add support optional libraries once we have a good use case | 1140 # Add support optional libraries once we have a good use case |
1110 optional = False | 1141 optional = False |
1111 l = Library(self, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps) | 1142 l = Library(self, name, path, optional, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps) |
1112 l.__dict__.update(attrs) | 1143 l.__dict__.update(attrs) |
1113 self.libs.append(l) | 1144 self.libs.append(l) |
1114 | 1145 |
1115 for name, attrs in distsMap.iteritems(): | 1146 for name, attrs in distsMap.iteritems(): |
1147 context = 'distribution ' + name | |
1116 path = attrs.pop('path') | 1148 path = attrs.pop('path') |
1117 sourcesPath = attrs.pop('sourcesPath', None) | 1149 sourcesPath = attrs.pop('sourcesPath', None) |
1118 deps = pop_list(attrs, 'dependencies') | 1150 deps = pop_list(attrs, 'dependencies', context) |
1119 mainClass = attrs.pop('mainClass', None) | 1151 mainClass = attrs.pop('mainClass', None) |
1120 exclDeps = pop_list(attrs, 'exclude') | 1152 exclDeps = pop_list(attrs, 'exclude', context) |
1121 distDeps = pop_list(attrs, 'distDependencies') | 1153 distDeps = pop_list(attrs, 'distDependencies', context) |
1122 javaCompliance = attrs.pop('javaCompliance', None) | 1154 javaCompliance = attrs.pop('javaCompliance', None) |
1123 d = Distribution(self, name, path, sourcesPath, deps, mainClass, exclDeps, distDeps, javaCompliance) | 1155 d = Distribution(self, name, path, sourcesPath, deps, mainClass, exclDeps, distDeps, javaCompliance) |
1124 d.__dict__.update(attrs) | 1156 d.__dict__.update(attrs) |
1125 self.dists.append(d) | 1157 self.dists.append(d) |
1126 | 1158 |
1170 arc.zf.writestr(arcname, lp.read(arcname)) | 1202 arc.zf.writestr(arcname, lp.read(arcname)) |
1171 d.add_update_listener(_refineAnnotationProcessorServiceConfig) | 1203 d.add_update_listener(_refineAnnotationProcessorServiceConfig) |
1172 self.dists.append(d) | 1204 self.dists.append(d) |
1173 | 1205 |
1174 if self.name is None: | 1206 if self.name is None: |
1175 abort('Missing "suite=<name>" in ' + projectsFile) | 1207 abort('Missing "suite=<name>" in ' + projectsPyFile) |
1176 | 1208 |
1177 def _commands_name(self): | 1209 def _commands_name(self): |
1178 return 'mx_' + self.name.replace('-', '_') | 1210 return 'mx_' + self.name.replace('-', '_') |
1179 | 1211 |
1180 def _find_commands(self, name): | 1212 def _find_commands(self, name): |
3054 | 3086 |
3055 The exit code of this command reflects how many projects have non-canonical dependencies.""" | 3087 The exit code of this command reflects how many projects have non-canonical dependencies.""" |
3056 | 3088 |
3057 nonCanonical = [] | 3089 nonCanonical = [] |
3058 for s in suites(True): | 3090 for s in suites(True): |
3059 projectsPyFile = join(s.mxDir, 'projects') | |
3060 if not exists(projectsPyFile): | |
3061 continue | |
3062 | |
3063 for p in s.projects: | 3091 for p in s.projects: |
3064 for pkg in p.defined_java_packages(): | 3092 for pkg in p.defined_java_packages(): |
3065 if not pkg.startswith(p.name): | 3093 if not pkg.startswith(p.name): |
3066 abort('package in {0} does not have prefix matching project name: {1}'.format(p, pkg)) | 3094 abort('package in {0} does not have prefix matching project name: {1}'.format(p, pkg)) |
3067 | 3095 |
3541 | 3569 |
3542 generate_eclipse_workingsets() | 3570 generate_eclipse_workingsets() |
3543 | 3571 |
3544 def _check_ide_timestamp(suite, configZip, ide): | 3572 def _check_ide_timestamp(suite, configZip, ide): |
3545 """return True if and only if the projects file, eclipse-settings files, and mx itself are all older than configZip""" | 3573 """return True if and only if the projects file, eclipse-settings files, and mx itself are all older than configZip""" |
3546 projectsFile = join(suite.mxDir, 'projects') | 3574 projectsPyFiles = [join(suite.mxDir, e) for e in os.listdir(suite.mxDir) if e.startswith('projects') and e.endswith('.py')] |
3547 if configZip.isOlderThan(projectsFile): | 3575 if configZip.isOlderThan(projectsPyFiles): |
3548 return False | 3576 return False |
3549 # Assume that any mx change might imply changes to the generated IDE files | 3577 # Assume that any mx change might imply changes to the generated IDE files |
3550 if configZip.isOlderThan(__file__): | 3578 if configZip.isOlderThan(__file__): |
3551 return False | 3579 return False |
3552 | 3580 |
5085 run([javapExe, '-private', '-verbose', '-classpath', classpath()] + selection) | 5113 run([javapExe, '-private', '-verbose', '-classpath', classpath()] + selection) |
5086 | 5114 |
5087 def show_projects(args): | 5115 def show_projects(args): |
5088 """show all loaded projects""" | 5116 """show all loaded projects""" |
5089 for s in suites(): | 5117 for s in suites(): |
5090 projectsFile = join(s.mxDir, 'projects') | 5118 if len(s.projects) != 0: |
5091 if exists(projectsFile): | 5119 log(join(s.mxDir, 'projects*.py')) |
5092 log(projectsFile) | |
5093 for p in s.projects: | 5120 for p in s.projects: |
5094 log('\t' + p.name) | 5121 log('\t' + p.name) |
5095 | 5122 |
5096 def ask_yes_no(question, default=None): | 5123 def ask_yes_no(question, default=None): |
5097 """""" | 5124 """""" |
5175 """ | 5202 """ |
5176 if os.path.isdir(d): | 5203 if os.path.isdir(d): |
5177 for f in os.listdir(d): | 5204 for f in os.listdir(d): |
5178 if (mxDirName == None and (f == 'mx' or fnmatch.fnmatch(f, 'mx.*'))) or f == mxDirName: | 5205 if (mxDirName == None and (f == 'mx' or fnmatch.fnmatch(f, 'mx.*'))) or f == mxDirName: |
5179 mxDir = join(d, f) | 5206 mxDir = join(d, f) |
5180 if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')): | 5207 if exists(mxDir) and isdir(mxDir) and (exists(join(mxDir, 'projects.py')) or exists(join(mxDir, 'projects'))): |
5181 return mxDir | 5208 return mxDir |
5182 | 5209 |
5183 def _check_primary_suite(): | 5210 def _check_primary_suite(): |
5184 if _primary_suite is None: | 5211 if _primary_suite is None: |
5185 abort('no primary suite found') | 5212 abort('no primary suite found') |