Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Arvind Oruganti <aoruganti@microsoft.com>
Date: Thu, 14 May 2026 14:30:00 +0530
Subject: MSFT-PATCH: Remove icu4j directory validation from Cldr2Icu (icu4c-only fork)

diff --git a/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java b/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java
index d9b46014438..9ff85b38d86 100644
--- a/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java
+++ b/icu/tools/cldr/cldr-to-icu/src/main/java/org/unicode/icu/tool/cldrtoicu/Cldr2IcuCliOptions.java
@@ -380,7 +380,9 @@ private void validateEnvironment() {

if (!new File(icuDir).isDirectory()
|| ! new File(icuDir, "icu4c").isDirectory()
- || ! new File(icuDir, "icu4j").isDirectory()
+ // MSFT-Change: microsoft/icu fork is icu4c-only; no icu4j source tree.
+ // The Maven dependency on icu4j (used by TransformsMapper) is still
+ // resolved from ~/.m2 at runtime, so source-tree absence is harmless.
|| ! new File(icuDir, "tools/cldr/cldr-to-icu").isDirectory()
|| ! new File(icuDir, "tools/cldr/cldr-to-icu/pom.xml").isFile()) {
System.err.println("The `" + icuDir + "` directory does not look like a valid icu root.");
23 changes: 18 additions & 5 deletions icu/icu4c/source/common/common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
<PrecompiledHeaderOutputFile>$(OutDir)/icuuc.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(OutDir)/</AssemblerListingLocation>
<ObjectFileName>$(OutDir)/</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)/icuuc.pdb</ProgramDataBaseFileName>
<!-- MSFT-Change: Include the ICU major version number in the PDB filename. -->
<ProgramDataBaseFileName>$(OutDir)/icuuc$(IcuMajorVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<!-- The icudt.lib is for U_ICUDATA_ENTRY_POINT -->
Expand All @@ -53,24 +54,34 @@
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>RBBI_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<!-- MSFT-Change: Static link the VCRUNTIME, VCSTARTUP and STL, but dynamic link to the UCRT. -->
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<OutputFile>..\..\$(IcuBinOutputDir)\icuuc$(IcuMajorVersion)d.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuucd.pdb</ProgramDatabaseFile>
<!-- MSFT-Change: Include the ICU major version number in the PDB filename. -->
<ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuuc$(IcuMajorVersion)d.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\$(IcuLibOutputDir)\icuucd.lib</ImportLibrary>
<!-- MSFT-Change: This forces dynamic linking of the UCRT. -->
<IgnoreSpecificDefaultLibraries>libucrtd.lib;libucrt.lib</IgnoreSpecificDefaultLibraries>
<AdditionalOptions>/DEFAULTLIB:ucrtd.lib %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<!-- Options that are common to all 'Release' project configurations -->
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<!-- MSFT-Change: Static link the VCRUNTIME, VCSTARTUP and STL, but dynamic link to the UCRT. -->
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
</ClCompile>
<Link>
<OutputFile>..\..\$(IcuBinOutputDir)\icuuc$(IcuMajorVersion).dll</OutputFile>
<ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuuc.pdb</ProgramDatabaseFile>
<!-- MSFT-Change: Include the ICU major version number in the PDB filename. -->
<ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuuc$(IcuMajorVersion).pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\$(IcuLibOutputDir)\icuuc.lib</ImportLibrary>
<!-- MSFT-Change: This forces dynamic linking of the UCRT. -->
<IgnoreSpecificDefaultLibraries>libucrtd.lib;libucrt.lib</IgnoreSpecificDefaultLibraries>
<AdditionalOptions>/DEFAULTLIB:ucrt.lib %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
Expand Down Expand Up @@ -275,6 +286,7 @@
<ClCompile Include="static_unicode_sets.cpp" />
<ClCompile Include="restrace.cpp" />
<ClCompile Include="fixedstring.cpp" />
<ClCompile Include="uprefs.cpp" />
<ClInclude Include="localsvc.h" />
<ClInclude Include="msvcres.h" />
<ClInclude Include="pluralmap.h" />
Expand Down Expand Up @@ -394,6 +406,7 @@
<ClInclude Include="capi_helper.h" />
<ClInclude Include="restrace.h" />
<ClInclude Include="fixedstring.h" />
<ClInclude Include="uprefs.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc" />
Expand Down
2 changes: 2 additions & 0 deletions icu/icu4c/source/common/common_uwp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@
<ClCompile Include="static_unicode_sets.cpp" />
<ClCompile Include="restrace.cpp" />
<ClCompile Include="fixedstring.cpp" />
<ClCompile Include="uprefs.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="localsvc.h" />
Expand Down Expand Up @@ -529,6 +530,7 @@
<ClInclude Include="capi_helper.h" />
<ClInclude Include="restrace.h" />
<ClInclude Include="fixedstring.h" />
<ClInclude Include="uprefs.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc" />
Expand Down
35 changes: 32 additions & 3 deletions icu/icu4c/source/common/putil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include "locmap.h"
#include "ucln_cmn.h"
#include "charstr.h"
#include "uprefs.h"

/* Include standard headers. */
#include <stdio.h>
Expand Down Expand Up @@ -1794,10 +1795,37 @@ The leftmost codepage (.xxx) wins.
return posixID;

#elif U_PLATFORM_USES_ONLY_WIN32_API
#define POSIX_LOCALE_CAPACITY 64
UErrorCode status = U_ZERO_ERROR;
char *correctedPOSIXLocale = nullptr;

#if UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY

int32_t neededBufferSize = uprefs_getBCP47Tag(nullptr, 0, &status);
MaybeStackArray<char,ULOC_FULLNAME_CAPACITY> windowsLocale(neededBufferSize, status);
int32_t length = uprefs_getBCP47Tag(windowsLocale.getAlias(), neededBufferSize, &status);

if (length > 0) // If length is 0, then the call to uprefs_getBCP47Tag failed.
{
// Now normalize the resulting name
correctedPOSIXLocale = static_cast<char *>(uprv_malloc(length * 2));
/* TODO: Should we just exit on memory allocation failure? */
if (correctedPOSIXLocale)
{
int32_t posixLen = uloc_canonicalize(windowsLocale.getAlias(), correctedPOSIXLocale, length * 2, &status);
if (U_SUCCESS(status))
{
*(correctedPOSIXLocale + posixLen) = 0;
gCorrectedPOSIXLocale = correctedPOSIXLocale;
gCorrectedPOSIXLocaleHeapAllocated = true;
ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
}
else
{
uprv_free(correctedPOSIXLocale);
}
}
}
#else
// If we have already figured this out just use the cached value
if (gCorrectedPOSIXLocale != nullptr) {
return gCorrectedPOSIXLocale;
Expand Down Expand Up @@ -1839,11 +1867,11 @@ The leftmost codepage (.xxx) wins.
}

// Now normalize the resulting name
correctedPOSIXLocale = static_cast<char *>(uprv_malloc(POSIX_LOCALE_CAPACITY + 1));
correctedPOSIXLocale = static_cast<char *>(uprv_malloc(length * 2));
/* TODO: Should we just exit on memory allocation failure? */
if (correctedPOSIXLocale)
{
int32_t posixLen = uloc_canonicalize(modifiedWindowsLocale, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status);
int32_t posixLen = uloc_canonicalize(modifiedWindowsLocale, correctedPOSIXLocale, length * 2, &status);
if (U_SUCCESS(status))
{
*(correctedPOSIXLocale + posixLen) = 0;
Expand All @@ -1857,6 +1885,7 @@ The leftmost codepage (.xxx) wins.
}
}
}
#endif

// If unable to find a locale we can agree upon, use en-US by default
if (gCorrectedPOSIXLocale == nullptr) {
Expand Down
1 change: 1 addition & 0 deletions icu/icu4c/source/common/sources.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ unistr_titlecase_brkiter.cpp
unorm.cpp
unormcmp.cpp
uobject.cpp
uprefs.cpp
uprops.cpp
ures_cnv.cpp
uresbund.cpp
Expand Down
28 changes: 27 additions & 1 deletion icu/icu4c/source/common/ucln_cmn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
The cleanup order is important in this function.
Please be sure that you have read ucln.h
************************************************/
// MSFT-Change: Make u_cleanup a no-op for the Windows OS ICU version.
U_CAPI void U_EXPORT2
u_cleanup()
uprv_u_cleanup()
{
UTRACE_ENTRY_OC(UTRACE_U_CLEANUP);
icu::umtx_lock(nullptr); /* Force a memory barrier, so that we are sure to see */
Expand All @@ -52,6 +53,31 @@ u_cleanup()
/*#endif*/
}

U_CAPI void U_EXPORT2
u_cleanup()
{
// When ICU is built as an OS component for Windows, we make the public function u_cleanup
// effectively a no-op because of the following:
// - It is not thread-safe and *forcefully* unloads the ICU data file.
// - The ICU library can simultaneously be used by other threads when this happens,
// either by Windows.Globalization, or by sorting functions when ICU sorting is default.
// - This means an App can call the function at any time, which will cause random crashes. :(
//
// We don't completely remove the functionality though, as we still want/need to be able to
// unload resources when the ICU DLL is unloaded. Instead we make it a private (uprv) function
// so that the combined DLL can still call it, and we don't export it in the DEF file.
//
// Note: We don't unconditionally do this though, as we don't want to alter the behavior of the
// public function when ICU when used/consumed in a Nuget package (for example).
//
#if defined(ICU_DATA_DIR_WINDOWS)
((void)0); // no-op.
return;
#else
uprv_u_cleanup();
#endif
}

U_CAPI void U_EXPORT2 ucln_cleanupOne(ECleanupLibraryType libType)
{
if (gLibCleanupFunctions[libType])
Expand Down
8 changes: 6 additions & 2 deletions icu/icu4c/source/common/ucmndata.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@
#include "unicode/udata.h"
#include "umapfile.h"


#define COMMON_DATA_NAME U_ICUDATA_NAME
// MSFT-Change: In the Windows OS ICU build, we only have one data package, and we use a versionless name in filename.
#if defined(ICU_DATA_DIR_WINDOWS)
# define COMMON_DATA_NAME "icudtl"
#else
# define COMMON_DATA_NAME U_ICUDATA_NAME
#endif

typedef struct {
uint16_t headerSize;
Expand Down
10 changes: 10 additions & 0 deletions icu/icu4c/source/common/udata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,16 @@ openCommonData(const char *path, /* Path from OpenChoice? */
*----------------------------------------------------------------------*/
static UBool extendICUData(UErrorCode *pErr)
{
// MSFT-Change: For the Windows OS build of ICU, we only have one data file
// and we don't use the extended data at all. We make this function a no-op
// in order to save a few cycles for perf, but more importantly so that
// we don't try to load a versioned data file (ex: icudt78l.dat) after
// already loading the non-versioned common data file.
#if defined(ICU_DATA_DIR_WINDOWS)
(void)pErr; // suppress unused variable.
return false;
#endif

UDataMemory *pData;
UDataMemory copyPData;
UBool didUpdate = false;
Expand Down
6 changes: 5 additions & 1 deletion icu/icu4c/source/common/unicode/putil.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
* functions may have to be re-implemented.
*/

//IGNORE_WINDOWS_HEADERS_START
// MSFT-Change: The Windows OS version of ICU uses a single fixed data file.

/**
* Return the ICU data directory.
* The data directory is where common format ICU data files (.dat files)
Expand Down Expand Up @@ -112,7 +115,7 @@ U_CAPI const char * U_EXPORT2 u_getTimeZoneFilesDirectory(UErrorCode *status);
U_CAPI void U_EXPORT2 u_setTimeZoneFilesDirectory(const char *path, UErrorCode *status);
#endif /* U_HIDE_INTERNAL_API */


// MSFT-TODO: Should these be considered for Windows?
/**
* @{
* Filesystem file and path separator characters.
Expand All @@ -134,6 +137,7 @@ U_CAPI void U_EXPORT2 u_setTimeZoneFilesDirectory(const char *path, UErrorCode *
# define U_FILE_ALT_SEP_STRING "/"
# define U_PATH_SEP_STRING ":"
#endif
//IGNORE_WINDOWS_HEADERS_END

/** @} */

Expand Down
6 changes: 6 additions & 0 deletions icu/icu4c/source/common/unicode/uchar.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ typedef struct USet USet;

U_CDECL_BEGIN

//IGNORE_WINDOWS_HEADERS_START
// MSFT-Change: The value of these macros can change at runtime, so the API u_getUnicodeVersion
// should be used instead of any version macro.

/*==========================================================================*/
/* Unicode version number */
/*==========================================================================*/
Expand All @@ -63,6 +67,8 @@ U_CDECL_BEGIN
*/
#define U_UNICODE_VERSION "17.0"

//IGNORE_WINDOWS_HEADERS_END

/**
* \file
* \brief C API: Unicode Properties
Expand Down
27 changes: 27 additions & 0 deletions icu/icu4c/source/common/unicode/uconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
* @stable ICU 2.4
*/

//IGNORE_WINDOWS_HEADERS_START
// MSFT-Change: Since these are compile time settings, it doesn't make sense to
// load a user config header in the Windows OS SDK version.

/**
* If this switch is defined, ICU will attempt to load a header file named "uconfig_local.h"
* prior to determining default settings for uconfig variables.
Expand All @@ -55,6 +59,8 @@
#include "uconfig_local.h"
#endif

//IGNORE_WINDOWS_HEADERS_END

/**
* \def U_DEBUG
* Determines whether to include debugging code.
Expand Down Expand Up @@ -379,6 +385,9 @@
# define UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE UMSGPAT_APOS_DOUBLE_OPTIONAL
#endif

//IGNORE_WINDOWS_HEADERS_START
// MSFT-Change: We always use the OS LCID mapping API for the Windows OS build of ICU.

/**
* \def UCONFIG_USE_WINDOWS_LCID_MAPPING_API
* On platforms where U_PLATFORM_HAS_WIN32_API is true, this switch determines
Expand All @@ -391,6 +400,24 @@
# define UCONFIG_USE_WINDOWS_LCID_MAPPING_API 1
#endif

/**
* \def UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY
* On Windows platforms (ie: U_PLATFORM_HAS_WIN32_API is true), this switch enables ICU to
* detect additional user preferences by setting BCP47 Unicode extension within the default locale.
* This includes information such as calendar, currency, hour cycle, among others.
*
* If this switch is off (or set to 0) then the default behavior of only detecting the language
* and country/region occurs.
*
* For example, the default locale may be detected as "es-MX-u-hc-h24", instead of "es-MX",
* if the user has selected a 24 hour clock option.
*/
#ifndef UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY
# define UCONFIG_USE_WINDOWS_PREFERENCES_LIBRARY 1
#endif

//IGNORE_WINDOWS_HEADERS_END

/* i18n library switches ---------------------------------------------------- */

/**
Expand Down
5 changes: 5 additions & 0 deletions icu/icu4c/source/common/unicode/unistr.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class Edits;

U_NAMESPACE_END

//IGNORE_WINDOWS_HEADERS_START
// MSFT-Change: Hiding the @internal API below, since we don't expose the C++ UnicodeString.

// Not #ifndef U_HIDE_INTERNAL_API because UnicodeString needs the UStringCaseMapper.
/**
* Internal string case mapping function type.
Expand All @@ -77,6 +80,8 @@ UStringCaseMapper(int32_t caseLocale, uint32_t options,
icu::Edits *edits,
UErrorCode &errorCode);

//IGNORE_WINDOWS_HEADERS_END

U_NAMESPACE_BEGIN

class Locale; // unicode/locid.h
Expand Down
7 changes: 7 additions & 0 deletions icu/icu4c/source/common/unicode/utypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@

/** @} */

//IGNORE_WINDOWS_HEADERS_START
// MSFT-Change: For the Windows OS version of ICU, it doesn't make sense to expose these
// constants which are only for loading the main ICU data file. We also don't
// support using a data DLL either, so omit them from the Windows SDK header.

/*===========================================================================*/
/* ICUDATA naming scheme */
/*===========================================================================*/
Expand Down Expand Up @@ -191,6 +196,8 @@
#endif
#endif /* U_HIDE_INTERNAL_API */

//IGNORE_WINDOWS_HEADERS_END

/**
* \def NULL
* Define NULL if necessary, to nullptr for C++ and to ((void *)0) for C.
Expand Down
Loading
Loading