| # Copyright 2018 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # This file contains a set of functions that make it easier to configure the |
| # toolchain used by the emulator It's main responsibility is to create the |
| # toolchain by invoking the toolchain shell script that generates the proper |
| # wrappers around the compilers and sysroot that are found in the build tree. |
| # |
| # We need this to make sure that are builds are consistent accross different |
| # development environments. |
| |
| # Gets the desired clang version used by the various toolchains. Update this if |
| # you need to change the compiler |
| function(get_clang_version RET_VAL) |
| file(READ "${ANDROID_QEMU2_TOP_DIR}/android/build/toolchains.json" |
| TOOLCHAIN_JSON_STRING) |
| string(JSON CLANG_VERSION GET ${TOOLCHAIN_JSON_STRING} ${IDX} clang) |
| set(${RET_VAL} ${CLANG_VERSION} PARENT_SCOPE) |
| endfunction() |
| |
| # This invokes the toolchain generator HOST The host to use PARAM1, PARAM2 |
| # Parameters to pass on to the gen-android-sdk-toolchain.sh script. |
| # |
| # Sets STD_OUT The output produced by the script |
| function(toolchain_cmd HOST PARAM1 PARAM2) |
| set(VERBOSITY "2") |
| if(PARAM2 MATCHES ".*unused.*") |
| set(VERBOSITY "0") |
| endif() |
| get_filename_component( |
| GEN_SDK |
| "${CMAKE_CURRENT_LIST_FILE}/../../../scripts/unix/gen-android-sdk-toolchain.sh" |
| ABSOLUTE) |
| get_filename_component(AOSP "${CMAKE_CURRENT_LIST_DIR}/../../../../.." |
| ABSOLUTE) |
| get_clang_version(CLANG_VER) |
| |
| if(VERBOSITY MATCHES "2") |
| message( |
| "Running ${GEN_SDK} '--host=${HOST}' '${PARAM1}' '${PARAM2}' '--aosp-dir=${AOSP}' '--aosp-clang_ver=${CLANG_VER}' '--verbosity=${VERBOSITY}'" |
| ) |
| endif() |
| execute_process( |
| COMMAND |
| ${GEN_SDK} "--host=${HOST}" "--aosp-clang_ver=${CLANG_VER}" |
| "--aosp-dir=${AOSP}" "--verbosity=${VERBOSITY}" "${PARAM1}" "${PARAM2}" |
| RESULT_VARIABLE GEN_SDK_RES |
| OUTPUT_VARIABLE STD_OUT |
| ERROR_VARIABLE STD_ERR) |
| if(NOT "${GEN_SDK_RES}" STREQUAL "0") |
| message( |
| FATAL_ERROR |
| "Unable to retrieve sdk info from ${GEN_SDK} --host=${HOST} ${PARAM1} ${PARAM2}: ${STD_OUT}, ${STD_ERR}" |
| ) |
| endif() |
| |
| string(STRIP "${STD_OUT}" STD_OUT) |
| if(NOT STD_OUT STREQUAL "") |
| message("${STD_OUT}") |
| endif() |
| |
| # Clean up and make visibile |
| string(REPLACE "\n" "" STD_OUT "${STD_OUT}") |
| set(STD_OUT ${STD_OUT} PARENT_SCOPE) |
| endfunction() |
| |
| # Generates the toolchain for the given host. The toolchain is generated by |
| # calling the gen-android-sdk script |
| # |
| # It will set the all the necesary CMAKE compiler flags to use the android |
| # toolchain for the given host. |
| # |
| # TARGET_OS: The target environment for which we are creating the toolchain |
| # |
| # Returns: The variable ANDROID_SYSROOT will be set to point to the sysroot for |
| # the target os. The variablke ANDROID_COMPILER_PREFIX will point to the prefix |
| # for gcc, g++, ar, ld etc.. |
| function(toolchain_generate_internal TARGET_OS) |
| set(TOOLCHAIN "${PROJECT_BINARY_DIR}/toolchain") |
| |
| # First we generate the toolchain. |
| if(NOT EXISTS ${TOOLCHAIN}) |
| # Force update the windows sdk if the flag is provided |
| if(${OPTION_WINTOOLCHAIN}) |
| message( |
| WARNING |
| "Force downloading the Windows toolchain. This may take a couple of minutes..." |
| ) |
| toolchain_cmd("${TARGET_OS}" "--force-fetch-wintoolchain" "unused") |
| endif() |
| toolchain_cmd("${TARGET_OS}" "${TOOLCHAIN}" "") |
| endif() |
| |
| # Let's find the bin-prefix |
| toolchain_cmd("${TARGET_OS}" "--print=binprefix" "unused") |
| set(ANDROID_COMPILER_PREFIX "${TOOLCHAIN}/${STD_OUT}" PARENT_SCOPE) |
| |
| # And define all the compilers.. |
| toolchain_cmd("${TARGET_OS}" "--print=sysroot" "unused") |
| set(ANDROID_SYSROOT "${STD_OUT}" PARENT_SCOPE) |
| endfunction() |
| |
| # Retrieves the osxcross compiler toolchain variables |
| function(get_osxcross_settings TARGET_OS) |
| # This is a hack to workaround the fact that cmake will keep including the |
| # toolchain defintion over and over, and it will wipe out all the settings. so |
| # we will just store them in the environment, which gets blown away on exit of |
| # cmake anyway.. |
| internal_get_env_cache(OSXCROSS_SDK) |
| internal_get_env_cache(OSXCROSS_TARGET_DIR) |
| if("${OSXCROSS_SDK}" STREQUAL "") |
| toolchain_cmd("${TARGET_OS}" "--print=OSXCROSS_SDK" "unused") |
| internal_set_env_cache(OSXCROSS_SDK "${STD_OUT}") |
| toolchain_cmd("${TARGET_OS}" "--print=OSXCROSS_TARGET_DIR" "unused") |
| internal_set_env_cache(OSXCROSS_TARGET_DIR "${STD_OUT}") |
| endif() |
| set(OSXCROSS_SDK "${OSXCROSS_SDK}" PARENT_SCOPE) |
| set(OSXCROSS_TARGET_DIR "${OSXCROSS_TARGET_DIR}" PARENT_SCOPE) |
| endfunction() |
| |
| # Gets the given key from the enviroment. This your usual shell environment and |
| # is globally visuable during cmake generation. This used by the toolchain |
| # generator to work around some caching issues. (CMake blows away the internal |
| # variables when configuring the toolchain) No sane person would use this |
| # outside the toolchain generation. |
| function(internal_get_env_cache KEY) |
| set(${KEY} $ENV{ENV_CACHE_${KEY}} PARENT_SCOPE) |
| endfunction() |
| |
| # Sets the given key in the environment to the given value. |
| function(internal_set_env_cache KEY VAL) |
| set(ENV{ENV_CACHE_${KEY}} "${VAL}") |
| set(${KEY} "${VAL}" PARENT_SCOPE) |
| endfunction() |
| |
| function(toolchain_generate TARGET_OS) |
| # This is a hack to workaround the fact that cmake will keep including the |
| # toolchain defintion over and over, and it will wipe out all the settings. so |
| # we will just store them in the environment, which gets blown away on exit of |
| # cmake anyway.. |
| internal_get_env_cache(COMPILER_PREFIX) |
| internal_get_env_cache(ANDROID_SYSROOT) |
| if("${COMPILER_PREFIX}" STREQUAL "") |
| toolchain_generate_internal(${TARGET_OS}) |
| internal_set_env_cache(COMPILER_PREFIX "${ANDROID_COMPILER_PREFIX}") |
| internal_set_env_cache(ANDROID_SYSROOT "${ANDROID_SYSROOT}") |
| endif() |
| |
| set(CMAKE_RC_COMPILER ${COMPILER_PREFIX}windres CACHE PATH "windres") |
| set(CMAKE_C_COMPILER ${COMPILER_PREFIX}gcc CACHE PATH "C compiler") |
| set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}g++ CACHE PATH "C++ compiler") |
| set(CLANG_TIDY_EXE ${COMPILER_PREFIX}clang-tidy CACHE PATH "Clang tidy") |
| # We will use system bintools (Note, this might not work with msvc) As setting |
| # the AR somehow causes all sorts of strange issues. set(CMAKE_AR |
| # ${COMPILER_PREFIX}ar PARENT_SCOPE) |
| set(CMAKE_RANLIB ${COMPILER_PREFIX}ranlib CACHE PATH "Ranlib") |
| set(CMAKE_OBJCOPY ${COMPILER_PREFIX}objcopy CACHE PATH "Objcopy") |
| set(CMAKE_STRIP ${COMPILER_PREFIX}strip CACHE PATH "strip") |
| set(CMAKE_INSTALL_NAME_TOOL ${COMPILER_PREFIX}install_name_tool) |
| set(ANDROID_SYSROOT ${ANDROID_SYSROOT} CACHE PATH "Sysroot") |
| set(ANDROID_LLVM_SYMBOLIZER ${PROJECT_BINARY_DIR}/toolchain/llvm-symbolizer |
| CACHE PATH "symbolizer") |
| endfunction() |
| |
| function(_get_host_tag RET_VAL) |
| # Prebuilts to be used on the host os should fall under one of the below tags |
| if(APPLE) |
| # arm/x86? |
| execute_process(COMMAND uname -m OUTPUT_VARIABLE CPU_ARCH) |
| # cmake is currently ran under rosetta, which set CPU_ARCH above to x86, |
| # even on m1 machines. |
| execute_process( |
| COMMAND sysctl -n sysctl.proc_translated OUTPUT_VARIABLE IS_ARM_TRANSLATED |
| RESULT_VARIABLE SYSCTL_RESULT) |
| if(CPU_ARCH MATCHES ".*x86_64.*" |
| AND NOT (SYSCTL_RESULT EQUAL 0 AND IS_ARM_TRANSLATED MATCHES "1*")) |
| set(${RET_VAL} "darwin-x86_64" PARENT_SCOPE) |
| else() |
| set(${RET_VAL} "darwin-aarch64" PARENT_SCOPE) |
| endif() |
| elseif(UNIX) |
| set(${RET_VAL} "linux-x86_64" PARENT_SCOPE) |
| else() |
| set(${RET_VAL} "windows_msvc-x86_64" PARENT_SCOPE) |
| endif() |
| endfunction() |
| |
| function(toolchain_generate_msvc TARGET_OS) |
| # This is a hack to workaround the fact that cmake will keep including the |
| # toolchain defintion over and over, and it will wipe out all the settings. so |
| # we will just store them in the environment, which gets blown away on exit |
| # anyway.. |
| get_env_cache(COMPILER_PREFIX) |
| get_env_cache(ANDROID_SYSROOT) |
| if("${COMPILER_PREFIX}" STREQUAL "") |
| toolchain_generate_internal(${TARGET_OS}) |
| set_env_cache(COMPILER_PREFIX "${ANDROID_COMPILER_PREFIX}") |
| set_env_cache(ANDROID_SYSROOT "${ANDROID_SYSROOT}") |
| endif() |
| |
| set(triple x86_64-pc-win32) |
| set(CMAKE_RC_COMPILER ${COMPILER_PREFIX}windres PARENT_SCOPE) |
| set(CMAKE_C_COMPILER ${COMPILER_PREFIX}clang PARENT_SCOPE) |
| set(CMAKE_C_COMPILER_TARGET ${triple} PARENT_SCOPE) |
| set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}clang++ PARENT_SCOPE) |
| set(CMAKE_CXX_COMPILER_TARGET ${triple} PARENT_SCOPE) |
| # We will use system bintools set(CMAKE_AR ${COMPILER_PREFIX}ar PARENT_SCOPE) |
| set(CMAKE_RANLIB ${COMPILER_PREFIX}ranlib PARENT_SCOPE) |
| set(CMAKE_OBJCOPY ${COMPILER_PREFIX}objcopy PARENT_SCOPE) |
| set(CMAKE_STRIP ${COMPILER_PREFIX}strip PARENT_SCOPE) |
| set(ANDROID_SYSROOT ${ANDROID_SYSROOT} PARENT_SCOPE) |
| endfunction() |
| |
| function(toolchain_configure_tags tag) |
| set(ANDROID_TARGET_TAG ${tag}) |
| string(REGEX REPLACE "-.*" "" ANDROID_TARGET_OS ${tag}) |
| string(REGEX REPLACE "[-_].*" "" ANDROID_TARGET_OS_FLAVOR ${tag}) |
| |
| _get_host_tag(ANDROID_HOST_TAG) |
| |
| if(NOT ANDROID_TARGET_TAG STREQUAL ANDROID_HOST_TAG) |
| set(CROSSCOMPILE TRUE PARENT_SCOPE) |
| endif() |
| |
| if(ANDROID_TARGET_TAG STREQUAL "windows_msvc-x86_64") |
| set(WINDOWS TRUE PARENT_SCOPE) |
| set(WINDOWS_MSVC_X86_64 TRUE PARENT_SCOPE) |
| elseif(ANDROID_TARGET_TAG STREQUAL "linux-x86_64") |
| set(LINUX TRUE PARENT_SCOPE) |
| set(LINUX_X86_64 TRUE PARENT_SCOPE) |
| elseif(ANDROID_TARGET_TAG STREQUAL "linux-aarch64") |
| set(LINUX TRUE PARENT_SCOPE) |
| set(LINUX_AARCH64 TRUE PARENT_SCOPE) |
| set(BUILDING_FOR_AARCH64 TRUE) |
| set(BUILDING_FOR_AARCH64 TRUE PARENT_SCOPE) |
| elseif(ANDROID_TARGET_TAG STREQUAL "darwin-x86_64") |
| set(DARWIN_X86_64 TRUE PARENT_SCOPE) |
| elseif(ANDROID_TARGET_TAG STREQUAL "darwin-aarch64") |
| set(DARWIN TRUE PARENT_SCOPE) |
| set(DARWIN_AARCH64 TRUE PARENT_SCOPE) |
| set(BUILDING_FOR_AARCH64 TRUE) |
| set(BUILDING_FOR_AARCH64 TRUE PARENT_SCOPE) |
| endif() |
| |
| if(ANDROID_HOST_TAG STREQUAL "windows_msvc-x86_64") |
| set(HOST_WINDOWS_MSVC_X86_64 TRUE PARENT_SCOPE) |
| set(HOST_WINDOWS TRUE PARENT_SCOPE) |
| elseif(ANDROID_HOST_TAG STREQUAL "linux-x86_64") |
| set(HOST_LINUX_X86_64 TRUE PARENT_SCOPE) |
| elseif(ANDROID_HOST_TAG STREQUAL "darwin-x86_64") |
| set(HOST_DARWIN_X86_64 TRUE PARENT_SCOPE) |
| elseif(ANDROID_HOST_TAG STREQUAL "darwin-aarch64") |
| set(HOST_DARWIN_AARCH64 TRUE PARENT_SCOPE) |
| endif() |
| |
| # Export the oldschool tags as well. |
| set(ANDROID_TARGET_TAG ${tag} PARENT_SCOPE) |
| set(ANDROID_HOST_TAG ${ANDROID_HOST_TAG} PARENT_SCOPE) |
| |
| set(ANDROID_TARGET_OS "${ANDROID_TARGET_OS}" PARENT_SCOPE) |
| set(ANDROID_TARGET_OS_FLAVOR "${ANDROID_TARGET_OS_FLAVOR}" PARENT_SCOPE) |
| |
| set(BUILDING_FOR_AARCH64 ${BUILDING_FOR_AARCH64} PARENT_SCOPE) |
| endfunction() |
| |
| get_filename_component(ANDROID_QEMU2_TOP_DIR |
| "${CMAKE_CURRENT_LIST_FILE}/../../../.." ABSOLUTE) |