diff --git a/eng/RuntimeIdentifier.props b/eng/RuntimeIdentifier.props index a3c396d8e6b6c7..7a85c173a61d6a 100644 --- a/eng/RuntimeIdentifier.props +++ b/eng/RuntimeIdentifier.props @@ -8,7 +8,9 @@ + And, for flavors of Linux, like 'linux-musl' and 'linux-bionic', TargetOS is 'linux'. + ohos is an exception: its RID is kernel-agnostic, so TargetOS is 'ohos' (not 'linux'), + and it opts into the Linux family flags explicitly below. --> $(TargetOS.ToLowerInvariant()) win @@ -19,6 +21,7 @@ linux-musl linux-bionic + ohos $(PortableOS)-$(TargetArchitecture) @@ -47,10 +50,13 @@ true true true - true + + true true true - true + true + true true true true diff --git a/eng/Subsets.props b/eng/Subsets.props index 898741f170e185..3c20c2eb937d59 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -56,7 +56,7 @@ true <_UseNativeAotForComponentsCrossOS Condition="'$(CrossBuild)' == 'true' and '$(_hostArchitecture)' == '$(_targetArchitecture)' and '$(_hostOS)' != 'windows'">true - true + true @@ -77,6 +77,8 @@ clr+libs+host+packs clr.nativeaotruntime+clr.nativeaotlibs+mono+libs+host+packs clr.nativeaotruntime+clr.nativeaotlibs+libs+packs + + clr.nativeaotruntime+clr.nativeaotlibs+clr+libs+host+packs clr+libs+tools+host+packs clr+libs+tools+host+packs diff --git a/eng/build.sh b/eng/build.sh index b4496e0bc362f1..f0b85a3f45c379 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -32,7 +32,7 @@ usage() echo " [Default: Debug]" echo " --os Target operating system: windows, linux, freebsd, osx, maccatalyst, tvos," echo " tvossimulator, ios, iossimulator, android, browser, wasi, netbsd, illumos, solaris" - echo " linux-musl, linux-bionic, tizen, or haiku." + echo " linux-musl, linux-bionic, ohos, tizen, or haiku." echo " [Default: Your machine's OS.]" echo " --targetrid Optional argument that overrides the target rid name." echo " --projects Project or solution file(s) to build." @@ -146,8 +146,9 @@ initDistroRid() local isCrossBuild="$3" # Only pass ROOTFS_DIR if __DoCrossArchBuild is specified and the current platform is not an Apple platform (that doesn't use rootfs) - if [[ $isCrossBuild == 1 && "$targetOs" != "osx" && "$targetOs" != "android" && "$targetOs" != "ios" && "$targetOs" != "iossimulator" && "$targetOs" != "tvos" && "$targetOs" != "tvossimulator" && "$targetOs" != "maccatalyst" ]]; then - passedRootfsDir=${ROOTFS_DIR} + # OpenHarmony uses its NDK toolchain, so no rootfs is required either. + if [[ $isCrossBuild == 1 && "$targetOs" != "osx" && "$targetOs" != "android" && "$targetOs" != "ios" && "$targetOs" != "iossimulator" && "$targetOs" != "tvos" && "$targetOs" != "tvossimulator" && "$targetOs" != "maccatalyst" && "${__PortableTargetOS:-}" != "ohos" ]]; then + passedRootfsDir=${ROOTFS_DIR:-} fi initDistroRidGlobal "${targetOs}" "${targetArch}" "${passedRootfsDir}" } @@ -310,6 +311,10 @@ while [[ $# -gt 0 ]]; do os="linux" __PortableTargetOS=linux-musl ;; + ohos) + os="ohos" + __PortableTargetOS=ohos + ;; haiku) os="haiku" ;; *) @@ -626,6 +631,12 @@ export DOTNETSDK_ALLOW_TARGETING_PACK_CACHING=0 # In *proj files (XML docs), URL-encoded string are rendered in their decoded form. cmakeargs="${cmakeargs// /%20}" arguments+=("/p:TargetArchitecture=$arch" "/p:BuildArchitecture=$hostArch") +# Propagate the portable target OS (e.g. 'ohos', 'linux-musl', 'linux-bionic') to MSBuild. +# TargetOS stays 'linux' for these flavors; PortableOS in RuntimeIdentifier.props +# derives from __PortableTargetOS, and downstream (packaging, live builds) relies on it. +if [[ -n "${__PortableTargetOS:-}" ]]; then + arguments+=("/p:__PortableTargetOS=$__PortableTargetOS") +fi arguments+=("/p:CMakeArgs=\"$cmakeargs\"" ${extraargs[@]+"${extraargs[@]}"}) if [[ "$bootstrap" == "1" ]]; then diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index fdf156b16fec2e..657906c9353dbf 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -7,7 +7,7 @@ initTargetDistroRid() 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 + if [[ "$__CrossBuild" == 1 && "$platform" != "darwin" && "$__TargetOS" != "ohos" ]]; then passedRootfsDir="$ROOTFS_DIR" fi @@ -137,6 +137,38 @@ build_native() echo "Error: Unknown Android architecture $hostArch." exit 1 fi + elif [[ "$targetOS" == ohos ]]; then + # OpenHarmony NDK-style toolchain. The OHOS NDK provides its + # own CMake toolchain file (ohos.toolchain.cmake) which sets CMAKE_SYSTEM_NAME=OHOS + # and selects the aarch64/arm/x86_64 ohos clang wrappers + sysroot. + if [[ -z "$OHOS_NDK_HOME" ]]; then + echo "Error: You need to set the OHOS_NDK_HOME environment variable pointing to the OpenHarmony NDK root." + exit 1 + fi + + local ohosToolchainFile="$OHOS_NDK_HOME/native/build/cmake/ohos.toolchain.cmake" + if [[ ! -f "$ohosToolchainFile" ]]; then + echo "Error: OHOS CMake toolchain file not found at $ohosToolchainFile. Verify OHOS_NDK_HOME." + exit 1 + fi + + cmakeArgs="-DCMAKE_TOOLCHAIN_FILE=$ohosToolchainFile $cmakeArgs" + cmakeArgs="-DOHOS_NDK_HOME=$OHOS_NDK_HOME $cmakeArgs" + cmakeArgs="-C $__RepoRootDir/eng/native/tryrun.cmake $cmakeArgs" + + # Don't try to set CC/CXX in init-compiler.sh - it's handled in ohos.toolchain.cmake already + __Compiler="default" + + if [[ "$hostArch" == arm64 ]]; then + cmakeArgs="-DOHOS_ARCH=arm64-v8a $cmakeArgs" + elif [[ "$hostArch" == arm ]]; then + cmakeArgs="-DOHOS_ARCH=armeabi-v7a $cmakeArgs" + elif [[ "$hostArch" == x64 ]]; then + cmakeArgs="-DOHOS_ARCH=x86_64 $cmakeArgs" + else + echo "Error: Unknown OHOS architecture $hostArch." + exit 1 + fi elif [[ "$targetOS" == iossimulator ]]; then cmakeArgs="-C $__RepoRootDir/eng/native/tryrun_ios_tvos.cmake $cmakeArgs" @@ -596,6 +628,9 @@ elif [[ "$__TargetOS" == osx || "$__TargetOS" == maccatalyst ]]; then elif [[ "$__TargetOS" == android ]]; then # nothing to do here true +elif [[ "$__TargetOS" == ohos ]]; then + # OpenHarmony uses its NDK toolchain, no rootfs required + true else __CMakeArgs="-DFEATURE_DISTRO_AGNOSTIC_SSL=$__PortableBuild $__CMakeArgs" fi @@ -604,8 +639,8 @@ fi if [[ "$__CrossBuild" == 1 ]]; then CROSSCOMPILE=1 export CROSSCOMPILE - # Darwin that doesn't use rootfs - if [[ -z "$ROOTFS_DIR" && "$platform" != "darwin" ]]; then + # Darwin that doesn't use rootfs; OpenHarmony uses its NDK toolchain + if [[ -z "$ROOTFS_DIR" && "$platform" != "darwin" && "$__TargetOS" != "ohos" ]]; then ROOTFS_DIR="$__RepoRootDir/.tools/rootfs/$__TargetArch" export ROOTFS_DIR fi diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index bc5fcb1733acb7..55b1bfb309afbf 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -653,6 +653,20 @@ if (CLR_CMAKE_HOST_UNIX OR CLR_CMAKE_HOST_WASI) add_compile_options(-fstack-protector-strong) endif() + if(CLR_CMAKE_HOST_OPENHARMONY) + # The OHOS NDK toolchain injects --gcc-toolchain (via CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN) + # which clang reports as unused; silence it (in CMAKE_C_FLAGS so try_compile checks + # inherit it) so -Werror doesn't fail the build. Applies to assembly too. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Qunused-arguments") + # The arm64 asm helpers access t_ThreadStatics/t_runtime_thread_locals via TLS + # descriptors; the C++ definitions must use native (non-emulated) TLS with the + # global-dynamic model to match. + add_compile_options(-fno-emulated-tls) + add_compile_options(-ftls-model=global-dynamic) + endif() + # Suppress warnings-as-errors in release branches to reduce servicing churn if (PRERELEASE) add_compile_options(-Werror) @@ -845,6 +859,9 @@ if(CLR_CMAKE_TARGET_UNIX) if(CLR_CMAKE_TARGET_LINUX_MUSL) add_compile_definitions($<$>>:TARGET_LINUX_MUSL>) endif() + if(CLR_CMAKE_TARGET_OPENHARMONY) + add_compile_definitions($<$>>:TARGET_OPENHARMONY>) + endif() if(CLR_CMAKE_TARGET_ANDROID) add_compile_definitions($<$>>:TARGET_ANDROID>) endif() diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index 2ccced093f6b38..700e508c84f5f8 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -11,6 +11,13 @@ set(PRERELEASE 1) #---------------------------------------- set(CLR_CMAKE_HOST_OS ${CMAKE_SYSTEM_NAME}) string(TOLOWER ${CLR_CMAKE_HOST_OS} CLR_CMAKE_HOST_OS) +# OpenHarmony uses the OHOS NDK CMake toolchain which sets +# CMAKE_SYSTEM_NAME=OHOS. Its libc is musl-based, so treat it as a linux/musl target. +if(CLR_CMAKE_HOST_OS STREQUAL ohos) + set(CLR_CMAKE_HOST_OS linux) + set(CLR_CMAKE_HOST_LINUX_MUSL 1) + set(CLR_CMAKE_HOST_OPENHARMONY 1) +endif() if(CLR_CMAKE_HOST_OS STREQUAL linux) set(CLR_CMAKE_HOST_UNIX 1) if(CLR_CROSS_COMPONENTS_BUILD) @@ -357,6 +364,10 @@ if(CLR_CMAKE_HOST_LINUX_MUSL OR CLR_CMAKE_TARGET_OS STREQUAL alpine) set(CLR_CMAKE_TARGET_LINUX_MUSL 1) endif(CLR_CMAKE_HOST_LINUX_MUSL OR CLR_CMAKE_TARGET_OS STREQUAL alpine) +if(CLR_CMAKE_HOST_OPENHARMONY) + set(CLR_CMAKE_TARGET_OPENHARMONY 1) +endif() + 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) diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake index 16d039acc39830..555c35f5ca035e 100644 --- a/eng/native/configuretools.cmake +++ b/eng/native/configuretools.cmake @@ -28,11 +28,27 @@ if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER AND NOT CLR_CMAKE_TARGET_WASI) return() endif() + # For NDK-style toolchains (OpenHarmony) the compiler lives outside PATH. + # Hint find_program at the compiler's directory so tools like llvm-ar/nm are located. + # Guarded to OHOS only so other platforms keep their existing lookup behavior. + if(CLR_CMAKE_HOST_OPENHARMONY) + get_filename_component(CLR_COMPILER_DIR "${CMAKE_C_COMPILER}" DIRECTORY) + endif() + unset(EXEC_LOCATION_${exec} CACHE) - find_program(EXEC_LOCATION_${exec} - NAMES - "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" - "${TOOLSET_PREFIX}${exec}") + if(CLR_CMAKE_HOST_OPENHARMONY) + find_program(EXEC_LOCATION_${exec} + NAMES + "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" + "${TOOLSET_PREFIX}${exec}" + HINTS + "${CLR_COMPILER_DIR}") + else() + find_program(EXEC_LOCATION_${exec} + NAMES + "${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}" + "${TOOLSET_PREFIX}${exec}") + endif() if (required AND EXEC_LOCATION_${exec} STREQUAL "EXEC_LOCATION_${exec}-NOTFOUND") message(FATAL_ERROR "Unable to find toolchain executable. Name: '${exec}', Prefix: '${TOOLSET_PREFIX}'") diff --git a/eng/native/gen-buildsys.sh b/eng/native/gen-buildsys.sh index 72b82a136ce17d..087353cd3feac0 100755 --- a/eng/native/gen-buildsys.sh +++ b/eng/native/gen-buildsys.sh @@ -63,8 +63,8 @@ done cmake_extra_defines= if [[ "$CROSSCOMPILE" == "1" ]]; then platform="$(uname -s | tr '[:upper:]' '[:lower:]')" - # OSX doesn't use rootfs - if ! [[ -n "$ROOTFS_DIR" || "$platform" == "darwin" ]]; then + # OSX doesn't use rootfs; OpenHarmony uses its NDK toolchain + if ! [[ -n "$ROOTFS_DIR" || "$platform" == "darwin" || "$target_os" == "ohos" ]]; then echo "ROOTFS_DIR not set for crosscompile" exit 1 fi @@ -76,6 +76,9 @@ if [[ "$CROSSCOMPILE" == "1" ]]; then if [[ "$platform" == "darwin" ]]; then cmake_extra_defines="$cmake_extra_defines -DCMAKE_SYSTEM_NAME=Darwin" + elif [[ "$target_os" == "ohos" ]]; then + # OpenHarmony NDK toolchain is injected by build-commons.sh; do not override it. + true else cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$scriptroot/../common/cross/toolchain.cmake" fi diff --git a/src/native/libs/System.Native/CMakeLists.txt b/src/native/libs/System.Native/CMakeLists.txt index 5930703021940b..8273eb07010019 100644 --- a/src/native/libs/System.Native/CMakeLists.txt +++ b/src/native/libs/System.Native/CMakeLists.txt @@ -57,7 +57,7 @@ else() # WASI ) endif() -if (CLR_CMAKE_TARGET_APPLE OR CLR_CMAKE_TARGET_ANDROID OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI OR CLR_CMAKE_TARGET_OPENBSD OR CLR_CMAKE_TARGET_HAIKU) +if (CLR_CMAKE_TARGET_APPLE OR CLR_CMAKE_TARGET_ANDROID OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI OR CLR_CMAKE_TARGET_OPENBSD OR CLR_CMAKE_TARGET_HAIKU OR CLR_CMAKE_TARGET_OPENHARMONY) # These platforms do not support robust mutexes. # Keep an OS list instead of CMake configure checks since we also need to synchronize this with # the compile-time guards on the managed code side at diff --git a/src/native/libs/build-native.sh b/src/native/libs/build-native.sh index 05b77499d7d40a..77a616cd9c0ec0 100755 --- a/src/native/libs/build-native.sh +++ b/src/native/libs/build-native.sh @@ -58,7 +58,7 @@ else __CMakeArgs="-DFEATURE_DISTRO_AGNOSTIC_SSL=$__PortableBuild $__CMakeArgs" __CMakeArgs="-DCMAKE_STATIC_LIB_LINK=$__StaticLibLink $__CMakeArgs" - if [[ "$__TargetOS" != linux-bionic && "$__TargetArch" != x86 && "$__TargetArch" != x64 && "$__TargetArch" != "$__HostArch" ]]; then + if [[ "$__TargetOS" != linux-bionic && "$__TargetOS" != ohos && "$__TargetArch" != x86 && "$__TargetArch" != x64 && "$__TargetArch" != "$__HostArch" ]]; then __CrossBuild=1 echo "Set CrossBuild for $__TargetArch build" fi