Skip to content

Commit

Permalink
Add System.Globalization.Native support for Windows (dotnet#33704)
Browse files Browse the repository at this point in the history
* Add System.Globalization.Native support for Windows

* PR Feedback

* Fix build and address more feedback

* More PR Feedback

* Fix OSX build and update lib name in dllimport

* Remove un-necessary include and update issue link
  • Loading branch information
safern authored Mar 21, 2020
1 parent 1725f0e commit d07a30c
Show file tree
Hide file tree
Showing 22 changed files with 204 additions and 102 deletions.
2 changes: 1 addition & 1 deletion src/coreclr/build-runtime.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ if %__BuildNative% EQU 1 (

echo %__MsgPrefix%Regenerating the Visual Studio solution

set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native"
set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%"
call "%__SourceDir%\pal\tools\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs!
if not !errorlevel! == 0 (
echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project!
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ if %__BuildNative% EQU 1 (

echo %__MsgPrefix%Regenerating the Visual Studio solution

set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native"
set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%"
call "%__SourceDir%\pal\tools\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs!
if not !errorlevel! == 0 (
echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project!
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ set(CORECLR_LIBRARIES
utilcode
v3binder
libraries-native
System.Globalization.Native-Static
interop
)

Expand All @@ -136,7 +137,6 @@ else()
${END_WHOLE_ARCHIVE}
mscorrc
palrt
System.Globalization.Native-Static
)
endif(CLR_CMAKE_TARGET_WIN32)

Expand Down
10 changes: 4 additions & 6 deletions src/coreclr/src/libraries-native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(GLOBALIZATION_NATIVE_DIR ${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/System.Globalization.Native)

# Suppress exporting of the PAL APIs
add_definitions(-DPALEXPORT=)
add_definitions(-DPALEXPORT=EXTERN_C)

if(CLR_CMAKE_HOST_UNIX)
include_directories("${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/Common")
include_directories("${GLOBALIZATION_NATIVE_DIR}")
include_directories("${GLOBALIZATION_NATIVE_DIR}")
include_directories("${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/Common")

add_subdirectory(${GLOBALIZATION_NATIVE_DIR} System.Globalization.Native)
endif()
add_subdirectory(${GLOBALIZATION_NATIVE_DIR} System.Globalization.Native)

add_library(libraries-native
STATIC
Expand Down
9 changes: 2 additions & 7 deletions src/coreclr/src/libraries-native/entrypoints.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#ifdef TARGET_UNIX

#include "pal_types.h"
#include <stdint.h>

typedef uint16_t UChar;

Expand All @@ -19,15 +17,13 @@ typedef uint16_t UChar;
#include "pal_idna.h"
#include "pal_normalization.h"
#include "pal_timeZoneInfo.h"
#endif // TARGET_UNIX

#define FCFuncStart(name) extern const void* name[]; const void* name[] = {
#define FCFuncStart(name) EXTERN_C const void* name[]; const void* name[] = {
#define FCFuncEnd() (void*)0x01 /* FCFuncFlag_EndOfArray */ };

#define QCFuncElement(name,impl) \
(void*)0x8 /* FCFuncFlag_QCall */, (void*)(impl), (void*)name,

#ifdef TARGET_UNIX
FCFuncStart(gPalGlobalizationNative)
QCFuncElement("ChangeCase", GlobalizationNative_ChangeCase)
QCFuncElement("ChangeCaseInvariant", GlobalizationNative_ChangeCaseInvariant)
Expand Down Expand Up @@ -64,4 +60,3 @@ FCFuncStart(gPalGlobalizationNative)
QCFuncElement("ToAscii", GlobalizationNative_ToAscii)
QCFuncElement("ToUnicode", GlobalizationNative_ToUnicode)
FCFuncEnd()
#endif // TARGET_UNIX
2 changes: 1 addition & 1 deletion src/coreclr/src/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4795,7 +4795,7 @@ void NDirect::PopulateNDirectMethodDesc(NDirectMethodDesc* pNMD, PInvokeStaticSi
if (callConv == pmCallConvThiscall)
ndirectflags |= NDirectMethodDesc::kThisCall;

if (pNMD->GetLoaderModule()->IsSystem() && (strcmp(szLibName, "QCall") == 0 || strcmp(szLibName, "System.Globalization.Native") == 0))
if (pNMD->GetLoaderModule()->IsSystem() && (strcmp(szLibName, "QCall") == 0 || strcmp(szLibName, "libSystem.Globalization.Native") == 0))
{
ndirectflags |= NDirectMethodDesc::kIsQCall;
}
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/src/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -1239,11 +1239,9 @@ FCClassElement("FileLoadException", "System.IO", gFileLoadExceptionFuncs)
FCClassElement("GC", "System", gGCInterfaceFuncs)
FCClassElement("GCHandle", "System.Runtime.InteropServices", gGCHandleFuncs)
FCClassElement("GCSettings", "System.Runtime", gGCSettingsFuncs)
#ifdef TARGET_UNIX
#ifndef CROSSGEN_COMPILE
FCClassElement("Globalization", "", gPalGlobalizationNative)
#endif
#endif
#ifdef FEATURE_COMINTEROP
FCClassElement("IEnumerable", "System.Collections", gStdMngIEnumerableFuncs)
FCClassElement("IEnumerator", "System.Collections", gStdMngIEnumeratorFuncs)
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/Native/Unix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ endif(CLR_CMAKE_TARGET_FREEBSD)
#
if(CLR_CMAKE_TARGET_UNIX)
if (CLR_CMAKE_TARGET_DARWIN)
add_definitions(-DTARGET_DARWIN)
add_link_options(-Wl,-bind_at_load)
elseif (CLR_CMAKE_TARGET_ARCH_WASM)
# No object stripping for WASM
Expand All @@ -164,6 +165,7 @@ if(CLR_CMAKE_TARGET_UNIX)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}" )
add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS})
add_definitions(-DTARGET_UNIX)
endif(CLR_CMAKE_TARGET_UNIX)

function(install_library_and_symbols targetName)
Expand Down
19 changes: 19 additions & 0 deletions src/libraries/Native/Unix/Common/pal_atomic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//

#if defined(TARGET_UNIX)
#include <stdatomic.h>
#elif defined(TARGET_WINDOWS)
#include "windows.h"
#endif

static int pal_atomic_cas_ptr(void* volatile* dest, void* exchange, void* comparand)
{
#if defined(TARGET_UNIX)
return __atomic_compare_exchange_n(dest, exchange, comparand, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
#elif defined(TARGET_WINDOWS)
return InterlockedCompareExchangePointer(dest, exchange, comparand) == comparand;
#endif
}
14 changes: 13 additions & 1 deletion src/libraries/Native/Unix/Common/pal_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,17 @@
#endif

#ifndef PALEXPORT
#ifdef TARGET_UNIX
#define PALEXPORT __attribute__ ((__visibility__ ("default")))
#endif // ifndef PALEXPORT
#else
#define PALEXPORT
#endif
#endif // PALEXPORT

#ifndef EXTERN_C
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif // __cplusplus
#endif // EXTERN_C
Original file line number Diff line number Diff line change
@@ -1,45 +1,49 @@
project(System.Globalization.Native C)

add_compile_options(-Wno-switch-enum)
add_compile_options(-Wno-covered-switch-default)
if(CLR_CMAKE_TARGET_UNIX)
add_compile_options(-Wno-switch-enum)
add_compile_options(-Wno-covered-switch-default)

# Workaround for warnings produced by ICU headers
add_compile_options(-Wno-reserved-id-macro)
add_compile_options(-Wno-documentation)
add_compile_options(-Wno-documentation-unknown-command)
# Workaround for warnings produced by ICU headers
add_compile_options(-Wno-reserved-id-macro)
add_compile_options(-Wno-documentation)
add_compile_options(-Wno-documentation-unknown-command)

# Workaround for https://unicode-org.atlassian.net/browse/ICU-20601
add_compile_options(-Wno-extra-semi-stmt)
add_compile_options(-Wno-unknown-warning-option)
# Workaround for https://unicode-org.atlassian.net/browse/ICU-20601
add_compile_options(-Wno-extra-semi-stmt)
add_compile_options(-Wno-unknown-warning-option)

set(ICU_HOMEBREW_INC_PATH "/usr/local/opt/icu4c/include")
set(ICU_HOMEBREW_INC_PATH "/usr/local/opt/icu4c/include")

find_path(UTYPES_H "unicode/utypes.h" PATHS ${ICU_HOMEBREW_INC_PATH})
if(UTYPES_H STREQUAL UTYPES_H-NOTFOUND)
message(FATAL_ERROR "Cannot find utypes.h, try installing libicu-dev (or the appropriate package for your platform)")
return()
endif()

if(CLR_CMAKE_TARGET_DARWIN)
find_library(ICUCORE icucore)
if(ICUCORE STREQUAL ICUCORE-NOTFOUND)
message(FATAL_ERROR "Cannot find libicucore, skipping build for System.Globalization.Native. .NET globalization is not expected to function.")
return()
endif()
add_definitions(-DOSX_ICU_LIBRARY_PATH=\"${ICUCORE}\")
add_definitions(-DU_DISABLE_RENAMING)
else()
find_library(ICUUC icuuc)
if(ICUUC STREQUAL ICUUC-NOTFOUND)
message(FATAL_ERROR "Cannot find libicuuc, try installing libicu-dev (or the appropriate package for your platform)")
find_path(UTYPES_H "unicode/utypes.h" PATHS ${ICU_HOMEBREW_INC_PATH})
if(UTYPES_H STREQUAL UTYPES_H-NOTFOUND)
message(FATAL_ERROR "Cannot find utypes.h, try installing libicu-dev (or the appropriate package for your platform)")
return()
endif()

find_library(ICUI18N icui18n)
if(ICUI18N STREQUAL ICUI18N-NOTFOUND)
message(FATAL_ERROR "Cannot find libicui18n, try installing libicu-dev (or the appropriate package for your platform)")
return()
if(CLR_CMAKE_TARGET_DARWIN)
find_library(ICUCORE icucore)
if(ICUCORE STREQUAL ICUCORE-NOTFOUND)
message(FATAL_ERROR "Cannot find libicucore, skipping build for System.Globalization.Native. .NET globalization is not expected to function.")
return()
endif()
add_definitions(-DOSX_ICU_LIBRARY_PATH=\"${ICUCORE}\")
add_definitions(-DU_DISABLE_RENAMING)
else()
find_library(ICUUC icuuc)
if(ICUUC STREQUAL ICUUC-NOTFOUND)
message(FATAL_ERROR "Cannot find libicuuc, try installing libicu-dev (or the appropriate package for your platform)")
return()
endif()

find_library(ICUI18N icui18n)
if(ICUI18N STREQUAL ICUI18N-NOTFOUND)
message(FATAL_ERROR "Cannot find libicui18n, try installing libicu-dev (or the appropriate package for your platform)")
return()
endif()
endif()

include_directories(${UTYPES_H})
endif()

include(configure.cmake)
Expand All @@ -57,7 +61,6 @@ set(NATIVEGLOBALIZATION_SOURCES
pal_icushim.c
)

include_directories(${UTYPES_H})
include_directories("../Common")

if (GEN_SHARED_LIB)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
include(CheckCSourceCompiles)
include(CheckSymbolExists)

set(CMAKE_REQUIRED_INCLUDES ${UTYPES_H} ${ICU_HOMEBREW_INC_PATH})

if(CLR_CMAKE_TARGET_ANDROID)
string(REPLACE ";" ":" ANDROID_RPATHS "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}:${CMAKE_SYSTEM_LIBRARY_PATH}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rpath ${ANDROID_RPATHS}")
endif()

CHECK_C_SOURCE_COMPILES("
#include <unicode/udat.h>
int main(void) { enum UDateFormatSymbolType e = UDAT_STANDALONE_SHORTER_WEEKDAYS; }
" HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS)
if (CLR_CMAKE_TARGET_UNIX)
set(CMAKE_REQUIRED_INCLUDES ${UTYPES_H} ${ICU_HOMEBREW_INC_PATH})

if(CLR_CMAKE_TARGET_DARWIN)
set(CMAKE_REQUIRED_LIBRARIES ${ICUCORE})
else()
set(CMAKE_REQUIRED_LIBRARIES ${ICUUC} ${ICUI18N})
endif()
CHECK_C_SOURCE_COMPILES("
#include <unicode/udat.h>
int main(void) { enum UDateFormatSymbolType e = UDAT_STANDALONE_SHORTER_WEEKDAYS; }
" HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS)

check_symbol_exists(
ucol_setMaxVariable
"unicode/ucol.h"
HAVE_SET_MAX_VARIABLE)
if(CLR_CMAKE_TARGET_DARWIN)
set(CMAKE_REQUIRED_LIBRARIES ${ICUCORE})
else()
set(CMAKE_REQUIRED_LIBRARIES ${ICUUC} ${ICUI18N})
endif()

unset(CMAKE_REQUIRED_LIBRARIES)
unset(CMAKE_REQUIRED_INCLUDES)
check_symbol_exists(
ucol_setMaxVariable
"unicode/ucol.h"
HAVE_SET_MAX_VARIABLE)

unset(CMAKE_REQUIRED_LIBRARIES)
unset(CMAKE_REQUIRED_INCLUDES)
endif()

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "pal_locale_internal.h"
#include "pal_errors_internal.h"
#include "pal_calendarData.h"

#if defined(TARGET_UNIX)
#include <strings.h>

#define STRING_COPY(destination, numberOfElements, source) \
strncpy(destination, source, numberOfElements); \
destination[numberOfElements - 1] = 0;

#elif defined(TARGET_WINDOWS)
#define strcasecmp _stricmp
#define STRING_COPY(destination, numberOfElements, source) strncpy_s(destination, numberOfElements, source, _TRUNCATE);
#endif

#define GREGORIAN_NAME "gregorian"
#define JAPANESE_NAME "japanese"
#define BUDDHIST_NAME "buddhist"
Expand Down Expand Up @@ -226,7 +236,7 @@ static int InvokeCallbackForDatePattern(const char* locale,
UErrorCode ignore = U_ZERO_ERROR;
int32_t patternLen = udat_toPattern(pFormat, FALSE, NULL, 0, &ignore) + 1;

UChar* pattern = calloc((size_t)patternLen, sizeof(UChar));
UChar* pattern = (UChar*)calloc((size_t)patternLen, sizeof(UChar));
if (pattern == NULL)
{
udat_close(pFormat);
Expand Down Expand Up @@ -266,7 +276,7 @@ static int InvokeCallbackForDateTimePattern(const char* locale,
UErrorCode ignore = U_ZERO_ERROR;
int32_t patternLen = udatpg_getBestPattern(pGenerator, patternSkeleton, -1, NULL, 0, &ignore) + 1;

UChar* bestPattern = calloc((size_t)patternLen, sizeof(UChar));
UChar* bestPattern = (UChar*)calloc((size_t)patternLen, sizeof(UChar));
if (bestPattern == NULL)
{
udatpg_close(pGenerator);
Expand Down Expand Up @@ -306,8 +316,7 @@ static int32_t EnumSymbols(const char* locale,
return FALSE;

char localeWithCalendarName[ULOC_FULLNAME_CAPACITY];
strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY);
localeWithCalendarName[ULOC_FULLNAME_CAPACITY - 1] = 0;
STRING_COPY(localeWithCalendarName, sizeof(localeWithCalendarName), locale);

uloc_setKeywordValue("calendar", GetCalendarName(calendarId), localeWithCalendarName, ULOC_FULLNAME_CAPACITY, &err);

Expand Down Expand Up @@ -336,7 +345,7 @@ static int32_t EnumSymbols(const char* locale,
}
else
{
symbolBuf = calloc((size_t)symbolLen, sizeof(UChar));
symbolBuf = (UChar*)calloc((size_t)symbolLen, sizeof(UChar));
if (symbolBuf == NULL)
{
err = U_MEMORY_ALLOCATION_ERROR;
Expand Down Expand Up @@ -414,9 +423,7 @@ static int32_t EnumAbbrevEraNames(const char* locale,

char* localeNamePtr = localeNameBuf;
char* parentNamePtr = parentNameBuf;

strncpy(localeNamePtr, locale, ULOC_FULLNAME_CAPACITY);
localeNamePtr[ULOC_FULLNAME_CAPACITY - 1] = 0;
STRING_COPY(localeNamePtr, sizeof(localeNameBuf), locale);

while (TRUE)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#include "pal_icushim_internal.h"
#include "pal_casing.h"

#ifdef __clang__
// Workaround for warnings produced by U16_NEXT and U16_APPEND macro expansions
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wsign-conversion"
#endif

/*
Function:
Expand Down Expand Up @@ -146,4 +148,6 @@ void GlobalizationNative_ChangeCaseTurkish(
}
}

#ifdef __clang__
#pragma clang diagnostic pop
#endif
Loading

0 comments on commit d07a30c

Please sign in to comment.