1# Copyright (c) 2021-2024 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14# Generator of arch-dependent values for cross-compiling 15# 16# The target platforms should be specified with `create_cross_values_target(arch_name toolchain)` function. 17# Basically, the function adds an `ExternalProject` with ${PANDA_ROOT} as a source, configures it with 18# the specified toolchain and generates a header with values based on `asm_defines.def`. After that, 19# an umbrella-header `cross_values.h` is being generated (with the values included) 20# 21# Currently, only AMD64 cross-compiling is supported. 22 23# Prevent recursive generation: 24if (NOT CROSS_VALUES_CONFIG) 25 add_custom_target(cross_values_generator) 26 set(GENERATED_CROSS_VALUES_DIR "${PANDA_BINARY_ROOT}/cross_values/generated_values") 27 file(MAKE_DIRECTORY ${GENERATED_CROSS_VALUES_DIR}) 28 29 include(ExternalProject) 30 function(create_cross_values_target arch toolchain) 31 set(CROSS_ASM_DEF_TARGET_NAME "cross_asm_defines_${arch}") 32 set(PANDA_AUX_PROJECT_SOURCE ${PANDA_ROOT}) 33 set(PANDA_AUX_BINARY_DIR auxiliary_panda_binary_dirs/${arch}) 34 set(CMAKE_VARIABLES 35 "'-G${CMAKE_GENERATOR}' 36 -DES2PANDA_PATH=${ES2PANDA_PATH} 37 -DCMAKE_TOOLCHAIN_FILE=${toolchain} 38 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} 39 -DANDROID_ABI=${ANDROID_ABI} 40 -DANDROID_PLATFORM=${ANDROID_PLATFORM} 41 -DPANDA_TARGET_MOBILE_WITH_MANAGED_LIBS=${PANDA_TARGET_MOBILE_WITH_MANAGED_LIBS} 42 -DMOBILE_NATIVE_LIBS_SOURCE_PATH=${MOBILE_NATIVE_LIBS_SOURCE_PATH} 43 -DPANDA_TARGET_ARM32_ABI_HARD=${PANDA_TARGET_ARM32_ABI_HARD} 44 -DPANDA_PRODUCT_BUILD=${PANDA_PRODUCT_BUILD} 45 -DTOOLCHAIN_CLANG_ROOT=${TOOLCHAIN_CLANG_ROOT} 46 -DTOOLCHAIN_SYSROOT=${TOOLCHAIN_SYSROOT} 47 -DPANDA_WITH_TESTS=FALSE 48 -DPANDA_WITH_BENCHMARKS=FALSE 49 -DPANDA_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER=${PANDA_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER} 50 -DPANDA_ENABLE_ADDRESS_SANITIZER=${PANDA_ENABLE_ADDRESS_SANITIZER} 51 -DCROSS_VALUES_CONFIG=TRUE 52 --no-warn-unused-cli 53 -Wno-deprecated" 54 ) 55 56 foreach(plugin ${PLUGINS}) 57 string(TOUPPER ${plugin} plugin_name_upper) 58 string(CONCAT PANDA_WITH_PLUGIN "PANDA_WITH_" ${plugin_name_upper}) 59 string(APPEND CMAKE_VARIABLES " 60 -DPANDA_WITH_${plugin_name_upper}=${${PANDA_WITH_PLUGIN}}") 61 endforeach() 62 63 set(BUILD_COMMAND "${CMAKE_COMMAND} --build <BINARY_DIR> --target asm_defines") 64 separate_arguments(CMAKE_VARIABLES_SEP UNIX_COMMAND ${CMAKE_VARIABLES}) 65 separate_arguments(BUILD_COMMAND UNIX_COMMAND ${BUILD_COMMAND}) 66 67 # Configure subprojects at main project's configure step: 68 file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}") 69 message(STATUS " Configuring subproject in ${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR} via `execute_process()`") 70 set(TEMP_CMAKE_LOG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}/cmake_log.tmp") 71 execute_process( 72 COMMAND ${CMAKE_COMMAND} ${PANDA_AUX_PROJECT_SOURCE} ${CMAKE_VARIABLES_SEP} 73 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}" 74 RESULT_VARIABLE ret 75 OUTPUT_FILE ${TEMP_CMAKE_LOG_FILE} 76 ERROR_FILE ${TEMP_CMAKE_LOG_FILE} 77 ) 78 if (NOT ret EQUAL "0") 79 file(READ ${TEMP_CMAKE_LOG_FILE} TEMP_CMAKE_LOG) 80 string(REPLACE "\n" "\n " TEMP_CMAKE_LOG ${TEMP_CMAKE_LOG}) 81 string(REPLACE "\n" " " CMAKE_VARIABLES ${CMAKE_VARIABLES}) 82 message(FATAL_ERROR 83 " ${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR} configuration failed:\n" 84 " ${TEMP_CMAKE_LOG}\n" 85 " Reproduce:" 86 " cd ${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR} && ${CMAKE_COMMAND} ${PANDA_AUX_PROJECT_SOURCE} ${CMAKE_VARIABLES}\n" 87 ) 88 endif() 89 90 file(WRITE ${TEMP_CMAKE_LOG_FILE} "") 91 message(STATUS " Building `asm_defines` in ${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR} via `execute_process()`") 92 execute_process( 93 COMMAND ${CMAKE_COMMAND} --build . --target asm_defines 94 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}" 95 RESULT_VARIABLE ret 96 OUTPUT_FILE ${TEMP_CMAKE_LOG_FILE} 97 ERROR_FILE ${TEMP_CMAKE_LOG_FILE} 98 ) 99 if (NOT ret EQUAL "0") 100 file(READ ${TEMP_CMAKE_LOG_FILE} TEMP_CMAKE_LOG) 101 string(REPLACE "\n" "\n " TEMP_CMAKE_LOG ${TEMP_CMAKE_LOG}) 102 message(FATAL_ERROR 103 " ${PANDA_AUX_BINARY_DIR}/runtime/asm_defines failed:\n" 104 " ${TEMP_CMAKE_LOG}\n" 105 " Reproduce:" 106 " cd ${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR} && ${CMAKE_COMMAND} --build . --target asm_defines\n" 107 ) 108 endif() 109 110 # Add targets to the main project: 111 ExternalProject_Add(${CROSS_ASM_DEF_TARGET_NAME} 112 SOURCE_DIR "${PANDA_AUX_PROJECT_SOURCE}" 113 TMP_DIR "${PANDA_AUX_BINARY_DIR}/${CROSS_ASM_DEF_TARGET_NAME}_tmp" 114 STAMP_DIR "${PANDA_AUX_BINARY_DIR}/${CROSS_ASM_DEF_TARGET_NAME}_stamp" 115 DOWNLOAD_DIR "${PANDA_AUX_BINARY_DIR}" 116 BINARY_DIR "${PANDA_AUX_BINARY_DIR}" 117 INSTALL_DIR "${PANDA_AUX_BINARY_DIR}" 118 BUILD_IN_SOURCE FALSE 119 BUILD_ALWAYS TRUE 120 CONFIGURE_COMMAND "" 121 BUILD_COMMAND ${BUILD_COMMAND} 122 INSTALL_COMMAND "" 123 ) 124 125 set(ASM_DIR "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}/runtime/asm_defines") 126 set(ASM_FILE "libasm_defines.S") 127 128 add_custom_target(cross_asm_defines_${arch}_gen 129 COMMAND ${CMAKE_COMMAND} --build . --target asm_defines 130 >${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}/cross_asm_defines.log 131 || (cat ${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}/cross_asm_defines.log && false) 132 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_AUX_BINARY_DIR}" 133 BYPRODUCTS ${ASM_DIR}/${ASM_FILE} 134 ) 135 136 set(OUTPUT_DIR ${GENERATED_CROSS_VALUES_DIR}) 137 set(OUTPUT_FILE "${arch}_values_gen.h") 138 139 add_custom_command(OUTPUT ${OUTPUT_DIR}/${OUTPUT_FILE} 140 COMMAND ruby ${CMAKE_CURRENT_SOURCE_DIR}/cross_values_generator.rb ${ASM_DIR}/${ASM_FILE} ${OUTPUT_DIR}/${OUTPUT_FILE} ${arch} 141 DEPENDS ${ASM_DIR}/${ASM_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/cross_values_generator.rb 142 ) 143 144 add_custom_target(cross_values_generate_${arch} 145 DEPENDS ${OUTPUT_DIR}/${OUTPUT_FILE} 146 ) 147 add_dependencies(cross_values_generator cross_values_generate_${arch}) 148 set(GENERATED_CROSS_VALUES_HEADERS "${GENERATED_CROSS_VALUES_HEADERS} ${OUTPUT_DIR}/${OUTPUT_FILE}" PARENT_SCOPE) 149 endfunction() 150 151 # By default, gcc-toolchain is used: 152 set(PANDA_CROSS_X86_64_DEFAULT_TOOLCHAIN_FILE ${PANDA_ROOT}/cmake/toolchain/host_gcc_default.cmake) 153 set(PANDA_CROSS_AARCH64_DEFAULT_TOOLCHAIN_FILE ${PANDA_ROOT}/cmake/toolchain/cross-gcc-default-qemu-aarch64.cmake) 154 set(PANDA_CROSS_AARCH32_DEFAULT_TOOLCHAIN_FILE ${PANDA_ROOT}/cmake/toolchain/cross-gcc-default-qemu-arm-linux-gnueabi.cmake) 155 156 # Enable cross-target offsets for x86_64 only: 157 if (PANDA_TARGET_AMD64) 158 if (HOST_TOOLS) 159 create_cross_values_target(${PANDA_HOST_TOOLS_TARGET_ARCH} ${PANDA_HOST_TOOLS_TARGET_TOOLCHAIN}) 160 else() 161 set(TARGET_CROSS_VALUES ${PANDA_BINARY_ROOT}/cross_values/generated_values/X86_64_values_gen.h) 162 set(TARGET_ARCH X86_64) 163 if (PANDA_COMPILER_TARGET_X86_64) 164 message(STATUS "Generating cross-values for X86_64") 165 if (PANDA_CROSS_X86_64_TOOLCHAIN_FILE) 166 create_cross_values_target(X86_64 ${PANDA_CROSS_X86_64_TOOLCHAIN_FILE}) 167 else() 168 create_cross_values_target(X86_64 ${PANDA_CROSS_X86_64_DEFAULT_TOOLCHAIN_FILE}) 169 endif() 170 endif() 171 if (PANDA_COMPILER_TARGET_AARCH64) 172 message(STATUS "Generating cross-values for AARCH64") 173 if (PANDA_CROSS_AARCH64_TOOLCHAIN_FILE) 174 create_cross_values_target(AARCH64 ${PANDA_CROSS_AARCH64_TOOLCHAIN_FILE}) 175 else() 176 create_cross_values_target(AARCH64 ${PANDA_CROSS_AARCH64_DEFAULT_TOOLCHAIN_FILE}) 177 endif() 178 endif() 179 if (PANDA_COMPILER_TARGET_AARCH32) 180 message(STATUS "Generating cross-values for ARM") 181 if (PANDA_CROSS_AARCH32_TOOLCHAIN_FILE) 182 create_cross_values_target(AARCH32 ${PANDA_CROSS_AARCH32_TOOLCHAIN_FILE}) 183 else() 184 create_cross_values_target(AARCH32 ${PANDA_CROSS_AARCH32_DEFAULT_TOOLCHAIN_FILE}) 185 endif() 186 endif() 187 endif() 188 elseif(PANDA_TARGET_ARM64) 189 message(STATUS "Generating cross-values for AARCH64") 190 set(TARGET_CROSS_VALUES ${PANDA_BINARY_ROOT}/cross_values/generated_values/AARCH64_values_gen.h) 191 set(TARGET_ARCH AARCH64) 192 create_cross_values_target(AARCH64 "${CMAKE_TOOLCHAIN_FILE}") 193 if(PANDA_COMPILER_TARGET_X86_64 OR PANDA_COMPILER_TARGET_AARCH32) 194 message(FATAL_ERROR "Cross-compiling is supported for AMD64 only") 195 endif() 196 elseif(PANDA_TARGET_ARM32) 197 message(STATUS "Generating cross-values for ARM") 198 set(TARGET_CROSS_VALUES ${PANDA_BINARY_ROOT}/cross_values/generated_values/AARCH32_values_gen.h) 199 set(TARGET_ARCH AARCH32) 200 create_cross_values_target(AARCH32 "${CMAKE_TOOLCHAIN_FILE}") 201 if(PANDA_COMPILER_TARGET_X86_64 OR PANDA_COMPILER_TARGET_AARCH64) 202 message(FATAL_ERROR "Cross-compiling is supported for AMD64 only") 203 endif() 204 endif() 205 206 set(OUTPUT_DIR "${PANDA_BINARY_ROOT}/cross_values") 207 set(OUTPUT_FILE "cross_values.h") 208 209 set(ASM_DEFINES_INPUT "${CMAKE_SOURCE_DIR}/runtime/asm_defines/asm_defines.def") 210 set(ASM_DEFINES_OUTPUT "${OUTPUT_DIR}/asm_defines_def.cpp") 211 212 add_custom_command(OUTPUT ${ASM_DEFINES_OUTPUT} 213 COMMAND cmake -E copy ${ASM_DEFINES_INPUT} ${ASM_DEFINES_OUTPUT} 214 DEPENDS ${ASM_DEFINES_INPUT} 215 ) 216 217 panda_add_library(asm_defines_process OBJECT ${ASM_DEFINES_OUTPUT}) 218 panda_target_compile_options(asm_defines_process PRIVATE -E -P) 219 panda_target_include_directories(asm_defines_process 220 PUBLIC ${CMAKE_SOURCE_DIR} 221 PUBLIC ${CMAKE_BINARY_DIR} 222 PUBLIC ${CMAKE_BINARY_DIR}/runtime/asm_defines 223 ) 224 225 add_dependencies(cross_values_generator asm_defines_process) 226 227 string(REPLACE " " ";" GENERATED_CROSS_VALUES_HEADERS_LIST ${GENERATED_CROSS_VALUES_HEADERS}) 228 add_custom_command(OUTPUT ${OUTPUT_DIR}/${OUTPUT_FILE} 229 COMMAND ruby ${CMAKE_CURRENT_SOURCE_DIR}/cross_values_getters_generator.rb $<TARGET_OBJECTS:asm_defines_process> ${GENERATED_CROSS_VALUES_DIR} ${OUTPUT_DIR}/${OUTPUT_FILE} 230 DEPENDS cross_values_generator ${CMAKE_CURRENT_SOURCE_DIR}/cross_values_getters_generator.rb $<TARGET_OBJECTS:asm_defines_process> ${GENERATED_CROSS_VALUES_HEADERS_LIST} 231 ) 232 233 add_custom_target(cross_values 234 DEPENDS ${OUTPUT_DIR}/${OUTPUT_FILE} 235 ) 236 set(GENERATED_CROSS_VALUES_HEADERS ${GENERATED_CROSS_VALUES_HEADERS} PARENT_SCOPE) 237 add_dependencies(panda_gen_files cross_values) 238 239 if (NOT (HOST_TOOLS OR PANDA_TARGET_WINDOWS)) 240 # Generate `cross-values` using `asm_defines` from root-build to ensure later that they are the same as generated in `auxiliary_panda_binary_dirs`. 241 # The reason for this extra-generation is to check that `auxiliary_panda_binary_dirs` are being generated correctly, e.g. all 242 # of the `cmake`-flags are being passed correctly. 243 set(ROOT_ASM_DIR "${CMAKE_BINARY_DIR}/runtime/asm_defines") 244 set(ROOT_ASM_FILE "libasm_defines.S") 245 set(OUTPUT_DIR ${GENERATED_CROSS_VALUES_DIR}/test) 246 file(MAKE_DIRECTORY ${GENERATED_CROSS_VALUES_DIR}/test) 247 set(OUTPUT_FILE "values_root_build_gen.h") 248 set(ROOT_CROSS_VALUES ${OUTPUT_DIR}/${OUTPUT_FILE}) 249 add_dependencies(cross_values asm_defines_generator) 250 add_custom_command(TARGET cross_values POST_BUILD 251 COMMAND ruby ${CMAKE_CURRENT_SOURCE_DIR}/cross_values_generator.rb ${ROOT_ASM_DIR}/${ROOT_ASM_FILE} ${ROOT_CROSS_VALUES} ${TARGET_ARCH} 252 COMMAND ${PANDA_ROOT}/cross_values/diff_check_values.sh ${TARGET_CROSS_VALUES} ${ROOT_CROSS_VALUES} 253 ) 254 endif() 255else() 256 # Add mock-targets because of external dependencies on `cross_values`: 257 add_custom_target(asm_defines_process) 258 add_custom_target(cross_values) 259 add_custom_target(cross_values_generator) 260endif() 261 262if (CMAKE_CROSSCOMPILING) 263 add_dependencies(host_tools_depends cross_values) 264endif() 265