Add System.Globalization.Native support for Windows (#33704)
authorSantiago Fernandez Madero <safern@microsoft.com>
Sat, 21 Mar 2020 07:32:41 +0000 (00:32 -0700)
committerGitHub <noreply@github.com>
Sat, 21 Mar 2020 07:32:41 +0000 (00:32 -0700)
* 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

22 files changed:
src/coreclr/build-runtime.cmd
src/coreclr/build.cmd
src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt
src/coreclr/src/libraries-native/CMakeLists.txt
src/coreclr/src/libraries-native/entrypoints.c
src/coreclr/src/vm/dllimport.cpp
src/coreclr/src/vm/ecalllist.h
src/libraries/Native/Unix/CMakeLists.txt
src/libraries/Native/Unix/Common/pal_atomic.h [new file with mode: 0644]
src/libraries/Native/Unix/Common/pal_compiler.h
src/libraries/Native/Unix/System.Globalization.Native/CMakeLists.txt
src/libraries/Native/Unix/System.Globalization.Native/configure.cmake
src/libraries/Native/Unix/System.Globalization.Native/pal_calendarData.c
src/libraries/Native/Unix/System.Globalization.Native/pal_casing.c
src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c
src/libraries/Native/Unix/System.Globalization.Native/pal_collation.h
src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c
src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h
src/libraries/Native/Unix/System.Globalization.Native/pal_idna.c
src/libraries/Native/Unix/System.Globalization.Native/pal_localeNumberData.c
src/libraries/Native/Unix/System.Globalization.Native/pal_localeStringData.c
src/libraries/Native/Unix/System.Globalization.Native/pal_timeZoneInfo.c

index 3ec6d5d..77e6409 100644 (file)
@@ -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!
index fac90f6..995f181 100644 (file)
@@ -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!
index 8b5365f..bc111a0 100644 (file)
@@ -110,6 +110,7 @@ set(CORECLR_LIBRARIES
     utilcode
     v3binder
     libraries-native
+    System.Globalization.Native-Static
     interop
 )
 
@@ -136,7 +137,6 @@ else()
         ${END_WHOLE_ARCHIVE}
         mscorrc
         palrt
-        System.Globalization.Native-Static
     )
 endif(CLR_CMAKE_TARGET_WIN32)
 
index aaf7f9b..58a6e89 100644 (file)
@@ -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
index 75c5b73..68553e9 100644 (file)
@@ -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;
 
@@ -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)
@@ -64,4 +60,3 @@ FCFuncStart(gPalGlobalizationNative)
     QCFuncElement("ToAscii", GlobalizationNative_ToAscii)
     QCFuncElement("ToUnicode", GlobalizationNative_ToUnicode)
 FCFuncEnd()
-#endif // TARGET_UNIX
index 795ca66..4875c57 100644 (file)
@@ -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;
     }
index 3cbfa0e..d28a283 100644 (file)
@@ -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)
index 5e9c0f0..d921d23 100644 (file)
@@ -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
@@ -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)
diff --git a/src/libraries/Native/Unix/Common/pal_atomic.h b/src/libraries/Native/Unix/Common/pal_atomic.h
new file mode 100644 (file)
index 0000000..a2ebcf6
--- /dev/null
@@ -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
+}
index 52471c6..8661443 100644 (file)
 #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
index 25d0211..fbab4fa 100644 (file)
@@ -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)
@@ -57,7 +61,6 @@ set(NATIVEGLOBALIZATION_SOURCES
     pal_icushim.c
 )
 
-include_directories(${UTYPES_H})
 include_directories("../Common")
 
 if (GEN_SHARED_LIB)
index 6114a1b..68718ed 100644 (file)
@@ -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
index 10bdcfa..b687ac9 100644 (file)
@@ -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"
@@ -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);
@@ -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);
@@ -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);
 
@@ -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;
@@ -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)
     {
index 2e90f14..263c71d 100644 (file)
@@ -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:
@@ -146,4 +148,6 @@ void GlobalizationNative_ChangeCaseTurkish(
     }
 }
 
+#ifdef __clang__
 #pragma clang diagnostic pop
+#endif
index c5ba1ca..081a016 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "pal_errors_internal.h"
 #include "pal_collation.h"
+#include "pal_atomic.h"
 
 c_static_assert_msg(UCOL_EQUAL == 0, "managed side requires 0 for equal strings");
 c_static_assert_msg(UCOL_LESS < 0, "managed side requires less than zero for a < b");
@@ -168,7 +169,7 @@ static UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, i
         ((needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule) ? 5 * g_HalfFullCharsLength : 0);
 
     UChar* items;
-    customRules->items = items = malloc((size_t)capacity * sizeof(UChar));
+    customRules->items = items = (UChar*)malloc((size_t)capacity * sizeof(UChar));
     if (customRules->items == NULL)
     {
         free(customRules);
@@ -267,7 +268,7 @@ static UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t o
         const UChar* localeRules = ucol_getRules(pCollator, &localeRulesLength);
         int32_t completeRulesLength = localeRulesLength + customRuleLength + 1;
 
-        UChar* completeRules = calloc((size_t)completeRulesLength, sizeof(UChar));
+        UChar* completeRules = (UChar*)calloc((size_t)completeRulesLength, sizeof(UChar));
 
         for (int i = 0; i < localeRulesLength; i++)
         {
@@ -403,8 +404,7 @@ static const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32
         pCollator = CloneCollatorWithOptions(pSortHandle->collatorsPerOption[0], options, pErr);
         UCollator* pNull = NULL;
 
-        // we are not using the standard atomic_compare_exchange_strong to workaround bugs in clang 5.0 (https://bugs.llvm.org/show_bug.cgi?id=37457)
-        if (!__atomic_compare_exchange_n(&pSortHandle->collatorsPerOption[options], &pNull, pCollator, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
+        if (!pal_atomic_cas_ptr((void* volatile*)&pSortHandle->collatorsPerOption[options], &pNull, pCollator))
         {
             ucol_close(pCollator);
             pCollator = pSortHandle->collatorsPerOption[options];
@@ -419,7 +419,7 @@ int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle)
 {
     UErrorCode err = U_ZERO_ERROR;
     const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, 0, &err);
-    int32_t result = 0;
+    int32_t result = -1;
 
     if (U_SUCCESS(err))
     {
@@ -428,9 +428,6 @@ int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle)
     else
     {
         assert(FALSE && "Unexpected ucol_getVersion to fail.");
-
-        // we didn't use UCOL_TAILORINGS_VERSION because it is deprecated in ICU v5
-        result = UCOL_RUNTIME_VERSION << 16 | UCOL_BUILDER_VERSION;
     }
     return result;
 }
@@ -569,11 +566,15 @@ int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase(
         {
             UChar32 srcCodepoint, trgCodepoint;
 
+#ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wsign-conversion"
+#endif
             U16_NEXT(src, srcIdx, cwSourceLength, srcCodepoint);
             U16_NEXT(trg, trgIdx, cwTargetLength, trgCodepoint);
+#ifdef __clang__
 #pragma clang diagnostic pop
+#endif
 
             if (!AreEqualOrdinalIgnoreCase(srcCodepoint, trgCodepoint))
             {
@@ -852,11 +853,15 @@ int32_t GlobalizationNative_CompareStringOrdinalIgnoreCase(
     {
         UChar32 str1Codepoint, str2Codepoint;
 
+#ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wsign-conversion"
+#endif
         U16_NEXT(lpStr1, str1Idx, cwStr1Length, str1Codepoint);
         U16_NEXT(lpStr2, str2Idx, cwStr2Length, str2Codepoint);
+#ifdef __clang__
 #pragma clang diagnostic pop
+#endif
 
         if (str1Codepoint != str2Codepoint && u_toupper(str1Codepoint) != u_toupper(str2Codepoint))
         {
index dd2fcc4..3d04ba7 100644 (file)
@@ -14,6 +14,7 @@ PALEXPORT ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName,
 
 PALEXPORT void GlobalizationNative_CloseSortHandle(SortHandle* pSortHandle);
 
+// If we fail to get the sort version we will fallback to -1 as the sort version.
 PALEXPORT int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle);
 
 PALEXPORT int32_t GlobalizationNative_CompareString(SortHandle* pSortHandle,
index bb418e8..51e60a0 100644 (file)
@@ -3,7 +3,13 @@
 // See the LICENSE file in the project root for more information.
 //
 
+#if defined(TARGET_UNIX)
 #include <dlfcn.h>
+#elif defined(TARGET_WINDOWS)
+#include <windows.h>
+#include <libloaderapi.h>
+#include <errhandlingapi.h>
+#endif
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -20,7 +26,22 @@ FOR_ALL_ICU_FUNCTIONS
 static void* libicuuc = NULL;
 static void* libicui18n = NULL;
 
-#ifdef __APPLE__
+#if defined(TARGET_WINDOWS)
+
+static int FindICULibs()
+{
+    libicuuc = LoadLibraryExW(L"icu.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+    if (libicuuc == NULL)
+    {
+        return FALSE;
+    }
+
+    // Windows has a single dll for icu.
+    libicui18n = libicuuc;
+    return TRUE;
+}
+
+#elif defined(TARGET_DARWIN)
 
 static int FindICULibs()
 {
@@ -42,7 +63,7 @@ static int FindICULibs()
     return TRUE;
 }
 
-#else // __APPLE__
+#else // !TARGET_WINDOWS && !TARGET_DARWIN
 
 #define VERSION_PREFIX_NONE ""
 #define VERSION_PREFIX_SUSE "suse"
@@ -242,7 +263,7 @@ static int FindICULibs(const char* versionPrefix, char* symbolName, char* symbol
            FindLibWithMajorMinorSubVersion(versionPrefix, symbolName, symbolVersion);
 }
 
-#endif // __APPLE__
+#endif
 
 // GlobalizationNative_LoadICU
 // This method get called from the managed side during the globalization initialization.
@@ -250,7 +271,18 @@ static int FindICULibs(const char* versionPrefix, char* symbolName, char* symbol
 // return 0 if failed to load ICU and 1 otherwise
 int32_t GlobalizationNative_LoadICU()
 {
-#ifdef __APPLE__
+#if defined(TARGET_WINDOWS)
+
+    if (!FindICULibs())
+    {
+        return FALSE;
+    }
+
+#define PER_FUNCTION_BLOCK(fn, lib) \
+    fn##_ptr = (__typeof(fn)*)GetProcAddress((HMODULE)lib, #fn); \
+    if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %u\n", #fn, GetLastError()); abort(); }
+
+#elif defined(TARGET_DARWIN)
 
     if (!FindICULibs())
     {
@@ -262,7 +294,7 @@ int32_t GlobalizationNative_LoadICU()
     fn##_ptr = (__typeof(fn)*)dlsym(lib, #fn); \
     if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %s\n", #fn, dlerror()); abort(); }
 
-#else // __APPLE__
+#else // !TARGET_WINDOWS && !TARGET_DARWIN
 
     char symbolName[128];
     char symbolVersion[MaxICUVersionStringLength + 1] = "";
@@ -282,7 +314,7 @@ int32_t GlobalizationNative_LoadICU()
     fn##_ptr = (__typeof(fn)*)dlsym(lib, symbolName); \
     if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %s\n", symbolName, dlerror()); abort(); }
 
-#endif // __APPLE__
+#endif
 
     FOR_ALL_ICU_FUNCTIONS
 #undef PER_FUNCTION_BLOCK
index c6a48f9..2ee8fab 100644 (file)
@@ -8,6 +8,8 @@
 
 #pragma once
 
+#if defined(TARGET_UNIX)
+
 #include "config.h"
 
 #define U_DISABLE_RENAMING 1
 #include <unicode/urename.h>
 #include <unicode/ustring.h>
 
+#elif defined(TARGET_WINDOWS)
+
+#include "icu.h"
+
+#ifndef __typeof
+#define __typeof decltype
+#endif
+
+#define HAVE_SET_MAX_VARIABLE 1
+#define UDAT_STANDALONE_SHORTER_WEEKDAYS 1
+
+#endif
+
+#include "pal_compiler.h"
+
 // List of all functions from the ICU libraries that are used in the System.Globalization.Native.so
 #define FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \
     PER_FUNCTION_BLOCK(u_charsToUChars, libicuuc) \
     FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \
     PER_FUNCTION_BLOCK(ucol_setMaxVariable, libicui18n)
 #else
+
 #define FOR_ALL_ICU_FUNCTIONS \
     FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \
     PER_FUNCTION_BLOCK(ucol_setVariableTop, libicui18n)
 #endif
 
 // Declare pointers to all the used ICU functions
-#define PER_FUNCTION_BLOCK(fn, lib) extern __typeof(fn)* fn##_ptr;
+#define PER_FUNCTION_BLOCK(fn, lib) EXTERN_C __typeof(fn)* fn##_ptr;
 FOR_ALL_ICU_FUNCTIONS
 #undef PER_FUNCTION_BLOCK
 
index 97fe231..403145a 100644 (file)
@@ -8,6 +8,13 @@
 #include "pal_icushim_internal.h"
 #include "pal_idna.h"
 
+#if defined(TARGET_WINDOWS)
+// Windows icu headers doesn't define this member as it is marked as deprecated as of ICU 55.
+enum {
+    UIDNA_ALLOW_UNASSIGNED=1
+};
+#endif
+
 static const uint32_t AllowUnassigned = 0x1;
 static const uint32_t UseStd3AsciiRules = 0x2;
 
index b05ae70..2465f02 100644 (file)
@@ -87,13 +87,13 @@ static char* NormalizeNumericPattern(const UChar* srcPattern, int isNegative)
     if (isNegative && !minusAdded)
     {
         int length = (iEnd - iStart) + 2;
-        destPattern = calloc((size_t)length, sizeof(char));
+        destPattern = (char*)calloc((size_t)length, sizeof(char));
         destPattern[index++] = '-';
     }
     else
     {
         int length = (iEnd - iStart) + 1;
-        destPattern = calloc((size_t)length, sizeof(char));
+        destPattern = (char*)calloc((size_t)length, sizeof(char));
     }
 
     for (int i = iStart; i <= iEnd; i++)
@@ -162,7 +162,7 @@ static int GetNumericPattern(const UNumberFormat* pNumberFormat,
     UErrorCode ignore = U_ZERO_ERROR;
     int32_t icuPatternLength = unum_toPattern(pNumberFormat, FALSE, NULL, 0, &ignore) + 1;
 
-    UChar* icuPattern = calloc((size_t)icuPatternLength, sizeof(UChar));
+    UChar* icuPattern = (UChar*)calloc((size_t)icuPatternLength, sizeof(UChar));
     if (icuPattern == NULL)
     {
         return U_MEMORY_ALLOCATION_ERROR;
index f0894b7..0c2c94a 100644 (file)
@@ -78,7 +78,7 @@ static UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar
     UErrorCode status = U_ZERO_ERROR, ignore = U_ZERO_ERROR;
     int32_t length = uloc_getLanguage(locale, NULL, 0, &ignore) + 1;
 
-    char* buf = calloc((size_t)length, sizeof(char));
+    char* buf = (char*)calloc((size_t)length, sizeof(char));
     if (buf == NULL)
     {
         return U_MEMORY_ALLOCATION_ERROR;
@@ -121,7 +121,7 @@ static UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value,
     UErrorCode status = U_ZERO_ERROR, ignore = U_ZERO_ERROR;
     int32_t length = uloc_getCountry(locale, NULL, 0, &ignore) + 1;
 
-    char* buf = calloc((size_t)length, sizeof(char));
+    char* buf = (char*)calloc((size_t)length, sizeof(char));
     if (buf == NULL)
     {
         return U_MEMORY_ALLOCATION_ERROR;
index 537464d..c6eb7f3 100644 (file)
@@ -4,7 +4,6 @@
 //
 
 #include <stdint.h>
-#include <unistd.h>
 
 #include "pal_errors_internal.h"
 #include "pal_locale_internal.h"
@@ -26,7 +25,7 @@ ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName,
     int32_t timeZoneIdLength = -1; // timeZoneId is NULL-terminated
     UCalendar* calendar = ucal_open(timeZoneId, timeZoneIdLength, locale, UCAL_DEFAULT, &err);
 
-    // TODO (https://github.com/dotnet/corefx/issues/5741): need to support Generic names, but ICU "C" api
+    // TODO (https://github.com/dotnet/runtime/issues/16232): need to support Generic names, but ICU "C" api
     // has no public option for this. For now, just use the ICU standard name for both Standard and Generic
     // (which is the same behavior on Windows with the mincore TIME_ZONE_INFORMATION APIs).
     ucal_getTimeZoneDisplayName(