def main(): parser = argparse.ArgumentParser( description= 'Removes references to `migrated_manifest` from BUILD.gn files') parser.add_argument('--root', help='Path to the directory to inspect', default=FUCHSIA_ROOT) args = parser.parse_args() build_files = [] for base, _, files in os.walk(args.root): for file in files: if file == 'BUILD.gn': build_files.append(os.path.join(base, file)) for build_path in build_files: # Number of currently open curly brackets while processing a target to # remove. # A lesser than or equal to 0 number means no target is currently being # erased. curly_bracket_depth = 0 modified = False for line in fileinput.FileInput(build_path, inplace=True): if '//build/unification/images/migrated_manifest.gni' in line: continue target_match = re.match('\s*migrated_manifest\(', line) if target_match: curly_bracket_depth = 1 modified = True continue if curly_bracket_depth > 0: curly_bracket_depth += line.count('{') - line.count('}') if curly_bracket_depth >= 0: # Keep erasing. continue sys.stdout.write(line) if modified: fx_format(build_path) return 0
def main(): parser = argparse.ArgumentParser( description='Moves a C/C++ library from //zircon to //sdk') parser.add_argument('--lib', help='Name of the library folder to migrate, e.g. ' 'ulib/foo or dev/lib/bar', action='append') args = parser.parse_args() if not args.lib: print('Need to specify at least one library.') return 1 # Check that the fuchsia.git tree is clean. if not is_tree_clean(): return 1 movable_libs = [] for lib in args.lib: # Verify that the library may be migrated at this time. library = Library(lib) if not os.path.exists(library.build_path): print('Could not locate library ' + lib + ', ignoring') continue # No kernel! if library.has_kernel: print('Some libraries are used in the kernel and may not be ' 'migrated at the moment, ignoring ' + lib) continue # Only libraries that have been exported to the GN build already! if library.has_unexported: print( 'Can only convert libraries already exported to the GN build,' ' ignoring ' + lib) continue # No SDK libraries for now. if library.has_sdk and library.has_static: print('Cannot convert static SDK libraries for now, ignoring ' + lib) continue # Gather build files with references to the library. for base, _, files in os.walk(FUCHSIA_ROOT): for file in files: if file != 'BUILD.gn': continue file_path = os.path.join(base, file) with open(file_path, 'r') as build_file: content = build_file.read() for name in [s.name for s in library.stats]: reference = '"//zircon/public/lib/' + name + '"' if reference in content: library.build_files.append(file_path) if not is_in_fuchsia_project(file_path): library.cross_project = True break movable_libs.append(library) if not movable_libs: print('Could not find any library to convert, aborting') return 1 solo_libs = [ l.name for l in movable_libs if l.cross_project or l.has_shared ] if solo_libs and len(movable_libs) > 1: print('These libraries may only be moved in a dedicated change: ' + ', '.join(solo_libs)) return 1 for library in movable_libs: # Rewrite the library's build file. import_added = False for line in fileinput.FileInput(library.build_path, inplace=True): # Remove references to libzircon. if '$zx/system/ulib/zircon' in line and not 'zircon-internal' in line: line = '' # Update references to libraries. line = line.replace('$zx/system/ulib', '//zircon/public/lib') line = line.replace('$zx/system/dev/lib', '//zircon/public/lib') # Update known configs. line = line.replace( '$zx_build/public/gn/config:static-libc++', '//build/config/fuchsia:static_cpp_standard_library') # Update references to Zircon in general. line = line.replace('$zx', '//zircon') # Update deps on libdriver. line = line.replace('//zircon/public/lib/driver', '//src/devices/lib/driver') # Remove header target specifier. line = line.replace('.headers', '') line = line.replace(':headers', '') sys.stdout.write(line) if not line.strip() and not import_added: import_added = True sys.stdout.write( '##########################################\n') sys.stdout.write( '# Though under //zircon, this build file #\n') sys.stdout.write( '# is meant to be used in the Fuchsia GN #\n') sys.stdout.write( '# build. #\n') sys.stdout.write( '# See fxb/36548. #\n') sys.stdout.write( '##########################################\n') sys.stdout.write('\n') sys.stdout.write( 'assert(!defined(zx) || zx != "/", "This file can only be used in the Fuchsia GN build.")\n' ) sys.stdout.write('\n') sys.stdout.write( 'import("//build/unification/zx_library.gni")\n') sys.stdout.write('\n') fx_format(library.build_path) # Edit references to the library. for file_path in library.build_files: for line in fileinput.FileInput(file_path, inplace=True): for name in [s.name for s in library.stats]: new_label = '"' + library.base_label if os.path.basename(new_label) != name: new_label = new_label + ':' + name new_label = new_label + '"' line = re.sub('"//zircon/public/lib/' + name + '"', new_label, line) sys.stdout.write(line) fx_format(file_path) # Remove references to the library in the unification scaffolding if # necessary. if library.has_shared: unification_path = os.path.join(FUCHSIA_ROOT, 'build', 'unification', 'images', 'BUILD.gn') def unification_replacer(line): for name in [s.name for s in library.stats]: if re.match('^\s*"' + name + '",$', line): # Remove the line. return '' replace_lines(unification_path, unification_replacer) # Generate an alias for the library under //zircon/public/lib if a soft # transition is necessary. if library.cross_project: alias_path = os.path.join(FUCHSIA_ROOT, 'build', 'unification', 'zircon_library_mappings.json') with open(alias_path, 'r') as alias_file: data = json.load(alias_file) for s in library.stats: data.append({ 'name': s.name, 'sdk': s.sdk_publishable, 'label': library.base_label + ":" + s.name, }) data = sorted(data, key=lambda item: item['name']) with open(alias_path, 'w') as alias_file: json.dump(data, alias_file, indent=2, sort_keys=True, separators=(',', ': ')) # Update references to the library if it belongs to any SDK. if library.has_sdk: sdk_path = os.path.join(FUCHSIA_ROOT, 'sdk', 'BUILD.gn') folder = os.path.basename(library.name) def sdk_replacer(line): for name in [s.name for s in library.stats]: if '"//zircon/public/lib/' + folder + ':' + name + '_sdk' + '"' in line: return line.replace('public/lib', 'system/ulib') replace_lines(sdk_path, sdk_replacer) fx_format(sdk_path) # Remove the reference in the ZN aggregation target. aggregation_path = os.path.join(FUCHSIA_ROOT, 'zircon', 'system', os.path.dirname(library.name), 'BUILD.gn') if os.path.exists(aggregation_path): folder = os.path.basename(library.name) def aggregation_replacer(line): for name in [s.name for s in library.stats]: if ('"' + folder + ':' + name + '"' in line or '"' + folder + '"' in line): return '' replace_lines(aggregation_path, aggregation_replacer) else: print('Warning: some references to ' + lib + ' might still exist ' 'in the ZN build, please remove them manually') # Create a commit. libs = sorted([l.name for l in movable_libs]) under_libs = [l.replace('/', '_') for l in libs] branch_name = 'lib-move-' + under_libs[0] lib_name = '//zircon/system/' + libs[0] if len(libs) > 1: branch_name += '-and-co' lib_name += ' and others' run_command(['git', 'checkout', '-b', branch_name, 'JIRI_HEAD']) run_command(['git', 'add', FUCHSIA_ROOT]) message = [ '[unification] Move ' + lib_name + ' to the GN build', '', 'Affected libraries:' ] + ['//zircon/system/' + l for l in libs] if any(l.has_shared for l in movable_libs): message += [ '', 'scripts/unification/verify_element_move.py --reference local/initial.json:', '', 'TODO PASTE VERIFICATION RESULT HERE', ] message += ['', 'Generated with ' + SCRIPT_LABEL, '', 'Bug: 36548'] fd, message_path = tempfile.mkstemp() with open(message_path, 'w') as message_file: message_file.write('\n'.join(message)) commit_command = ['git', 'commit', '-a', '-F', message_path] run_command(commit_command) os.close(fd) os.remove(message_path) if any(l.cross_project for l in movable_libs): print('*** Warning: multiple Git projects were affected by this move!') print('Run jiri status to view affected projects.') print('Staging procedure:') print( ' - use "jiri upload" to start the review process on the fuchsia.git change;' ) print( ' - prepare dependent CLs for each affected project and get them review;' ) print( ' - when the fuchsia.git change has rolled into GI, get the other CLs submitted;' ) print( ' - when these CLs have rolled into GI, prepare a change to remove the forwarding' ) print( ' targets under //build/unification/zircon_library_mappings.json' ) else: print( 'Change is ready, use "jiri upload" to start the review process.') return 0
def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( '--base', help='Path to the directory in which files will be fixed', required=True) args = parser.parse_args() # Fix manifest files. manifest_paths = [] for root, _, files in os.walk(args.base): for file in files: name, extension = os.path.splitext(file) if extension != '.cmx': continue file_path = os.path.join(root, file) with open(file_path, 'r') as manifest_file: contents = manifest_file.read() if '"bin/app"' not in contents: continue contents = contents.replace('"bin/app"', '"bin/' + name + '"') with open(file_path, 'w') as manifest_file: manifest_file.write(contents) manifest_paths.append(file_path) # Fix build files. build_changes = {} # file path --> list of affected binaries for root, _, files in os.walk(args.base): for file in files: if file != 'BUILD.gn': continue file_path = os.path.join(root, file) found_reference = False for line in fileinput.FileInput(file_path, inplace=True): match = re.match('^(\s*)binary = "([^"]+)"\s*$', line) if match: found_reference = True line = match.group( 1) + 'binaries = [{ name = "' + match.group(2) + '" }]' build_changes.setdefault(file_path, []).append(match.group(2)) sys.stdout.write(line) if found_reference: fx_format(file_path) # Cross-reference the two lists of modified files and attempt to identify # issues. print('-----------------------------') print('Updated %d component manifest files' % len(manifest_paths)) print( 'Updated %d references in %d build files' % ( sum([len(v) for v in build_changes.values()], 0), len(build_changes.keys()))) print('') # First off, build a list of manifest files we expect to see given the # changes made to build files. expected_manifest_paths = [] matched_manifest_paths = [] for build_file, binaries in sorted(build_changes.iteritems()): base_dir = os.path.dirname(build_file) for binary in binaries: manifest = os.path.join(base_dir, 'meta', binary + '.cmx') if manifest in manifest_paths: # We found a manifest exactly where we expected it: great! manifest_paths.remove(manifest) matched_manifest_paths.append(manifest) continue if '_' in binary: # Since '_' is technically not allowed in package URIs, some # manifest files are renamed by turning '_' into '-'. alternate_manifest = os.path.join( base_dir, 'meta', binary.replace('_', '-') + '.cmx') if alternate_manifest in manifest_paths: manifest_paths.remove(alternate_manifest) matched_manifest_paths.append(alternate_manifest) continue expected_manifest_paths.append(manifest) print('-----------------------------') print( 'After exact matches: %d references, %d manifest files unmatched' % (len(expected_manifest_paths), len(manifest_paths))) print('Matches:') for path in matched_manifest_paths: print(path) print('') # Second step is to look at manifests with the same file name as what we # would expect AND under the same directory. print('-----------------------------') print('Likely matches') for potential_path in list(expected_manifest_paths): base_dir = os.path.dirname(os.path.dirname(potential_path)) name = os.path.basename(potential_path) for path in list(manifest_paths): if os.path.commonprefix([ base_dir, path ]) == base_dir and os.path.basename(path) == name: expected_manifest_paths.remove(potential_path) manifest_paths.remove(path) print('[---] ' + potential_path) print('[+++] ' + path) break print('') print('-----------------------------') print( 'Leftovers: %d references, %d manifest files' % (len(expected_manifest_paths), len(manifest_paths))) combined = [(p, '---') for p in expected_manifest_paths] + [ (p, '+++') for p in manifest_paths ] for path, type in sorted(combined): print('[%s] %s' % (type, path)) return 0
def main(): parser = argparse.ArgumentParser( description='Moves a Banjo library from //zircon to //sdk') parser.add_argument('lib', help='Name of the library to migrate') args = parser.parse_args() lib = args.lib # Check that the fuchsia.git tree is clean. if not is_tree_clean(): return 1 sdk_base = os.path.join(FUCHSIA_ROOT, 'sdk', 'banjo') sdk_dir = os.path.join(sdk_base, lib) banjo_base = os.path.join(FUCHSIA_ROOT, 'zircon', 'system', 'banjo') source_dir = os.path.join(banjo_base, lib) # Move the sources. shutil.move(source_dir, sdk_base) # Edit the build file. is_dummy = not (lib.startswith('ddk.protocol') or lib.startswith('ddk.hw')) build_path = os.path.join(sdk_dir, 'BUILD.gn') for line in fileinput.FileInput(build_path, inplace=True): line = line.replace('$zx_build/public/gn/banjo.gni', '//build/banjo/banjo.gni') line = line.replace('banjo_library', 'banjo_dummy' if is_dummy else 'banjo') line = line.replace('public_deps', 'deps') line = line.replace('$zx/system/banjo', '//zircon/system/banjo') sys.stdout.write(line) fx_format(build_path) # Edit references to the library. for base, _, files in os.walk(FUCHSIA_ROOT): for file in files: if file != 'BUILD.gn': continue file_path = os.path.join(base, file) has_changes = False for original_line in fileinput.FileInput(file_path, inplace=True): # Make sure that only exact matches are replaced, as some # library names are prefix of other names. # Examples: # //zircon/s/b/ddk.foo.bar" --> "//sdk/b/foo.bar" # //zircon/s/b/ddk.foo.bar:boop" --> "//sdk/b/foo.bar:boop" line = re.sub('"(//zircon/system/banjo/' + lib + ')([:"])', '"//sdk/banjo/' + lib + '\\2', original_line) if line != original_line: has_changes = True sys.stdout.write(line) if has_changes: fx_format(file_path) for line in fileinput.FileInput(os.path.join(banjo_base, 'BUILD.gn'), inplace=True): if not '"' + lib + '"' in line: sys.stdout.write(line) # Create a commit. run_command(['git', 'checkout', '-b', 'banjo-move-' + lib, 'JIRI_HEAD']) run_command(['git', 'add', sdk_dir]) message = [ '[unification] Move ' + lib + ' to //sdk/banjo', '', 'Generated with: //scripts/unification/move_banjo_library.py ' + lib, '', 'Bug: 36540' ] commit_command = ['git', 'commit', '-a'] for line in message: commit_command += ['-m', line] run_command(commit_command) print('Change is ready, use "jiri upload" to start the review process.') return 0
def transform_build_file(build): # First pass: identify contents of the build file. binaries = [] has_test_binaries = False has_drivers = False binary_types = BINARY_TYPES.keys() unclear_types = ['library'] n_lines = 0 with open(build, 'r') as build_file: lines = build_file.readlines() n_lines = len(lines) for line in lines: match = re.match(r'\A([^\(]+)\("([^"]+)"\)', line) if match: type, name = match.groups() if type in binary_types: binaries.append(name) if type == Type.TEST: has_test_binaries = True if type == Type.DRIVER or type == Type.TEST_DRIVER: has_drivers = True if type in unclear_types: print('Warning: target ' + name + ' of type ' + type + ' ' 'needs to be manually converted.') # Second pass: rewrite contents to match GN build standards. imports_added = False for line in fileinput.FileInput(build, inplace=True): # Apply required edits. # Update target types. starting_type = '' for type in binary_types: new_type_line = line.replace(type, BINARY_TYPES[type]) if new_type_line != line: starting_type = type line = new_type_line break # Remove references to libzircon. if '$zx/system/ulib/zircon' in line and not 'zircon-internal' in line: line = '' # Update references to libraries. line = line.replace('$zx/system/ulib', '//zircon/public/lib') line = line.replace('$zx/system/dev/lib', '//zircon/public/lib') # Update references to Zircon in general. line = line.replace('$zx', '//zircon') # Update import for fuzzers. line = line.replace('//zircon/public/gn/fuzzer.gni', '//build/fuzzing/fuzzer.gni') # Update references to firmware. line = line.replace('//zircon/public/gn/firmware.gni', '//build/unification/firmware.gni') line = line.replace('$firmware_dir/', '') # Update deps on libdriver. line = line.replace('//zircon/public/lib/driver', '//src/devices/lib/driver') # Print the line, if any content is left. if line: sys.stdout.write(line) # Insert required imports at the start of the file. if not line.strip() and not imports_added: imports_added = True sys.stdout.write('##########################################\n') sys.stdout.write('# Though under //zircon, this build file #\n') sys.stdout.write('# is meant to be used in the Fuchsia GN #\n') sys.stdout.write('# build. #\n') sys.stdout.write('# See fxb/36139. #\n') sys.stdout.write('##########################################\n') sys.stdout.write('\n') sys.stdout.write( 'assert(!defined(zx) || zx != "/", "This file can only be used in the Fuchsia GN build.")\n' ) sys.stdout.write('\n') if has_drivers: sys.stdout.write( 'import("//build/config/fuchsia/rules.gni")\n') if has_test_binaries: sys.stdout.write('import("//build/test.gni")\n') sys.stdout.write( 'import("//build/unification/images/migrated_manifest.gni")\n') sys.stdout.write('\n') # Add extra parameters to tests. if starting_type == Type.TEST: sys.stdout.write( ' # Dependent manifests unfortunately cannot be marked as `testonly`.\n' ) sys.stdout.write( ' # TODO(44278): Remove when converting this file to proper GN build idioms.\n' ) sys.stdout.write(' if (is_fuchsia) {\n') sys.stdout.write(' testonly = false\n') sys.stdout.write(' }\n') if starting_type == Type.TEST_DRIVER: sys.stdout.write(' test = true\n') if starting_type in [Type.DRIVER, Type.TEST_DRIVER]: sys.stdout.write(' defines = [ "_ALL_SOURCE" ]\n') sys.stdout.write( ' configs += [ "//build/config/fuchsia:enable_zircon_asserts" ]\n' ) sys.stdout.write( ' configs -= [ "//build/config/fuchsia:no_cpp_standard_library" ]\n' ) sys.stdout.write( ' configs += [ "//build/config/fuchsia:static_cpp_standard_library" ]\n' ) if starting_type in Type.all(): sys.stdout.write(' if (is_fuchsia) {\n') sys.stdout.write( ' configs += [ "//build/unification/config:zircon-migrated" ]\n' ) sys.stdout.write(' }\n') if starting_type in [Type.EXECUTABLE, Type.TEST]: sys.stdout.write(' if (is_fuchsia) {\n') sys.stdout.write( ' fdio_config = [ "//build/config/fuchsia:fdio_config" ]\n') sys.stdout.write( ' if (configs + fdio_config - fdio_config != configs) {\n') sys.stdout.write(' configs -= fdio_config\n') sys.stdout.write(' }\n') sys.stdout.write(' }\n') # Third pass: add manifest targets at the end of the file. with open(build, 'a') as build_file: for binary in binaries: build_file.write('\n') build_file.write('migrated_manifest("' + binary + '-manifest") {\n') build_file.write(' deps = [\n') build_file.write(' ":' + binary + '",\n') build_file.write(' ]\n') build_file.write('}\n') # Format the file. fx_format(build) return 0
def main(): parser = argparse.ArgumentParser( description='Moves a C/C++ library from //zircon to //sdk') parser.add_argument('lib', help='Name of the library folder to migrate, e.g. ' 'ulib/foo or dev/lib/bar') args = parser.parse_args() # Check that the fuchsia.git tree is clean. if not is_tree_clean(): return 1 # Verify that the library may be migrated at this time. build_path = os.path.join(FUCHSIA_ROOT, 'zircon', 'system', args.lib, 'BUILD.gn') base_label = '//zircon/system/' + args.lib stats = get_library_stats(build_path) # No kernel! has_kernel = len([s for s in stats if s.kernel]) != 0 if has_kernel: print('Some libraries in the given folder are used in the kernel and ' 'may not be migrated at the moment') return 1 # Only source libraries! non_source_sdk = len([s for s in stats if s.sdk != Sdk.SOURCE]) != 0 if non_source_sdk: print('Can only convert libraries exported as "sources" for now') return 1 # Rewrite the library's build file. import_added = False for line in fileinput.FileInput(build_path, inplace=True): # Remove references to libzircon. if '$zx/system/ulib/zircon' in line and not 'zircon-internal' in line: line = '' # Update references to libraries. line = line.replace('$zx/system/ulib', '//zircon/public/lib') line = line.replace('$zx/system/dev/lib', '//zircon/public/lib') # Update known configs. line = line.replace( '$zx_build/public/gn/config:static-libc++', '//build/config/fuchsia:static_cpp_standard_library') # Update references to Zircon in general. line = line.replace('$zx', '//zircon') # Update deps on libdriver. line = line.replace('//zircon/public/lib/driver', '//src/devices/lib/driver') # Remove header target specifier. line = line.replace('.headers', '') line = line.replace(':headers', '') sys.stdout.write(line) if not line.strip() and not import_added: import_added = True sys.stdout.write('##########################################\n') sys.stdout.write('# Though under //zircon, this build file #\n') sys.stdout.write('# is meant to be used in the Fuchsia GN #\n') sys.stdout.write('# build. #\n') sys.stdout.write('# See fxb/36548. #\n') sys.stdout.write('##########################################\n') sys.stdout.write('\n') sys.stdout.write( 'assert(!defined(zx) || zx != "/", "This file can only be used in the Fuchsia GN build.")\n' ) sys.stdout.write('\n') sys.stdout.write('import("//build/unification/zx_library.gni")\n') sys.stdout.write('\n') fx_format(build_path) # Track whether fuchsia.git was the only affected project. multiple_projects_affected = False # Edit references to the library. for base, _, files in os.walk(FUCHSIA_ROOT): for file in files: if file != 'BUILD.gn': continue has_matches = False file_path = os.path.join(base, file) for line in fileinput.FileInput(file_path, inplace=True): for name in [s.name for s in stats]: new_label = '"' + base_label if os.path.basename(new_label) != name: new_label = new_label + ':' + name new_label = new_label + '"' line, count = re.subn('"//zircon/public/lib/' + name + '"', new_label, line) if count: has_matches = True sys.stdout.write(line) if has_matches: fx_format(file_path) if not is_in_fuchsia_project(file_path): multiple_projects_affected = True # Generate an alias for the library under //zircon/public/lib if a soft # transition is necessary. if multiple_projects_affected: alias_path = os.path.join(FUCHSIA_ROOT, 'build', 'unification', 'zircon_library_mappings.json') with open(alias_path, 'r') as alias_file: data = json.load(alias_file) for s in stats: data.append({ 'name': s.name, 'sdk': s.sdk_publishable, 'label': base_label + ":" + s.name, }) data = sorted(data, key=lambda item: item['name']) with open(alias_path, 'w') as alias_file: json.dump(data, alias_file, indent=2, sort_keys=True, separators=(',', ': ')) # Remove the reference in the ZN aggregation target. aggregation_path = os.path.join(FUCHSIA_ROOT, 'zircon', 'system', os.path.dirname(args.lib), 'BUILD.gn') folder = os.path.basename(args.lib) for line in fileinput.FileInput(aggregation_path, inplace=True): for s in stats: if (not '"' + folder + ':' + name + '"' in line and not '"' + folder + '"' in line): sys.stdout.write(line) # Create a commit. lib = args.lib.replace('/', '_') run_command(['git', 'checkout', '-b', 'lib-move-' + lib, 'JIRI_HEAD']) run_command(['git', 'add', FUCHSIA_ROOT]) message = [ '[unification] Move //zircon/system/' + args.lib + ' to the GN build', '', 'Generated with: ' + SCRIPT_LABEL + ' ' + args.lib, '', 'Bug: 36548' ] commit_command = ['git', 'commit', '-a'] for line in message: commit_command += ['-m', line] run_command(commit_command) if multiple_projects_affected: print('*** Warning: multiple Git projects were affected by this move!') print('Run jiri status to view affected projects.') print('Staging procedure:') print( ' - use "jiri upload" to start the review process on the fuchsia.git change;' ) print( ' - prepare dependent CLs for each affected project and get them review;' ) print( ' - when the fuchsia.git change has rolled into GI, get the other CLs submitted;' ) print( ' - when these CLs have rolled into GI, prepare a change to remove the forwarding' ) print( ' targets under //build/unification/zircon_library_mappings.json' ) else: print( 'Change is ready, use "jiri upload" to start the review process.') return 0
def main(): parser = argparse.ArgumentParser( description='Moves a FIDL library from //zircon to //sdk') parser.add_argument('lib', help='Name of the library to migrate') args = parser.parse_args() # Accept library names with dots or dashes. lib = args.lib.replace('-', '.') lib_with_dash = args.lib.replace('.', '-') # Check that the fuchsia.git tree is clean. if not is_tree_clean(): return 1 sdk_base = os.path.join(FUCHSIA_ROOT, 'sdk', 'fidl') sdk_dir = os.path.join(sdk_base, lib) fidl_base = os.path.join(FUCHSIA_ROOT, 'zircon', 'system', 'fidl') source_dir = os.path.join(fidl_base, lib_with_dash) # Move the sources. # The destination directory sometimes already exists. if not os.path.isdir(sdk_dir): os.mkdir(sdk_dir) for _, _, files in os.walk(source_dir): for file in files: shutil.move(os.path.join(source_dir, file), sdk_dir) dest_file = os.path.join(sdk_dir, file) fx_format(dest_file) break # Edit the build file in its new location. in_sdk = False build_path = os.path.join(sdk_dir, 'BUILD.gn') for line in fileinput.FileInput(build_path, inplace=True): if 'sdk = false' in line: continue if 'sdk = true' in line: in_sdk = True print(' sdk_category = "partner"') print(' api = "' + lib + '.api"') continue line = line.replace('$zx_build/public/gn/fidl.gni', '//build/fidl/fidl.gni') line = line.replace('fidl_library', 'fidl') line = line.replace(lib_with_dash, lib) line = line.replace('$zx/system/fidl', '//zircon/system/fidl') sys.stdout.write(line) fx_format(build_path) # Track whether fuchsia.git was the only affected project. multiple_projects_affected = False # Edit references to the library. for base, _, files in os.walk(FUCHSIA_ROOT): for file in files: if file != 'BUILD.gn': continue has_matches = False file_path = os.path.join(base, file) for line in fileinput.FileInput(file_path, inplace=True): match = re.search( '"//zircon/system/fidl/' + lib_with_dash + '(?::(?P<target>[^"]+))?"', line) if match: has_matches = True original_target = match.group('target') if original_target: if original_target == 'c': target = lib + '_c' elif original_target == 'c.headers': target = lib + '_c' elif original_target == 'llcpp': target = lib + '_llcpp' elif original_target == 'llcpp.headers': target = lib + '_llcpp' else: target = original_target.replace( lib_with_dash, lib) line = line.replace( '"//zircon/system/fidl/' + lib_with_dash + ':' + original_target + '"', '"//sdk/fidl/' + lib + ':' + target + '"') else: line = line.replace( '"//zircon/system/fidl/' + lib_with_dash + '"', '"//sdk/fidl/' + lib + '"') sys.stdout.write(line) if has_matches: # Format the file. fx_format(file_path) if not is_in_fuchsia_project(file_path): multiple_projects_affected = True if multiple_projects_affected: # Set up an alias in the old location. with open(os.path.join(source_dir, 'BUILD.gn'), 'w') as build_file: build_file.writelines([ '# Copyright 2020 The Fuchsia Authors. All rights reserved.\n', '# Use of this source code is governed by a BSD-style license that can be\n', '# found in the LICENSE file.\n', '\n', 'import("//build/unification/fidl_alias.gni")\n', '\n', 'fidl_alias("%s") {\n' % lib_with_dash, ' sdk_category = "partner"\n' if in_sdk else '\n', '}\n', ]) # Edit references to the library. # Only editing the ZN file listing all FIDL libraries. for line in fileinput.FileInput(os.path.join(fidl_base, 'BUILD.gn'), inplace=True): if not '"' + lib_with_dash + '"' in line: sys.stdout.write(line) # Create a commit. run_command(['git', 'checkout', '-b', 'fidl-move-' + lib, 'JIRI_HEAD']) run_command(['git', 'add', sdk_dir]) message = [ '[unification] Move ' + lib + ' to //sdk/fidl', '', 'Generated with: //scripts/unification/move_fidl_library.py ' + lib, '', 'Bug: 36547' ] commit_command = ['git', 'commit', '-a'] for line in message: commit_command += ['-m', line] run_command(commit_command) if multiple_projects_affected: print('*** Warning: multiple Git projects were affected by this move!') print('Run jiri status to view affected projects.') print('Staging procedure:') print( ' - use "jiri upload" to start the review process on the fuchsia.git change;' ) print( ' - prepare dependent CLs for each affected project and get them review;' ) print( ' - when the fuchsia.git change has rolled into GI, get the other CLs submitted;' ) print( ' - when these CLs have rolled into GI, prepare a change to remove the forwarding' ) print(' target under //zircon/system/fidl/' + lib_with_dash) else: print( 'Change is ready, use "jiri upload" to start the review process.') return 0