diff --git a/CMakeLists.txt b/CMakeLists.txt index f7872e00ee3f..81fd930488fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,7 +121,7 @@ function(generate_exports_file inputFilename outputFilename) add_custom_command( OUTPUT ${outputFilename} COMMAND ${AWK} -f ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} ${inputFilename} >${outputFilename} - DEPENDS ${inputFilename} + DEPENDS ${inputFilename} ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} COMMENT "Generating exports file ${outputFilename}" ) set_source_files_properties(${outputFilename} diff --git a/generateexportedsymbols.awk b/generateexportedsymbols.awk index 19312c381eab..1d9b200d2361 100644 --- a/generateexportedsymbols.awk +++ b/generateexportedsymbols.awk @@ -2,5 +2,10 @@ # Remove the CR character in case the sources are mapped from # a Windows share and contain CRLF line endings gsub(/\r/,"", $0); - print "_" $0; + + # Skip empty lines and comment lines starting with semicolon + if (NF && !match($0, /^[:space:]*;/)) + { + print "_" $0; + } } diff --git a/generateversionscript.awk b/generateversionscript.awk index 2aa1f4f0a2f9..d1c294be5818 100644 --- a/generateversionscript.awk +++ b/generateversionscript.awk @@ -6,7 +6,12 @@ BEGIN { # Remove the CR character in case the sources are mapped from # a Windows share and contain CRLF line endings gsub(/\r/,"", $0); - print " " $0 ";"; + + # Skip empty lines and comment lines starting with semicolon + if (NF && !match($0, /^[:space:]*;/)) + { + print " " $0 ";"; + } } END { print " local: *;" diff --git a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp index 4f6ffa033082..ecbbf392903c 100644 --- a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp +++ b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp @@ -24,29 +24,31 @@ static const char * const coreClrDll = "libcoreclr.dylib"; static const char * const coreClrDll = "libcoreclr.so"; #endif -// Windows types used by the ExecuteAssembly function -typedef unsigned int DWORD; -typedef const char16_t* LPCWSTR; -typedef const char* LPCSTR; -typedef int32_t HRESULT; - -#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) - -// Prototype of the ExecuteAssembly function from the libcoreclr.do -typedef HRESULT (*ExecuteAssemblyFunction)( - LPCSTR exePath, - LPCSTR coreClrPath, - LPCSTR appDomainFriendlyName, - int propertyCount, - LPCSTR* propertyKeys, - LPCSTR* propertyValues, - int argc, - LPCSTR* argv, - LPCSTR managedAssemblyPath, - LPCSTR entryPointAssemblyName, - LPCSTR entryPointTypeName, - LPCSTR entryPointMethodsName, - DWORD* exitCode); +#define SUCCEEDED(Status) ((Status) >= 0) + +// Prototype of the coreclr_initialize function from the libcoreclr.so +typedef int (*InitializeCoreCLRFunction)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + +// Prototype of the coreclr_shutdown function from the libcoreclr.so +typedef int (*ShutdownCoreCLRFunction)( + void* hostHandle, + unsigned int domainId); + +// Prototype of the coreclr_execute_assembly function from the libcoreclr.so +typedef int (*ExecuteAssemblyFunction)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); bool GetAbsolutePath(const char* path, std::string& absolutePath) { @@ -233,8 +235,23 @@ int ExecuteManagedAssembly( void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL); if (coreclrLib != nullptr) { - ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "ExecuteAssembly"); - if (executeAssembly != nullptr) + InitializeCoreCLRFunction initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib, "coreclr_initialize"); + ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "coreclr_execute_assembly"); + ShutdownCoreCLRFunction shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib, "coreclr_shutdown"); + + if (initializeCoreCLR == nullptr) + { + fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n"); + } + else if (executeAssembly == nullptr) + { + fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n"); + } + else if (shutdownCoreCLR == nullptr) + { + fprintf(stderr, "Function coreclr_shutdown not found in the libcoreclr.so\n"); + } + else { // Allowed property names: // APPBASE @@ -272,30 +289,46 @@ int ExecuteManagedAssembly( "UseLatestBehaviorWhenTFMNotSpecified" }; - HRESULT st = executeAssembly( - currentExeAbsolutePath, - coreClrDllPath.c_str(), - "unixcorerun", - sizeof(propertyKeys) / sizeof(propertyKeys[0]), - propertyKeys, - propertyValues, - managedAssemblyArgc, - managedAssemblyArgv, - managedAssemblyAbsolutePath, - NULL, - NULL, - NULL, - (DWORD*)&exitCode); + void* hostHandle; + unsigned int domainId; + + int st = initializeCoreCLR( + currentExeAbsolutePath, + "unixcorerun", + sizeof(propertyKeys) / sizeof(propertyKeys[0]), + propertyKeys, + propertyValues, + &hostHandle, + &domainId); if (!SUCCEEDED(st)) { - fprintf(stderr, "ExecuteAssembly failed - status: 0x%08x\n", st); + fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st); exitCode = -1; } - } - else - { - fprintf(stderr, "Function ExecuteAssembly not found in the libcoreclr.so\n"); + else + { + st = executeAssembly( + hostHandle, + domainId, + managedAssemblyArgc, + managedAssemblyArgv, + managedAssemblyAbsolutePath, + (unsigned int*)&exitCode); + + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st); + exitCode = -1; + } + + st = shutdownCoreCLR(hostHandle, domainId); + if (!SUCCEEDED(st)) + { + fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st); + exitCode = -1; + } + } } if (dlclose(coreclrLib) != 0) diff --git a/src/dlls/mscoree/mscorwks_unixexports.src b/src/dlls/mscoree/mscorwks_unixexports.src index 81a99d6a7ed2..e96b25a66462 100644 --- a/src/dlls/mscoree/mscorwks_unixexports.src +++ b/src/dlls/mscoree/mscorwks_unixexports.src @@ -1,7 +1,30 @@ +; Unix hosting API +coreclr_create_delegate +coreclr_execute_assembly +coreclr_initialize +coreclr_shutdown + +; Obsolete Unix hosting API, to be removed +ExecuteAssembly + +; PAL initialization and module registration +PAL_InitializeCoreCLR +PAL_RegisterModule +PAL_UnregisterModule + +; Functions exported by the coreclr +CoreDllMain +DllMain +GetCLRRuntimeHost + +; Functions used by CoreFX +EnsureOpenSslInitialized +ForkAndExecProcess + +; Win32 API and other PAL functions used by the mscorlib CloseHandle CoCreateGuid CopyFileW -CoreDllMain CoTaskMemAlloc CoTaskMemFree CreateDirectoryW @@ -10,19 +33,14 @@ CreateFileW CreateMutexW CreateSemaphoreW DeleteFileW -DllMain DuplicateHandle -EnsureOpenSslInitialized -ExecuteAssembly FindClose FindFirstFileW FindNextFileW FlushFileBuffers -ForkAndExecProcess FormatMessageW FreeEnvironmentStringsW GetACP -GetCLRRuntimeHost GetConsoleCP GetConsoleOutputCP GetCurrentDirectoryW @@ -53,10 +71,7 @@ MultiByteToWideChar OpenEventW OpenMutexW OpenSemaphoreW -PAL_InitializeCoreCLR PAL_Random -PAL_RegisterModule -PAL_UnregisterModule QueryPerformanceCounter QueryPerformanceFrequency RaiseException diff --git a/src/dlls/mscoree/unixinterface.cpp b/src/dlls/mscoree/unixinterface.cpp index 21419173e957..5c5e1dacc715 100644 --- a/src/dlls/mscoree/unixinterface.cpp +++ b/src/dlls/mscoree/unixinterface.cpp @@ -88,48 +88,30 @@ static LPCWSTR* StringArrayToUnicode(int argc, LPCSTR* argv) } // -// Execute a managed assembly with given arguments +// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain // // Parameters: // exePath - Absolute path of the executable that invoked the ExecuteAssembly -// coreClrPath - Absolute path of the libcoreclr.so // appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly // propertyCount - Number of properties (elements of the following two arguments) // propertyKeys - Keys of properties of the app domain // propertyValues - Values of properties of the app domain -// argc - Number of arguments passed to the executed assembly -// argv - Array of arguments passed to the executed assembly -// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint). -// enntyPointAssemblyName - Name of the assembly which holds the custom entry point (or NULL to use managedAssemblyPath). -// entryPointTypeName - Name of the type which holds the custom entry point (or NULL to use managedAssemblyPath). -// entryPointMethodName - Name of the method which is the custom entry point (or NULL to use managedAssemblyPath). -// exitCode - Exit code returned by the executed assembly +// hostHandle - Output parameter, handle of the created host +// domainId - Output parameter, id of the created app domain // // Returns: // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed // extern "C" -HRESULT ExecuteAssembly( - LPCSTR exePath, - LPCSTR coreClrPath, - LPCSTR appDomainFriendlyName, +int coreclr_initialize( + const char* exePath, + const char* appDomainFriendlyName, int propertyCount, - LPCSTR* propertyKeys, - LPCSTR* propertyValues, - int argc, - LPCSTR* argv, - LPCSTR managedAssemblyPath, - LPCSTR entryPointAssemblyName, - LPCSTR entryPointTypeName, - LPCSTR entryPointMethodName, - DWORD* exitCode) + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId) { - if (exitCode == NULL) - { - return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); - } - *exitCode = -1; - DWORD error = PAL_InitializeCoreCLR(exePath); HRESULT hr = HRESULT_FROM_WIN32(error); @@ -161,8 +143,6 @@ HRESULT ExecuteAssembly( ConstWStringArrayHolder propertyValuesW; propertyValuesW.Set(StringArrayToUnicode(propertyCount, propertyValues), propertyCount); - DWORD domainId; - hr = host->CreateAppDomainWithManager( appDomainFriendlyNameW, // Flags: @@ -187,7 +167,172 @@ HRESULT ExecuteAssembly( propertyCount, propertyKeysW, propertyValuesW, - &domainId); + domainId); + + if (SUCCEEDED(hr)) + { + host.SuppressRelease(); + *hostHandle = host; + } + + return hr; +} + +// +// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host. +// +// Parameters: +// hostHandle - Handle of the host +// domainId - Id of the domain +// +// Returns: +// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed +// +extern "C" +int coreclr_shutdown( + void* hostHandle, + unsigned int domainId) +{ + ReleaseHolder host(reinterpret_cast(hostHandle)); + HRESULT hr = host->UnloadAppDomain(domainId, + true); // Wait until done + IfFailRet(hr); + + hr = host->Stop(); + + // The PAL_Terminate is not called here since it would terminate the current process. + + return hr; +} + +// +// Create a native callable delegate for a managed method. +// +// Parameters: +// hostHandle - Handle of the host +// domainId - Id of the domain +// entryPointAssemblyName - Name of the assembly which holds the custom entry point +// entryPointTypeName - Name of the type which holds the custom entry point +// entryPointMethodName - Name of the method which is the custom entry point +// delegate - Output parameter, the function stores a pointer to the delegate at the specified address +// +// Returns: +// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed +// +extern "C" +int coreclr_create_delegate( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate) +{ + ICLRRuntimeHost2* host = reinterpret_cast(hostHandle); + + ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName); + ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName); + ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName); + + HRESULT hr = host->CreateDelegate( + domainId, + entryPointAssemblyNameW, + entryPointTypeNameW, + entryPointMethodNameW, + (INT_PTR*)delegate); + + return hr; +} + +// +// Execute a managed assembly with given arguments +// +// Parameters: +// hostHandle - Handle of the host +// domainId - Id of the domain +// argc - Number of arguments passed to the executed assembly +// argv - Array of arguments passed to the executed assembly +// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint). +// exitCode - Exit code returned by the executed assembly +// +// Returns: +// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed +// +extern "C" +int coreclr_execute_assembly( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode) +{ + if (exitCode == NULL) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + *exitCode = -1; + + ICLRRuntimeHost2* host = reinterpret_cast(hostHandle); + + ConstWStringArrayHolder argvW; + argvW.Set(StringArrayToUnicode(argc, argv), argc); + + ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath); + + HRESULT hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, exitCode); + IfFailRet(hr); + + return hr; +} + +// +// Execute a managed assembly with given arguments +// +// Parameters: +// exePath - Absolute path of the executable that invoked the ExecuteAssembly +// coreClrPath - Absolute path of the libcoreclr.so +// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly +// propertyCount - Number of properties (elements of the following two arguments) +// propertyKeys - Keys of properties of the app domain +// propertyValues - Values of properties of the app domain +// argc - Number of arguments passed to the executed assembly +// argv - Array of arguments passed to the executed assembly +// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint). +// enntyPointAssemblyName - Name of the assembly which holds the custom entry point (or NULL to use managedAssemblyPath). +// entryPointTypeName - Name of the type which holds the custom entry point (or NULL to use managedAssemblyPath). +// entryPointMethodName - Name of the method which is the custom entry point (or NULL to use managedAssemblyPath). +// exitCode - Exit code returned by the executed assembly +// +// Returns: +// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed +// +extern "C" +HRESULT ExecuteAssembly( + LPCSTR exePath, + LPCSTR coreClrPath, + LPCSTR appDomainFriendlyName, + int propertyCount, + LPCSTR* propertyKeys, + LPCSTR* propertyValues, + int argc, + LPCSTR* argv, + LPCSTR managedAssemblyPath, + LPCSTR entryPointAssemblyName, + LPCSTR entryPointTypeName, + LPCSTR entryPointMethodName, + DWORD* exitCode) +{ + if (exitCode == NULL) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); + } + *exitCode = -1; + + ReleaseHolder host; //(reinterpret_cast(hostHandle)); + DWORD domainId; + + HRESULT hr = coreclr_initialize(exePath, appDomainFriendlyName, propertyCount, propertyKeys, propertyValues, &host, &domainId); IfFailRet(hr); ConstWStringArrayHolder argvW; @@ -219,14 +364,8 @@ HRESULT ExecuteAssembly( *exitCode = pHostMain(argc, argvW); } - - hr = host->UnloadAppDomain(domainId, - true); // Wait until done - IfFailRet(hr); - - hr = host->Stop(); - // The PAL_Terminate is not called here since it would terminate the current process. + hr = coreclr_shutdown(host, domainId); return hr; } diff --git a/src/dlls/mscorrc/CMakeLists.txt b/src/dlls/mscorrc/CMakeLists.txt index 198fe8deb649..e139bc3a30d9 100644 --- a/src/dlls/mscorrc/CMakeLists.txt +++ b/src/dlls/mscorrc/CMakeLists.txt @@ -28,7 +28,7 @@ else() COMMAND ${CMAKE_CXX_COMPILER} -E -P ${PREPROCESS_DEFINITIONS} ${INCLUDE_DIRECTORIES} -o ${PREPROCESSED_SOURCE} -x c ${SOURCE} # Convert the preprocessed .rc file to a C++ file which will be used to make a static lib. COMMAND ${AWK} -f ${RC_TO_CPP} -f ${PROCESS_RC} ${PREPROCESSED_SOURCE} >${RESOURCE_ENTRY_ARRAY_CPP} - DEPENDS ${SOURCE} + DEPENDS ${SOURCE} ${RC_TO_CPP} ${PROCESS_RC} ) include_directories(${RESOURCE_STRING_HEADER_DIR})