From: Adeel <3840695+am11@users.noreply.github.com> Date: Thu, 28 Oct 2021 09:54:38 +0000 (+0300) Subject: Copy infra files from runtime X-Git-Tag: submit/tizen/20220302.040122~18^2^2~32^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=08cf75a3895ba9f2ac0cd43f2f0741147787029a;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Copy infra files from runtime --- diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh new file mode 100755 index 000000000..93afd4afe --- /dev/null +++ b/eng/native/build-commons.sh @@ -0,0 +1,462 @@ +#!/usr/bin/env bash + +initTargetDistroRid() +{ + source "$__RepoRootDir/eng/native/init-distro-rid.sh" + + local passedRootfsDir="" + + # Only pass ROOTFS_DIR if cross is specified and the target platform is not Darwin that doesn't use rootfs + if [[ "$__CrossBuild" == 1 && "$platform" != "Darwin" ]]; then + passedRootfsDir="$ROOTFS_DIR" + fi + + initDistroRidGlobal "$__TargetOS" "$__BuildArch" "$__PortableBuild" "$passedRootfsDir" +} + +setup_dirs() +{ + echo Setting up directories for build + + mkdir -p "$__RootBinDir" + mkdir -p "$__BinDir" + mkdir -p "$__IntermediatesDir" +} + +# Check the system to ensure the right prereqs are in place +check_prereqs() +{ + echo "Checking prerequisites..." + + if [[ "$__HostOS" == "OSX" ]]; then + # Check presence of pkg-config on the path + command -v pkg-config 2>/dev/null || { echo >&2 "Please install pkg-config before running this script, see https://github.com/dotnet/runtime/blob/main/docs/workflow/requirements/macos-requirements.md"; exit 1; } + + if ! pkg-config openssl ; then + # We export the proper PKG_CONFIG_PATH where openssl was installed by Homebrew + # It's important to _export_ it since build-commons.sh is sourced by other scripts such as build-native.sh + export PKG_CONFIG_PATH=$(brew --prefix)/opt/openssl@1.1/lib/pkgconfig:$(brew --prefix)/opt/openssl/lib/pkgconfig + # We try again with the PKG_CONFIG_PATH in place, if pkg-config still can't find OpenSSL, exit with an error, cmake won't find OpenSSL either + pkg-config openssl || { echo >&2 "Please install openssl before running this script, see https://github.com/dotnet/runtime/blob/main/docs/workflow/requirements/macos-requirements.md"; exit 1; } + fi + fi + + if [[ "$__UseNinja" == 1 ]]; then + command -v ninja 2>/dev/null || command -v ninja-build 2>/dev/null || { echo "Unable to locate ninja!"; exit 1; } + fi +} + +build_native() +{ + eval "$__RepoRootDir/eng/native/version/copy_version_files.sh" + + targetOS="$1" + platformArch="$2" + cmakeDir="$3" + intermediatesDir="$4" + target="$5" + cmakeArgs="$6" + message="$7" + + # All set to commence the build + echo "Commencing build of \"$target\" target in \"$message\" for $__TargetOS.$__BuildArch.$__BuildType in $intermediatesDir" + + if [[ "$targetOS" == OSX || "$targetOS" == MacCatalyst ]]; then + if [[ "$platformArch" == x64 ]]; then + cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $cmakeArgs" + elif [[ "$platformArch" == arm64 ]]; then + cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $cmakeArgs" + else + echo "Error: Unknown OSX architecture $platformArch." + exit 1 + fi + fi + + if [[ "$targetOS" == MacCatalyst ]]; then + cmakeArgs="-DCMAKE_SYSTEM_VARIANT=MacCatalyst $cmakeArgs" + fi + + if [[ "$targetOS" == Android && -z "$ROOTFS_DIR" ]]; then + if [[ -z "$ANDROID_NDK_ROOT" ]]; then + echo "Error: You need to set the ANDROID_NDK_ROOT environment variable pointing to the Android NDK root." + exit 1 + fi + + # keep ANDROID_NATIVE_API_LEVEL in sync with src/mono/Directory.Build.props + cmakeArgs="-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=21 $cmakeArgs" + + # Don't try to set CC/CXX in init-compiler.sh - it's handled in android.toolchain.cmake already + __Compiler="default" + + if [[ "$platformArch" == x64 ]]; then + cmakeArgs="-DANDROID_ABI=x86_64 $cmakeArgs" + elif [[ "$platformArch" == x86 ]]; then + cmakeArgs="-DANDROID_ABI=x86 $cmakeArgs" + elif [[ "$platformArch" == arm64 ]]; then + cmakeArgs="-DANDROID_ABI=arm64-v8a $cmakeArgs" + elif [[ "$platformArch" == arm ]]; then + cmakeArgs="-DANDROID_ABI=armeabi-v7a $cmakeArgs" + else + echo "Error: Unknown Android architecture $platformArch." + exit 1 + fi + fi + + if [[ "$__UseNinja" == 1 ]]; then + generator="ninja" + buildTool="$(command -v ninja || command -v ninja-build)" + else + buildTool="make" + fi + + if [[ "$__SkipConfigure" == 0 ]]; then + + if [[ "$__StaticAnalyzer" == 1 ]]; then + scan_build=scan-build + fi + + nextCommand="\"$__RepoRootDir/eng/native/gen-buildsys.sh\" \"$cmakeDir\" \"$intermediatesDir\" $platformArch $__Compiler \"$__CompilerMajorVersion\" \"$__CompilerMinorVersion\" $__BuildType \"$generator\" $scan_build $cmakeArgs" + echo "Invoking $nextCommand" + eval $nextCommand + + local exit_code="$?" + if [[ "$exit_code" != 0 ]]; then + echo "${__ErrMsgPrefix}Failed to generate \"$message\" build project!" + exit "$exit_code" + fi + fi + + # Check that the makefiles were created. + if [[ ! -f "$intermediatesDir/CMakeCache.txt" ]]; then + echo "${__ErrMsgPrefix}Unable to find generated build files for \"$message\" project!" + exit 1 + fi + + # Build + if [[ "$__ConfigureOnly" == 1 ]]; then + echo "Finish configuration & skipping \"$message\" build." + return + fi + + SAVED_CFLAGS="${CFLAGS}" + SAVED_CXXFLAGS="${CXXFLAGS}" + SAVED_LDFLAGS="${LDFLAGS}" + + # Let users provide additional compiler/linker flags via EXTRA_CFLAGS/EXTRA_CXXFLAGS/EXTRA_LDFLAGS. + # If users directly override CFLAG/CXXFLAGS/LDFLAGS, that may lead to some configure tests working incorrectly. + # See https://github.com/dotnet/runtime/issues/35727 for more information. + export CFLAGS="${CFLAGS} ${EXTRA_CFLAGS}" + export CXXFLAGS="${CXXFLAGS} ${EXTRA_CXXFLAGS}" + export LDFLAGS="${LDFLAGS} ${EXTRA_LDFLAGS}" + + local exit_code + if [[ "$__StaticAnalyzer" == 1 ]]; then + pushd "$intermediatesDir" + + buildTool="$SCAN_BUILD_COMMAND -o $__BinDir/scan-build-log $buildTool" + echo "Executing $buildTool $target -j $__NumProc" + "$buildTool" $target -j "$__NumProc" + exit_code="$?" + + popd + else + cmake_command=cmake + if [[ "$build_arch" == "wasm" ]]; then + cmake_command="emcmake cmake" + echo "Executing $cmake_command --build \"$intermediatesDir\" --target $target -- -j $__NumProc" + $cmake_command --build "$intermediatesDir" --target $target -- -j "$__NumProc" + exit_code="$?" + else + # For non-wasm Unix scenarios, we may have to use an old version of CMake that doesn't support + # multiple targets. Instead, directly invoke the build tool to build multiple targets in one invocation. + pushd "$intermediatesDir" + + echo "Executing $buildTool $target -j $__NumProc" + "$buildTool" $target -j "$__NumProc" + exit_code="$?" + + popd + fi + fi + + CFLAGS="${SAVED_CFLAGS}" + CXXFLAGS="${SAVED_CXXFLAGS}" + LDFLAGS="${SAVED_LDFLAGS}" + + if [[ "$exit_code" != 0 ]]; then + echo "${__ErrMsgPrefix}Failed to build \"$message\"." + exit "$exit_code" + fi +} + +usage() +{ + echo "Usage: $0 " + echo "" + echo "Common Options:" + echo "" + echo "BuildArch can be: -arm, -armel, -arm64, -s390x, x64, x86, -wasm" + echo "BuildType can be: -debug, -checked, -release" + echo "-os: target OS (defaults to running OS)" + echo "-bindir: output directory (defaults to $__ProjectRoot/artifacts)" + echo "-ci: indicates if this is a CI build." + echo "-clang: optional argument to build using clang in PATH (default)." + echo "-clangx.y: optional argument to build using clang version x.y." + echo "-cmakeargs: user-settable additional arguments passed to CMake." + echo "-configureonly: do not perform any builds; just configure the build." + echo "-cross: optional argument to signify cross compilation," + echo " will use ROOTFS_DIR environment variable if set." + echo "-gcc: optional argument to build using gcc in PATH." + echo "-gccx.y: optional argument to build using gcc version x.y." + echo "-ninja: target ninja instead of GNU make" + echo "-numproc: set the number of build processes." + echo "-portablebuild: pass -portablebuild=false to force a non-portable build." + echo "-skipconfigure: skip build configuration." + echo "-keepnativesymbols: keep native/unmanaged debug symbols." + echo "-verbose: optional argument to enable verbose build output." + echo "" + echo "Additional Options:" + echo "" + for i in "${!usage_list[@]}"; do + echo "${usage_list[${i}]}" + done + echo "" + exit 1 +} + +source "$__RepoRootDir/eng/native/init-os-and-arch.sh" + +__BuildArch=$arch +__HostArch=$arch +__TargetOS=$os +__HostOS=$os +__BuildOS=$os + +# Get the number of processors available to the scheduler +# Other techniques such as `nproc` only get the number of +# processors available to a single process. +platform="$(uname)" +if [[ "$platform" == "FreeBSD" ]]; then + __NumProc=$(($(sysctl -n hw.ncpu)+1)) +elif [[ "$platform" == "NetBSD" || "$platform" == "SunOS" ]]; then + __NumProc=$(($(getconf NPROCESSORS_ONLN)+1)) +elif [[ "$platform" == "Darwin" ]]; then + __NumProc=$(($(getconf _NPROCESSORS_ONLN)+1)) +else + if command -v nproc > /dev/null 2>&1; then + __NumProc=$(nproc --all) + elif (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then + __NumProc=$(getconf _NPROCESSORS_ONLN) + else + __NumProc=1 + fi +fi + +while :; do + if [[ "$#" -le 0 ]]; then + break + fi + + lowerI="$(echo "$1" | tr "[:upper:]" "[:lower:]")" + case "$lowerI" in + -\?|-h|--help) + usage + exit 1 + ;; + + arm|-arm) + __BuildArch=arm + ;; + + arm64|-arm64) + __BuildArch=arm64 + ;; + + armel|-armel) + __BuildArch=armel + ;; + + bindir|-bindir) + if [[ -n "$2" ]]; then + __RootBinDir="$2" + if [[ ! -d "$__RootBinDir" ]]; then + mkdir "$__RootBinDir" + fi + __RootBinParent=$(dirname "$__RootBinDir") + __RootBinName="${__RootBinDir##*/}" + __RootBinDir="$(cd "$__RootBinParent" &>/dev/null && printf %s/%s "$PWD" "$__RootBinName")" + shift + else + echo "ERROR: 'bindir' requires a non-empty option argument" + exit 1 + fi + ;; + + checked|-checked) + __BuildType=Checked + ;; + + ci|-ci) + __ArcadeScriptArgs="--ci" + __ErrMsgPrefix="##vso[task.logissue type=error]" + ;; + + clang*|-clang*) + __Compiler=clang + # clangx.y or clang-x.y + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + parts=(${version//./ }) + __CompilerMajorVersion="${parts[0]}" + __CompilerMinorVersion="${parts[1]}" + if [[ -z "$__CompilerMinorVersion" && "$__CompilerMajorVersion" -le 6 ]]; then + __CompilerMinorVersion=0; + fi + ;; + + cmakeargs|-cmakeargs) + if [[ -n "$2" ]]; then + __CMakeArgs="$2 $__CMakeArgs" + shift + else + echo "ERROR: 'cmakeargs' requires a non-empty option argument" + exit 1 + fi + ;; + + configureonly|-configureonly) + __ConfigureOnly=1 + __SkipMSCorLib=1 + __SkipNuget=1 + ;; + + cross|-cross) + __CrossBuild=1 + ;; + + debug|-debug) + __BuildType=Debug + ;; + + gcc*|-gcc*) + __Compiler=gcc + # gccx.y or gcc-x.y + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + parts=(${version//./ }) + __CompilerMajorVersion="${parts[0]}" + __CompilerMinorVersion="${parts[1]}" + ;; + + keepnativesymbols|-keepnativesymbols) + __CMakeArgs="$__CMakeArgs -DCLR_CMAKE_KEEP_NATIVE_SYMBOLS=true" + ;; + + ninja|-ninja) + __UseNinja=1 + ;; + + numproc|-numproc) + if [[ -n "$2" ]]; then + __NumProc="$2" + shift + else + echo "ERROR: 'numproc' requires a non-empty option argument" + exit 1 + fi + ;; + + portablebuild=false|-portablebuild=false) + __PortableBuild=0 + ;; + + release|-release) + __BuildType=Release + ;; + + skipconfigure|-skipconfigure) + __SkipConfigure=1 + ;; + + verbose|-verbose) + __VerboseBuild=1 + ;; + + x86|-x86) + __BuildArch=x86 + ;; + + x64|-x64) + __BuildArch=x64 + ;; + + s390x|-s390x) + __BuildArch=s390x + ;; + + wasm|-wasm) + __BuildArch=wasm + ;; + + os|-os) + if [[ -n "$2" ]]; then + __TargetOS="$2" + shift + else + echo "ERROR: 'os' requires a non-empty option argument" + exit 1 + fi + ;; + + *) + handle_arguments "$1" "$2" + if [[ "$__ShiftArgs" == 1 ]]; then + shift + __ShiftArgs=0 + fi + ;; + esac + + shift +done + +__CommonMSBuildArgs="/p:TargetArchitecture=$__BuildArch /p:Configuration=$__BuildType /p:TargetOS=$__TargetOS /nodeReuse:false $__OfficialBuildIdArg $__SignTypeArg $__SkipRestoreArg" + +# Configure environment if we are doing a verbose build +if [[ "$__VerboseBuild" == 1 ]]; then + VERBOSE=1 + export VERBOSE + __CommonMSBuildArgs="$__CommonMSBuildArgs /v:detailed" +fi + +if [[ "$__PortableBuild" == 0 ]]; then + __CommonMSBuildArgs="$__CommonMSBuildArgs /p:PortableBuild=false" +fi + +if [[ "$__BuildArch" == wasm ]]; then + # nothing to do here + true +elif [[ "$__TargetOS" == iOS || "$__TargetOS" == iOSSimulator ]]; then + # nothing to do here + true +elif [[ "$__TargetOS" == tvOS || "$__TargetOS" == tvOSSimulator ]]; then + # nothing to do here + true +elif [[ "$__TargetOS" == Android ]]; then + # nothing to do here + true +else + __CMakeArgs="-DFEATURE_DISTRO_AGNOSTIC_SSL=$__PortableBuild $__CMakeArgs" +fi + +# Configure environment if we are doing a cross compile. +if [[ "$__CrossBuild" == 1 ]]; then + CROSSCOMPILE=1 + export CROSSCOMPILE + # Darwin that doesn't use rootfs + if [[ ! -n "$ROOTFS_DIR" && "$platform" != "Darwin" ]]; then + ROOTFS_DIR="$__RepoRootDir/.tools/rootfs/$__BuildArch" + export ROOTFS_DIR + fi +fi + +# init the target distro name +initTargetDistroRid diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake new file mode 100644 index 000000000..a29857451 --- /dev/null +++ b/eng/native/configurecompiler.cmake @@ -0,0 +1,701 @@ +include(${CMAKE_CURRENT_LIST_DIR}/configuretools.cmake) + +# Set initial flags for each configuration + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) + +# "configureoptimization.cmake" must be included after CLR_CMAKE_HOST_UNIX has been set. +include(${CMAKE_CURRENT_LIST_DIR}/configureoptimization.cmake) + +#----------------------------------------------------- +# Initialize Cmake compiler flags and other variables +#----------------------------------------------------- + +if (CLR_CMAKE_HOST_UNIX) + add_compile_options(-g) + add_compile_options(-Wall) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-null-conversion) + else() + add_compile_options($<$:-Werror=conversion-null>) + endif() +endif() + +if (CMAKE_CONFIGURATION_TYPES) # multi-configuration generator? + set(CMAKE_CONFIGURATION_TYPES "Debug;Checked;Release;RelWithDebInfo" CACHE STRING "" FORCE) +endif (CMAKE_CONFIGURATION_TYPES) + +set(CMAKE_C_FLAGS_CHECKED "") +set(CMAKE_CXX_FLAGS_CHECKED "") +set(CMAKE_EXE_LINKER_FLAGS_CHECKED "") +set(CMAKE_SHARED_LINKER_FLAGS_CHECKED "") + +set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "") +set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "") +set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") +set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "") + +add_compile_definitions("$<$:DEBUG;_DEBUG;_DBG;URTBLDENV_FRIENDLY=Debug;BUILDENV_DEBUG=1>") +add_compile_definitions("$<$:DEBUG;_DEBUG;_DBG;URTBLDENV_FRIENDLY=Checked;BUILDENV_CHECKED=1>") +add_compile_definitions("$<$,$>:NDEBUG;URTBLDENV_FRIENDLY=Retail>") + +if (MSVC) + add_linker_flag(/guard:cf) + + # Linker flags + # + set (WINDOWS_SUBSYSTEM_VERSION 6.01) + + if (CLR_CMAKE_HOST_ARCH_ARM) + set(WINDOWS_SUBSYSTEM_VERSION 6.02) #windows subsystem - arm minimum is 6.02 + elseif(CLR_CMAKE_HOST_ARCH_ARM64) + set(WINDOWS_SUBSYSTEM_VERSION 6.03) #windows subsystem - arm64 minimum is 6.03 + endif () + + #Do not create Side-by-Side Assembly Manifest + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO") + # can handle addresses larger than 2 gigabytes + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LARGEADDRESSAWARE") + #shrink pdb size + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /PDBCOMPRESS") + + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4197,4013,4254,4070,4221") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,${WINDOWS_SUBSYSTEM_VERSION}") + + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221") + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /PDBCOMPRESS") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1572864") + + # Checked build specific flags + add_linker_flag(/INCREMENTAL:NO CHECKED) # prevent "warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:REF' specification" + add_linker_flag(/OPT:REF CHECKED) + add_linker_flag(/OPT:NOICF CHECKED) + + # Release build specific flags + add_linker_flag(/LTCG RELEASE) + add_linker_flag(/OPT:REF RELEASE) + add_linker_flag(/OPT:ICF RELEASE) + add_linker_flag(/INCREMENTAL:NO RELEASE) + set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG") + + # ReleaseWithDebugInfo build specific flags + add_linker_flag(/LTCG RELWITHDEBINFO) + add_linker_flag(/OPT:REF RELWITHDEBINFO) + add_linker_flag(/OPT:ICF RELWITHDEBINFO) + set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO} /LTCG") + + # Force uCRT to be dynamically linked for Release build + add_linker_flag(/NODEFAULTLIB:libucrt.lib RELEASE) + add_linker_flag(/DEFAULTLIB:ucrt.lib RELEASE) + +elseif (CLR_CMAKE_HOST_UNIX) + # Set the values to display when interactively configuring CMAKE_BUILD_TYPE + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "DEBUG;CHECKED;RELEASE;RELWITHDEBINFO") + + # Use uppercase CMAKE_BUILD_TYPE for the string comparisons below + string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_CMAKE_BUILD_TYPE) + + set(CLR_SANITIZE_CXX_OPTIONS "") + set(CLR_SANITIZE_LINK_OPTIONS "") + + # set the CLANG sanitizer flags for debug build + if(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL CHECKED) + # obtain settings from running enablesanitizers.sh + string(FIND "$ENV{DEBUG_SANITIZERS}" "asan" __ASAN_POS) + string(FIND "$ENV{DEBUG_SANITIZERS}" "ubsan" __UBSAN_POS) + if ((${__ASAN_POS} GREATER -1) OR (${__UBSAN_POS} GREATER -1)) + list(APPEND CLR_SANITIZE_CXX_OPTIONS -fsanitize-blacklist=${CMAKE_CURRENT_SOURCE_DIR}/sanitizerblacklist.txt) + set (CLR_CXX_SANITIZERS "") + set (CLR_LINK_SANITIZERS "") + if (${__ASAN_POS} GREATER -1) + list(APPEND CLR_CXX_SANITIZERS address) + list(APPEND CLR_LINK_SANITIZERS address) + set(CLR_SANITIZE_CXX_FLAGS "${CLR_SANITIZE_CXX_FLAGS}address,") + set(CLR_SANITIZE_LINK_FLAGS "${CLR_SANITIZE_LINK_FLAGS}address,") + add_definitions(-DHAS_ASAN) + message("Address Sanitizer (asan) enabled") + endif () + if (${__UBSAN_POS} GREATER -1) + # all sanitizier flags are enabled except alignment (due to heavy use of __unaligned modifier) + list(APPEND CLR_CXX_SANITIZERS + "bool" + bounds + enum + float-cast-overflow + float-divide-by-zero + "function" + integer + nonnull-attribute + null + object-size + "return" + returns-nonnull-attribute + shift + unreachable + vla-bound + vptr) + list(APPEND CLR_LINK_SANITIZERS + undefined) + message("Undefined Behavior Sanitizer (ubsan) enabled") + endif () + list(JOIN CLR_CXX_SANITIZERS "," CLR_CXX_SANITIZERS_OPTIONS) + list(APPEND CLR_SANITIZE_CXX_OPTIONS "-fsanitize=${CLR_CXX_SANITIZERS_OPTIONS}") + list(JOIN CLR_LINK_SANITIZERS "," CLR_LINK_SANITIZERS_OPTIONS) + list(APPEND CLR_SANITIZE_LINK_OPTIONS "-fsanitize=${CLR_LINK_SANITIZERS_OPTIONS}") + + # -fdata-sections -ffunction-sections: each function has own section instead of one per .o file (needed for --gc-sections) + # -O1: optimization level used instead of -O0 to avoid compile error "invalid operand for inline asm constraint" + add_compile_options("$<$,$>:${CLR_SANITIZE_CXX_OPTIONS};-fdata-sections;--ffunction-sections;-O1>") + add_linker_flag("${CLR_SANITIZE_LINK_OPTIONS}" DEBUG CHECKED) + # -Wl and --gc-sections: drop unused sections\functions (similar to Windows /Gy function-level-linking) + add_linker_flag("-Wl,--gc-sections" DEBUG CHECKED) + endif () + endif(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL CHECKED) + + if(CLR_CMAKE_HOST_BROWSER) + # The emscripten build has additional warnings so -Werror breaks + add_compile_options(-Wno-unused-parameter) + add_compile_options(-Wno-alloca) + add_compile_options(-Wno-implicit-int-float-conversion) + endif() +endif(MSVC) + +# CLR_ADDITIONAL_LINKER_FLAGS - used for passing additional arguments to linker +# CLR_ADDITIONAL_COMPILER_OPTIONS - used for passing additional arguments to compiler +# +# For example: +# ./build-native.sh cmakeargs "-DCLR_ADDITIONAL_COMPILER_OPTIONS=<...>" cmakeargs "-DCLR_ADDITIONAL_LINKER_FLAGS=<...>" +# +if(CLR_CMAKE_HOST_UNIX) + foreach(ADDTL_LINKER_FLAG ${CLR_ADDITIONAL_LINKER_FLAGS}) + add_linker_flag(${ADDTL_LINKER_FLAG}) + endforeach() +endif(CLR_CMAKE_HOST_UNIX) + +if(CLR_CMAKE_HOST_LINUX) + add_compile_options($<$:-Wa,--noexecstack>) + add_linker_flag(-Wl,--build-id=sha1) + add_linker_flag(-Wl,-z,relro,-z,now) +elseif(CLR_CMAKE_HOST_FREEBSD) + add_compile_options($<$:-Wa,--noexecstack>) + add_linker_flag("-Wl,--build-id=sha1") +elseif(CLR_CMAKE_HOST_SUNOS) + add_compile_options($<$:-Wa,--noexecstack>) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") + add_definitions(-D__EXTENSIONS__ -D_XPG4_2 -D_POSIX_PTHREAD_SEMANTICS) +elseif(CLR_CMAKE_HOST_OSX AND NOT CLR_CMAKE_HOST_IOS AND NOT CLR_CMAKE_HOST_TVOS) + add_definitions(-D_XOPEN_SOURCE) + add_linker_flag("-Wl,-bind_at_load") +endif() + +#------------------------------------ +# Definitions (for platform) +#----------------------------------- +if (CLR_CMAKE_HOST_ARCH_AMD64) + set(ARCH_HOST_NAME x64) + add_definitions(-DHOST_AMD64 -DHOST_64BIT) +elseif (CLR_CMAKE_HOST_ARCH_I386) + set(ARCH_HOST_NAME x86) + add_definitions(-DHOST_X86) +elseif (CLR_CMAKE_HOST_ARCH_ARM) + set(ARCH_HOST_NAME arm) + add_definitions(-DHOST_ARM) +elseif (CLR_CMAKE_HOST_ARCH_ARM64) + set(ARCH_HOST_NAME arm64) + add_definitions(-DHOST_ARM64 -DHOST_64BIT) +elseif (CLR_CMAKE_HOST_ARCH_S390X) + set(ARCH_HOST_NAME s390x) + add_definitions(-DHOST_S390X -DHOST_64BIT -DBIGENDIAN) +elseif (CLR_CMAKE_HOST_ARCH_WASM) + set(ARCH_HOST_NAME wasm) + add_definitions(-DHOST_WASM -DHOST_32BIT=1) +elseif (CLR_CMAKE_HOST_ARCH_MIPS64) + set(ARCH_HOST_NAME mips64) + add_definitions(-DHOST_MIPS64 -DHOST_64BIT=1) +else () + clr_unknown_arch() +endif () + +if (CLR_CMAKE_HOST_UNIX) + if(CLR_CMAKE_HOST_LINUX) + if(CLR_CMAKE_HOST_UNIX_AMD64) + message("Detected Linux x86_64") + elseif(CLR_CMAKE_HOST_UNIX_ARM) + message("Detected Linux ARM") + elseif(CLR_CMAKE_HOST_UNIX_ARM64) + message("Detected Linux ARM64") + elseif(CLR_CMAKE_HOST_UNIX_X86) + message("Detected Linux i686") + elseif(CLR_CMAKE_HOST_UNIX_S390X) + message("Detected Linux s390x") + else() + clr_unknown_arch() + endif() + endif(CLR_CMAKE_HOST_LINUX) +endif(CLR_CMAKE_HOST_UNIX) + +if (CLR_CMAKE_HOST_UNIX) + add_definitions(-DHOST_UNIX) + + if(CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_MACCATALYST) + add_definitions(-DHOST_OSX) + if(CLR_CMAKE_HOST_UNIX_AMD64) + message("Detected OSX x86_64") + elseif(CLR_CMAKE_HOST_UNIX_ARM64) + message("Detected OSX ARM64") + else() + clr_unknown_arch() + endif() + elseif(CLR_CMAKE_HOST_FREEBSD) + message("Detected FreeBSD amd64") + elseif(CLR_CMAKE_HOST_NETBSD) + message("Detected NetBSD amd64") + elseif(CLR_CMAKE_HOST_SUNOS) + message("Detected SunOS amd64") + endif(CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_MACCATALYST) +endif(CLR_CMAKE_HOST_UNIX) + +if (CLR_CMAKE_HOST_WIN32) + add_definitions(-DHOST_WINDOWS) + + # Define the CRT lib references that link into Desktop imports + set(STATIC_MT_CRT_LIB "libcmt$<$,$>:d>.lib") + set(STATIC_MT_VCRT_LIB "libvcruntime$<$,$>:d>.lib") + set(STATIC_MT_CPP_LIB "libcpmt$<$,$>:d>.lib") +endif(CLR_CMAKE_HOST_WIN32) + +# Unconditionally define _FILE_OFFSET_BITS as 64 on all platforms. +add_definitions(-D_FILE_OFFSET_BITS=64) + +# Architecture specific files folder name +if (CLR_CMAKE_TARGET_ARCH_AMD64) + set(ARCH_SOURCES_DIR amd64) + set(ARCH_TARGET_NAME x64) + add_compile_definitions($<$>>:TARGET_AMD64>) + add_compile_definitions($<$>>:TARGET_64BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_ARM64) + set(ARCH_SOURCES_DIR arm64) + set(ARCH_TARGET_NAME arm64) + add_compile_definitions($<$>>:TARGET_ARM64>) + add_compile_definitions($<$>>:TARGET_64BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_ARM) + set(ARCH_SOURCES_DIR arm) + set(ARCH_TARGET_NAME arm) + add_compile_definitions($<$>>:TARGET_ARM>) + add_compile_definitions($<$>>:TARGET_32BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_I386) + set(ARCH_TARGET_NAME x86) + set(ARCH_SOURCES_DIR i386) + add_compile_definitions($<$>>:TARGET_X86>) + add_compile_definitions($<$>>:TARGET_32BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_S390X) + set(ARCH_TARGET_NAME s390x) + set(ARCH_SOURCES_DIR s390x) + add_compile_definitions($<$>>:TARGET_S390X>) + add_compile_definitions($<$>>:TARGET_64BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_WASM) + set(ARCH_TARGET_NAME wasm) + set(ARCH_SOURCES_DIR wasm) + add_compile_definitions($<$>>:TARGET_WASM>) + add_compile_definitions($<$>>:TARGET_32BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_MIPS64) + set(ARCH_TARGET_NAME mips64) + set(ARCH_SOURCES_DIR mips64) + add_compile_definitions($<$>>:TARGET_MIPS64>) + add_compile_definitions($<$>>:TARGET_64BIT>) +else () + clr_unknown_arch() +endif () + +#-------------------------------------- +# Compile Options +#-------------------------------------- +if (CLR_CMAKE_HOST_UNIX) + # Disable frame pointer optimizations so profilers can get better call stacks + add_compile_options(-fno-omit-frame-pointer) + + # The -fms-extensions enable the stuff like __if_exists, __declspec(uuid()), etc. + add_compile_options(-fms-extensions) + #-fms-compatibility Enable full Microsoft Visual C++ compatibility + #-fms-extensions Accept some non-standard constructs supported by the Microsoft compiler + + # Make signed arithmetic overflow of addition, subtraction, and multiplication wrap around + # using twos-complement representation (this is normally undefined according to the C++ spec). + add_compile_options(-fwrapv) + + if(CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_MACCATALYST) + # We cannot enable "stack-protector-strong" on OS X due to a bug in clang compiler (current version 7.0.2) + add_compile_options(-fstack-protector) + elseif(NOT CLR_CMAKE_HOST_BROWSER) + check_c_compiler_flag(-fstack-protector-strong COMPILER_SUPPORTS_F_STACK_PROTECTOR_STRONG) + if (COMPILER_SUPPORTS_F_STACK_PROTECTOR_STRONG) + add_compile_options(-fstack-protector-strong) + endif() + endif(CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_MACCATALYST) + + # Suppress warnings-as-errors in release branches to reduce servicing churn + if (PRERELEASE) + add_compile_options(-Werror) + endif(PRERELEASE) + + # Disabled common warnings + add_compile_options(-Wno-unused-variable) + add_compile_options(-Wno-unused-value) + add_compile_options(-Wno-unused-function) + add_compile_options(-Wno-tautological-compare) + add_compile_options(-Wno-unknown-pragmas) + + # Explicitly enabled warnings + check_c_compiler_flag(-Wimplicit-fallthrough COMPILER_SUPPORTS_W_IMPLICIT_FALLTHROUGH) + if (COMPILER_SUPPORTS_W_IMPLICIT_FALLTHROUGH) + add_compile_options(-Wimplicit-fallthrough) + endif() + + #These seem to indicate real issues + add_compile_options($<$:-Wno-invalid-offsetof>) + + add_compile_options(-Wno-unused-but-set-variable) + + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-unknown-warning-option) + + # The -ferror-limit is helpful during the porting, it makes sure the compiler doesn't stop + # after hitting just about 20 errors. + add_compile_options(-ferror-limit=4096) + + # Disabled warnings + add_compile_options(-Wno-unused-private-field) + # There are constants of type BOOL used in a condition. But BOOL is defined as int + # and so the compiler thinks that there is a mistake. + add_compile_options(-Wno-constant-logical-operand) + # We use pshpack1/2/4/8.h and poppack.h headers to set and restore packing. However + # clang 6.0 complains when the packing change lifetime is not contained within + # a header file. + add_compile_options(-Wno-pragma-pack) + + # The following warning indicates that an attribute __attribute__((__ms_struct__)) was applied + # to a struct or a class that has virtual members or a base class. In that case, clang + # may not generate the same object layout as MSVC. + add_compile_options(-Wno-incompatible-ms-struct) + + add_compile_options(-Wno-reserved-identifier) + else() + add_compile_options(-Wno-uninitialized) + add_compile_options(-Wno-strict-aliasing) + add_compile_options(-Wno-array-bounds) + add_compile_options($<$:-Wno-class-memaccess>) + add_compile_options($<$:-Wno-misleading-indentation>) + add_compile_options($<$:-Wno-stringop-overflow>) + add_compile_options($<$:-Wno-stringop-truncation>) + add_compile_options($<$:-Wno-placement-new>) + + if (CMAKE_CXX_COMPILER_ID) + check_cxx_compiler_flag(-faligned-new COMPILER_SUPPORTS_F_ALIGNED_NEW) + if (COMPILER_SUPPORTS_F_ALIGNED_NEW) + add_compile_options($<$:-faligned-new>) + endif() + endif() + endif() + + # Some architectures (e.g., ARM) assume char type is unsigned while CoreCLR assumes char is signed + # as x64 does. It has been causing issues in ARM (https://github.com/dotnet/runtime/issues/5778) + add_compile_options(-fsigned-char) + + # We mark the function which needs exporting with DLLEXPORT + add_compile_options(-fvisibility=hidden) + + # Specify the minimum supported version of macOS + # Mac Catalyst needs a special CFLAG, exclusive with mmacosx-version-min + if(CLR_CMAKE_HOST_MACCATALYST) + # Somewhere between CMake 3.17 and 3.19.4, it became impossible to not pass + # a value for mmacosx-version-min (blank CMAKE_OSX_DEPLOYMENT_TARGET gets + # replaced with a default value, and always gets expanded to an OS version. + # https://gitlab.kitware.com/cmake/cmake/-/issues/20132 + # We need to disable the warning that -tagret replaces -mmacosx-version-min + set(DISABLE_OVERRIDING_MIN_VERSION_ERROR -Wno-overriding-t-option) + add_link_options(-Wno-overriding-t-option) + if(CLR_CMAKE_HOST_ARCH_ARM64) + set(MACOS_VERSION_MIN_FLAGS "-target arm64-apple-ios14.2-macabi") + add_link_options(-target arm64-apple-ios14.2-macabi) + elseif(CLR_CMAKE_HOST_ARCH_AMD64) + set(MACOS_VERSION_MIN_FLAGS "-target x86_64-apple-ios13.5-macabi") + add_link_options(-target x86_64-apple-ios13.5-macabi) + else() + clr_unknown_arch() + endif() + # These options are intentionally set using the CMAKE_XXX_FLAGS instead of + # add_compile_options so that they take effect on the configuration functions + # in various configure.cmake files. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") + elseif(CLR_CMAKE_HOST_OSX) + if(CLR_CMAKE_HOST_ARCH_ARM64) + set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") + add_compile_options(-arch arm64) + elseif(CLR_CMAKE_HOST_ARCH_AMD64) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") + add_compile_options(-arch x86_64) + else() + clr_unknown_arch() + endif() + endif(CLR_CMAKE_HOST_MACCATALYST) + +endif(CLR_CMAKE_HOST_UNIX) + +if(CLR_CMAKE_TARGET_UNIX) + add_compile_definitions($<$>>:TARGET_UNIX>) + # Contracts are disabled on UNIX. + add_definitions(-DDISABLE_CONTRACTS) + if(CLR_CMAKE_TARGET_OSX AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS) + add_compile_definitions($<$>>:TARGET_OSX>) + elseif(CLR_CMAKE_TARGET_FREEBSD) + add_compile_definitions($<$>>:TARGET_FREEBSD>) + elseif(CLR_CMAKE_TARGET_ANDROID) + add_compile_definitions($<$>>:TARGET_ANDROID>) + elseif(CLR_CMAKE_TARGET_LINUX) + add_compile_definitions($<$>>:TARGET_LINUX>) + elseif(CLR_CMAKE_TARGET_NETBSD) + add_compile_definitions($<$>>:TARGET_NETBSD>) + elseif(CLR_CMAKE_TARGET_SUNOS) + add_compile_definitions($<$>>:TARGET_SUNOS>) + endif() +else(CLR_CMAKE_TARGET_UNIX) + add_compile_definitions($<$>>:TARGET_WINDOWS>) +endif(CLR_CMAKE_TARGET_UNIX) + +if(CLR_CMAKE_HOST_UNIX_ARM) + if (NOT DEFINED CLR_ARM_FPU_TYPE) + set(CLR_ARM_FPU_TYPE vfpv3) + endif(NOT DEFINED CLR_ARM_FPU_TYPE) + + # Because we don't use CMAKE_C_COMPILER/CMAKE_CXX_COMPILER to use clang + # we have to set the triple by adding a compiler argument + add_compile_options(-mthumb) + add_compile_options(-mfpu=${CLR_ARM_FPU_TYPE}) + if (NOT DEFINED CLR_ARM_FPU_CAPABILITY) + set(CLR_ARM_FPU_CAPABILITY 0x7) + endif(NOT DEFINED CLR_ARM_FPU_CAPABILITY) + add_definitions(-DCLR_ARM_FPU_CAPABILITY=${CLR_ARM_FPU_CAPABILITY}) + add_compile_options(-march=armv7-a) + if(ARM_SOFTFP) + add_definitions(-DARM_SOFTFP) + add_compile_options(-mfloat-abi=softfp) + endif(ARM_SOFTFP) +endif(CLR_CMAKE_HOST_UNIX_ARM) + +if(CLR_CMAKE_HOST_UNIX_X86) + add_compile_options(-msse2) +endif() + +if(CLR_CMAKE_HOST_UNIX) + add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS}) +endif(CLR_CMAKE_HOST_UNIX) + +if (MSVC) + # Compile options for targeting windows + + add_compile_options($<$:/nologo>) # Suppress Startup Banner + # /W3 is added by default by CMake, so remove it + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REPLACE "/W3" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + # set default warning level to 3 but allow targets to override it. + add_compile_options($<$:/W$>,$,3>>>) + add_compile_options($<$:/WX>) # treat warnings as errors + add_compile_options($<$:/Oi>) # enable intrinsics + add_compile_options($<$:/Oy->) # disable suppressing of the creation of frame pointers on the call stack for quicker function calls + add_compile_options($<$:/Gm->) # disable minimal rebuild + add_compile_options($<$:/Zp8>) # pack structs on 8-byte boundary + add_compile_options($<$:/Gy>) # separate functions for linker + add_compile_options($<$:/GS>) # Explicitly enable the buffer security checks + add_compile_options($<$:/fp:precise>) # Enable precise floating point + + # disable C++ RTTI + # /GR is added by default by CMake, so remove it manually. + string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-") + + add_compile_options($<$:/FC>) # use full pathnames in diagnostics + add_compile_options($<$:/MP>) # Build with Multiple Processes (number of processes equal to the number of processors) + add_compile_options($<$:/Zm200>) # Specify Precompiled Header Memory Allocation Limit of 150MB + add_compile_options($<$:/Zc:strictStrings>) # Disable string-literal to char* or wchar_t* conversion + add_compile_options($<$:/Zc:wchar_t>) # wchar_t is a built-in type. + add_compile_options($<$:/Zc:inline>) # All inline functions must have their definition available in the current translation unit. + add_compile_options($<$:/Zc:forScope>) # Enforce standards-compliant for scope. + + # Disable Warnings: + add_compile_options($<$:/wd4065>) # switch statement contains 'default' but no 'case' labels + add_compile_options($<$:/wd4100>) # 'identifier' : unreferenced formal parameter + add_compile_options($<$:/wd4127>) # conditional expression is constant + add_compile_options($<$:/wd4189>) # local variable is initialized but not referenced + add_compile_options($<$:/wd4200>) # nonstandard extension used : zero-sized array in struct/union + add_compile_options($<$:/wd4201>) # nonstandard extension used : nameless struct/union + add_compile_options($<$:/wd4245>) # conversion from 'type1' to 'type2', signed/unsigned mismatch + add_compile_options($<$:/wd4291>) # no matching operator delete found; memory will not be freed if initialization throws an exception + add_compile_options($<$:/wd4456>) # declaration of 'identifier' hides previous local declaration + add_compile_options($<$:/wd4457>) # declaration of 'identifier' hides function parameter + add_compile_options($<$:/wd4458>) # declaration of 'identifier' hides class member + add_compile_options($<$:/wd4733>) # Inline asm assigning to 'FS:0' : handler not registered as safe handler + add_compile_options($<$:/wd4838>) # conversion from 'type_1' to 'type_2' requires a narrowing conversion + add_compile_options($<$:/wd4960>) # 'function' is too big to be profiled + add_compile_options($<$:/wd4961>) # No profile data was merged into '.pgd file', profile-guided optimizations disabled + add_compile_options($<$:/wd5105>) # macro expansion producing 'defined' has undefined behavior + + # Treat Warnings as Errors: + add_compile_options($<$:/we4007>) # 'main' : must be __cdecl. + add_compile_options($<$:/we4013>) # 'function' undefined - assuming extern returning int. + add_compile_options($<$:/we4102>) # "'%$S' : unreferenced label". + add_compile_options($<$:/we4551>) # Function call missing argument list. + add_compile_options($<$:/we4700>) # Local used w/o being initialized. + add_compile_options($<$:/we4640>) # 'instance' : construction of local static object is not thread-safe + add_compile_options($<$:/we4806>) # Unsafe operation involving type 'bool'. + + # Set Warning Level 3: + add_compile_options($<$:/w34092>) # Sizeof returns 'unsigned long'. + add_compile_options($<$:/w34121>) # Structure is sensitive to alignment. + add_compile_options($<$:/w34125>) # Decimal digit in octal sequence. + add_compile_options($<$:/w34130>) # Logical operation on address of string constant. + add_compile_options($<$:/w34132>) # Const object should be initialized. + add_compile_options($<$:/w34212>) # Function declaration used ellipsis. + add_compile_options($<$:/w34530>) # C++ exception handler used, but unwind semantics are not enabled. Specify -GX. + add_compile_options($<$:/w35038>) # data member 'member1' will be initialized after data member 'member2'. + + # Set Warning Level 4: + add_compile_options($<$:/w44177>) # Pragma data_seg s/b at global scope. + + add_compile_options($<$:/Zi>) # enable debugging information + add_compile_options($<$:/ZH:SHA_256>) # use SHA256 for generating hashes of compiler processed source files. + add_compile_options($<$:/source-charset:utf-8>) # Force MSVC to compile source as UTF-8. + + if (CLR_CMAKE_HOST_ARCH_I386) + add_compile_options($<$:/Gz>) + endif (CLR_CMAKE_HOST_ARCH_I386) + + add_compile_options($<$,$,$>>:/GL>) + + if (CLR_CMAKE_HOST_ARCH_AMD64) + # The generator expression in the following command means that the /homeparams option is added only for debug builds for C and C++ source files + add_compile_options($<$,$>:/homeparams>) # Force parameters passed in registers to be written to the stack + endif (CLR_CMAKE_HOST_ARCH_AMD64) + + # enable control-flow-guard support for native components for non-Arm64 builds + # Added using variables instead of add_compile_options to let individual projects override it + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /guard:cf") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /guard:cf") + + # Enable EH-continuation table and CET-compatibility for native components for amd64 builds except for components of the Mono + # runtime. Added some switches using variables instead of add_compile_options to let individual projects override it. + if (CLR_CMAKE_HOST_ARCH_AMD64 AND NOT CLR_CMAKE_RUNTIME_MONO) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /guard:ehcont") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /guard:ehcont") + set(CMAKE_ASM_MASM_FLAGS "${CMAKE_ASM_MASM_FLAGS} /guard:ehcont") + add_linker_flag(/guard:ehcont) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /CETCOMPAT") + endif (CLR_CMAKE_HOST_ARCH_AMD64 AND NOT CLR_CMAKE_RUNTIME_MONO) + + # Statically linked CRT (libcmt[d].lib, libvcruntime[d].lib and libucrt[d].lib) by default. This is done to avoid + # linking in VCRUNTIME140.DLL for a simplified xcopy experience by reducing the dependency on VC REDIST. + # + # For Release builds, we shall dynamically link into uCRT [ucrtbase.dll] (which is pushed down as a Windows Update on downlevel OS) but + # wont do the same for debug/checked builds since ucrtbased.dll is not redistributable and Debug/Checked builds are not + # production-time scenarios. + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$,$>,$>>>:Debug>) + + add_compile_options($<$:/ZH:SHA_256>) + + if (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64) + # Contracts work too slow on ARM/ARM64 DEBUG/CHECKED. + add_definitions(-DDISABLE_CONTRACTS) + endif (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64) + + # Don't display the output header when building RC files. + add_compile_options($<$:/nologo>) +endif (MSVC) + +if(CLR_CMAKE_ENABLE_CODE_COVERAGE) + + if(CLR_CMAKE_HOST_UNIX) + string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_CMAKE_BUILD_TYPE) + if(NOT UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG) + message( WARNING "Code coverage results with an optimised (non-Debug) build may be misleading" ) + endif(NOT UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG) + + add_compile_options(-fprofile-arcs) + add_compile_options(-ftest-coverage) + add_linker_flag(--coverage) + else() + message(FATAL_ERROR "Code coverage builds not supported on current platform") + endif(CLR_CMAKE_HOST_UNIX) + +endif(CLR_CMAKE_ENABLE_CODE_COVERAGE) + +if (CMAKE_GENERATOR MATCHES "(Makefile|Ninja)") + set(CMAKE_RC_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY}") +endif() + +# Ensure other tools are present +if (CLR_CMAKE_HOST_WIN32) + if(CLR_CMAKE_HOST_ARCH_ARM) + + # Explicitly specify the assembler to be used for Arm32 compile + file(TO_CMAKE_PATH "$ENV{VCToolsInstallDir}\\bin\\HostX86\\arm\\armasm.exe" CMAKE_ASM_COMPILER) + + set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER}) + message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}") + + # Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly + # use ml[64].exe as the assembler. + enable_language(ASM) + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "") + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "") + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "") + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "") + set(CMAKE_ASM_COMPILE_OBJECT " -g -o ") + + elseif(CLR_CMAKE_HOST_ARCH_ARM64) + + # Explicitly specify the assembler to be used for Arm64 compile + file(TO_CMAKE_PATH "$ENV{VCToolsInstallDir}\\bin\\HostX86\\arm64\\armasm64.exe" CMAKE_ASM_COMPILER) + + set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER}) + message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}") + + # Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly + # use ml[64].exe as the assembler. + enable_language(ASM) + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "") + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "") + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "") + set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "") + set(CMAKE_ASM_COMPILE_OBJECT " -g -o ") + else() + enable_language(ASM_MASM) + set(CMAKE_ASM_MASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "") + set(CMAKE_ASM_MASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "") + set(CMAKE_ASM_MASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "") + set(CMAKE_ASM_MASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "") + endif() + + # Ensure that MC is present + find_program(MC mc) + if (MC STREQUAL "MC-NOTFOUND") + message(FATAL_ERROR "MC not found") + endif() + +elseif (NOT CLR_CMAKE_HOST_BROWSER) + enable_language(ASM) + +endif(CLR_CMAKE_HOST_WIN32) diff --git a/eng/native/configureoptimization.cmake b/eng/native/configureoptimization.cmake new file mode 100644 index 000000000..50c7b1cfa --- /dev/null +++ b/eng/native/configureoptimization.cmake @@ -0,0 +1,17 @@ +if(CLR_CMAKE_HOST_WIN32) + add_compile_options($<$,$>:/Od>) + if (CLR_CMAKE_HOST_ARCH_I386) + # The Windows x86 Checked CLR has some kind of problem with exception handling + # when compiled with /O2. Issue: https://github.com/dotnet/runtime/issues/59845. + add_compile_options($<$,$>:/O1>) + else() + add_compile_options($<$,$>:/O2>) + endif() + add_compile_options($<$,$>:/Ox>) + add_compile_options($<$,$>:/O2>) +elseif(CLR_CMAKE_HOST_UNIX) + add_compile_options($<$:-O0>) + add_compile_options($<$:-O2>) + add_compile_options($<$:-O3>) + add_compile_options($<$:-O2>) +endif() diff --git a/eng/native/configurepaths.cmake b/eng/native/configurepaths.cmake new file mode 100644 index 000000000..19407a40a --- /dev/null +++ b/eng/native/configurepaths.cmake @@ -0,0 +1,9 @@ +get_filename_component(CLR_REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../.. ABSOLUTE) +set(CLR_ENG_NATIVE_DIR ${CMAKE_CURRENT_LIST_DIR}) +get_filename_component(CLR_SRC_NATIVE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../src/native ABSOLUTE) +get_filename_component(CLR_SRC_LIBS_NATIVE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../src/libraries/Native ABSOLUTE) +set (CLR_ARTIFACTS_OBJ_DIR "${CLR_REPO_ROOT_DIR}/artifacts/obj") +set(VERSION_HEADER_PATH "${CLR_ARTIFACTS_OBJ_DIR}/_version.h") +set(VERSION_FILE_PATH "${CLR_ARTIFACTS_OBJ_DIR}/_version.c") +set(VERSION_FILE_RC_PATH "${CLR_ARTIFACTS_OBJ_DIR}/NativeVersion.rc") +set(RUNTIME_VERSION_HEADER_PATH "${CLR_ARTIFACTS_OBJ_DIR}/runtime_version.h") diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake new file mode 100644 index 000000000..f5c8abe66 --- /dev/null +++ b/eng/native/configureplatform.cmake @@ -0,0 +1,427 @@ +include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake) + +# If set, indicates that this is not an officially supported release +# Keep in sync with IsPrerelease in Directory.Build.props +set(PRERELEASE 1) + +#---------------------------------------- +# Detect and set platform variable names +# - for non-windows build platform & architecture is detected using inbuilt CMAKE variables and cross target component configure +# - for windows we use the passed in parameter to CMAKE to determine build arch +#---------------------------------------- +set(CLR_CMAKE_HOST_OS ${CMAKE_SYSTEM_NAME}) +if(CLR_CMAKE_HOST_OS STREQUAL Linux) + set(CLR_CMAKE_HOST_UNIX 1) + if(CLR_CROSS_COMPONENTS_BUILD) + # CMAKE_HOST_SYSTEM_PROCESSOR returns the value of `uname -p` on host. + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL amd64) + if(CLR_CMAKE_TARGET_ARCH STREQUAL "arm" OR CLR_CMAKE_TARGET_ARCH STREQUAL "armel") + if(CMAKE_CROSSCOMPILING) + set(CLR_CMAKE_HOST_UNIX_X86 1) + else() + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + endif() + else() + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + endif() + elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL i686) + set(CLR_CMAKE_HOST_UNIX_X86 1) + else() + clr_unknown_arch() + endif() + else() + # CMAKE_SYSTEM_PROCESSOR returns the value of `uname -p` on target. + # For the AMD/Intel 64bit architecture two different strings are common. + # Linux and Darwin identify it as "x86_64" while FreeBSD and netbsd uses the + # "amd64" string. Accept either of the two here. + if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l) + set(CLR_CMAKE_HOST_UNIX_ARM 1) + set(CLR_CMAKE_HOST_UNIX_ARMV7L 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL arm OR CMAKE_SYSTEM_PROCESSOR STREQUAL armv7-a) + set(CLR_CMAKE_HOST_UNIX_ARM 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) + set(CLR_CMAKE_HOST_UNIX_ARM64 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686 OR CMAKE_SYSTEM_PROCESSOR STREQUAL x86) + set(CLR_CMAKE_HOST_UNIX_X86 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL s390x) + set(CLR_CMAKE_HOST_UNIX_S390X 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL mips64) + set(CLR_CMAKE_HOST_UNIX_MIPS64 1) + else() + clr_unknown_arch() + endif() + endif() + set(CLR_CMAKE_HOST_LINUX 1) + + # Detect Linux ID + set(LINUX_ID_FILE "/etc/os-release") + if(CMAKE_CROSSCOMPILING) + set(LINUX_ID_FILE "${CMAKE_SYSROOT}${LINUX_ID_FILE}") + endif() + + if(EXISTS ${LINUX_ID_FILE}) + execute_process( + COMMAND bash -c "source ${LINUX_ID_FILE} && echo \$ID" + OUTPUT_VARIABLE CLR_CMAKE_LINUX_ID + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + + if(DEFINED CLR_CMAKE_LINUX_ID) + if(CLR_CMAKE_LINUX_ID STREQUAL tizen) + set(CLR_CMAKE_TARGET_TIZEN_LINUX 1) + set(CLR_CMAKE_HOST_OS ${CLR_CMAKE_LINUX_ID}) + elseif(CLR_CMAKE_LINUX_ID STREQUAL alpine) + set(CLR_CMAKE_HOST_ALPINE_LINUX 1) + set(CLR_CMAKE_HOST_OS ${CLR_CMAKE_LINUX_ID}) + endif() + endif(DEFINED CLR_CMAKE_LINUX_ID) +endif(CLR_CMAKE_HOST_OS STREQUAL Linux) + +if(CLR_CMAKE_HOST_OS STREQUAL Darwin) + set(CLR_CMAKE_HOST_UNIX 1) + + if(CMAKE_SYSTEM_VARIANT STREQUAL MacCatalyst) + set(CLR_CMAKE_HOST_MACCATALYST 1) + else() + set(CLR_CMAKE_HOST_OSX 1) + endif(CMAKE_SYSTEM_VARIANT STREQUAL MacCatalyst) + + if(CMAKE_OSX_ARCHITECTURES STREQUAL x86_64) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + elseif(CMAKE_OSX_ARCHITECTURES STREQUAL arm64) + set(CLR_CMAKE_HOST_UNIX_ARM64 1) + else() + clr_unknown_arch() + endif() + set(CMAKE_ASM_COMPILE_OBJECT "${CMAKE_C_COMPILER} -o -c ") +endif(CLR_CMAKE_HOST_OS STREQUAL Darwin) + +if(CLR_CMAKE_HOST_OS STREQUAL iOS OR CLR_CMAKE_HOST_OS STREQUAL iOSSimulator) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_IOS 1) + if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + elseif(CMAKE_OSX_ARCHITECTURES MATCHES "i386") + set(CLR_CMAKE_HOST_UNIX_X86 1) + elseif(CMAKE_OSX_ARCHITECTURES MATCHES "armv7") + set(CLR_CMAKE_HOST_UNIX_ARM 1) + elseif(CMAKE_OSX_ARCHITECTURES MATCHES "arm64") + set(CLR_CMAKE_HOST_UNIX_ARM64 1) + else() + clr_unknown_arch() + endif() +endif(CLR_CMAKE_HOST_OS STREQUAL iOS OR CLR_CMAKE_HOST_OS STREQUAL iOSSimulator) + +if(CLR_CMAKE_HOST_OS STREQUAL tvOS OR CLR_CMAKE_HOST_OS STREQUAL tvOSSimulator) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_TVOS 1) + if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + elseif(CMAKE_OSX_ARCHITECTURES MATCHES "arm64") + set(CLR_CMAKE_HOST_UNIX_ARM64 1) + else() + clr_unknown_arch() + endif() +endif(CLR_CMAKE_HOST_OS STREQUAL tvOS OR CLR_CMAKE_HOST_OS STREQUAL tvOSSimulator) + +if(CLR_CMAKE_HOST_OS STREQUAL Android) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_LINUX 1) + set(CLR_CMAKE_HOST_ANDROID 1) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7-a) + set(CLR_CMAKE_HOST_UNIX_ARM 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) + set(CLR_CMAKE_HOST_UNIX_ARM64 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686) + set(CLR_CMAKE_HOST_UNIX_X86 1) + else() + clr_unknown_arch() + endif() +endif(CLR_CMAKE_HOST_OS STREQUAL Android) + +if(CLR_CMAKE_HOST_OS STREQUAL FreeBSD) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + set(CLR_CMAKE_HOST_FREEBSD 1) +endif(CLR_CMAKE_HOST_OS STREQUAL FreeBSD) + +if(CLR_CMAKE_HOST_OS STREQUAL OpenBSD) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + set(CLR_CMAKE_HOST_OPENBSD 1) +endif(CLR_CMAKE_HOST_OS STREQUAL OpenBSD) + +if(CLR_CMAKE_HOST_OS STREQUAL NetBSD) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + set(CLR_CMAKE_HOST_NETBSD 1) +endif(CLR_CMAKE_HOST_OS STREQUAL NetBSD) + +if(CLR_CMAKE_HOST_OS STREQUAL SunOS) + set(CLR_CMAKE_HOST_UNIX 1) + EXECUTE_PROCESS( + COMMAND isainfo -n + OUTPUT_VARIABLE SUNOS_NATIVE_INSTRUCTION_SET) + + if(SUNOS_NATIVE_INSTRUCTION_SET MATCHES "amd64" OR CMAKE_CROSSCOMPILING) + set(CLR_CMAKE_HOST_UNIX_AMD64 1) + set(CMAKE_SYSTEM_PROCESSOR "amd64") + else() + clr_unknown_arch() + endif() + + EXECUTE_PROCESS( + COMMAND uname -o + OUTPUT_VARIABLE SUNOS_KERNEL_KIND + ERROR_QUIET) + + set(CLR_CMAKE_HOST_SUNOS 1) + if(SUNOS_KERNEL_KIND STREQUAL illumos OR CMAKE_CROSSCOMPILING) + set(CLR_CMAKE_HOST_OS_ILLUMOS 1) + else(SUNOS_KERNEL_KIND STREQUAL illumos OR CMAKE_CROSSCOMPILING) + set(CLR_CMAKE_HOST_OS_SOLARIS 1) + endif(SUNOS_KERNEL_KIND STREQUAL illumos OR CMAKE_CROSSCOMPILING) +endif(CLR_CMAKE_HOST_OS STREQUAL SunOS) + +if(CLR_CMAKE_HOST_OS STREQUAL Windows) + set(CLR_CMAKE_HOST_OS windows) + set(CLR_CMAKE_HOST_WIN32 1) +endif(CLR_CMAKE_HOST_OS STREQUAL Windows) + +if(CLR_CMAKE_HOST_OS STREQUAL Emscripten) + set(CLR_CMAKE_HOST_UNIX 1) + set(CLR_CMAKE_HOST_BROWSER 1) +endif(CLR_CMAKE_HOST_OS STREQUAL Emscripten) + +#-------------------------------------------- +# This repo builds two set of binaries +# 1. binaries which execute on target arch machine +# - for such binaries host architecture & target architecture are same +# - eg. coreclr.dll +# 2. binaries which execute on host machine but target another architecture +# - host architecture is different from target architecture +# - eg. crossgen.exe - runs on x64 machine and generates nis targeting arm64 +# - for complete list of such binaries refer to file crosscomponents.cmake +#------------------------------------------------------------- +# Set HOST architecture variables +if(CLR_CMAKE_HOST_UNIX_ARM) + set(CLR_CMAKE_HOST_ARCH_ARM 1) + set(CLR_CMAKE_HOST_ARCH "arm") + + if(CLR_CMAKE_HOST_UNIX_ARMV7L) + set(CLR_CMAKE_HOST_ARCH_ARMV7L 1) + endif() +elseif(CLR_CMAKE_HOST_UNIX_ARM64) + set(CLR_CMAKE_HOST_ARCH_ARM64 1) + set(CLR_CMAKE_HOST_ARCH "arm64") +elseif(CLR_CMAKE_HOST_UNIX_AMD64) + set(CLR_CMAKE_HOST_ARCH_AMD64 1) + set(CLR_CMAKE_HOST_ARCH "x64") +elseif(CLR_CMAKE_HOST_UNIX_X86) + set(CLR_CMAKE_HOST_ARCH_I386 1) + set(CLR_CMAKE_HOST_ARCH "x86") +elseif(CLR_CMAKE_HOST_UNIX_S390X) + set(CLR_CMAKE_HOST_ARCH_S390X 1) + set(CLR_CMAKE_HOST_ARCH "s390x") +elseif(CLR_CMAKE_HOST_BROWSER) + set(CLR_CMAKE_HOST_ARCH_WASM 1) + set(CLR_CMAKE_HOST_ARCH "wasm") +elseif(CLR_CMAKE_HOST_UNIX_MIPS64) + set(CLR_CMAKE_HOST_ARCH_MIPS64 1) + set(CLR_CMAKE_HOST_ARCH "mips64") +elseif(WIN32) + # CLR_CMAKE_HOST_ARCH is passed in as param to cmake + if (CLR_CMAKE_HOST_ARCH STREQUAL x64) + set(CLR_CMAKE_HOST_ARCH_AMD64 1) + elseif(CLR_CMAKE_HOST_ARCH STREQUAL x86) + set(CLR_CMAKE_HOST_ARCH_I386 1) + elseif(CLR_CMAKE_HOST_ARCH STREQUAL arm) + set(CLR_CMAKE_HOST_ARCH_ARM 1) + elseif(CLR_CMAKE_HOST_ARCH STREQUAL arm64) + set(CLR_CMAKE_HOST_ARCH_ARM64 1) + else() + clr_unknown_arch() + endif() +endif() + +# Set TARGET architecture variables +# Target arch will be a cmake param (optional) for both windows as well as non-windows build +# if target arch is not specified then host & target are same +if(NOT DEFINED CLR_CMAKE_TARGET_ARCH OR CLR_CMAKE_TARGET_ARCH STREQUAL "" ) + set(CLR_CMAKE_TARGET_ARCH ${CLR_CMAKE_HOST_ARCH}) + + # This is required for "arm" targets (CMAKE_SYSTEM_PROCESSOR "armv7l"), + # for which this flag otherwise won't be set up below + if (CLR_CMAKE_HOST_ARCH_ARMV7L) + set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1) + endif() +endif() + +# Set target architecture variables +if (CLR_CMAKE_TARGET_ARCH STREQUAL x64) + set(CLR_CMAKE_TARGET_ARCH_AMD64 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL x86) + set(CLR_CMAKE_TARGET_ARCH_I386 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm64) + set(CLR_CMAKE_TARGET_ARCH_ARM64 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm) + set(CLR_CMAKE_TARGET_ARCH_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armel) + set(CLR_CMAKE_TARGET_ARCH_ARM 1) + set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1) + set(ARM_SOFTFP 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL s390x) + set(CLR_CMAKE_TARGET_ARCH_S390X 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm) + set(CLR_CMAKE_TARGET_ARCH_WASM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL mips64) + set(CLR_CMAKE_TARGET_ARCH_MIPS64 1) + else() + clr_unknown_arch() +endif() + +# Set TARGET architecture variables +# Target os will be a cmake param (optional) for both windows as well as non-windows build +# if target os is not specified then host & target os are same +if (NOT DEFINED CLR_CMAKE_TARGET_OS OR CLR_CMAKE_TARGET_OS STREQUAL "" ) + set(CLR_CMAKE_TARGET_OS ${CLR_CMAKE_HOST_OS}) +endif() + +if(CLR_CMAKE_TARGET_OS STREQUAL Linux) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_LINUX 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL Linux) + +if(CLR_CMAKE_TARGET_OS STREQUAL tizen) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_LINUX 1) + set(CLR_CMAKE_TARGET_TIZEN_LINUX 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL tizen) + +if(CLR_CMAKE_TARGET_OS STREQUAL alpine) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_LINUX 1) + set(CLR_CMAKE_TARGET_ALPINE_LINUX 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL alpine) + +if(CLR_CMAKE_TARGET_OS STREQUAL Android) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_LINUX 1) + set(CLR_CMAKE_TARGET_ANDROID 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL Android) + +if(CLR_CMAKE_TARGET_OS STREQUAL Darwin) + set(CLR_CMAKE_TARGET_UNIX 1) + + if(CMAKE_SYSTEM_VARIANT STREQUAL MacCatalyst) + set(CLR_CMAKE_TARGET_MACCATALYST 1) + else() + set(CLR_CMAKE_TARGET_OSX 1) + endif(CMAKE_SYSTEM_VARIANT STREQUAL MacCatalyst) +endif(CLR_CMAKE_TARGET_OS STREQUAL Darwin) + +if(CLR_CMAKE_TARGET_OS STREQUAL iOS OR CLR_CMAKE_TARGET_OS STREQUAL iOSSimulator) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_IOS 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL iOS OR CLR_CMAKE_TARGET_OS STREQUAL iOSSimulator) + +if(CLR_CMAKE_TARGET_OS STREQUAL tvOS OR CLR_CMAKE_TARGET_OS STREQUAL tvOSSimulator) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_TVOS 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL tvOS OR CLR_CMAKE_TARGET_OS STREQUAL tvOSSimulator) + +if(CLR_CMAKE_TARGET_OS STREQUAL FreeBSD) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_FREEBSD 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL FreeBSD) + +if(CLR_CMAKE_TARGET_OS STREQUAL OpenBSD) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_OPENBSD 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL OpenBSD) + +if(CLR_CMAKE_TARGET_OS STREQUAL NetBSD) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_NETBSD 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL NetBSD) + +if(CLR_CMAKE_TARGET_OS STREQUAL SunOS) + set(CLR_CMAKE_TARGET_UNIX 1) + if(CLR_CMAKE_HOST_OS_ILLUMOS) + set(CLR_CMAKE_TARGET_OS_ILLUMOS 1) + else(CLR_CMAKE_HOST_OS_ILLUMOS) + set(CLR_CMAKE_TARGET_OS_SOLARIS 1) + endif(CLR_CMAKE_HOST_OS_ILLUMOS) + set(CLR_CMAKE_TARGET_SUNOS 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL SunOS) + +if(CLR_CMAKE_TARGET_OS STREQUAL Emscripten) + set(CLR_CMAKE_TARGET_UNIX 1) + set(CLR_CMAKE_TARGET_LINUX 1) + set(CLR_CMAKE_TARGET_BROWSER 1) +endif(CLR_CMAKE_TARGET_OS STREQUAL Emscripten) + +if(CLR_CMAKE_TARGET_UNIX) + if(CLR_CMAKE_TARGET_ARCH STREQUAL x64) + set(CLR_CMAKE_TARGET_UNIX_AMD64 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armel) + set(CLR_CMAKE_TARGET_UNIX_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm) + set(CLR_CMAKE_TARGET_UNIX_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm64) + set(CLR_CMAKE_TARGET_UNIX_ARM64 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL x86) + set(CLR_CMAKE_TARGET_UNIX_X86 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL s390x) + set(CLR_CMAKE_TARGET_UNIX_S390X 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm) + set(CLR_CMAKE_TARGET_UNIX_WASM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL mips64) + set(CLR_CMAKE_TARGET_UNIX_MIPS64 1) + else() + clr_unknown_arch() + endif() +else() + set(CLR_CMAKE_TARGET_WIN32 1) +endif(CLR_CMAKE_TARGET_UNIX) + +# check if host & target os/arch combination are valid +if (CLR_CMAKE_TARGET_OS STREQUAL CLR_CMAKE_HOST_OS) + if(NOT(CLR_CMAKE_TARGET_ARCH STREQUAL CLR_CMAKE_HOST_ARCH)) + if(NOT((CLR_CMAKE_HOST_ARCH_AMD64 AND CLR_CMAKE_TARGET_ARCH_ARM64) OR (CLR_CMAKE_HOST_ARCH_I386 AND CLR_CMAKE_TARGET_ARCH_ARM) OR (CLR_CMAKE_HOST_ARCH_AMD64 AND CLR_CMAKE_TARGET_ARCH_ARM) OR (CLR_CMAKE_HOST_ARCH_AMD64 AND CLR_CMAKE_TARGET_ARCH_I386))) + message(FATAL_ERROR "Invalid platform and target arch combination TARGET_ARCH=${CLR_CMAKE_TARGET_ARCH} HOST_ARCH=${CLR_CMAKE_HOST_ARCH}") + endif() + endif() +else() + if(NOT (CLR_CMAKE_HOST_OS STREQUAL windows)) + message(FATAL_ERROR "Invalid host and target os/arch combination. Host OS: ${CLR_CMAKE_HOST_OS}") + endif() + if(NOT (CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_ALPINE_LINUX)) + message(FATAL_ERROR "Invalid host and target os/arch combination. Target OS: ${CLR_CMAKE_TARGET_OS}") + endif() + if(NOT ((CLR_CMAKE_HOST_ARCH_AMD64 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64)) OR (CLR_CMAKE_HOST_ARCH_I386 AND CLR_CMAKE_TARGET_ARCH_ARM))) + message(FATAL_ERROR "Invalid host and target os/arch combination. Host Arch: ${CLR_CMAKE_HOST_ARCH} Target Arch: ${CLR_CMAKE_TARGET_ARCH}") + endif() +endif() + +if(NOT CLR_CMAKE_TARGET_BROWSER) + # The default linker on Solaris also does not support PIE. + if(NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_TARGET_SUNOS AND NOT CLR_CMAKE_TARGET_OSX AND NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_HOST_TVOS AND NOT CLR_CMAKE_HOST_IOS AND NOT MSVC) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") + add_compile_options($<$,EXECUTABLE>:-fPIE>) + add_compile_options($<$,SHARED_LIBRARY>:-fPIC>) + endif() + + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +string(TOLOWER "${CMAKE_BUILD_TYPE}" LOWERCASE_CMAKE_BUILD_TYPE) +if(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL debug) + # Clear _FORTIFY_SOURCE=2, if set + string(REPLACE "-D_FORTIFY_SOURCE=2 " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REPLACE "-D_FORTIFY_SOURCE=2 " "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +endif() diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake new file mode 100644 index 000000000..136cd6792 --- /dev/null +++ b/eng/native/configuretools.cmake @@ -0,0 +1,82 @@ +include(${CMAKE_CURRENT_LIST_DIR}/configureplatform.cmake) + +# Get the version of the compiler that is in the file name for tool location. +set (CLR_CMAKE_COMPILER_FILE_NAME_VERSION "") +if (CMAKE_C_COMPILER MATCHES "-?[0-9]+(\.[0-9]+)?$") + set(CLR_CMAKE_COMPILER_FILE_NAME_VERSION "${CMAKE_MATCH_0}") +endif() + +if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(APPLE) + set(TOOLSET_PREFIX "") + else() + set(TOOLSET_PREFIX "llvm-") + endif() + elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + if(CMAKE_CROSSCOMPILING) + set(TOOLSET_PREFIX "${CMAKE_CXX_COMPILER_TARGET}-") + else() + set(TOOLSET_PREFIX "") + endif() + endif() + + function(locate_toolchain_exec exec var) + string(TOUPPER ${exec} EXEC_UPPERCASE) + if(NOT "$ENV{CLR_${EXEC_UPPERCASE}}" STREQUAL "") + set(${var} "$ENV{CLR_${EXEC_UPPERCASE}}" PARENT_SCOPE) + return() + endif() + + find_program(EXEC_LOCATION_${exec} + NAMES + "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" + "${TOOLSET_PREFIX}${exec}") + + if (EXEC_LOCATION_${exec} STREQUAL "EXEC_LOCATION_${exec}-NOTFOUND") + message(FATAL_ERROR "Unable to find toolchain executable. Name: ${exec}, Prefix: ${TOOLSET_PREFIX}.") + endif() + set(${var} ${EXEC_LOCATION_${exec}} PARENT_SCOPE) + endfunction() + + locate_toolchain_exec(ar CMAKE_AR) + locate_toolchain_exec(nm CMAKE_NM) + locate_toolchain_exec(ranlib CMAKE_RANLIB) + + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + locate_toolchain_exec(link CMAKE_LINKER) + endif() + + if(NOT CLR_CMAKE_TARGET_OSX AND NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND (NOT CLR_CMAKE_TARGET_ANDROID OR CROSS_ROOTFS)) + locate_toolchain_exec(objdump CMAKE_OBJDUMP) + + if(CLR_CMAKE_TARGET_ANDROID) + set(TOOLSET_PREFIX ${ANDROID_TOOLCHAIN_PREFIX}) + elseif(CMAKE_CROSSCOMPILING AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD AND (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR + CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm OR CMAKE_SYSTEM_PROCESSOR STREQUAL s390x)) + set(TOOLSET_PREFIX "${TOOLCHAIN}-") + else() + set(TOOLSET_PREFIX "") + endif() + + locate_toolchain_exec(objcopy CMAKE_OBJCOPY) + endif() +endif() + +if (NOT CLR_CMAKE_HOST_WIN32) + # detect linker + separate_arguments(ldVersion UNIX_COMMAND "${CMAKE_C_COMPILER} ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version") + execute_process(COMMAND ${ldVersion} + ERROR_QUIET + OUTPUT_VARIABLE ldVersionOutput) + + if("${ldVersionOutput}" MATCHES "LLD") + set(LD_LLVM 1) + elseif("${ldVersionOutput}" MATCHES "GNU ld" OR "${ldVersionOutput}" MATCHES "GNU gold" OR "${ldVersionOutput}" MATCHES "GNU linkers") + set(LD_GNU 1) + elseif("${ldVersionOutput}" MATCHES "Solaris Link") + set(LD_SOLARIS 1) + else(CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_MACCATALYST) + set(LD_OSX 1) + endif() +endif() diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake new file mode 100644 index 000000000..66a91ca0a --- /dev/null +++ b/eng/native/functions.cmake @@ -0,0 +1,526 @@ +function(clr_unknown_arch) + if (WIN32) + message(FATAL_ERROR "Only AMD64, ARM64, ARM and I386 are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") + elseif(CLR_CROSS_COMPONENTS_BUILD) + message(FATAL_ERROR "Only AMD64, I386 host are supported for linux cross-architecture component. Found: ${CMAKE_SYSTEM_PROCESSOR}") + else() + message(FATAL_ERROR "Only AMD64, ARM64 and ARM are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") + endif() +endfunction() + +# Build a list of compiler definitions by putting -D in front of each define. +function(get_compile_definitions DefinitionName) + # Get the current list of definitions + get_directory_property(COMPILE_DEFINITIONS_LIST COMPILE_DEFINITIONS) + + # The entries that contain generator expressions must have the -D inside of the + # expression. So we transform e.g. $<$:_DEBUG> to $<$:-D_DEBUG> + + # CMake's support for multiple values within a single generator expression is somewhat ad-hoc. + # Since we have a number of complex generator expressions, we use them with multiple values to ensure that + # we don't forget to update all of the generator expressions if one needs to be updated. + # As a result, we need to expand out the multi-valued generator expression to wrap each individual value here. + # Otherwise, CMake will fail to expand it. + set(LastGeneratorExpression "") + foreach(DEFINITION IN LISTS COMPILE_DEFINITIONS_LIST) + # If there is a definition that uses the $ generator expression + # we need to remove it since that generator expression is only valid on binary targets. + # Assume that the value is 0. + string(REGEX REPLACE "\\$]+>" "0" DEFINITION "${DEFINITION}") + + if (${DEFINITION} MATCHES "^\\$<(.+):([^>]+)(>?)$") + if("${CMAKE_MATCH_3}" STREQUAL "") + set(DEFINITION "$<${CMAKE_MATCH_1}:-D${CMAKE_MATCH_2}>") + set(LastGeneratorExpression "${CMAKE_MATCH_1}") + else() + set(DEFINITION "$<${CMAKE_MATCH_1}:-D${CMAKE_MATCH_2}>") + endif() + elseif(${DEFINITION} MATCHES "([^>]+)>$") + # This entry is the last in a list nested within a generator expression. + set(DEFINITION "$<${LastGeneratorExpression}:-D${CMAKE_MATCH_1}>") + set(LastGeneratorExpression "") + elseif(NOT "${LastGeneratorExpression}" STREQUAL "") + set(DEFINITION "$<${LastGeneratorExpression}:-D${DEFINITION}>") + else() + set(DEFINITION -D${DEFINITION}) + endif() + list(APPEND DEFINITIONS ${DEFINITION}) + endforeach() + set(${DefinitionName} ${DEFINITIONS} PARENT_SCOPE) +endfunction(get_compile_definitions) + +# Build a list of include directories +function(get_include_directories IncludeDirectories) + get_directory_property(dirs INCLUDE_DIRECTORIES) + foreach(dir IN LISTS dirs) + + if (CLR_CMAKE_HOST_ARCH_ARM AND WIN32) + list(APPEND INC_DIRECTORIES /I${dir}) + else() + list(APPEND INC_DIRECTORIES -I${dir}) + endif(CLR_CMAKE_HOST_ARCH_ARM AND WIN32) + + endforeach() + set(${IncludeDirectories} ${INC_DIRECTORIES} PARENT_SCOPE) +endfunction(get_include_directories) + +# Build a list of include directories for consumption by the assembler +function(get_include_directories_asm IncludeDirectories) + get_directory_property(dirs INCLUDE_DIRECTORIES) + + foreach(dir IN LISTS dirs) + list(APPEND INC_DIRECTORIES -I${dir};) + endforeach() + + set(${IncludeDirectories} ${INC_DIRECTORIES} PARENT_SCOPE) +endfunction(get_include_directories_asm) + +# Finds and returns unwind libs +function(find_unwind_libs UnwindLibs) + if(CLR_CMAKE_HOST_ARCH_ARM) + find_library(UNWIND_ARCH NAMES unwind-arm) + endif() + + if(CLR_CMAKE_HOST_ARCH_ARM64) + find_library(UNWIND_ARCH NAMES unwind-aarch64) + endif() + + if(CLR_CMAKE_HOST_ARCH_AMD64) + find_library(UNWIND_ARCH NAMES unwind-x86_64) + endif() + + if(CLR_CMAKE_HOST_ARCH_S390X) + find_library(UNWIND_ARCH NAMES unwind-s390x) + endif() + + if(NOT UNWIND_ARCH STREQUAL UNWIND_ARCH-NOTFOUND) + set(UNWIND_LIBS ${UNWIND_ARCH}) + endif() + + find_library(UNWIND_GENERIC NAMES unwind-generic) + + if(NOT UNWIND_GENERIC STREQUAL UNWIND_GENERIC-NOTFOUND) + set(UNWIND_LIBS ${UNWIND_LIBS} ${UNWIND_GENERIC}) + endif() + + find_library(UNWIND NAMES unwind) + + if(UNWIND STREQUAL UNWIND-NOTFOUND) + message(FATAL_ERROR "Cannot find libunwind. Try installing libunwind8-dev or libunwind-devel.") + endif() + + set(${UnwindLibs} ${UNWIND_LIBS} ${UNWIND} PARENT_SCOPE) +endfunction(find_unwind_libs) + +# Set the passed in RetSources variable to the list of sources with added current source directory +# to form absolute paths. +# The parameters after the RetSources are the input files. +function(convert_to_absolute_path RetSources) + set(Sources ${ARGN}) + foreach(Source IN LISTS Sources) + list(APPEND AbsolutePathSources ${CMAKE_CURRENT_SOURCE_DIR}/${Source}) + endforeach() + set(${RetSources} ${AbsolutePathSources} PARENT_SCOPE) +endfunction(convert_to_absolute_path) + +#Preprocess file +function(preprocess_file inputFilename outputFilename) + get_compile_definitions(PREPROCESS_DEFINITIONS) + get_include_directories(PREPROCESS_INCLUDE_DIRECTORIES) + if (MSVC) + add_custom_command( + OUTPUT ${outputFilename} + COMMAND ${CMAKE_CXX_COMPILER} ${PREPROCESS_INCLUDE_DIRECTORIES} /P /EP /TC ${PREPROCESS_DEFINITIONS} /Fi${outputFilename} ${inputFilename} /nologo + DEPENDS ${inputFilename} + COMMENT "Preprocessing ${inputFilename}. Outputting to ${outputFilename}" + ) + else() + add_custom_command( + OUTPUT ${outputFilename} + COMMAND ${CMAKE_CXX_COMPILER} -E -P ${PREPROCESS_DEFINITIONS} ${PREPROCESS_INCLUDE_DIRECTORIES} -o ${outputFilename} -x c ${inputFilename} + DEPENDS ${inputFilename} + COMMENT "Preprocessing ${inputFilename}. Outputting to ${outputFilename}" + ) + endif() + + set_source_files_properties(${outputFilename} + PROPERTIES GENERATED TRUE) +endfunction() + +# preprocess_files(PreprocessedFilesList [fileToPreprocess1 [fileToPreprocess2 ...]]) +function(preprocess_files PreprocessedFilesList) + set(FilesToPreprocess ${ARGN}) + foreach(ASM_FILE IN LISTS FilesToPreprocess) + # Inserts a custom command in CMake build to preprocess each asm source file + get_filename_component(name ${ASM_FILE} NAME_WE) + file(TO_CMAKE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${name}.asm" ASM_PREPROCESSED_FILE) + preprocess_file(${ASM_FILE} ${ASM_PREPROCESSED_FILE}) + list(APPEND PreprocessedFiles ${ASM_PREPROCESSED_FILE}) + endforeach() + set(${PreprocessedFilesList} ${PreprocessedFiles} PARENT_SCOPE) +endfunction() + +function(set_exports_linker_option exports_filename) + if(LD_GNU OR LD_SOLARIS OR LD_LLVM) + # Add linker exports file option + if(LD_SOLARIS) + set(EXPORTS_LINKER_OPTION -Wl,-M,${exports_filename} PARENT_SCOPE) + else() + set(EXPORTS_LINKER_OPTION -Wl,--version-script=${exports_filename} PARENT_SCOPE) + endif() + elseif(LD_OSX) + # Add linker exports file option + set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${exports_filename} PARENT_SCOPE) + endif() +endfunction() + +# compile_asm(TARGET target ASM_FILES file1 [file2 ...] OUTPUT_OBJECTS [variableName]) +# CMake does not support the ARM or ARM64 assemblers on Windows when using the +# MSBuild generator. When the MSBuild generator is in use, we manually compile the assembly files +# using this function. +function(compile_asm) + set(options "") + set(oneValueArgs TARGET OUTPUT_OBJECTS) + set(multiValueArgs ASM_FILES) + cmake_parse_arguments(COMPILE_ASM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV}) + + get_include_directories_asm(ASM_INCLUDE_DIRECTORIES) + + set (ASSEMBLED_OBJECTS "") + + foreach(ASM_FILE ${COMPILE_ASM_ASM_FILES}) + get_filename_component(name ${ASM_FILE} NAME_WE) + # Produce object file where CMake would store .obj files for an OBJECT library. + # ex: artifacts\obj\coreclr\windows.arm64.Debug\src\vm\wks\cee_wks.dir\Debug\AsmHelpers.obj + set (OBJ_FILE "${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_ASM_TARGET}.dir/${CMAKE_CFG_INTDIR}/${name}.obj") + + # Need to compile asm file using custom command as include directories are not provided to asm compiler + add_custom_command(OUTPUT ${OBJ_FILE} + COMMAND "${CMAKE_ASM_COMPILER}" -g ${ASM_INCLUDE_DIRECTORIES} -o ${OBJ_FILE} ${ASM_FILE} + DEPENDS ${ASM_FILE} + COMMENT "Assembling ${ASM_FILE} ---> \"${CMAKE_ASM_COMPILER}\" -g ${ASM_INCLUDE_DIRECTORIES} -o ${OBJ_FILE} ${ASM_FILE}") + + # mark obj as source that does not require compile + set_source_files_properties(${OBJ_FILE} PROPERTIES EXTERNAL_OBJECT TRUE) + + # Add the generated OBJ in the dependency list so that it gets consumed during linkage + list(APPEND ASSEMBLED_OBJECTS ${OBJ_FILE}) + endforeach() + + set(${COMPILE_ASM_OUTPUT_OBJECTS} ${ASSEMBLED_OBJECTS} PARENT_SCOPE) +endfunction() + +# add_component(componentName [targetName] [EXCLUDE_FROM_ALL]) +function(add_component componentName) + if (${ARGC} GREATER 2 OR ${ARGC} EQUAL 2) + set(componentTargetName "${ARGV1}") + else() + set(componentTargetName "${componentName}") + endif() + if (${ARGC} EQUAL 3 AND "${ARG2}" STREQUAL "EXCLUDE_FROM_ALL") + set(exclude_from_all_flag "EXCLUDE_FROM_ALL") + endif() + get_property(definedComponents GLOBAL PROPERTY CLR_CMAKE_COMPONENTS) + list (FIND definedComponents "${componentName}" componentIndex) + if (${componentIndex} EQUAL -1) + list (APPEND definedComponents "${componentName}") + add_custom_target("${componentTargetName}" + COMMAND "${CMAKE_COMMAND}" "-DCMAKE_INSTALL_COMPONENT=${componentName}" "-DBUILD_TYPE=$" -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" + ${exclude_from_all_flag}) + set_property(GLOBAL PROPERTY CLR_CMAKE_COMPONENTS ${definedComponents}) + endif() +endfunction() + +function(generate_exports_file) + set(INPUT_LIST ${ARGN}) + list(GET INPUT_LIST -1 outputFilename) + list(REMOVE_AT INPUT_LIST -1) + + if(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) + set(SCRIPT_NAME generateexportedsymbols.sh) + else() + set(SCRIPT_NAME generateversionscript.sh) + endif() + + add_custom_command( + OUTPUT ${outputFilename} + COMMAND ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} ${INPUT_LIST} >${outputFilename} + DEPENDS ${INPUT_LIST} ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} + COMMENT "Generating exports file ${outputFilename}" + ) + set_source_files_properties(${outputFilename} + PROPERTIES GENERATED TRUE) +endfunction() + +function(generate_exports_file_prefix inputFilename outputFilename prefix) + + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(SCRIPT_NAME generateexportedsymbols.sh) + else() + set(SCRIPT_NAME generateversionscript.sh) + if (NOT ${prefix} STREQUAL "") + set(EXTRA_ARGS ${prefix}) + endif() + endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) + + add_custom_command( + OUTPUT ${outputFilename} + COMMAND ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} ${inputFilename} ${EXTRA_ARGS} >${outputFilename} + DEPENDS ${inputFilename} ${CLR_ENG_NATIVE_DIR}/${SCRIPT_NAME} + COMMENT "Generating exports file ${outputFilename}" + ) + set_source_files_properties(${outputFilename} + PROPERTIES GENERATED TRUE) +endfunction() + +function (get_symbol_file_name targetName outputSymbolFilename) + if (CLR_CMAKE_HOST_UNIX) + if (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) + set(strip_destination_file $.dwarf) + else () + set(strip_destination_file $.dbg) + endif () + + set(${outputSymbolFilename} ${strip_destination_file} PARENT_SCOPE) + else(CLR_CMAKE_HOST_UNIX) + # We can't use the $ generator expression here since + # the generator expression isn't supported on resource DLLs. + set(${outputSymbolFilename} $/$$.pdb PARENT_SCOPE) + endif(CLR_CMAKE_HOST_UNIX) +endfunction() + +function(strip_symbols targetName outputFilename) + get_symbol_file_name(${targetName} strip_destination_file) + set(${outputFilename} ${strip_destination_file} PARENT_SCOPE) + if (CLR_CMAKE_HOST_UNIX) + set(strip_source_file $) + + if (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) + + # Ensure that dsymutil and strip are present + find_program(DSYMUTIL dsymutil) + if (DSYMUTIL STREQUAL "DSYMUTIL-NOTFOUND") + message(FATAL_ERROR "dsymutil not found") + endif() + + find_program(STRIP strip) + if (STRIP STREQUAL "STRIP-NOTFOUND") + message(FATAL_ERROR "strip not found") + endif() + + string(TOLOWER "${CMAKE_BUILD_TYPE}" LOWERCASE_CMAKE_BUILD_TYPE) + if (LOWERCASE_CMAKE_BUILD_TYPE STREQUAL release) + set(strip_command ${STRIP} -no_code_signature_warning -S ${strip_source_file} && codesign -f -s - ${strip_source_file}) + else () + set(strip_command) + endif () + + add_custom_command( + TARGET ${targetName} + POST_BUILD + VERBATIM + COMMAND ${DSYMUTIL} --flat --minimize ${strip_source_file} + COMMAND ${strip_command} + COMMENT "Stripping symbols from ${strip_source_file} into file ${strip_destination_file}" + ) + else (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) + + add_custom_command( + TARGET ${targetName} + POST_BUILD + VERBATIM + COMMAND ${CMAKE_OBJCOPY} --only-keep-debug ${strip_source_file} ${strip_destination_file} + COMMAND ${CMAKE_OBJCOPY} --strip-unneeded ${strip_source_file} + COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=${strip_destination_file} ${strip_source_file} + COMMENT "Stripping symbols from ${strip_source_file} into file ${strip_destination_file}" + ) + endif (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) + endif(CLR_CMAKE_HOST_UNIX) +endfunction() + +function(install_with_stripped_symbols targetName kind destination) + if(NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) + strip_symbols(${targetName} symbol_file) + install_symbol_file(${symbol_file} ${destination} ${ARGN}) + endif() + + if ((CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) AND ("${kind}" STREQUAL "TARGETS")) + # We want to avoid the kind=TARGET install behaviors which corrupt code signatures on osx-arm64 + set(kind PROGRAMS) + endif() + + if ("${kind}" STREQUAL "TARGETS") + set(install_source ${targetName}) + elseif("${kind}" STREQUAL "PROGRAMS") + set(install_source $) + else() + message(FATAL_ERROR "The `kind` argument has to be either TARGETS or PROGRAMS, ${kind} was provided instead") + endif() + install(${kind} ${install_source} DESTINATION ${destination} ${ARGN}) +endfunction() + +function(install_symbol_file symbol_file destination_path) + if(CLR_CMAKE_TARGET_WIN32) + install(FILES ${symbol_file} DESTINATION ${destination_path}/PDB ${ARGN}) + else() + install(FILES ${symbol_file} DESTINATION ${destination_path} ${ARGN}) + endif() +endfunction() + +# install_clr(TARGETS targetName [targetName2 ...] [DESTINATIONS destination [destination2 ...]] [COMPONENT componentName]) +function(install_clr) + set(multiValueArgs TARGETS DESTINATIONS) + set(singleValueArgs COMPONENT) + set(options "") + cmake_parse_arguments(INSTALL_CLR "${options}" "${singleValueArgs}" "${multiValueArgs}" ${ARGV}) + + if ("${INSTALL_CLR_TARGETS}" STREQUAL "") + message(FATAL_ERROR "At least one target must be passed to install_clr(TARGETS )") + endif() + + if ("${INSTALL_CLR_DESTINATIONS}" STREQUAL "") + message(FATAL_ERROR "At least one destination must be passed to install_clr.") + endif() + + set(destinations "") + + if (NOT "${INSTALL_CLR_DESTINATIONS}" STREQUAL "") + list(APPEND destinations ${INSTALL_CLR_DESTINATIONS}) + endif() + + if ("${INSTALL_CLR_COMPONENT}" STREQUAL "") + set(INSTALL_CLR_COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}) + endif() + + foreach(targetName ${INSTALL_CLR_TARGETS}) + if (NOT "${INSTALL_CLR_COMPONENT}" STREQUAL "${targetName}") + get_property(definedComponents GLOBAL PROPERTY CLR_CMAKE_COMPONENTS) + list(FIND definedComponents "${INSTALL_CLR_COMPONENT}" componentIdx) + if (${componentIdx} EQUAL -1) + message(FATAL_ERROR "The ${INSTALL_CLR_COMPONENT} component is not defined. Add a call to `add_component(${INSTALL_CLR_COMPONENT})` to define the component in the build.") + endif() + add_dependencies(${INSTALL_CLR_COMPONENT} ${targetName}) + endif() + get_target_property(targetType ${targetName} TYPE) + if (NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS AND NOT "${targetType}" STREQUAL "STATIC_LIBRARY") + get_symbol_file_name(${targetName} symbolFile) + endif() + + foreach(destination ${destinations}) + # We don't need to install the export libraries for our DLLs + # since they won't be directly linked against. + install(PROGRAMS $ DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT}) + if (NOT "${symbolFile}" STREQUAL "") + install_symbol_file(${symbolFile} ${destination} COMPONENT ${INSTALL_CLR_COMPONENT}) + endif() + + if(CLR_CMAKE_PGO_INSTRUMENT) + if(WIN32) + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$/${targetName}.pgd DESTINATION ${destination}/PGD OPTIONAL COMPONENT ${INSTALL_CLR_COMPONENT}) + else() + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${targetName}.pgd DESTINATION ${destination}/PGD OPTIONAL COMPONENT ${INSTALL_CLR_COMPONENT}) + endif() + endif() + endif() + endforeach() + endforeach() +endfunction() + +# Disable PAX mprotect that would prevent JIT and other codegen in coreclr from working. +# PAX mprotect prevents: +# - changing the executable status of memory pages that were +# not originally created as executable, +# - making read-only executable pages writable again, +# - creating executable pages from anonymous memory, +# - making read-only-after-relocations (RELRO) data pages writable again. +function(disable_pax_mprotect targetName) + # Disabling PAX hardening only makes sense in systems that use Elf image formats. Particularly, looking + # for paxctl in macOS is problematic as it collides with popular software for that OS that performs completely + # unrelated functionality. Only look for it when we'll generate Elf images. + if (CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) + # Try to locate the paxctl tool. Failure to find it is not fatal, + # but the generated executables won't work on a system where PAX is set + # to prevent applications to create executable memory mappings. + find_program(PAXCTL paxctl) + + if (NOT PAXCTL STREQUAL "PAXCTL-NOTFOUND") + add_custom_command( + TARGET ${targetName} + POST_BUILD + VERBATIM + COMMAND ${PAXCTL} -c -m $ + ) + endif() + endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) +endfunction() + +if (CMAKE_VERSION VERSION_LESS "3.12") + # Polyfill add_compile_definitions when it is unavailable + function(add_compile_definitions) + get_directory_property(DIR_COMPILE_DEFINITIONS COMPILE_DEFINITIONS) + list(APPEND DIR_COMPILE_DEFINITIONS ${ARGV}) + set_directory_properties(PROPERTIES COMPILE_DEFINITIONS "${DIR_COMPILE_DEFINITIONS}") + endfunction() +endif() + +if (CMAKE_VERSION VERSION_LESS "3.16") + # Provide a no-op polyfill for precompiled headers on old CMake versions + function(target_precompile_headers) + endfunction() +endif() + +# add_linker_flag(Flag [Config1 Config2 ...]) +function(add_linker_flag Flag) + if (ARGN STREQUAL "") + set("CMAKE_EXE_LINKER_FLAGS" "${CMAKE_EXE_LINKER_FLAGS} ${Flag}" PARENT_SCOPE) + set("CMAKE_SHARED_LINKER_FLAGS" "${CMAKE_SHARED_LINKER_FLAGS} ${Flag}" PARENT_SCOPE) + else() + foreach(Config ${ARGN}) + set("CMAKE_EXE_LINKER_FLAGS_${Config}" "${CMAKE_EXE_LINKER_FLAGS_${Config}} ${Flag}" PARENT_SCOPE) + set("CMAKE_SHARED_LINKER_FLAGS_${Config}" "${CMAKE_SHARED_LINKER_FLAGS_${Config}} ${Flag}" PARENT_SCOPE) + endforeach() + endif() +endfunction() + +function(link_natvis_sources_for_target targetName linkKind) + if (NOT CLR_CMAKE_HOST_WIN32) + return() + endif() + foreach(source ${ARGN}) + if (NOT IS_ABSOLUTE "${source}") + convert_to_absolute_path(source ${source}) + endif() + get_filename_component(extension "${source}" EXT) + if ("${extension}" STREQUAL ".natvis") + message("Embedding natvis ${source}") + # Since natvis embedding is only supported on Windows + # we can use target_link_options since our minimum version is high enough + target_link_options(${targetName} "${linkKind}" "-NATVIS:${source}") + endif() + endforeach() +endfunction() + +function(add_executable_clr targetName) + if(NOT WIN32) + add_executable(${ARGV} ${VERSION_FILE_PATH}) + disable_pax_mprotect(${ARGV}) + else() + add_executable(${ARGV}) + endif(NOT WIN32) + if(NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) + strip_symbols(${ARGV0} symbolFile) + endif() +endfunction() + +function(add_library_clr targetName kind) + if(NOT WIN32 AND "${kind}" STREQUAL "SHARED") + add_library(${ARGV} ${VERSION_FILE_PATH}) + else() + add_library(${ARGV}) + endif() + if("${kind}" STREQUAL "SHARED" AND NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) + strip_symbols(${ARGV0} symbolFile) + endif() +endfunction() diff --git a/eng/native/gen-buildsys.cmd b/eng/native/gen-buildsys.cmd new file mode 100644 index 000000000..243921d93 --- /dev/null +++ b/eng/native/gen-buildsys.cmd @@ -0,0 +1,106 @@ +@if not defined _echo @echo off +rem +rem This file invokes cmake and generates the build system for windows. + +setlocal + +set argC=0 +for %%x in (%*) do Set /A argC+=1 + +if %argC% lss 4 GOTO :USAGE +if %1=="/?" GOTO :USAGE + +setlocal enabledelayedexpansion +set basePath=%~dp0 +set __repoRoot=%~dp0..\..\ +:: remove quotes +set "basePath=%basePath:"=%" +:: remove trailing slash +if %basePath:~-1%==\ set "basePath=%basePath:~0,-1%" + +set __SourceDir=%1 +set __IntermediatesDir=%2 +set __VSVersion=%3 +set __Arch=%4 +set __CmakeGenerator=Visual Studio +set __UseEmcmake=0 +if /i "%__Ninja%" == "1" ( + set __CmakeGenerator=Ninja +) else ( + if /i NOT "%__Arch%" == "wasm" ( + if /i "%__VSVersion%" == "vs2022" (set __CmakeGenerator=%__CmakeGenerator% 17 2022) + if /i "%__VSVersion%" == "vs2019" (set __CmakeGenerator=%__CmakeGenerator% 16 2019) + if /i "%__VSVersion%" == "vs2017" (set __CmakeGenerator=%__CmakeGenerator% 15 2017) + + if /i "%__Arch%" == "x64" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A x64) + if /i "%__Arch%" == "arm" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A ARM) + if /i "%__Arch%" == "arm64" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A ARM64) + if /i "%__Arch%" == "x86" (set __ExtraCmakeParams=%__ExtraCmakeParams% -A Win32) + ) else ( + set __CmakeGenerator=NMake Makefiles + ) +) + +if /i "%__Arch%" == "wasm" ( + + if "%EMSDK_PATH%" == "" ( + if not exist "%__repoRoot%src\mono\wasm\emsdk" ( + echo Error: Should set EMSDK_PATH environment variable pointing to emsdk root. + exit /B 1 + ) + + set EMSDK_PATH=%__repoRoot%src\mono\wasm\emsdk + set EMSDK_PATH=!EMSDK_PATH:\=/! + ) + + set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCMAKE_TOOLCHAIN_FILE=!EMSDK_PATH!/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake" + set __UseEmcmake=1 +) else ( + set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCMAKE_SYSTEM_VERSION=10.0" +) + +:loop +if [%5] == [] goto end_loop +set __ExtraCmakeParams=%__ExtraCmakeParams% %5 +shift +goto loop +:end_loop + +set __ExtraCmakeParams="-DCMAKE_INSTALL_PREFIX=%__CMakeBinDir%" "-DCLR_CMAKE_HOST_ARCH=%__Arch%" %__ExtraCmakeParams% + +set __CmdLineOptionsUpToDateFile=%__IntermediatesDir%\cmake_cmd_line.txt +set __CMakeCmdLineCache= +if not "%__ConfigureOnly%" == "1" ( + REM MSBuild can't reload from a CMake reconfigure during build correctly, so only do this + REM command-line up to date check for non-VS generators. + if "%__CmakeGenerator:Visual Studio=%" == "%__CmakeGenerator%" ( + if exist "%__CmdLineOptionsUpToDateFile%" ( + set /p __CMakeCmdLineCache=<"%__CmdLineOptionsUpToDateFile%" + REM Strip the extra space from the end of the cached command line + if "!__ExtraCmakeParams!" == "!__CMakeCmdLineCache:~0,-1!" ( + echo The CMake command line is the same as the last run. Skipping running CMake. + exit /B 0 + ) else ( + echo The CMake command line differs from the last run. Running CMake again. + echo %__ExtraCmakeParams% > %__CmdLineOptionsUpToDateFile% + ) + ) else ( + echo %__ExtraCmakeParams% > %__CmdLineOptionsUpToDateFile% + ) + ) +) + +if /i "%__UseEmcmake%" == "1" ( + call "!EMSDK_PATH!/emsdk_env.bat" > nul 2>&1 && emcmake "%CMakePath%" %__ExtraCmakeParams% --no-warn-unused-cli -G "%__CmakeGenerator%" -B %__IntermediatesDir% -S %__SourceDir% +) else ( + "%CMakePath%" %__ExtraCmakeParams% --no-warn-unused-cli -G "%__CmakeGenerator%" -B %__IntermediatesDir% -S %__SourceDir% +) +endlocal +exit /B %errorlevel% + +:USAGE + echo "Usage..." + echo "gen-buildsys.cmd " + echo "Specify the path to the top level CMake file - /src/NDP" + echo "Specify the VSVersion to be used - VS2017 or VS2019" + EXIT /B 1 diff --git a/eng/native/gen-buildsys.sh b/eng/native/gen-buildsys.sh new file mode 100755 index 000000000..730d4dcef --- /dev/null +++ b/eng/native/gen-buildsys.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# +# This file invokes cmake and generates the build system for Clang. +# + +scriptroot="$( cd -P "$( dirname "$0" )" && pwd )" + +if [[ "$#" -lt 4 ]]; then + echo "Usage..." + echo "gen-buildsys.sh [build flavor] [ninja] [scan-build] [cmakeargs]" + echo "Specify the path to the top level CMake file." + echo "Specify the path that the build system files are generated in." + echo "Specify the target architecture." + echo "Specify the name of compiler (clang or gcc)." + echo "Specify the major version of compiler." + echo "Specify the minor version of compiler." + echo "Optionally specify the build configuration (flavor.) Defaults to DEBUG." + echo "Optionally specify 'scan-build' to enable build with clang static analyzer." + echo "Use the Ninja generator instead of the Unix Makefiles generator." + echo "Pass additional arguments to CMake call." + exit 1 +fi + +build_arch="$3" +compiler="$4" +majorVersion="$5" +minorVersion="$6" + +if [[ "$compiler" != "default" ]]; then + nativescriptroot="$( cd -P "$scriptroot/../common/native" && pwd )" + source "$nativescriptroot/init-compiler.sh" "$nativescriptroot" "$build_arch" "$compiler" "$majorVersion" "$minorVersion" + + CCC_CC="$CC" + CCC_CXX="$CXX" +fi + +export CCC_CC CCC_CXX + +buildtype=DEBUG +code_coverage=OFF +build_tests=OFF +scan_build=OFF +generator="Unix Makefiles" +__UnprocessedCMakeArgs="" + +for i in "${@:7}"; do + upperI="$(echo "$i" | tr "[:lower:]" "[:upper:]")" + case "$upperI" in + # Possible build types are DEBUG, CHECKED, RELEASE, RELWITHDEBINFO. + DEBUG | CHECKED | RELEASE | RELWITHDEBINFO) + buildtype="$upperI" + ;; + NINJA) + generator=Ninja + ;; + SCAN-BUILD) + echo "Static analysis is turned on for this build." + scan_build=ON + ;; + *) + __UnprocessedCMakeArgs="${__UnprocessedCMakeArgs}${__UnprocessedCMakeArgs:+ }$i" + esac +done + +cmake_extra_defines= +if [[ "$CROSSCOMPILE" == "1" ]]; then + platform="$(uname)" + # OSX doesn't use rootfs + if ! [[ -n "$ROOTFS_DIR" || "$platform" == "Darwin" ]]; then + echo "ROOTFS_DIR not set for crosscompile" + exit 1 + fi + + TARGET_BUILD_ARCH="$build_arch" + export TARGET_BUILD_ARCH + + cmake_extra_defines="$cmake_extra_defines -C $scriptroot/tryrun.cmake" + + if [[ "$platform" == "Darwin" ]]; then + cmake_extra_defines="$cmake_extra_defines -DCMAKE_SYSTEM_NAME=Darwin" + else + cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$scriptroot/../common/cross/toolchain.cmake" + fi +fi + +if [[ "$build_arch" == "armel" ]]; then + cmake_extra_defines="$cmake_extra_defines -DARM_SOFTFP=1" +fi + +if ! cmake_command=$(command -v cmake); then + echo "CMake was not found in PATH." + exit 1 +fi + +if [[ "$scan_build" == "ON" && -n "$SCAN_BUILD_COMMAND" ]]; then + cmake_command="$SCAN_BUILD_COMMAND $cmake_command" +fi + +if [[ "$build_arch" == "wasm" ]]; then + cmake_command="emcmake $cmake_command" +fi + +cmake_args_to_cache="$scan_build\n$SCAN_BUILD_COMMAND\n$generator\n$__UnprocessedCMakeArgs" +cmake_args_cache_file="$2/cmake_cmd_line.txt" +if [[ -z "$__ConfigureOnly" ]]; then + if [[ -e "$cmake_args_cache_file" ]]; then + cmake_args_cache=$(<"$cmake_args_cache_file") + if [[ "$cmake_args_cache" == "$cmake_args_to_cache" ]]; then + echo "CMake command line is unchanged. Reusing previous cache instead of regenerating." + exit 0 + fi + fi + echo $cmake_args_to_cache > $cmake_args_cache_file +fi + +# We have to be able to build with CMake 3.6.2, so we can't use the -S or -B options +pushd "$2" + +$cmake_command \ + --no-warn-unused-cli \ + -G "$generator" \ + "-DCMAKE_BUILD_TYPE=$buildtype" \ + "-DCMAKE_INSTALL_PREFIX=$__CMakeBinDir" \ + $cmake_extra_defines \ + $__UnprocessedCMakeArgs \ + "$1" + +popd diff --git a/eng/native/generateexportedsymbols.sh b/eng/native/generateexportedsymbols.sh new file mode 100755 index 000000000..4a23aa85c --- /dev/null +++ b/eng/native/generateexportedsymbols.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +saved=("$@") +while test $# -gt 0; do + case "$1" in + --help|-h) + printf "Usage:\ngenerateexportedsymbols.sh \n" + exit 1;; + esac + shift +done +set -- "${saved[@]}" + +while read -r line; do + # Skip empty lines and comment lines starting with semicolon + if [[ "$line" =~ ^\;.*$|^[[:space:]]*$ ]]; then + continue + fi + + # Remove the CR character in case the sources are mapped from + # a Windows share and contain CRLF line endings + line="${line//$'\r'/}" + + printf "_%s\n" "${line//#/}" +done < "$1" diff --git a/eng/native/generateversionscript.sh b/eng/native/generateversionscript.sh new file mode 100755 index 000000000..83e249067 --- /dev/null +++ b/eng/native/generateversionscript.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +saved=("$@") +while test $# -gt 0; do + case "$1" in + --help|-h) + printf "Usage:\ngenerateversionscript.sh \n" + exit 1;; + esac + shift +done +set -- "${saved[@]}" + +prefix="$2" + +printf "V1.0 {\n global:\n" + +while read -r line; do + # Skip empty lines and comment lines starting with semicolon + if [[ "$line" =~ ^\;.*$|^[[:space:]]*$ ]]; then + continue + fi + + # Remove the CR character in case the sources are mapped from + # a Windows share and contain CRLF line endings + line="${line//$'\r'/}" + + # Only prefix the entries that start with "#" + if [[ "$line" =~ ^#.*$ ]]; then + printf " %s%s;\n" "$prefix" "${line//#/}" + else + printf " %s;\n" "$line" + fi +done < "$1" + +printf " local: *;\n};\n" diff --git a/eng/native/genmoduleindex.cmd b/eng/native/genmoduleindex.cmd new file mode 100644 index 000000000..a6be85146 --- /dev/null +++ b/eng/native/genmoduleindex.cmd @@ -0,0 +1,25 @@ +@echo off +REM Generate module index header + +if [%1]==[] goto :Usage +if [%2]==[] goto :Usage + +setlocal +for /f "tokens=1" %%i in ('dumpbin /HEADERS %1 ^| findstr /c:"size of image"') do set imagesize=%%i +REM Pad the extracted size to 8 hex digits +set imagesize=00000000%imagesize% +set imagesize=%imagesize:~-8% + +for /f "tokens=1" %%i in ('dumpbin /HEADERS %1 ^| findstr /c:"time date"') do set timestamp=%%i +REM Pad the extracted time stamp to 8 hex digits +set timestamp=00000000%timestamp% +set timestamp=%timestamp:~-8% + +echo 0x08, 0x%timestamp:~6,2%, 0x%timestamp:~4,2%, 0x%timestamp:~2,2%, 0x%timestamp:~0,2%, 0x%imagesize:~6,2%, 0x%imagesize:~4,2%, 0x%imagesize:~2,2%, 0x%imagesize:~0,2%, > %2 + +endlocal +exit /b 0 + +:Usage +echo Usage: genmoduleindex.cmd ModuleBinaryFile IndexHeaderFile +exit /b 1 diff --git a/eng/native/genmoduleindex.sh b/eng/native/genmoduleindex.sh new file mode 100755 index 000000000..399a972d7 --- /dev/null +++ b/eng/native/genmoduleindex.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# +# Generate module index header +# +set -euo pipefail + +if [[ "$#" -lt 2 ]]; then + echo "Usage: genmoduleindex.sh ModuleBinaryFile IndexHeaderFile" + exit 1 +fi + +function printIdAsBinary() { + id="$1" + + # Print length in bytes + bytesLength="${#id}" + printf "0x%02x, " "$((bytesLength/2))" + + # Print each pair of hex digits with 0x prefix followed by a comma + while [[ "$id" ]]; do + printf '0x%s, ' "${id:0:2}" + id=${id:2} + done +} + +case "$(uname -s)" in +Darwin) + cmd="dwarfdump -u $1" + pattern='^UUID: ([0-9A-Fa-f\-]+)';; +*) + cmd="readelf -n $1" + pattern='^[[:space:]]*Build ID: ([0-9A-Fa-f\-]+)';; +esac + +while read -r line; do + if [[ "$line" =~ $pattern ]]; then + printIdAsBinary "${BASH_REMATCH[1]//-/}" + break + fi +done < <(eval "$cmd") > "$2" diff --git a/eng/native/init-distro-rid.sh b/eng/native/init-distro-rid.sh new file mode 100644 index 000000000..5f6b19460 --- /dev/null +++ b/eng/native/init-distro-rid.sh @@ -0,0 +1,206 @@ +#!/usr/bin/env bash + +# initNonPortableDistroRid +# +# Input: +# targetOs: (str) +# buildArch: (str) +# isPortable: (int) +# rootfsDir: (str) +# +# Return: +# None +# +# Notes: +# +# initNonPortableDistroRid will attempt to initialize a non portable rid. These +# rids are specific to distros need to build the product/package and consume +# them on the same platform. +# +# If -portablebuild=false is passed a non-portable rid will be created for any +# distro. +# +# It is important to note that the function does not return anything, but it +# exports __DistroRid, if there is a non-portable distro rid to be used. +# +initNonPortableDistroRid() +{ + # Make sure out parameter is cleared. + __DistroRid= + + local targetOs="$1" + local buildArch="$2" + local isPortable="$3" + local rootfsDir="$4" + local nonPortableBuildID="" + + if [ "$targetOs" = "Linux" ]; then + if [ -e "${rootfsDir}/etc/os-release" ]; then + source "${rootfsDir}/etc/os-release" + + # We have forced __PortableBuild=0. This is because -portablebuld + # has been passed as false. + if (( isPortable == 0 )); then + if [ "${ID}" = "rhel" ] || [ "${ID}" = "rocky" ]; then + # remove the last version digit + VERSION_ID="${VERSION_ID%.*}" + fi + + if [ -z "${VERSION_ID+x}" ]; then + # Rolling release distros do not set VERSION_ID, so omit + # it here to be consistent with everything else. + nonPortableBuildID="${ID}-${buildArch}" + else + nonPortableBuildID="${ID}.${VERSION_ID}-${buildArch}" + fi + fi + + elif [ -e "${rootfsDir}/android_platform" ]; then + source "$rootfsDir"/android_platform + nonPortableBuildID="$RID" + fi + fi + + if [ "$targetOs" = "FreeBSD" ]; then + if (( isPortable == 0 )); then + # $rootfsDir can be empty. freebsd-version is shell script and it should always work. + __freebsd_major_version=$($rootfsDir/bin/freebsd-version | { read v; echo "${v%%.*}"; }) + nonPortableBuildID="freebsd.$__freebsd_major_version-${buildArch}" + fi + elif command -v getprop && getprop ro.product.system.model 2>&1 | grep -qi android; then + __android_sdk_version=$(getprop ro.build.version.sdk) + nonPortableBuildID="android.$__android_sdk_version-${buildArch}" + elif [ "$targetOs" = "illumos" ]; then + __uname_version=$(uname -v) + case "$__uname_version" in + omnios-*) + __omnios_major_version=$(echo "${__uname_version:8:2}") + nonPortableBuildID=omnios."$__omnios_major_version"-"$buildArch" + ;; + joyent_*) + __smartos_major_version=$(echo "${__uname_version:7:4}") + nonPortableBuildID=smartos."$__smartos_major_version"-"$buildArch" + ;; + illumos_*) + nonPortableBuildID=openindiana-"$buildArch" + ;; + esac + elif [ "$targetOs" = "Solaris" ]; then + __uname_version=$(uname -v) + __solaris_major_version=$(echo "${__uname_version%.*}") + nonPortableBuildID=solaris."$__solaris_major_version"-"$buildArch" + fi + + if [ -n "${nonPortableBuildID}" ]; then + __DistroRid="${nonPortableBuildID}" + + # We are using a non-portable build rid. Force __PortableBuild to false. + __PortableBuild=0 + + export __DistroRid __PortableBuild + fi +} + +# initDistroRidGlobal +# +# Input: +# os: (str) +# arch: (str) +# isPortable: (int) +# rootfsDir?: (nullable:string) +# +# Return: +# None +# +# Notes: +# +# It is important to note that the function does not return anything, but it +# exports the following variables on success: +# +# __DistroRid +# __PortableBuild +# +initDistroRidGlobal() +{ + # __DistroRid must be set at the end of the function. + # Previously we would create a variable __HostDistroRid and/or __DistroRid. + # + # __HostDistroRid was used in the case of a non-portable build, it has been + # deprecated. Now only __DistroRid is supported. It will be used for both + # portable and non-portable rids and will be used in build-packages.sh + + local targetOs="$1" + local buildArch="$2" + local isPortable="$3" + local rootfsDir="" + if [ "$#" -ge 4 ]; then + rootfsDir="$4" + fi + + if [ -n "${rootfsDir}" ]; then + # We may have a cross build. Check for the existance of the rootfsDir + if [ ! -e "${rootfsDir}" ]; then + echo "Error rootfsDir has been passed, but the location is not valid." + exit 1 + fi + fi + + initNonPortableDistroRid "${targetOs}" "${buildArch}" "${isPortable}" "${rootfsDir}" + + if [ "$buildArch" = "wasm" ]; then + __DistroRid=browser-wasm + export __DistroRid + fi + + if [ -z "${__DistroRid}" ]; then + # The non-portable build rid was not set. Set the portable rid. + + __PortableBuild=1 + export __PortableBuild + local distroRid="" + + # Check for musl-based distros (e.g Alpine Linux, Void Linux). + if "${rootfsDir}/usr/bin/ldd" --version 2>&1 | grep -q musl || + strings "${rootfsDir}/usr/bin/ldd" 2>&1 | grep -q musl; then + distroRid="linux-musl-${buildArch}" + fi + + if [ -z "${distroRid}" ]; then + if [ "$targetOs" = "Linux" ]; then + distroRid="linux-$buildArch" + elif [ "$targetOs" = "OSX" ]; then + distroRid="osx-$buildArch" + elif [ "$targetOs" = "MacCatalyst" ]; then + distroRid="maccatalyst-$buildArch" + elif [ "$targetOs" = "tvOS" ]; then + distroRid="tvos-$buildArch" + elif [ "$targetOs" = "tvOSSimulator" ]; then + distroRid="tvossimulator-$buildArch" + elif [ "$targetOs" = "iOS" ]; then + distroRid="ios-$buildArch" + elif [ "$targetOs" = "iOSSimulator" ]; then + distroRid="iossimulator-$buildArch" + elif [ "$targetOs" = "Android" ]; then + distroRid="android-$buildArch" + elif [ "$targetOs" = "Browser" ]; then + distroRid="browser-$buildArch" + elif [ "$targetOs" = "FreeBSD" ]; then + distroRid="freebsd-$buildArch" + elif [ "$targetOs" = "illumos" ]; then + distroRid="illumos-$buildArch" + elif [ "$targetOs" = "Solaris" ]; then + distroRid="solaris-$buildArch" + fi + fi + + __DistroRid="${distroRid}" + export __DistroRid + fi + + if [ -z "$__DistroRid" ]; then + echo "DistroRid is not set. This is almost certainly an error" + exit 1 + fi + + echo "__DistroRid: ${__DistroRid}" +} diff --git a/eng/native/init-os-and-arch.sh b/eng/native/init-os-and-arch.sh new file mode 100644 index 000000000..fc4078fa3 --- /dev/null +++ b/eng/native/init-os-and-arch.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +# Use uname to determine what the OS is. +OSName=$(uname -s) + +if command -v getprop && getprop ro.product.system.model 2>&1 | grep -qi android; then + OSName="Android" +fi + +case "$OSName" in +FreeBSD|Linux|NetBSD|OpenBSD|SunOS|Android) + os="$OSName" ;; +Darwin) + os=OSX ;; +*) + echo "Unsupported OS $OSName detected, configuring as if for Linux" + os=Linux ;; +esac + +# On Solaris, `uname -m` is discouraged, see https://docs.oracle.com/cd/E36784_01/html/E36870/uname-1.html +# and `uname -p` returns processor type (e.g. i386 on amd64). +# The appropriate tool to determine CPU is isainfo(1) https://docs.oracle.com/cd/E36784_01/html/E36870/isainfo-1.html. +if [ "$os" = "SunOS" ]; then + if uname -o 2>&1 | grep -q illumos; then + os="illumos" + else + os="Solaris" + fi + CPUName=$(isainfo -n) +else + # For the rest of the operating systems, use uname(1) to determine what the CPU is. + CPUName=$(uname -m) +fi + +case "$CPUName" in + arm64|aarch64) + arch=arm64 + ;; + + amd64|x86_64) + arch=x64 + ;; + + armv7l) + if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then + arch=armel + else + arch=arm + fi + ;; + + i[3-6]86) + echo "Unsupported CPU $CPUName detected, build might not succeed!" + arch=x86 + ;; + + s390x) + arch=s390x + ;; + + *) + echo "Unknown CPU $CPUName detected, configuring as if for x64" + arch=x64 + ;; +esac diff --git a/eng/native/init-vs-env.cmd b/eng/native/init-vs-env.cmd new file mode 100644 index 000000000..7eefeea12 --- /dev/null +++ b/eng/native/init-vs-env.cmd @@ -0,0 +1,76 @@ +@if not defined _echo @echo off + +:: Initializes Visual Studio developer environment. If a build architecture is passed +:: as an argument, it also initializes VC++ build environment and CMakePath. + +set "__VCBuildArch=" +if /i "%~1" == "x86" (set __VCBuildArch=x86) +if /i "%~1" == "x64" (set __VCBuildArch=x86_amd64) +if /i "%~1" == "arm" (set __VCBuildArch=x86_arm) +if /i "%~1" == "arm64" (set __VCBuildArch=x86_arm64) +if /i "%~1" == "wasm" (set __VCBuildArch=x86_amd64) + +:: Default to highest Visual Studio version available that has Visual C++ tools. +:: +:: For VS2017 and later, multiple instances can be installed on the same box SxS and VS1*0COMNTOOLS +:: is no longer set as a global environment variable and is instead only set if the user +:: has launched the Visual Studio Developer Command Prompt. +:: +:: Following this logic, we will default to the Visual Studio toolset assocated with the active +:: Developer Command Prompt. Otherwise, we will query VSWhere to locate the later version of +:: Visual Studio available on the machine. Finally, we will fail the script if no supported +:: instance can be found. + +if defined VisualStudioVersion goto :VSDetected + +set "__VSWhere=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +set "__VSCOMNTOOLS=" + +if exist "%__VSWhere%" ( + for /f "tokens=*" %%p in ( + '"%__VSWhere%" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath' + ) do set __VSCOMNTOOLS=%%p\Common7\Tools +) + +if not exist "%__VSCOMNTOOLS%" goto :VSMissing + +:: Make sure the current directory stays intact +set "VSCMD_START_DIR=%CD%" + +call "%__VSCOMNTOOLS%\VsDevCmd.bat" -no_logo + +:: Clean up helper variables +set "__VSWhere=" +set "__VSCOMNTOOLS=" +set "VSCMD_START_DIR=" + +:VSDetected +if "%VisualStudioVersion%"=="16.0" ( + set __VSVersion=vs2019 + set __PlatformToolset=v142 + goto :SetVCEnvironment +) +if "%VisualStudioVersion%"=="17.0" ( + set __VSVersion=vs2022 + set __PlatformToolset=v142 + goto :SetVCEnvironment +) + +:VSMissing +echo %__MsgPrefix%Error: Visual Studio 2019 or 2022 with C++ tools required. ^ +Please see https://github.com/dotnet/runtime/blob/main/docs/workflow/requirements/windows-requirements.md for build requirements. +exit /b 1 + +:SetVCEnvironment + +if "%__VCBuildArch%"=="" exit /b 0 + +:: Set the environment for the native build +call "%VCINSTALLDIR%Auxiliary\Build\vcvarsall.bat" %__VCBuildArch% +if not "%ErrorLevel%"=="0" exit /b 1 + +set "__VCBuildArch=" + +:: Set CMakePath by evaluating the output from set-cmake-path.ps1. +:: In case of a failure the output is "exit /b 1". +for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass -File "%~dp0set-cmake-path.ps1"') do %%a diff --git a/eng/native/naming.props b/eng/native/naming.props new file mode 100644 index 000000000..7a02d6c6c --- /dev/null +++ b/eng/native/naming.props @@ -0,0 +1,54 @@ + + + lib + + + + + + + .exe + .dll + .lib + .pdb + + + + + lib + .dylib + .a + .dwarf + + + + + lib + .so + .a + + .debug + + + + + lib + .so + .a + .dbg + + + + + + + + + + + + $(SymbolsSuffix) + + + diff --git a/eng/native/output-toolchain-info.cmake b/eng/native/output-toolchain-info.cmake new file mode 100644 index 000000000..8eed988e5 --- /dev/null +++ b/eng/native/output-toolchain-info.cmake @@ -0,0 +1,21 @@ +# Output the toolchain information required to create a command line that builds with the right rootfs as XML + +set (ADDED_COMPILE_OPTIONS) +if (CMAKE_SCRIPT_MODE_FILE) + # add_compile_options and add_definitions can't be used in scripts, + # so override the implementations to append to a local property + macro(add_compile_options) + list(APPEND ADDED_COMPILE_OPTIONS ${ARGV}) + endmacro() + macro(add_definitions) + list(APPEND ADDED_COMPILE_OPTIONS ${ARGV}) + endmacro() +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/../common/cross/toolchain.cmake) + +message("") +message("${TOOLCHAIN}") +message("${CMAKE_SHARED_LINKER_FLAGS_INIT}") +message("${ADDED_COMPILE_OPTIONS}") +message("") \ No newline at end of file diff --git a/eng/native/sanitizerblacklist.txt b/eng/native/sanitizerblacklist.txt new file mode 100644 index 000000000..ecc8bef9b --- /dev/null +++ b/eng/native/sanitizerblacklist.txt @@ -0,0 +1,14 @@ +# This file has exclusions to the Clang address sanitizer to suppress error reports +# When Clang 3.8 is available, convert these to suppression list instead as that is preferred for internal code + +# CMiniMdBase::UsesAllocatedMemory - suppress stack-buffer-underflow (code backs up pointer by -1 to check allocation ownership) +fun:_ZN11CMiniMdBase19UsesAllocatedMemoryEP11CMiniColDef + +# JIT_InitPInvokeFrame - suppress unknown sanitizer issue causing SEGV on unknown address 0x000000000000 +# 0 0x4e8a0c in __ubsan::checkDynamicType(void*, void*, unsigned long) +# 1 0x4e807f in HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned long, unsigned long, __ubsan::ReportOptions) +# 2 0x4e8051 in __ubsan_handle_dynamic_type_cache_miss +# 3 0x7f02ce676cd8 in JIT_InitPInvokeFrame(InlinedCallFrame*, void*) /home/steveharter/git/dotnet_coreclr/vm/jithelpers.cpp:6491:9 +# 4 0x7f0252bbceb2 () +fun:_Z20JIT_InitPInvokeFrameP16InlinedCallFramePv + diff --git a/eng/native/set-cmake-path.ps1 b/eng/native/set-cmake-path.ps1 new file mode 100644 index 000000000..d83ce5ab5 --- /dev/null +++ b/eng/native/set-cmake-path.ps1 @@ -0,0 +1,48 @@ +# This script locates the CMake executable for the build system and outputs either the "set CMakePath=..." +# command (if CMake is found) or the "exit /b 1" command (if not found) for evaluating from batch files. + +Set-StrictMode -Version 3 + +function LocateCMake { + # Find the first cmake.exe on the PATH + $cmakeApp = (Get-Command cmake.exe -ErrorAction SilentlyContinue) + if ($cmakeApp -ne $null) { + return $cmakeApp.Path + } + + # Find cmake.exe using the registry + $cmakeRegKey = Get-ItemProperty HKLM:\SOFTWARE\Kitware\CMake -Name InstallDir -ErrorAction SilentlyContinue + if ($cmakeRegKey -eq $null) { + $cmakeRegKey = Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Kitware\CMake -Name InstallDir -ErrorAction SilentlyContinue + } + + if ($cmakeRegKey -ne $null) { + $cmakePath = $cmakeRegKey.InstallDir + "bin\cmake.exe" + if (Test-Path $cmakePath -PathType Leaf) { + return $cmakePath + } + } + + return $null +} + +try { + $cmakePath = LocateCMake + + if ($cmakePath -eq $null) { + throw "CMake is a pre-requisite to build this repository but it was not found on the PATH or in the registry. Please install CMake from https://cmake.org/download/." + } + + $version = [Version]$(& $cmakePath --version | Select-String -Pattern '\d+\.\d+\.\d+' | %{$_.Matches.Value}) + + if ($version -lt [Version]"3.16.4") { + throw "CMake 3.16.4 or newer is required for building this repository. The newest version of CMake installed is $version. Please install CMake 3.16.4 or newer from https://cmake.org/download/." + } + + [System.Console]::WriteLine("set CMakePath=" + $cmakePath) + +} +catch { + [System.Console]::Error.WriteLine($_.Exception.Message) + [System.Console]::WriteLine("exit /b 1") +} diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake new file mode 100644 index 000000000..96199969d --- /dev/null +++ b/eng/native/tryrun.cmake @@ -0,0 +1,154 @@ +set(CROSS_ROOTFS $ENV{ROOTFS_DIR}) +set(TARGET_ARCH_NAME $ENV{TARGET_BUILD_ARCH}) + +macro(set_cache_value) + set(${ARGV0} ${ARGV1} CACHE STRING "Result from TRY_RUN" FORCE) + set(${ARGV0}__TRYRUN_OUTPUT "dummy output" CACHE STRING "Output from TRY_RUN" FORCE) +endmacro() + +if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv7-alpine-linux-musleabihf OR + EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf OR + EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl) + + set(ALPINE_LINUX 1) +elseif(EXISTS ${CROSS_ROOTFS}/bin/freebsd-version) + set(FREEBSD 1) + set(CMAKE_SYSTEM_NAME FreeBSD) + set(CLR_CMAKE_TARGET_OS FreeBSD) +elseif(EXISTS ${CROSS_ROOTFS}/usr/platform/i86pc) + set(ILLUMOS 1) + set(CLR_CMAKE_TARGET_OS SunOS) +elseif(EXISTS /System/Library/CoreServices) + set(DARWIN 1) +endif() + +if(DARWIN) + if(TARGET_ARCH_NAME MATCHES "^(arm64|x64)$") + set_cache_value(FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL_EXITCODE 1) + set_cache_value(GETPWUID_R_SETS_ERRNO_EXITCODE 1) + set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 1) + set_cache_value(HAVE_BROKEN_FIFO_KEVENT_EXITCODE 1) + set_cache_value(HAVE_BROKEN_FIFO_SELECT_EXITCODE 1) + set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 1) + set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) + set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) + set_cache_value(HAVE_CLOCK_THREAD_CPUTIME_EXITCODE 0) + set_cache_value(HAVE_CLOCK_GETTIME_NSEC_NP_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ACOS_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ASIN_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ATAN2_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_EXP_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_ILOGB0_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ILOGBNAN_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_LOG10_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_LOG_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_POW_EXITCODE 0) + set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 1) + set_cache_value(HAVE_LARGE_SNPRINTF_SUPPORT_EXITCODE 0) + set_cache_value(HAVE_MMAP_DEV_ZERO_EXITCODE 1) + set_cache_value(HAVE_PROCFS_CTL_EXITCODE 1) + set_cache_value(HAVE_PROCFS_MAPS_EXITCODE 1) + set_cache_value(HAVE_PROCFS_STATUS_EXITCODE 1) + set_cache_value(HAVE_PROCFS_STAT_EXITCODE 1) + set_cache_value(HAVE_SCHED_GETCPU_EXITCODE 1) + set_cache_value(HAVE_SCHED_GET_PRIORITY_EXITCODE 0) + set_cache_value(HAVE_VALID_NEGATIVE_INF_POW_EXITCODE 0) + set_cache_value(HAVE_VALID_POSITIVE_INF_POW_EXITCODE 0) + set_cache_value(HAVE_WORKING_CLOCK_GETTIME_EXITCODE 0) + set_cache_value(HAVE_WORKING_GETTIMEOFDAY_EXITCODE 0) + set_cache_value(MMAP_ANON_IGNORES_PROTECTION_EXITCODE 1) + set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE 1) + set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1) + set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1) + set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1) + set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 1) + set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 0) + set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 1) + set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE 0) + else() + message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm64 or x64 is supported for OSX cross build!") + endif() +elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|arm64|s390x|x86)$" OR FREEBSD OR ILLUMOS) + set_cache_value(FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL_EXITCODE 1) + set_cache_value(GETPWUID_R_SETS_ERRNO_EXITCODE 0) + set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 0) + set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 0) + set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) + set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) + set_cache_value(HAVE_CLOCK_THREAD_CPUTIME_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ACOS_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ASIN_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ATAN2_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_ILOGB0_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_ILOGBNAN_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_LOG10_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_LOG_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_POW_EXITCODE 0) + set_cache_value(HAVE_LARGE_SNPRINTF_SUPPORT_EXITCODE 0) + set_cache_value(HAVE_MMAP_DEV_ZERO_EXITCODE 0) + set_cache_value(HAVE_PROCFS_CTL_EXITCODE 1) + set_cache_value(HAVE_PROCFS_MAPS_EXITCODE 0) + set_cache_value(HAVE_PROCFS_STATUS_EXITCODE 0) + set_cache_value(HAVE_PROCFS_STAT_EXITCODE 0) + set_cache_value(HAVE_SCHED_GETCPU_EXITCODE 0) + set_cache_value(HAVE_SCHED_GET_PRIORITY_EXITCODE 0) + set_cache_value(HAVE_VALID_NEGATIVE_INF_POW_EXITCODE 0) + set_cache_value(HAVE_VALID_POSITIVE_INF_POW_EXITCODE 0) + set_cache_value(HAVE_WORKING_CLOCK_GETTIME_EXITCODE 0) + set_cache_value(HAVE_WORKING_GETTIMEOFDAY_EXITCODE 0) + set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE 1) + set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1) + set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1) + set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1) + + + if(ALPINE_LINUX) + set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE 1) + set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 0) + set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 1) + set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 1) + else() + set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE 0) + set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 1) + set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 0) + set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 0) + endif() + + if (FREEBSD) + set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP 1) + set_cache_value(HAVE_CLOCK_MONOTONIC 1) + set_cache_value(HAVE_CLOCK_REALTIME 1) + set_cache_value(HAVE_BROKEN_FIFO_KEVENT_EXITCODE 1) + set_cache_value(HAVE_PROCFS_MAPS 0) + set_cache_value(HAVE_PROCFS_STAT 0) + set_cache_value(HAVE_PROCFS_STATUS_EXITCODE 1) + set_cache_value(GETPWUID_R_SETS_ERRNO 0) + set_cache_value(UNGETC_NOT_RETURN_EOF 0) + set_cache_value(HAVE_COMPATIBLE_ILOGBNAN 1) + set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) + elseif(ILLUMOS) + set_cache_value(GETPWUID_R_SETS_ERRNO_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_ACOS_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_ASIN_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_ATAN2_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_POW_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_ILOGBNAN_EXITCODE 0) + set_cache_value(HAVE_COMPATIBLE_LOG10_EXITCODE 1) + set_cache_value(HAVE_COMPATIBLE_LOG_EXITCODE 1) + set_cache_value(HAVE_LARGE_SNPRINTF_SUPPORT_EXITCODE 1) + set_cache_value(HAVE_PROCFS_CTL_EXITCODE 0) + set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 1) + set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 1) + set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 0) + set_cache_value(COMPILER_SUPPORTS_W_CLASS_MEMACCESS 1) + set_cache_value(HAVE_SET_MAX_VARIABLE 1) + set_cache_value(HAVE_FULLY_FEATURED_PTHREAD_MUTEXES 1) + set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) + endif() +else() + message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64, s390x and x86 are supported!") +endif() + +if(TARGET_ARCH_NAME STREQUAL "x86" OR TARGET_ARCH_NAME STREQUAL "s390x") + set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) +endif() diff --git a/eng/native/version/NativeVersion.rc b/eng/native/version/NativeVersion.rc new file mode 100644 index 000000000..618bb1145 --- /dev/null +++ b/eng/native/version/NativeVersion.rc @@ -0,0 +1,41 @@ +#include "_version.h" + +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS VER_DEBUG +FILEOS VOS__WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + /* The following line should only be modified for localized versions. */ + /* It consists of any number of WORD,WORD pairs, with each pair */ + /* describing a language,codepage combination supported by the file. */ + /* */ + /* For example, a file might have values "0x409,1252" indicating that it */ + /* supports English language (0x409) in the Windows ANSI codepage (1252). */ + + VALUE "Translation", 0x409, 1252 + + END +END diff --git a/eng/native/version/_version.c b/eng/native/version/_version.c new file mode 100644 index 000000000..153d9f05f --- /dev/null +++ b/eng/native/version/_version.c @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +static char sccsid[] __attribute__((used)) = "@(#)No version information produced"; diff --git a/eng/native/version/_version.h b/eng/native/version/_version.h new file mode 100644 index 000000000..25268bf7e --- /dev/null +++ b/eng/native/version/_version.h @@ -0,0 +1,29 @@ +#ifndef VER_COMPANYNAME_STR +#define VER_COMPANYNAME_STR ".NET Foundation" +#endif +#ifndef VER_FILEDESCRIPTION_STR +#define VER_FILEDESCRIPTION_STR ".NET Runtime" +#endif +#ifndef VER_INTERNALNAME_STR +#define VER_INTERNALNAME_STR VER_FILEDESCRIPTION_STR +#endif +#ifndef VER_ORIGINALFILENAME_STR +#define VER_ORIGINALFILENAME_STR VER_FILEDESCRIPTION_STR +#endif +#ifndef VER_PRODUCTNAME_STR +#define VER_PRODUCTNAME_STR ".NET" +#endif +#undef VER_PRODUCTVERSION +#define VER_PRODUCTVERSION 00,00,00,00000 +#undef VER_PRODUCTVERSION_STR +#define VER_PRODUCTVERSION_STR "0.0.0" +#undef VER_FILEVERSION +#define VER_FILEVERSION 00,00,00,00000 +#undef VER_FILEVERSION_STR +#define VER_FILEVERSION_STR "00,00,00,00000" +#ifndef VER_LEGALCOPYRIGHT_STR +#define VER_LEGALCOPYRIGHT_STR ".NET Foundation" +#endif +#ifndef VER_DEBUG +#define VER_DEBUG VS_FF_DEBUG +#endif diff --git a/eng/native/version/copy_version_files.cmd b/eng/native/version/copy_version_files.cmd new file mode 100644 index 000000000..ef5f31e24 --- /dev/null +++ b/eng/native/version/copy_version_files.cmd @@ -0,0 +1,12 @@ +@if not defined _echo @echo off +setlocal EnableDelayedExpansion EnableExtensions + +set __VersionFolder=%~dp0 +set __RepoRoot=%~dp0..\..\.. +set __artifactsObjDir=%__RepoRoot%\artifacts\obj + +for /r "%__VersionFolder%" %%a in (*.h *.rc) do ( + if not exist "%__artifactsObjDir%\%%~nxa" ( + copy "%%a" "%__artifactsObjDir%" + ) +) diff --git a/eng/native/version/copy_version_files.sh b/eng/native/version/copy_version_files.sh new file mode 100755 index 000000000..d60ed4715 --- /dev/null +++ b/eng/native/version/copy_version_files.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +__VersionFolder="$(cd "$(dirname "$0")"; pwd -P)" +__RepoRoot="$(cd "$(dirname "$__VersionFolder")/../../"; pwd -P)" + +for path in "${__VersionFolder}/"*{.h,.c}; do + if [[ "$(basename $path)" == _version.c ]]; then + # For _version.c, update the commit ID if it has changed from the last build. + # Set IFS to nothing to prevent the shell from combining all of the piped output into a single line in the script below + IFS= + # update commit + commit="$(git rev-parse HEAD 2>/dev/null)" + commit="${commit:-N/A}" + substitute="$(printf 'static char sccsid[] __attribute__((used)) = "@(#)Version N/A @Commit: %s";\n' "$commit")" + version_file_contents="$(cat "$path" | sed "s|^static.*|$substitute|")" + version_file_destination="$__RepoRoot/artifacts/obj/_version.c" + current_contents= + is_placeholder_file= + if [[ -e "$version_file_destination" ]]; then + current_contents="$(<"$__RepoRoot/artifacts/obj/_version.c")" + # If the current file has the version placeholder this script uses, we can update it + # to have the current commit. Otherwise, use the current version file that has the actual product version. + is_placeholder_file="$(echo $current_contents | grep "@(#)Version N/A @Commit:")" + else + # Treat a non-existent file like a file that doesn't exist. + is_placeholder_file=1 + fi + if [[ "$is_placeholder_file" && "$version_file_contents" != "$current_contents" ]]; then + echo "$version_file_contents" > "$version_file_destination" + fi + elif [[ ! -e "$__RepoRoot/artifacts/obj/$(basename "$path")" ]]; then + cp "$path" "$__RepoRoot/artifacts/obj/" + fi +done diff --git a/eng/native/version/runtime_version.h b/eng/native/version/runtime_version.h new file mode 100644 index 000000000..12b55fe60 --- /dev/null +++ b/eng/native/version/runtime_version.h @@ -0,0 +1,10 @@ +#define RuntimeAssemblyMajorVersion 0 +#define RuntimeAssemblyMinorVersion 0 +#define RuntimeFileMajorVersion 0 +#define RuntimeFileMinorVersion 0 +#define RuntimeFileBuildVersion 0 +#define RuntimeFileRevisionVersion 0 +#define RuntimeProductMajorVersion 0 +#define RuntimeProductMinorVersion 0 +#define RuntimeProductPatchVersion 0 +#define RuntimeProductVersion 0.0.0-dev