#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2020 The ChromiumOS Authors # 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.""" 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)