1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2025 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import os 17import subprocess 18import argparse 19import shutil 20 21 22def check_uapi_dir_exists(uapi_dir): 23 """Check if the UAPI directory exists""" 24 return os.path.isdir(uapi_dir) 25 26 27def make_uapi_headers(kernel_dir, target_cpu, output_dir): 28 """Generate UAPI header file""" 29 uapi_dir = os.path.join(output_dir, "usr/include") 30 31 try: 32 # Clean up and generate header files 33 subprocess.run(['rm', '-rf', str(uapi_dir)], check=True) 34 cmd = [ 'make', 35 '-C', 36 str(kernel_dir), 37 '-sj', 38 'headers', 39 'O=%s' % output_dir, 40 'ARCH=%s' % target_cpu ] 41 subprocess.run(cmd, check=True) 42 43 # Special handling of individual files 44 ashmem_src = os.path.join(kernel_dir, "drivers/staging/android/uapi/ashmem.h") 45 ashmem_dst = os.path.join(uapi_dir, "linux/ashmem.h") 46 if os.path.exists(ashmem_src): 47 subprocess.run(['cp', '-f', str(ashmem_src), str(ashmem_dst)], check=True) 48 49 input_h = os.path.join(uapi_dir, "linux/input.h") 50 if os.path.exists(input_h): 51 input_cmd = [ 'sed', 52 '-i', 53 r'/#define _INPUT_H/i#define _UAPI_INPUT_H', 54 str(input_h) ] 55 subprocess.run(input_cmd, check=True) 56 57 socket_h = os.path.join(uapi_dir, "linux/socket.h") 58 if os.path.exists(socket_h): 59 sockaddr_cmd = [ 'sed', 60 '-i', 61 r'/struct __kernel_sockaddr_storage/i#define sockaddr_storage __kernel_sockaddr_storage', 62 str(socket_h) ] 63 subprocess.run(sockaddr_cmd, check=True) 64 65 return True 66 except subprocess.CalledProcessError as e: 67 print("Failed to make UAPI headers: {e}") 68 return False 69 70 71def list_uapi_files(uapi_dir, exclude_pattern): 72 """List UAPI files and filter them""" 73 try: 74 list_files = subprocess.run(['ls', str(uapi_dir)], capture_output=True, text=True, check=True) 75 result = subprocess.run(['grep', '-vE', str(exclude_pattern)], 76 input=list_files.stdout, capture_output=True, text=True, check=True) 77 return result.stdout.strip().split('\n') 78 except subprocess.CalledProcessError as e: 79 print(f"Failed to list UAPI files: {e}") 80 return [] 81 82 83def copy_filtered_uapi_dirs(uapi_dir, final_uapi_dir, output_uapi): 84 copied_files = [] 85 try: 86 os.makedirs(output_uapi, exist_ok=True) 87 88 for item in uapi_dir: 89 src_path = os.path.join(final_uapi_dir, item) 90 dst_path = os.path.join(output_uapi, item) 91 92 if os.path.isdir(src_path): 93 for root, dirs, files in os.walk(src_path): 94 for file in files: 95 src_file = os.path.join(root, file) 96 rel_path = os.path.relpath(src_file, final_uapi_dir) 97 dst_file = os.path.join(output_uapi, rel_path) 98 99 os.makedirs(os.path.dirname(dst_file), exist_ok=True) 100 shutil.copy2(src_file, dst_file) 101 copied_files.append(dst_file) 102 print(f"Copied: {rel_path} -> {dst_file}") 103 else: 104 # Processing individual files 105 os.makedirs(os.path.dirname(dst_path), exist_ok=True) 106 shutil.copy2(src_path, dst_path) 107 copied_files.append(dst_path) 108 print("Copied: {item} -> {dst_path}") 109 except Exception as e: 110 print(f"Error copying: {e}") 111 112 return copied_files 113 114 115def main(): 116 parser = argparse.ArgumentParser() 117 parser.add_argument("--musl-uapi-dir", required=True) 118 parser.add_argument("--musl-linux-kernel-dir", required=True) 119 parser.add_argument("--target-cpu", required=True) 120 parser.add_argument("--uapi-file-list", required=True) 121 parser.add_argument("--output-uapi", required=True) 122 args = parser.parse_args() 123 124 # Determine the source of UAPI 125 if not check_uapi_dir_exists(args.musl_uapi_dir): 126 print("UAPI directory not found, generating from kernel...") 127 kernel_out_dir = os.path.join(args.musl_linux_kernel_dir, "make_output") 128 success = make_uapi_headers( 129 args.musl_linux_kernel_dir, 130 args.target_cpu, 131 kernel_out_dir 132 ) 133 if not success: 134 exit(1) 135 uapi_from = "make" 136 final_uapi_dir = os.path.join(kernel_out_dir, "usr/include") 137 else: 138 print("Using existing UAPI directory") 139 uapi_from = "local" 140 final_uapi_dir = args.musl_uapi_dir 141 142 exclude_pattern = "^asm$|^scsi$" if uapi_from == "make" else "^asm-arm$|^asm-arm64$|^scsi$" 143 144 # List UAPI 145 uapi_files = list_uapi_files(final_uapi_dir, exclude_pattern) 146 147 copied_files = copy_filtered_uapi_dirs(uapi_files, final_uapi_dir, args.output_uapi) 148 149 # Write output file 150 with os.fdopen(os.open(args.uapi_file_list, os.O_WRONLY | os.O_CREAT, mode=0o640), 'w') as f: 151 f.write(f"UAPI_FROM:{uapi_from}\n") 152 f.write(f"UAPI_DIR:{final_uapi_dir}\n") 153 f.write("UAPI_FILES:\n") 154 f.write("\n".join(copied_files) + "\n") 155 156 157if __name__ == "__main__": 158 main()