From e0c80c5f5c7d395d79aa350a26f46101a78af95d Mon Sep 17 00:00:00 2001 From: "John Chen (JOCHEN7)" Date: Tue, 28 Apr 2015 13:20:01 -0700 Subject: Build crossgen for Linux - Crossgen is now built as part of coreclr - Crossgen successfully compiles mscorlib.dll - Resulting mscorlib.ni.dll not yet usable --- src/tools/CMakeLists.txt | 7 +++- src/tools/crossgen/CMakeLists.txt | 61 ++++++++++++++-------------- src/tools/crossgen/crossgen.cpp | 51 +++++++++++++++++++----- src/tools/util/consoleargs.cpp | 84 ++++++++++++++++++++++++--------------- src/tools/util/consoleargs.h | 8 ++-- 5 files changed, 132 insertions(+), 79 deletions(-) (limited to 'src/tools') diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index d23b7e0b82..87c3eae90f 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,3 +1,6 @@ add_subdirectory(crossgen) -add_subdirectory(GenClrDebugResource) -add_subdirectory(InjectResource) \ No newline at end of file + +if(WIN32) + add_subdirectory(GenClrDebugResource) + add_subdirectory(InjectResource) +endif(WIN32) diff --git a/src/tools/crossgen/CMakeLists.txt b/src/tools/crossgen/CMakeLists.txt index e7e2b65086..e35db0f4a7 100644 --- a/src/tools/crossgen/CMakeLists.txt +++ b/src/tools/crossgen/CMakeLists.txt @@ -7,26 +7,40 @@ include_directories(../util) include_directories(../../pal/prebuilt/corerror) set(crossgen_SOURCES crossgen.cpp ../util/consoleargs.cpp) -set(crossgen_RESOURCES Native.rc) +if(WIN32) + set(crossgen_RESOURCES Native.rc) +endif() add_definitions(-DFX_VER_INTERNALNAME_STR=crossgen.exe) add_definitions(-DNO_NGENPDB) -if(CLR_CMAKE_PLATFORM_UNIX) - # This does not compile on Linux yet - if(CAN_BE_COMPILED_ON_LINUX) - add_executable(crossgen - ${crossgen_SOURCES} - ${crossgen_RESOURCES} - ) - endif(CAN_BE_COMPILED_ON_LINUX) +add_executable(crossgen + ${crossgen_SOURCES} + ${crossgen_RESOURCES} +) -else() - add_executable(crossgen - ${crossgen_SOURCES} - ${crossgen_RESOURCES} - ) +target_link_libraries(crossgen + cee_crossgen + mdcompiler_crossgen + mdruntime_crossgen + mdruntimerw_crossgen + mdhotdata_crossgen + corguids + jit_crossgen + gcinfo_crossgen + corzap_crossgen + mscorlib_crossgen + strongname_crossgen + utilcode_crossgen + v3binder_crossgen +) +if(CLR_CMAKE_PLATFORM_UNIX) + target_link_libraries(crossgen + coreclrpal + palrt + ) +else() target_link_libraries(crossgen advapi32 ole32 @@ -36,32 +50,17 @@ else() version shlwapi bcrypt - corguids - utilcode_crossgen - corzap_crossgen - jit_crossgen - gcinfo_crossgen - strongname_crossgen - mdcompiler_crossgen mdwinmd_crossgen - mdruntimerw_crossgen - mdhotdata_crossgen - mdruntime_crossgen - cee_crossgen - mscorlib_crossgen - v3binder_crossgen ${STATIC_MT_CRT_LIB} ) - # Can't compile on linux yet so only add for windows - # add the install targets - install (TARGETS crossgen DESTINATION .) - # We will generate PDB only for the debug configuration install (FILES ${CMAKE_CURRENT_BINARY_DIR}/$/crossgen.pdb DESTINATION PDB) endif(CLR_CMAKE_PLATFORM_UNIX) +install (TARGETS crossgen DESTINATION .) + add_subdirectory(../../zap/crossgen ../../zap/crossgen) add_subdirectory(../../vm/crossgen ../../vm/crossgen) add_subdirectory(../../vm/crossgen_mscorlib ../../vm/crossgen_mscorlib) diff --git a/src/tools/crossgen/crossgen.cpp b/src/tools/crossgen/crossgen.cpp index db663f0c81..5005ea4cab 100644 --- a/src/tools/crossgen/crossgen.cpp +++ b/src/tools/crossgen/crossgen.cpp @@ -23,9 +23,6 @@ #include "coregen.h" #include "consoleargs.h" -#define SEPARATOR_CHAR_W W('\\') -#define SEPARATOR_STRING_W W("\\") - // Return values from wmain() in case of error enum ReturnValues { @@ -41,7 +38,7 @@ STDAPI CreatePDBWorker(LPCWSTR pwzAssemblyPath, LPCWSTR pwzPlatformAssembliesPat STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, LPCWSTR pwzPlatformWinmdPaths=NULL, ICorSvcLogger *pLogger = NULL); void SetSvcLogger(ICorSvcLogger *pCorSvcLogger); #ifdef FEATURE_CORECLR -void SetMscorlibPath(LPCWCHAR wzSystemDirectory); +void SetMscorlibPath(LPCWSTR wzSystemDirectory); #endif /* --------------------------------------------------------------------------- * @@ -57,7 +54,7 @@ void Outputf(LPCWSTR szFormat, ...) { va_list args; va_start(args, szFormat); - vwprintf(szFormat, args); + vfwprintf(stdout, szFormat, args); va_end(args); } @@ -259,7 +256,7 @@ bool MatchParameter(LPCWSTR szArg, LPCWSTR szTestParamName) // Returns true if pwzString ends with the string in pwzCandidate // Ignores case // -bool StringEndsWith(LPWSTR pwzString, LPWSTR pwzCandidate) +bool StringEndsWith(LPCWSTR pwzString, LPCWSTR pwzCandidate) { size_t stringLength = wcslen(pwzString); size_t candidateLength = wcslen(pwzCandidate); @@ -269,7 +266,7 @@ bool StringEndsWith(LPWSTR pwzString, LPWSTR pwzCandidate) return false; } - LPWSTR pwzStringEnd = pwzString + stringLength - candidateLength; + LPCWSTR pwzStringEnd = pwzString + stringLength - candidateLength; return !_wcsicmp(pwzStringEnd, pwzCandidate); } @@ -322,7 +319,7 @@ bool ComputeMscorlibPathFromTrustedPlatformAssemblies(LPWSTR pwzMscorlibPath, DW // Given a path terminated with "\\" and a search mask, this function will add // the enumerated files, corresponding to the search mask, from the path into // the refTPAList. -void PopulateTPAList(SString path, LPWSTR pwszMask, SString &refTPAList, bool fCompilingMscorlib, bool fCreatePDB) +void PopulateTPAList(SString path, LPCWSTR pwszMask, SString &refTPAList, bool fCompilingMscorlib, bool fCreatePDB) { _ASSERTE(path.GetCount() > 0); ClrDirectoryEnumerator folderEnumerator(path.GetUnicode(), pwszMask); @@ -444,7 +441,9 @@ extern HMODULE g_hThisInst; int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) { +#ifndef FEATURE_PAL g_hThisInst = WszGetModuleHandle(NULL); +#endif ///////////////////////////////////////////////////////////////////////// // @@ -468,8 +467,10 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) HRESULT hr; +#ifndef PLATFORM_UNIX // This is required to properly display Unicode characters _setmode(_fileno(stdout), _O_U8TEXT); +#endif // Skip this executable path argv++; @@ -690,7 +691,7 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) argc--; // Ensure output dir ends in a backslash, or else diasymreader has issues - if (wzDirectoryToStorePDB[wcslen(wzDirectoryToStorePDB)-1] != SEPARATOR_CHAR_W) + if (wzDirectoryToStorePDB[wcslen(wzDirectoryToStorePDB)-1] != DIRECTORY_SEPARATOR_CHAR_W) { if (wcscat_s( wzDirectoryToStorePDB, @@ -811,7 +812,7 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) Output(W("You must specify an output filename (/out )\n")); exit(INVALID_ARGUMENTS); } - if (CopyFileExW(pwzFilename, pwzOutputFilename, NULL, NULL, NULL, 0) == 0) + if (CopyFileW(pwzFilename, pwzOutputFilename, FALSE) == 0) { DWORD dwLastError = GetLastError(); OutputErrf(W("Error: x86 copy failed for \"%s\" (0x%08x)\n"), pwzFilename, HRESULT_FROM_WIN32(dwLastError)); @@ -928,7 +929,7 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) exit(CLR_INIT_ERROR); } - wchar_t* pszSep = wcsrchr(wzTrustedPathRoot, SEPARATOR_CHAR_W); + wchar_t* pszSep = wcsrchr(wzTrustedPathRoot, DIRECTORY_SEPARATOR_CHAR_W); if (pszSep == NULL) { ERROR_HR(W("Error: wcsrchr returned NULL; GetModuleFileName must have given us something bad\n"), E_UNEXPECTED); @@ -988,3 +989,31 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) return 0; } + +#ifdef PLATFORM_UNIX +int main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAILURE_RESULT; + } + + wchar_t **wargv = new wchar_t*[argc]; + for (int i = 0; i < argc; i++) + { + size_t len = strlen(argv[i]) + 1; + wargv[i] = new wchar_t[len]; + WszMultiByteToWideChar(CP_ACP, 0, argv[i], -1, wargv[i], len); + } + + int ret = wmain(argc, wargv); + + for (int i = 0; i < argc; i++) + { + delete[] wargv[i]; + } + delete[] wargv; + + return ret; +} +#endif // PLATFORM_UNIX diff --git a/src/tools/util/consoleargs.cpp b/src/tools/util/consoleargs.cpp index ad316e7a55..5bf88a5a59 100644 --- a/src/tools/util/consoleargs.cpp +++ b/src/tools/util/consoleargs.cpp @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +#include #include "consoleargs.h" #include @@ -45,6 +46,7 @@ inline int HexValue (WCHAR c) return (c >= '0' && c <= '9') ? c - '0' : (c & 0xdf) - 'A' + 10; } +#ifndef PLATFORM_UNIX // Get canonical file path from a user specified path. wszSrcfileName can include relative paths, etc. // Much of this function was taken from csc.exe. DWORD GetCanonFilePath(_In_z_ LPCWSTR wszSrcFileName, _Out_z_cap_(cchDestFileName) LPWSTR wszDestFileName, _In_ DWORD cchDestFileName, _In_ bool fPreserveSrcCasing) @@ -103,12 +105,12 @@ DWORD GetCanonFilePath(_In_z_ LPCWSTR wszSrcFileName, _Out_z_cap_(cchDestFileNam // devices beginning with "\\.\" // or wildcards // or characters 0-31 - if (wcschr( full_path + (hasDrive ? 2 : 0), L':') != NULL || - wcsncmp( full_path, L"\\\\?\\", 4) == 0 || - wcsncmp( full_path, L"\\\\.\\", 4) == 0 || - wcspbrk(full_path, L"?*\x1\x2\x3\x4\x5\x6\x7\x8\x9" - L"\xA\xB\xC\xD\xE\xF\x10\x11\x12\x13\x14\x15" - L"\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\0") != NULL) { + if (wcschr( full_path + (hasDrive ? 2 : 0), W(':')) != NULL || + wcsncmp( full_path, W("\\\\?\\"), 4) == 0 || + wcsncmp( full_path, W("\\\\.\\"), 4) == 0 || + wcspbrk(full_path, W("?*\x1\x2\x3\x4\x5\x6\x7\x8\x9") + W("\xA\xB\xC\xD\xE\xF\x10\x11\x12\x13\x14\x15") + W("\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\0")) != NULL) { SetLastError(ERROR_INVALID_NAME); goto FAIL; } @@ -299,6 +301,7 @@ FAIL: } return 0; } +#endif // !PLATFORM_UNIX bool FreeString(LPCWSTR szText) { @@ -334,19 +337,26 @@ void ConsoleArgs::CleanUpArgs() } } -bool ConsoleArgs::GetFullFileName(LPCWSTR szSource, __deref_out_ecount(cbFilenameBuffer) LPWSTR filenameBuffer, DWORD cbFilenameBuffer, bool fOutputFilename) +bool ConsoleArgs::GetFullFileName(LPCWSTR szSource, __deref_out_ecount(cchFilenameBuffer) LPWSTR filenameBuffer, DWORD cchFilenameBuffer, bool fOutputFilename) { - if (0 == GetCanonFilePath( szSource, filenameBuffer, cbFilenameBuffer, fOutputFilename)) +#ifdef PLATFORM_UNIX + WCHAR tempBuffer[MAX_PATH]; + memset(filenameBuffer, 0, cchFilenameBuffer * sizeof(WCHAR)); + if (!PathCanonicalizeW(tempBuffer, szSource) || + StringCchCopyW(filenameBuffer, cchFilenameBuffer, tempBuffer) != S_OK) +#else + if (0 == GetCanonFilePath( szSource, filenameBuffer, cchFilenameBuffer, fOutputFilename)) +#endif { if (filenameBuffer[0] == L'\0') { // This could easily fail because of an overflow, but that's OK // we only want what will fit in the output buffer so we can print // a good error message - StringCchCopyW(filenameBuffer, cbFilenameBuffer - 4, szSource); + StringCchCopyW(filenameBuffer, cchFilenameBuffer - 4, szSource); // Don't cat on the ..., only stick it in the last 4 characters // to indicate truncation (if the string is short than this it just won't print) - StringCchCopyW(filenameBuffer + cbFilenameBuffer - 4, 4, L"..."); + StringCchCopyW(filenameBuffer + cchFilenameBuffer - 4, 4, W("...")); } return false; } @@ -374,7 +384,7 @@ void ConsoleArgs::SetErrorMessage(__deref_in LPCWSTR pwzMessage) return; } - wcscpy_s(m_lastErrorMessage, wcslen(pwzMessage) + 1, pwzMessage); + wcscpy_s((LPWSTR)m_lastErrorMessage, wcslen(pwzMessage) + 1, pwzMessage); } // @@ -633,7 +643,7 @@ LEADINGWHITE: if (chIllegal != 0) { - SetErrorMessage(L"Illegal option character."); + SetErrorMessage(W("Illegal option character.")); break; } @@ -641,13 +651,13 @@ LEADINGWHITE: WCHAR * szArgCopy = new WCHAR[cchLen]; if (!szArgCopy || FAILED(StringCchCopyW(szArgCopy, cchLen, pFirst))) { - SetErrorMessage(L"Out of memory."); + SetErrorMessage(W("Out of memory.")); break; } WStrList * listArgNew = new WStrList( szArgCopy, (*argLast)); if (!listArgNew) { - SetErrorMessage(L"Out of memory."); + SetErrorMessage(W("Out of memory.")); break; } @@ -678,7 +688,7 @@ bool ConsoleArgs::ExpandResponseFiles(__in int argc, __deref_in_ecount(argc) con LPWSTR copyArg = new WCHAR[wcslen(argv[0]) + 1]; if (!copyArg) { - SetErrorMessage(L"Out of memory."); + SetErrorMessage(W("Out of memory.")); return false; } wcscpy_s(copyArg, wcslen(argv[0]) + 1, argv[0]); @@ -686,7 +696,7 @@ bool ConsoleArgs::ExpandResponseFiles(__in int argc, __deref_in_ecount(argc) con WStrList * listArgNew = new WStrList(copyArg, (*argLast)); if (!listArgNew) { - SetErrorMessage(L"Out of memory."); + SetErrorMessage(W("Out of memory.")); return false; } @@ -713,7 +723,7 @@ bool ConsoleArgs::ExpandResponseFiles(__in int argc, __deref_in_ecount(argc) con m_rgArgs = new LPWSTR[newArgc]; if (!m_rgArgs) { - SetErrorMessage(L"Out of memory."); + SetErrorMessage(W("Out of memory.")); return false; } int i = 0; @@ -745,21 +755,23 @@ bool ConsoleArgs::ReadTextFile(LPCWSTR pwzFilename, __deref_out LPWSTR *ppwzText HANDLE hFile = CreateFile(pwzFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { - SetErrorMessage(L"Cannot open response file."); + SetErrorMessage(W("Cannot open response file.")); goto ErrExit; } + + { DWORD size = GetFileSize(hFile, NULL); bufA = new char[size]; if (!bufA) { - SetErrorMessage(L"Out of memory"); + SetErrorMessage(W("Out of memory")); goto ErrExit; } DWORD numRead = 0; if (!ReadFile(hFile, bufA, size, &numRead, NULL) || numRead != size) { - SetErrorMessage(L"Failure reading response file."); + SetErrorMessage(W("Failure reading response file.")); goto ErrExit; } @@ -790,13 +802,13 @@ bool ConsoleArgs::ReadTextFile(LPCWSTR pwzFilename, __deref_out LPWSTR *ppwzText } else if (byte0 == 0xFE && byte1 == 0xFF) { - SetErrorMessage(L"Invalid response file format. Use little endian encoding with Unicode"); + SetErrorMessage(W("Invalid response file format. Use little endian encoding with Unicode")); goto ErrExit; } - else if (byte0 == 0xFF && byte1 == 0xFE && byte2 == 0x00 && byte3 == 0x00 || - byte0 == 0x00 && byte1 == 0x00 && byte2 == 0xFE && byte3 == 0xFF) + else if ((byte0 == 0xFF && byte1 == 0xFE && byte2 == 0x00 && byte3 == 0x00) || + (byte0 == 0x00 && byte1 == 0x00 && byte2 == 0xFE && byte3 == 0xFF)) { - SetErrorMessage(L"Invalid response file format. Use ANSI, UTF-8, or UTF-16"); + SetErrorMessage(W("Invalid response file format. Use ANSI, UTF-8, or UTF-16")); goto ErrExit; } @@ -810,7 +822,7 @@ bool ConsoleArgs::ReadTextFile(LPCWSTR pwzFilename, __deref_out LPWSTR *ppwzText // Sanity check - requiredSize better be an even number since we're dealing with UTF-16 if (requiredSize % 2 != 0) { - SetErrorMessage(L"Response file corrupt. Expected UTF-16 encoding but we had an odd number of bytes"); + SetErrorMessage(W("Response file corrupt. Expected UTF-16 encoding but we had an odd number of bytes")); goto ErrExit; } @@ -819,7 +831,7 @@ bool ConsoleArgs::ReadTextFile(LPCWSTR pwzFilename, __deref_out LPWSTR *ppwzText bufW = new WCHAR[requiredSize]; if (!bufW) { - SetErrorMessage(L"Out of memory"); + SetErrorMessage(W("Out of memory")); goto ErrExit; } @@ -835,13 +847,13 @@ bool ConsoleArgs::ReadTextFile(LPCWSTR pwzFilename, __deref_out LPWSTR *ppwzText bufW = new WCHAR[requiredSize + 1]; if (!bufW) { - SetErrorMessage(L"Out of memory"); + SetErrorMessage(W("Out of memory")); goto ErrExit; } if (!MultiByteToWideChar(CP_UTF8, 0, postByteOrderMarks, size, bufW, requiredSize)) { - SetErrorMessage(L"Failure reading response file."); + SetErrorMessage(W("Failure reading response file.")); goto ErrExit; } @@ -851,6 +863,7 @@ bool ConsoleArgs::ReadTextFile(LPCWSTR pwzFilename, __deref_out LPWSTR *ppwzText *ppwzTextBuffer = bufW; success = true; + } ErrExit: if (bufA) @@ -883,7 +896,7 @@ void ConsoleArgs::ProcessResponseArgs() if (wcslen(szArg) == 1) { - SetErrorMessage(L"No response file specified"); + SetErrorMessage(W("No response file specified")); goto CONTINUE; } @@ -895,22 +908,27 @@ void ConsoleArgs::ProcessResponseArgs() hr = TreeAdd(&response_files, szFilename); if (hr == E_OUTOFMEMORY) { - SetErrorMessage(L"Out of memory."); + SetErrorMessage(W("Out of memory.")); goto CONTINUE; } else if (hr == S_FALSE) { - SetErrorMessage(L"Duplicate response file."); + SetErrorMessage(W("Duplicate response file.")); goto CONTINUE; } - LPWSTR pwzFileBuffer = nullptr; + { + LPWSTR pwzFileBuffer; + pwzFileBuffer = nullptr; if (!ReadTextFile(szFilename, &pwzFileBuffer)) { goto CONTINUE; } LPWSTR szActualText = nullptr; +#ifdef PLATFORM_UNIX + szActualText = pwzFileBuffer; +#else DWORD dwNumChars = ExpandEnvironmentStrings(pwzFileBuffer, NULL, 0); LPWSTR szExpandedBuffer = new WCHAR[dwNumChars]; if (szExpandedBuffer != nullptr) @@ -927,8 +945,10 @@ void ConsoleArgs::ProcessResponseArgs() } } +#endif TextToArgs(szActualText, &listCurArg->next); + } CONTINUE: // remove the response file argument, and continue to the next. listCurArg->arg = NULL; diff --git a/src/tools/util/consoleargs.h b/src/tools/util/consoleargs.h index 869cee3629..e9bc93bcdc 100644 --- a/src/tools/util/consoleargs.h +++ b/src/tools/util/consoleargs.h @@ -10,10 +10,12 @@ #include "tree.h" #include +#include "palclr.h" + typedef tree b_tree; typedef list WStrList; -const LPWSTR kOutOfMemory = L"Out of memory"; +const LPCWSTR kOutOfMemory = W("Out of memory"); class ConsoleArgs { @@ -40,7 +42,7 @@ public: // Frees all memory used by the arg list and the argv/argc array void CleanUpArgs(); - LPWSTR ErrorMessage() + LPCWSTR ErrorMessage() { if (m_errorOccured) { @@ -65,7 +67,7 @@ private: WStrList * m_listArgs; bool m_errorOccured; - LPWSTR m_lastErrorMessage; + LPCWSTR m_lastErrorMessage; }; #endif // __CONSOLEARGS_H__ -- cgit v1.2.3