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