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