| #!/usr/bin/env python3 |
| # -*- coding: utf-8 -*- |
| # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Generate board-specific scripts for Go compiler testing.""" |
| |
| from __future__ import print_function |
| |
| import argparse |
| import getpass |
| import os |
| import sys |
| |
| from cros_utils import command_executer |
| |
| SUCCESS = 0 |
| DEBUG = False |
| |
| ARCH_DATA = {'x86_64': 'amd64', 'arm32': 'arm', 'arm64': 'arm64'} |
| |
| CROS_TOOLCHAIN_DATA = { |
| 'x86_64': 'x86_64-cros-linux-gnu', |
| 'arm32': 'armv7a-cros-linux-gnueabihf', |
| 'arm64': 'aarch64-cros-linux-gnu' |
| } |
| |
| GLIBC_DATA = {'x86_64': 'glibc', 'arm32': 'glibc32', 'arm64': 'glibc'} |
| |
| CONFIG_TEMPLATE = """ |
| Host %s |
| HostName %s |
| User root |
| UserKnownHostsFile /dev/null |
| BatchMode yes |
| CheckHostIP no |
| StrictHostKeyChecking no |
| IdentityFile %%d/.ssh/testing_rsa |
| """ |
| |
| BASE_TEMPLATE = """#!/bin/bash |
| |
| # Invoke the Go cross compiler for %s. |
| # Uses ../go_target to add PIE flags. |
| # |
| # This is just an example for an %s board. |
| |
| GOOS="linux" GOARCH="%s" CGO_ENABLED="1" \\ |
| GOROOT="/usr/lib/go/%s" \\ |
| CC="%s-clang" \\ |
| CXX="%s-clang++" \\ |
| exec go_target "$@" |
| """ |
| |
| EXEC_TEMPLATE = """#!/bin/bash |
| |
| # Copy and remotely execute a binary on the %s device. |
| # |
| # For this to work, the corresponding entry must exist in |
| # ~/.ssh/config and the device must already be setup for |
| # password-less authentication. See setup instructions at |
| # http://go/chromeos-toolchain-team/go-toolchain |
| |
| GOOS="linux" GOARCH="%s" \\ |
| GOLOADER="/tmp/%s/ld.so" \\ |
| exec go_target_exec %s "$@" |
| """ |
| |
| |
| def log(msg): |
| |
| if DEBUG: |
| print(msg) |
| |
| |
| def WriteFile(file_content, file_name): |
| with open(file_name, 'w', encoding='utf-8') as out_file: |
| out_file.write(file_content) |
| |
| |
| def GenerateGoHelperScripts(ce, arm_board, x86_board, chromeos_root): |
| keys = ['x86_64', 'arm32', 'arm64'] |
| names = { |
| 'x86_64': x86_board, |
| 'arm64': arm_board, |
| 'arm32': ('%s32' % arm_board) |
| } |
| |
| toolchain_dir = os.path.join(chromeos_root, 'src', 'third_party', |
| 'toolchain-utils', 'go', 'chromeos') |
| for k in keys: |
| name = names[k] |
| arch = ARCH_DATA[k] |
| toolchain = CROS_TOOLCHAIN_DATA[k] |
| glibc = GLIBC_DATA[k] |
| |
| base_file = os.path.join(toolchain_dir, ('go_%s' % name)) |
| base_file_content = BASE_TEMPLATE % (name, arch, arch, toolchain, toolchain, |
| toolchain) |
| WriteFile(base_file_content, base_file) |
| cmd = 'chmod 755 %s' % base_file |
| ce.RunCommand(cmd) |
| |
| exec_file = os.path.join(toolchain_dir, ('go_%s_exec' % name)) |
| exec_file_content = EXEC_TEMPLATE % (name, arch, glibc, name) |
| WriteFile(exec_file_content, exec_file) |
| cmd = 'chmod 755 %s' % exec_file |
| ce.RunCommand(cmd) |
| |
| return 0 |
| |
| |
| def UpdateChrootSshConfig(ce, arm_board, arm_dut, x86_board, x86_dut, |
| chromeos_root): |
| log('Entering UpdateChrootSshConfig') |
| # Copy testing_rsa to .ssh and set file protections properly. |
| user = getpass.getuser() |
| ssh_dir = os.path.join(chromeos_root, 'chroot', 'home', user, '.ssh') |
| dest_file = os.path.join(ssh_dir, 'testing_rsa') |
| src_file = os.path.join(chromeos_root, 'src', 'scripts', |
| 'mod_for_test_scripts', 'testing_rsa') |
| if not os.path.exists(dest_file): |
| if os.path.exists(src_file): |
| cmd = 'cp %s %s' % (src_file, dest_file) |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print('Error executing "%s". Exiting now...' % cmd) |
| sys.exit(1) |
| cmd = 'chmod 600 %s' % dest_file |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print('Error executing %s; may need to re-run this manually.' % cmd) |
| else: |
| print('Cannot find %s; you will need to update testing_rsa by hand.' % |
| src_file) |
| else: |
| log('testing_rsa exists already.') |
| |
| # Save ~/.ssh/config file, if not already done. |
| config_file = os.path.expanduser('~/.ssh/config') |
| saved_config_file = os.path.join( |
| os.path.expanduser('~/.ssh'), 'config.save.go-scripts') |
| if not os.path.exists(saved_config_file): |
| cmd = 'cp %s %s' % (config_file, saved_config_file) |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print('Error making save copy of ~/.ssh/config. Exiting...') |
| sys.exit(1) |
| |
| # Update ~/.ssh/config file |
| log('Reading ssh config file') |
| with open(config_file, 'r') as input_file: |
| config_lines = input_file.read() |
| |
| x86_host_config = CONFIG_TEMPLATE % (x86_board, x86_dut) |
| arm_names = '%s %s32' % (arm_board, arm_board) |
| arm_host_config = CONFIG_TEMPLATE % (arm_names, arm_dut) |
| |
| config_lines += x86_host_config |
| config_lines += arm_host_config |
| |
| log('Writing ~/.ssh/config') |
| WriteFile(config_lines, config_file) |
| |
| return 0 |
| |
| |
| def CleanUp(ce, x86_board, arm_board, chromeos_root): |
| # Find and remove go helper scripts |
| keys = ['x86_64', 'arm32', 'arm64'] |
| names = { |
| 'x86_64': x86_board, |
| 'arm64': arm_board, |
| 'arm32': ('%s32' % arm_board) |
| } |
| |
| toolchain_dir = os.path.join(chromeos_root, 'src', 'third_party', |
| 'toolchain-utils', 'go', 'chromeos') |
| for k in keys: |
| name = names[k] |
| base_file = os.path.join(toolchain_dir, ('go_%s' % name)) |
| exec_file = os.path.join(toolchain_dir, ('go_%s_exec' % name)) |
| cmd = ('rm -f %s; rm -f %s' % (base_file, exec_file)) |
| ce.RunCommand(cmd) |
| |
| # Restore saved config_file |
| config_file = os.path.expanduser('~/.ssh/config') |
| saved_config_file = os.path.join( |
| os.path.expanduser('~/.ssh'), 'config.save.go-scripts') |
| if not os.path.exists(saved_config_file): |
| print('Could not find file: %s; unable to restore ~/.ssh/config .' % |
| saved_config_file) |
| else: |
| cmd = 'mv %s %s' % (saved_config_file, config_file) |
| ce.RunCommand(cmd) |
| |
| return 0 |
| |
| |
| def Main(argv): |
| # pylint: disable=global-statement |
| global DEBUG |
| |
| parser = argparse.ArgumentParser() |
| parser.add_argument('-a', '--arm64_board', dest='arm_board', required=True) |
| parser.add_argument( |
| '-b', '--x86_64_board', dest='x86_64_board', required=True) |
| parser.add_argument( |
| '-c', '--chromeos_root', dest='chromeos_root', required=True) |
| parser.add_argument('-x', '--x86_64_dut', dest='x86_64_dut', required=True) |
| parser.add_argument('-y', '--arm64_dut', dest='arm_dut', required=True) |
| parser.add_argument( |
| '-z', '--cleanup', dest='cleanup', default=False, action='store_true') |
| parser.add_argument( |
| '-v', '--verbose', dest='verbose', default=False, action='store_true') |
| |
| options = parser.parse_args(argv[1:]) |
| |
| if options.verbose: |
| DEBUG = True |
| |
| if not os.path.exists(options.chromeos_root): |
| print('Invalid ChromeOS Root: %s' % options.chromeos_root) |
| |
| ce = command_executer.GetCommandExecuter() |
| all_good = True |
| for m in (options.x86_64_dut, options.arm_dut): |
| cmd = 'ping -c 3 %s > /dev/null' % m |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print('Machine %s is currently not responding to ping.' % m) |
| all_good = False |
| |
| if not all_good: |
| return 1 |
| |
| if not options.cleanup: |
| UpdateChrootSshConfig(ce, options.arm_board, options.arm_dut, |
| options.x86_64_board, options.x86_64_dut, |
| options.chromeos_root) |
| GenerateGoHelperScripts(ce, options.arm_board, options.x86_64_board, |
| options.chromeos_root) |
| else: |
| CleanUp(ce, options.x86_64_board, options.arm_board, options.chromeos_root) |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| val = Main(sys.argv) |
| sys.exit(val) |