From 3318e08496e30da2adbc777751488d4eee731ca1 Mon Sep 17 00:00:00 2001 From: panwentao Date: Fri, 17 Nov 2023 10:02:21 +0800 Subject: [PATCH 1/3] fix_env: Add environment preparation function * Add environment preparation function Signed-off-by: panwentao --- src/oebuild/app/conf/plugins.yaml | 3 + src/oebuild/app/plugins/fix_env/fix_env.py | 166 +++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 src/oebuild/app/plugins/fix_env/fix_env.py diff --git a/src/oebuild/app/conf/plugins.yaml b/src/oebuild/app/conf/plugins.yaml index 64c0311..7fbf92d 100644 --- a/src/oebuild/app/conf/plugins.yaml +++ b/src/oebuild/app/conf/plugins.yaml @@ -20,3 +20,6 @@ plugins: - name: runqemu class: RunQemu path: plugins/run_qemu/run_qemu.py +- name: fix_env + class: FixEnv + path: plugins/fix_env/fix_env.py diff --git a/src/oebuild/app/plugins/fix_env/fix_env.py b/src/oebuild/app/plugins/fix_env/fix_env.py new file mode 100644 index 0000000..4a6e6e4 --- /dev/null +++ b/src/oebuild/app/plugins/fix_env/fix_env.py @@ -0,0 +1,166 @@ +''' +Copyright (c) 2023 openEuler Embedded +oebuild is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +''' + +import argparse +import datetime +import fcntl + +import pty +import re +import struct +import sys +import termios +import subprocess +import textwrap +import logging + +from oebuild.command import OebuildCommand +from oebuild.util import * +from oebuild.configure import Configure + +logger = logging.getLogger() + + +class FixEnv(OebuildCommand): + + def __init__(self): + self.configure = Configure() + super().__init__( + 'fixenv', + 'preparation of the environment before compilation', + description=textwrap.dedent('''\ + This is an environment preparation method. You can either pass in the folder path after the + execution of the SDK, or the corresponding SDK environment preparation has been carried out + on the SDK path. This environment preparation will not affect your current environment. +''' + )) + + def do_add_parser(self, parser_adder) -> argparse.ArgumentParser: + parser = self._parser( + parser_adder, + usage=''' + %(prog)s [-d directory] [-f file] +''') + + parser.add_argument('-d', '--directory', dest='directory', + help=''' + this param is build directory + ''' + ) + + parser.add_argument('-f', '--file', dest='file', + help=''' + this param is build file + ''' + ) + + return parser + + def do_run(self, args: argparse.Namespace, unknown=None): + # perpare parse help command + if self.pre_parse_help(args, unknown): + return + + args = args.parse_args(unknown) + # Check if the file path exists + if args.directory and os.path.exists(args.directory): + return self.execute_setup_directory(args.directory) + + elif args.file and os.path.exists(args.file): + return self.execute_sdk_file(args.file) + print('Please provide the correct folder path') + + def execute_setup_directory(self, setup_file_path): + """ + Prepare the environment using the parsed SDK folder provided + Args: + setup_file_path: Resolve completed sdk folder path + + Returns: results of execution + + """ + file_list = str(os.listdir(setup_file_path)) + # number of setup_file + setup_num = len(re.findall('environment-setup', file_list)) + # Determine the number of setup_files + if setup_num == 1: + try: + # Determine if the path ends with / + setup_file_path = setup_file_path if setup_file_path.endswith('/') else setup_file_path + '/' + # Convert relative path to absolute path + file_path = setup_file_path + re.search('environment-setup.*?(?=\')', file_list).group() + absolute_file_path = os.path.abspath(file_path) + # Splice Execution Command + shell_command = '. ' + absolute_file_path + + print(shell_command) + print('setup_file matching successful') + # Obtain the current terminal height and length + terminal_info = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, "1234") + rows_and_cloumns = struct.unpack('HH', terminal_info) + rows_command = f'stty rows {rows_and_cloumns[0]} columns {rows_and_cloumns[1]}' + subprocess.check_output(f'''sed -i '$a\{rows_command}' ~/.bashrc''', shell=True) + # Add the command to execute the setup file in the .bashrc file in the working directory + subprocess.check_output(f'''sed -i '$a\{shell_command}' ~/.bashrc''', shell=True) + # Replace Console Prompt + subprocess.check_output('''sed -i 's/\$ />>>>> /g' ~/.bashrc''', shell=True) + # Add prompt words + separator = "====================================================" + prompt_one = "Your environment is ready" + prompt_two = "Please proceed with the subsequent operations here" + wrap = '\\n###!###\\n' + prompt_words = separator + wrap + prompt_one + wrap + prompt_two + wrap + separator + subprocess.check_output(f'''sed -i '$a\echo "{prompt_words}"' ~/.bashrc''', shell=True) + pty.spawn("/bin/bash") + # Add delete command + delete_shell_command = shell_command.replace('/', '\/') + subprocess.check_output(f'''sed -i '/{rows_command}/d' ~/.bashrc''', shell=True) + subprocess.check_output(f'''sed -i '/{delete_shell_command}/d' ~/.bashrc''', shell=True) + # delete Console Prompt + subprocess.check_output('''sed -i 's/>>>>> /\$ /g' ~/.bashrc''', shell=True) + # delete prompt words + delete_prompt = f""" + sed -i 's/echo \"{separator}\|{prompt_one}\|{prompt_two}\|###!###\|{separator}\"//g' ~/.bashrc + """ + subprocess.check_output(f'''{delete_prompt}''', shell=True) + except Exception as c_e: + print(c_e) + print('Please provide the correct folder path') + logger.error(c_e) + return False + return True + elif setup_num == 0: + print('not setup_file, please check your directory') + return False + else: + print('Illegal path, only one environment setup file allowed') + return False + + def execute_sdk_file(self, sdk_file): + """ + Execute the SDK file, produce the setup folder, and then execute the corresponding method for the setup file + Args: + sdk_file: SDK file path + + Returns: results of execution + + """ + setup_file_path = 'sdk_info_' + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + try: + execte_sdk = subprocess.check_output(f'sh {sdk_file} -d {setup_file_path} -y', shell=True) + print(execte_sdk.decode()) + self.execute_setup_directory(os.getcwd() + '/' + setup_file_path) + except Exception as c_e: + print(c_e) + logger.error(c_e) + print('Please provide the correct folder path') + -- Gitee From 810421b6bb95256b73f182ecadc3c53642e8c430 Mon Sep 17 00:00:00 2001 From: panwentao Date: Fri, 17 Nov 2023 10:07:12 +0800 Subject: [PATCH 2/3] README: Add environment preparation function document * Add environment preparation function document Signed-off-by: panwentao --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 05dfb7e..80d1236 100644 --- a/README.md +++ b/README.md @@ -286,6 +286,15 @@ oebuild bitbake -h 由于oebuild二进制包存放在gitee仓库中,因此oebuild在升级时会先克隆最新的二进制仓到用户根目录,并以一个随机文件名命名,然后执行`sudo pip install `来完成升级,在这之中会要求用户输入root密码,在完成升级后会自动删除oebuild二进制包 +##### oebuild fix_env +``` +oebuild fix_env [-d setup_file_directory] [-f sdk_file_path] +``` +setup_file_directory: 表示已经解压完成的对应sdk产生的setup文件夹。此文件夹中有且只能有一个setup文件 + +sdk_file_path: 对应sdk文件路径,需要指定到sdk文件名。会在当前工作目录下产生一个sdk_info_当前时间戳的文件夹, +用于存放对应的setup_file等文件。 + ##### oebuild runqemu qemu 仿真命令,通过该命令可以在本地实现qemu仿真,该功能运行依赖qemuboot.conf,如果用户不指定或创建,oebuild会根据相关参数自动创建,该文件中记录有qemu启动相关参数,用户可以手动进行修改,如果在当下目录中有多个qemuboot.conf,则会给出选择交互由用户进行选择 -- Gitee From a1542986c1b31b076958a3d4e8b06cc6c3b637df Mon Sep 17 00:00:00 2001 From: panwentao Date: Tue, 21 Nov 2023 15:57:57 +0800 Subject: [PATCH 3/3] README: Add environmental management features * Add environmental management features Signed-off-by: panwentao --- src/oebuild/app/plugins/fix_env/fix_env.py | 174 +++++++++++++++++++-- 1 file changed, 163 insertions(+), 11 deletions(-) diff --git a/src/oebuild/app/plugins/fix_env/fix_env.py b/src/oebuild/app/plugins/fix_env/fix_env.py index 4a6e6e4..2255428 100644 --- a/src/oebuild/app/plugins/fix_env/fix_env.py +++ b/src/oebuild/app/plugins/fix_env/fix_env.py @@ -11,7 +11,6 @@ See the Mulan PSL v2 for more details. ''' import argparse -import datetime import fcntl import pty @@ -23,6 +22,9 @@ import subprocess import textwrap import logging +import yaml + +from oebuild import util from oebuild.command import OebuildCommand from oebuild.util import * from oebuild.configure import Configure @@ -34,6 +36,8 @@ class FixEnv(OebuildCommand): def __init__(self): self.configure = Configure() + self.oebuild_env_path = os.path.expanduser('~') + '/.local/oebuild_env/' + self.oebuild_env_yaml_path = pathlib.Path(os.path.join(self.oebuild_env_path, 'oebuild_env.yaml')) super().__init__( 'fixenv', 'preparation of the environment before compilation', @@ -48,7 +52,7 @@ class FixEnv(OebuildCommand): parser = self._parser( parser_adder, usage=''' - %(prog)s [-d directory] [-f file] + %(prog)s [-d directory] [-f file] [-n env_name] [-a env_name] [-rm env_name] [-l] ''') parser.add_argument('-d', '--directory', dest='directory', @@ -63,6 +67,30 @@ class FixEnv(OebuildCommand): ''' ) + parser.add_argument('-n', '--env_name', dest='env_name', + help=''' + this param is env_name + ''' + ) + + parser.add_argument('-a', '--activation', dest='activation', + help=''' + this param is activation env_name + ''' + ) + + parser.add_argument('-l', '--view_env', action='store_true', + help=''' + this param is view environment + ''' + ) + + parser.add_argument('-rm', '--rm_env_name', dest='rm_env_name', + help=''' + this param is delete environment + ''' + ) + return parser def do_run(self, args: argparse.Namespace, unknown=None): @@ -72,11 +100,33 @@ class FixEnv(OebuildCommand): args = args.parse_args(unknown) # Check if the file path exists - if args.directory and os.path.exists(args.directory): + if args.directory and os.path.isdir(args.directory): return self.execute_setup_directory(args.directory) + # Creating an environment elif args.file and os.path.exists(args.file): - return self.execute_sdk_file(args.file) + sdk_name = args.env_name if args.env_name else args.file.split('/')[-1].replace('.sh', '') + setup_file_path = self.oebuild_env_path + sdk_name + self.create_or_update_env_yaml(sdk_name, setup_file_path) + return self.execute_sdk_file(args.file, setup_file_path) + + # Activate Environment + if args.activation: + return self.activate_environment(args.activation) + + # view environment + if args.view_env: + env_dict = util.read_yaml(self.oebuild_env_yaml_path) + if env_dict and 'env_config' in env_dict: + self.view_environment(None, env_dict) + else: + print('No environment has been created yet') + return + + # delete environment + if args.rm_env_name: + return self.delete_environment(args.rm_env_name) + print('Please provide the correct folder path') def execute_setup_directory(self, setup_file_path): @@ -145,22 +195,124 @@ class FixEnv(OebuildCommand): print('Illegal path, only one environment setup file allowed') return False - def execute_sdk_file(self, sdk_file): + def execute_sdk_file(self, sdk_file, setup_file_path): """ Execute the SDK file, produce the setup folder, and then execute the corresponding method for the setup file Args: sdk_file: SDK file path + setup_file_path: setup file path Returns: results of execution """ - setup_file_path = 'sdk_info_' + datetime.datetime.now().strftime('%Y%m%d%H%M%S') try: - execte_sdk = subprocess.check_output(f'sh {sdk_file} -d {setup_file_path} -y', shell=True) - print(execte_sdk.decode()) - self.execute_setup_directory(os.getcwd() + '/' + setup_file_path) + if os.path.isdir(setup_file_path): + print(f'The setup file folder already exists.path is {setup_file_path}') + else: + subprocess.check_output(f'sh {sdk_file} -d {setup_file_path} -y', shell=True) + except Exception as c_e: - print(c_e) - logger.error(c_e) print('Please provide the correct folder path') + logger.error(c_e) + + def create_or_update_env_yaml(self, env_name, setup_file_path): + """ + + Args: + env_name: + setup_file_path: + + Returns: + + """ + env_dict = util.read_yaml(self.oebuild_env_yaml_path) + if env_dict and 'env_config' in env_dict: + env_list = self.input_or_update_dict(env_name, setup_file_path, env_dict['env_config']) + env_dict['env_config'] = env_list + util.write_yaml(self.oebuild_env_yaml_path, env_dict) + return + + env_dict = {'env_config': [{'env_name': env_name, 'env_value': setup_file_path}]} + util.write_yaml(self.oebuild_env_yaml_path, env_dict) + + def input_or_update_dict(self, env_name, env_value, env_list): + """ + Modify or insert environmental data + Args: + env_name: Environment Name + env_value: Setup file file path + env_list: Environment + + Returns: new Environment + + """ + insert_flag = True + for env_data in env_list: + if 'env_name' not in env_data: + print('env_name not exits') + return + if env_data['env_name'] == env_name: + while True: + user_input = input( + "Do you want to overwrite the path of the original environment configuration(Y/N)") + if user_input.lower() == 'y': + env_data['env_value'] = env_value + break + elif user_input.lower() == 'n': + return [] + insert_flag = False + if insert_flag: + env_list.append({'env_name': env_name, 'env_value': env_value}) + return env_list + def activate_environment(self, env_name): + env_dict = util.read_yaml(self.oebuild_env_yaml_path) + if env_dict and 'env_config' in env_dict: + setup_file_path = self.view_environment(env_name, env_dict) + if setup_file_path: + self.execute_setup_directory(setup_file_path) + else: + print('The environment does not exist') + return + print('No environment has been created yet') + + def view_environment(self, env_name, env_dict): + """ + View the environment, if env_ If name exists, it is necessary to find the corresponding + environment's setup file + Args: + env_name: environment name + env_dict: environment yaml + Returns: + + """ + for env_data in env_dict['env_config']: + if env_name and env_data['env_name'] == env_name: + return env_data['env_value'] + print(env_data['env_name']) + + return + + def delete_environment(self, env_name): + """ + delete your environment + Args: + env_name: The environment you want to delete + + Returns: + + """ + env_dict = util.read_yaml(self.oebuild_env_yaml_path) + if env_dict and 'env_config' in env_dict: + env_list = [] + for env_data in env_dict['env_config']: + if env_data['env_name'] != env_name: + env_list.append(env_data) + if len(env_list) == len(env_dict['env_config']): + print('The environment does not exist, please check the input') + return + else: + env_dict['env_config'] = env_list + util.write_yaml(self.oebuild_env_yaml_path, env_dict) + print('Successfully deleted') + return -- Gitee