-
-
Notifications
You must be signed in to change notification settings - Fork 760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ICU-22787 Fix ClangCL compilation on Windows #3023
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,9 @@ | |
# define NOMCX | ||
#include <windows.h> | ||
#include <time.h> | ||
# if defined(__clang__) | ||
# include <exception> | ||
# endif | ||
# ifdef __GNUC__ | ||
# define WINDOWS_WITH_GNUC | ||
# endif | ||
|
@@ -294,6 +297,11 @@ checkAssemblyHeaderName(const char* optAssembly) { | |
return false; | ||
} | ||
|
||
U_CAPI UBool U_EXPORT2 | ||
checkCpuArchitecture(const char* optCpuArch) { | ||
return strcmp(optCpuArch, "x64") == 0 || strcmp(optCpuArch, "x86") == 0 || strcmp(optCpuArch, "arm64") == 0; | ||
} | ||
|
||
|
||
U_CAPI void U_EXPORT2 | ||
printAssemblyHeadersToStdErr() { | ||
|
@@ -799,7 +807,12 @@ getOutFilename( | |
|
||
#ifdef CAN_GENERATE_OBJECTS | ||
static void | ||
getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *optMatchArch) { | ||
getArchitecture( | ||
uint16_t *pCPU, | ||
uint16_t *pBits, | ||
UBool *pIsBigEndian, | ||
const char *optMatchArch, | ||
[[maybe_unused]] const char *optCpuArch) { | ||
union { | ||
char bytes[2048]; | ||
#ifdef U_ELF | ||
|
@@ -847,7 +860,25 @@ getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char | |
# if defined(_M_IX86) | ||
*pCPU = IMAGE_FILE_MACHINE_I386; | ||
# else | ||
*pCPU = IMAGE_FILE_MACHINE_UNKNOWN; | ||
// Linker for ClangCL doesn't handle IMAGE_FILE_MACHINE_UNKNOWN the same as | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I read the existing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In
It would, but I do not know how to write linker-specific code (I'm not saying it is impossible). What can be done from my perspective is to detect the compiler (MSVC or Clang) and then infer a linker (link.exe or lld-link.exe), which is more or less what we have now after these changes. |
||
// linker for MSVC. Because of this optCpuArch is used to define the CPU | ||
// architecture in that case. While _M_AMD64 and _M_ARM64 could be used, | ||
// this would potentially be problematic when cross-compiling as this code | ||
// would most likely be ran on host machine to generate the .obj file for | ||
// the target architecture. | ||
# if defined(__clang__) | ||
if (strcmp(optCpuArch, "x64") == 0) { | ||
*pCPU = IMAGE_FILE_MACHINE_AMD64; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are 32-bit builds not supported? It's been a long time since I last had any reason to do one, but I wasn't aware that they're no longer supported. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. I've added a Above this code there is:
but that would only apply if |
||
} else if (strcmp(optCpuArch, "x86") == 0) { | ||
*pCPU = IMAGE_FILE_MACHINE_I386; | ||
} else if (strcmp(optCpuArch, "arm64") == 0) { | ||
*pCPU = IMAGE_FILE_MACHINE_ARM64; | ||
} else { | ||
std::terminate(); // Unreachable. | ||
} | ||
# else | ||
*pCPU = IMAGE_FILE_MACHINE_UNKNOWN; | ||
# endif | ||
# endif | ||
# if defined(_M_IA64) || defined(_M_AMD64) || defined (_M_ARM64) | ||
*pBits = 64; // Doesn't seem to be used for anything interesting though? | ||
|
@@ -934,6 +965,7 @@ writeObjectCode( | |
const char *destdir, | ||
const char *optEntryPoint, | ||
const char *optMatchArch, | ||
const char *optCpuArch, | ||
const char *optFilename, | ||
char *outFilePath, | ||
size_t outFilePathCapacity, | ||
|
@@ -1201,7 +1233,7 @@ writeObjectCode( | |
#endif | ||
|
||
/* deal with options, files and the entry point name */ | ||
getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch); | ||
getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch, optCpuArch); | ||
if (optMatchArch) | ||
{ | ||
printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%d\n", cpu, bits, makeBigEndian); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be easier to use this tool correctly if this commandline flag was
#ifdef
'ed out altogether on platforms where it isn't implemented?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I've only
#ifdef
ed out the parts ingenccode.c
, as I didn't want to makewriteObjectCode
signature different depending on which compiler is used on Windows. I just pass itNULL
if Clang isn't used. If you think I should make the signature#ifdef
ed too, let me know.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to leave it a generic argument, even if it is only currently valid for ClangCL. It may be needed in other situations.