Skip to content

Commit

Permalink
Mono musl support (#76500)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Köplinger <[email protected]>
Fixes #76805
  • Loading branch information
ayakael authored Jan 27, 2023
1 parent 1022253 commit f478cfe
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
<_runtimeOS Condition="'$(TargetsMobile)' == 'true'">$(TargetOS.ToLowerInvariant())</_runtimeOS>

<_portableOS>linux</_portableOS>
<_portableOS Condition="'$(_runtimeOS)' == 'linux-musl'">linux-musl</_portableOS>
<_portableOS Condition="'$(_runtimeOS)' == 'linux-musl' or $(_runtimeOS.StartsWith('alpine'))">linux-musl</_portableOS>
<_portableOS Condition="'$(_runtimeOS)' == 'linux-bionic'">linux-bionic</_portableOS>
<_portableOS Condition="'$(_hostOS)' == 'osx'">osx</_portableOS>
<_portableOS Condition="'$(_runtimeOS)' == 'win' or '$(TargetOS)' == 'windows'">win</_portableOS>
Expand Down Expand Up @@ -219,6 +219,7 @@
<OutputRid Condition="'$(OutputRid)' == ''">$(PackageRID)</OutputRid>
<OutputRid Condition="'$(PortableBuild)' == 'true'">$(_portableOS)-$(TargetArchitecture)</OutputRid>
<TargetsLinuxBionic Condition="$(OutputRid.StartsWith('linux-bionic'))">true</TargetsLinuxBionic>
<TargetsLinuxMusl Condition="'$(_portableOS)' == 'linux-musl'">true</TargetsLinuxMusl>
</PropertyGroup>

<PropertyGroup Label="CalculateTargetOSName" Condition="'$(SkipInferTargetOSName)' != 'true'">
Expand Down
6 changes: 5 additions & 1 deletion eng/native/tryrun.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ 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)
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl OR
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/s390x-alpine-linux-musl OR
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/ppc64le-alpine-linux-musl OR
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/i586-alpine-linux-musl OR
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/riscv64-alpine-linux-musl)

set(ALPINE_LINUX 1)
elseif(EXISTS ${CROSS_ROOTFS}/bin/freebsd-version)
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/pal/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,11 @@ if(CLR_CMAKE_TARGET_LINUX)
target_link_libraries(coreclrpal ${UNWIND_LIBS})
endif(CLR_CMAKE_USE_SYSTEM_LIBUNWIND)

# bundled libunwind requires using libucontext on alpine and x86 and ppc64le
if(CLR_CMAKE_TARGET_ALPINE_LINUX AND (CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_POWERPC64))
target_link_libraries(coreclrpal ucontext)
endif(CLR_CMAKE_TARGET_ALPINE_LINUX AND (CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_POWERPC64))

endif(CLR_CMAKE_TARGET_LINUX)

if(CLR_CMAKE_TARGET_NETBSD)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/pal/src/misc/perfjitdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
#include <linux/limits.h>
#include <limits.h>

#include "../inc/llvm/ELF.h"

Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/vm/i386/cgenx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ extern "C" DWORD __stdcall avx512StateSupport()

#else // !TARGET_UNIX

#if !__has_builtin(__cpuid)
void __cpuid(int cpuInfo[4], int function_id)
{
// Based on the Clang implementation provided in cpuid.h:
Expand All @@ -1143,7 +1144,9 @@ void __cpuid(int cpuInfo[4], int function_id)
: "0"(function_id)
);
}
#endif

#if !__has_builtin(__cpuidex)
void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id)
{
// Based on the Clang implementation provided in cpuid.h:
Expand All @@ -1154,6 +1157,7 @@ void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id)
: "0"(function_id), "2"(subFunction_id)
);
}
#endif

extern "C" DWORD __stdcall xmmYmmStateSupport()
{
Expand Down
42 changes: 39 additions & 3 deletions src/mono/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,36 @@ elseif(CLR_CMAKE_HOST_OS STREQUAL "linux")
# Enable the "full RELRO" options (RELRO & BIND_NOW) at link time
add_link_options(-Wl,-z,relro)
add_link_options(-Wl,-z,now)

# Detect Linux ID
# TODO: Eventually merge with eng/native/configureplatform.cmake
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)

execute_process(
COMMAND bash -c "if strings \"${CMAKE_SYSROOT}/usr/bin/ldd\" 2>&1 | grep -q musl; then echo musl; fi"
OUTPUT_VARIABLE CLR_CMAKE_LINUX_MUSL
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()

if(DEFINED CLR_CMAKE_LINUX_ID)
if(CLR_CMAKE_LINUX_ID STREQUAL alpine)
set(CLR_CMAKE_HOST_ALPINE_LINUX 1)
set(CLR_CMAKE_HOST_OS ${CLR_CMAKE_LINUX_ID})
endif()

if(CLR_CMAKE_LINUX_MUSL STREQUAL musl)
set(CLR_CMAKE_HOST_LINUX_MUSL 1)
endif()
endif(DEFINED CLR_CMAKE_LINUX_ID)
elseif(CLR_CMAKE_HOST_OS STREQUAL "android")
set(HOST_LINUX 1)
add_definitions(-D_GNU_SOURCE -D_REENTRANT)
Expand Down Expand Up @@ -309,7 +339,7 @@ elseif(TARGET_SYSTEM_NAME STREQUAL "ios" OR TARGET_SYSTEM_NAME STREQUAL "tvos")
set(TARGET_TVOS 1)
endif()
set(TARGET_APPLE_MOBILE 1)
elseif(TARGET_SYSTEM_NAME STREQUAL "linux")
elseif(TARGET_SYSTEM_NAME STREQUAL "linux" OR TARGET_SYSTEM_NAME STREQUAL "alpine")
set(TARGET_LINUX 1)
elseif(TARGET_SYSTEM_NAME STREQUAL "android")
set(TARGET_ANDROID 1)
Expand Down Expand Up @@ -592,10 +622,10 @@ if(LLVM_PREFIX)
set(llvm_cxxflags "-I${LLVM_PREFIX}/include -std=c++14 -fno-exceptions -fno-rtti -D__STDC_CONSTANT_MACROS -D__STD_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
set(llvm_includedir "${LLVM_PREFIX}/include")

if(CLR_CMAKE_HOST_OS STREQUAL "linux")
if(HOST_LINUX)
# llvm-config --system-libs
set(llvm_system_libs "-lz" "-lrt" "-ldl" "-lpthread" "-lm")
elseif(CLR_CMAKE_HOST_OS STREQUAL "darwin")
elseif(HOST_OSX)
# llvm-config --system-libs
set(llvm_system_libs "-lz" "-lm")
endif()
Expand Down Expand Up @@ -876,6 +906,12 @@ if(HOST_IOS OR HOST_ANDROID OR HOST_MACCAT)
else()
set(DISABLE_DLLMAP 1)
endif()

if(CLR_CMAKE_HOST_ALPINE_LINUX)
# On Alpine Linux, we need to ensure that the reported stack range for the primary thread is
# larger than the initial committed stack size.
add_definitions(-DENSURE_PRIMARY_STACK_SIZE)
endif()
### End of OS specific checks

include_directories("${CLR_SRC_NATIVE_DIR}")
Expand Down
22 changes: 12 additions & 10 deletions src/mono/mono.proj
Original file line number Diff line number Diff line change
Expand Up @@ -633,19 +633,21 @@
<MonoToolchainPrebuiltOS Condition="$([MSBuild]::IsOSPlatform('OSX'))">darwin-x86_64</MonoToolchainPrebuiltOS>
<MonoToolchainPrebuiltOS Condition="'$(HostOS)' == 'windows'">windows-x86_64</MonoToolchainPrebuiltOS>
<_MonoRuntimeFilePath>$(MonoObjDir)out\lib\$(MonoFileName)</_MonoRuntimeFilePath>
<_LinuxAbi Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsLinuxBionic)' != 'true'">gnu</_LinuxAbi>
<_LinuxAbi Condition="'$(TargetsAndroid)' == 'true' or '$(TargetsLinuxBionic)' == 'true'">android</_LinuxAbi>
<_LinuxAbi Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsLinuxBionic)' != 'true' and '$(TargetsLinuxMusl)' != 'true'">linux-gnu</_LinuxAbi>
<_LinuxAbi Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsLinuxBionic)' != 'true' and '$(TargetsLinuxMusl)' == 'true'">alpine-linux-musl</_LinuxAbi>
<_LinuxAbi Condition="'$(TargetsAndroid)' == 'true' or '$(TargetsLinuxBionic)' == 'true'">linux-android</_LinuxAbi>
<_LinuxFloatAbi Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsLinuxBionic)' != 'true'">hf</_LinuxFloatAbi>
<_Objcopy>objcopy</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'arm'">arm-linux-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'armv6'">arm-linux-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'arm64'">aarch64-linux-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'riscv64'">riscv64-linux-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 's390x'">s390x-linux-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'ppc64le'">powerpc64le-linux-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'x64'">x86_64-linux-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'x86'">i686-linux-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'arm'">arm-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'armv6'">arm-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'arm64'">aarch64-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'riscv64'">riscv64-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 's390x'">s390x-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'ppc64le'">powerpc64le-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'x64'">x86_64-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(Platform)' == 'x86'">i686-$(_LinuxAbi)-$(_Objcopy)</_Objcopy>
<_Objcopy Condition="'$(TargetsAndroid)' == 'true' or '$(TargetsLinuxBionic)' == 'true'">$(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(MonoToolchainPrebuiltOS)/bin/llvm-objcopy</_Objcopy>
<_Objcopy Condition="'$(TargetsLinuxMusl)' == 'true' and '$(CrossBuild)' != 'true'">objcopy</_Objcopy>

<_ObjcopyPrefix Condition="'$(MonoCrossDir)' != '' and '$(Platform)' == 'riscv64'">llvm-objcopy-</_ObjcopyPrefix>
</PropertyGroup>
Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/mini/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,10 @@ if(NOT DISABLE_SHARED_LIBS)
target_compile_definitions(monosgen-objects PRIVATE -DMONO_DLL_EXPORT)
endif()
target_sources(monosgen-shared PRIVATE $<TARGET_OBJECTS:eglib_objects>)
# Alpine Linux implements ucontext in a different library
if(CLR_CMAKE_HOST_ALPINE_LINUX AND TARGET_S390X)
target_link_libraries(monosgen-shared PRIVATE ucontext)
endif(CLR_CMAKE_HOST_ALPINE_LINUX AND TARGET_S390X)
set_target_properties(monosgen-shared PROPERTIES OUTPUT_NAME ${MONO_SHARED_LIB_NAME})
target_link_libraries (monosgen-shared PRIVATE monoapi)
target_include_directories (monosgen-shared PRIVATE monoapi)
Expand Down Expand Up @@ -534,6 +538,10 @@ if(NOT DISABLE_EXECUTABLES)
set_target_properties(mono-sgen PROPERTIES OUTPUT_NAME mono-aot-cross)
endif()
target_link_libraries(mono-sgen PRIVATE monoapi monosgen-static ${OS_LIBS} ${LLVM_LIBS} ${ICU_LIBS} ${Z_LIBS})
# Alpine Linux implements ucontext in a different library
if(CLR_CMAKE_HOST_ALPINE_LINUX AND TARGET_S390X)
target_link_libraries(mono-sgen PRIVATE ucontext)
endif(CLR_CMAKE_HOST_ALPINE_LINUX AND TARGET_S390X)
if(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS AND NOT DISABLE_LINK_STATIC_COMPONENTS)
# if components are built statically, link them into runtime.
target_sources(mono-sgen PRIVATE "${mono-components-objects}")
Expand Down
29 changes: 29 additions & 0 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4393,6 +4393,30 @@ mini_llvm_init (void)
#endif
}

#ifdef ENSURE_PRIMARY_STACK_SIZE
/*++
Function:
EnsureStackSize
Abstract:
This fixes a problem on MUSL where the initial stack size reported by the
pthread_attr_getstack is about 128kB, but this limit is not fixed and
the stack can grow dynamically. The problem is that it makes the
functions ReflectionInvocation::[Try]EnsureSufficientExecutionStack
to fail for real life scenarios like e.g. compilation of corefx.
Since there is no real fixed limit for the stack, the code below
ensures moving the stack limit to a value that makes reasonable
real life scenarios work.
--*/
static MONO_NO_OPTIMIZATION MONO_NEVER_INLINE void
ensure_stack_size (size_t size)
{
volatile uint8_t *s = (uint8_t *)g_alloca(size);
*s = 0;
}
#endif // ENSURE_PRIMARY_STACK_SIZE

void
mini_add_profiler_argument (const char *desc)
{
Expand Down Expand Up @@ -4554,6 +4578,11 @@ mini_init (const char *filename)
mono_w32handle_init ();
#endif

#ifdef ENSURE_PRIMARY_STACK_SIZE
// TODO: https:/dotnet/runtime/issues/72920
ensure_stack_size (5 * 1024 * 1024);
#endif // ENSURE_PRIMARY_STACK_SIZE

mono_thread_info_runtime_init (&ticallbacks);

if (g_hasenv ("MONO_DEBUG")) {
Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/utils/mono-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
#ifndef __MONO_MONO_CONTEXT_H__
#define __MONO_MONO_CONTEXT_H__

/*
* Handle non-gnu libc versions with nothing in features.h
* We have no idea what they're compatible with, so always fail.
*/
#ifndef __GLIBC_PREREQ
# define __GLIBC_PREREQ(x,y) 0
#endif

#include "mono-compiler.h"
#include "mono-sigcontext.h"
#include "mono-machine.h"
Expand Down
2 changes: 1 addition & 1 deletion src/native/libs/System.Native/pal_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd, int64_t
// Try copying data using a copy-on-write clone. This shares storage between the files.
if (sourceLength != 0)
{
while ((ret = ioctl(outFd, FICLONE, inFd)) < 0 && errno == EINTR);
while ((ret = ioctl(outFd, (int)FICLONE, inFd)) < 0 && errno == EINTR);
copied = ret == 0;
}
#endif
Expand Down

0 comments on commit f478cfe

Please sign in to comment.