Merge pull request #681 from schellap/refac
Refactor and build library for corehost
This commit is contained in:
commit
697debb5d4
22 changed files with 279 additions and 82 deletions
|
@ -26,11 +26,16 @@ try {
|
|||
if (!(Test-Path $HostDir)) {
|
||||
mkdir $HostDir | Out-Null
|
||||
}
|
||||
cp "$RepoRoot\src\corehost\cmake\$Rid\$Configuration\corehost.exe" $HostDir
|
||||
cp "$RepoRoot\src\corehost\cmake\$Rid\cli\$Configuration\corehost.exe" $HostDir
|
||||
cp "$RepoRoot\src\corehost\cmake\$Rid\cli\dll\$Configuration\clihost.dll" $HostDir
|
||||
|
||||
if (Test-Path "$RepoRoot\src\corehost\cmake\$Rid\$Configuration\corehost.pdb")
|
||||
if (Test-Path "$RepoRoot\src\corehost\cmake\$Rid\cli\$Configuration\corehost.pdb")
|
||||
{
|
||||
cp "$RepoRoot\src\corehost\cmake\$Rid\$Configuration\corehost.pdb" $HostDir
|
||||
cp "$RepoRoot\src\corehost\cmake\$Rid\cli\$Configuration\corehost.pdb" $HostDir
|
||||
}
|
||||
if (Test-Path "$RepoRoot\src\corehost\cmake\$Rid\cli\dll\$Configuration\clihost.pdb")
|
||||
{
|
||||
cp "$RepoRoot\src\corehost\cmake\$Rid\cli\dll\$Configuration\clihost.pdb" $HostDir
|
||||
}
|
||||
} finally {
|
||||
popd
|
||||
|
|
|
@ -24,5 +24,11 @@ make
|
|||
|
||||
# Publish to artifacts
|
||||
[ -d "$HOST_DIR" ] || mkdir -p $HOST_DIR
|
||||
cp "$REPOROOT/src/corehost/cmake/$RID/corehost" $HOST_DIR
|
||||
if [[ "$OSNAME" == "osx" ]]; then
|
||||
COREHOST_LIBNAME=libclihost.dylib
|
||||
else
|
||||
COREHOST_LIBNAME=libclihost.so
|
||||
fi
|
||||
cp "$REPOROOT/src/corehost/cmake/$RID/cli/corehost" $HOST_DIR
|
||||
cp "$REPOROOT/src/corehost/cmake/$RID/cli/dll/${COREHOST_LIBNAME}" $HOST_DIR
|
||||
popd 2>&1 >/dev/null
|
||||
|
|
|
@ -1,43 +1,2 @@
|
|||
# Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (corehost)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
include_directories(inc)
|
||||
|
||||
# CMake does not recommend using globbing since it messes with the freshness checks
|
||||
set(SOURCES
|
||||
src/args.cpp
|
||||
src/main.cpp
|
||||
src/deps_resolver.cpp
|
||||
src/trace.cpp
|
||||
src/utils.cpp
|
||||
src/coreclr.cpp
|
||||
src/servicing_index.cpp
|
||||
|
||||
inc/args.h
|
||||
inc/pal.h
|
||||
inc/servicing_index.h
|
||||
inc/deps_resolver.h
|
||||
inc/trace.h
|
||||
inc/coreclr.h
|
||||
inc/utils.h)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND SOURCES src/pal.windows.cpp)
|
||||
else()
|
||||
list(APPEND SOURCES src/pal.unix.cpp)
|
||||
endif()
|
||||
|
||||
add_executable(corehost ${SOURCES})
|
||||
|
||||
# Older CMake doesn't support CMAKE_CXX_STANDARD and GCC/Clang need a switch to enable C++ 11
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "(Clang|GNU)")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_definitions(-D__LINUX__)
|
||||
target_link_libraries (corehost "dl")
|
||||
endif()
|
||||
add_subdirectory(cli)
|
||||
|
|
47
src/corehost/cli/CMakeLists.txt
Normal file
47
src/corehost/cli/CMakeLists.txt
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (corehost)
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/MTd")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/MT")
|
||||
endif()
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
|
||||
include_directories(../common)
|
||||
|
||||
# CMake does not recommend using globbing since it messes with the freshness checks
|
||||
set(SOURCES
|
||||
../corehost.cpp
|
||||
|
||||
../common/trace.cpp
|
||||
../common/utils.cpp
|
||||
|
||||
args.cpp
|
||||
clihost.cpp
|
||||
coreclr.cpp
|
||||
deps_resolver.cpp
|
||||
servicing_index.cpp)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND SOURCES ../common/pal.windows.cpp)
|
||||
else()
|
||||
list(APPEND SOURCES ../common/pal.unix.cpp)
|
||||
endif()
|
||||
|
||||
add_executable(corehost ${SOURCES})
|
||||
|
||||
# Older CMake doesn't support CMAKE_CXX_STANDARD and GCC/Clang need a switch to enable C++ 11
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "(Clang|GNU)")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_definitions(-D__LINUX__)
|
||||
target_link_libraries (corehost "dl")
|
||||
endif()
|
||||
|
||||
add_subdirectory(dll)
|
|
@ -26,18 +26,6 @@ void display_help()
|
|||
|
||||
bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args)
|
||||
{
|
||||
// Read trace environment variable
|
||||
pal::string_t trace_str;
|
||||
if (pal::getenv(_X("COREHOST_TRACE"), &trace_str))
|
||||
{
|
||||
auto trace_val = pal::xtoi(trace_str.c_str());
|
||||
if (trace_val > 0)
|
||||
{
|
||||
trace::enable();
|
||||
trace::info(_X("Tracing enabled"));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the full name of the application
|
||||
if (!pal::get_own_executable_path(&args.own_path) || !pal::realpath(&args.own_path))
|
||||
{
|
|
@ -8,16 +8,18 @@
|
|||
#include "utils.h"
|
||||
#include "coreclr.h"
|
||||
|
||||
SHARED_API const pal::char_t* g_LIBHOST_NAME = MAKE_LIBNAME("clihost");
|
||||
|
||||
enum StatusCode
|
||||
{
|
||||
Failure = 0x87FF0000,
|
||||
InvalidArgFailure = Failure | 0x1,
|
||||
CoreClrResolveFailure = Failure | 0x2,
|
||||
CoreClrBindFailure = Failure | 0x3,
|
||||
CoreClrInitFailure = Failure | 0x4,
|
||||
CoreClrExeFailure = Failure | 0x5,
|
||||
ResolverInitFailure = Failure | 0x6,
|
||||
ResolverResolveFailure = Failure | 0x7,
|
||||
// 0x80 prefix to distinguish from corehost main's error codes.
|
||||
InvalidArgFailure = 0x81,
|
||||
CoreClrResolveFailure = 0x82,
|
||||
CoreClrBindFailure = 0x83,
|
||||
CoreClrInitFailure = 0x84,
|
||||
CoreClrExeFailure = 0x85,
|
||||
ResolverInitFailure = 0x86,
|
||||
ResolverResolveFailure = 0x87,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
@ -223,11 +225,7 @@ int run(const arguments_t& args, const pal::string_t& clr_path)
|
|||
return exit_code;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
int __cdecl wmain(const int argc, const pal::char_t* argv[])
|
||||
#else
|
||||
int main(const int argc, const pal::char_t* argv[])
|
||||
#endif
|
||||
SHARED_API int corehost_main(const int argc, const pal::char_t* argv[])
|
||||
{
|
||||
// Take care of arguments
|
||||
arguments_t args;
|
30
src/corehost/cli/dll/CMakeLists.txt
Normal file
30
src/corehost/cli/dll/CMakeLists.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project(clihost)
|
||||
|
||||
include_directories(../../common)
|
||||
|
||||
# CMake does not recommend using globbing since it messes with the freshness checks
|
||||
set(SOURCES
|
||||
../../common/trace.cpp
|
||||
../../common/utils.cpp
|
||||
|
||||
../args.cpp
|
||||
../clihost.cpp
|
||||
../coreclr.cpp
|
||||
../deps_resolver.cpp
|
||||
../servicing_index.cpp)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND SOURCES ../../common/pal.windows.cpp)
|
||||
else()
|
||||
list(APPEND SOURCES ../../common/pal.unix.cpp)
|
||||
endif()
|
||||
|
||||
add_definitions(-DCOREHOST_MAKE_DLL=1)
|
||||
|
||||
add_library(clihost SHARED ${SOURCES})
|
||||
|
|
@ -49,13 +49,15 @@
|
|||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define LIBCORECLR_NAME L"coreclr.dll"
|
||||
#define MAKE_LIBNAME(NAME) (_X(NAME) _X(".dll"))
|
||||
#elif defined(__APPLE__)
|
||||
#define LIBCORECLR_NAME "libcoreclr.dylib"
|
||||
#define MAKE_LIBNAME(NAME) (_X("lib") _X(NAME) _X(".dylib"))
|
||||
#else
|
||||
#define LIBCORECLR_NAME "libcoreclr.so"
|
||||
#define MAKE_LIBNAME(NAME) (_X("lib") _X(NAME) _X(".so"))
|
||||
#endif
|
||||
|
||||
#define LIBCORECLR_NAME MAKE_LIBNAME("coreclr")
|
||||
|
||||
#if !defined(PATH_MAX) && !defined(_WIN32)
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
@ -64,6 +66,11 @@
|
|||
namespace pal
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#ifdef COREHOST_MAKE_DLL
|
||||
#define SHARED_API extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define SHARED_API
|
||||
#endif
|
||||
|
||||
typedef wchar_t char_t;
|
||||
typedef std::wstring string_t;
|
||||
|
@ -89,6 +96,12 @@ namespace pal
|
|||
void to_palstring(const char* str, pal::string_t* out);
|
||||
void to_stdstring(const pal::char_t* str, std::string* out);
|
||||
#else
|
||||
#ifdef COREHOST_MAKE_DLL
|
||||
#define SHARED_API extern "C"
|
||||
#else
|
||||
#define SHARED_API
|
||||
#endif
|
||||
|
||||
typedef char char_t;
|
||||
typedef std::string string_t;
|
||||
typedef std::stringstream stringstream_t;
|
|
@ -117,17 +117,18 @@ bool pal::get_own_executable_path(pal::string_t* recv)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Returns true only if an env variable can be read successfully to be non-empty.
|
||||
bool pal::getenv(const pal::char_t* name, pal::string_t* recv)
|
||||
{
|
||||
recv->clear();
|
||||
|
||||
auto result = ::getenv(name);
|
||||
if (result != nullptr)
|
||||
{
|
||||
recv->assign(result);
|
||||
}
|
||||
|
||||
// We don't return false. Windows does have a concept of an error reading the variable,
|
||||
// but Unix just returns null, which we treat as the variable not existing.
|
||||
return true;
|
||||
return (recv->length() > 0);
|
||||
}
|
||||
|
||||
bool pal::realpath(pal::string_t* path)
|
|
@ -36,7 +36,7 @@ bool pal::load_library(const char_t* path, dll_t* dll)
|
|||
*dll = ::LoadLibraryW(path);
|
||||
if (*dll == nullptr)
|
||||
{
|
||||
trace::error(_X("Failed to load coreclr.dll from %s, HRESULT: 0x%X"), path, HRESULT_FROM_WIN32(GetLastError()));
|
||||
trace::error(_X("Failed to load the dll from %s, HRESULT: 0x%X"), path, HRESULT_FROM_WIN32(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -85,18 +85,19 @@ bool pal::is_path_rooted(const string_t& path)
|
|||
return path.length() >= 2 && path[1] == L':';
|
||||
}
|
||||
|
||||
// Returns true only if an env variable can be read successfully to be non-empty.
|
||||
bool pal::getenv(const char_t* name, string_t* recv)
|
||||
{
|
||||
recv->clear();
|
||||
|
||||
auto length = ::GetEnvironmentVariableW(name, nullptr, 0);
|
||||
if (length == 0)
|
||||
{
|
||||
auto err = GetLastError();
|
||||
if (err == ERROR_ENVVAR_NOT_FOUND)
|
||||
if (err != ERROR_ENVVAR_NOT_FOUND)
|
||||
{
|
||||
// Leave the receiver empty and return success
|
||||
return true;
|
||||
trace::error(_X("Failed to read enviroment variable '%s', HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
trace::error(_X("Failed to read enviroment variable '%s', HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
auto buf = new char_t[length];
|
149
src/corehost/corehost.cpp
Normal file
149
src/corehost/corehost.cpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "common/trace.h"
|
||||
#include "common/pal.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
extern const pal::char_t* g_LIBHOST_NAME;
|
||||
extern int corehost_main(const int argc, const pal::char_t* argv[]);
|
||||
|
||||
namespace
|
||||
{
|
||||
enum StatusCode
|
||||
{
|
||||
Success = 0,
|
||||
CoreHostLibLoadFailure = 0x41,
|
||||
CoreHostLibMissingFailure = 0x42,
|
||||
CoreHostEntryPointFailure = 0x43,
|
||||
CoreHostCurExeFindFailure = 0x44,
|
||||
};
|
||||
|
||||
typedef int (*corehost_main_fn) (const int argc, const pal::char_t* argv[]);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Load the corehost library from the path specified
|
||||
//
|
||||
// Parameters:
|
||||
// lib_dir - dir path to the corehost library
|
||||
// h_host - handle to the library which will be kept live
|
||||
// main_fn - Contains the entrypoint "corehost_main" when returns success.
|
||||
//
|
||||
// Returns:
|
||||
// Non-zero exit code on failure. "main_fn" contains "corehost_main"
|
||||
// entrypoint on success.
|
||||
//
|
||||
StatusCode load_host_lib(const pal::string_t& lib_dir, pal::dll_t* h_host, corehost_main_fn* main_fn)
|
||||
{
|
||||
pal::string_t host_path = lib_dir;
|
||||
append_path(&host_path, g_LIBHOST_NAME);
|
||||
|
||||
// Missing library
|
||||
if (!pal::file_exists(host_path))
|
||||
{
|
||||
return StatusCode::CoreHostLibMissingFailure;
|
||||
}
|
||||
|
||||
// Load library
|
||||
if (!pal::load_library(host_path.c_str(), h_host))
|
||||
{
|
||||
trace::info(_X("Load library of %s failed"), host_path.c_str());
|
||||
return StatusCode::CoreHostLibLoadFailure;
|
||||
}
|
||||
|
||||
// Obtain entrypoint symbol
|
||||
*main_fn = (corehost_main_fn) pal::get_symbol(*h_host, "corehost_main");
|
||||
|
||||
return (*main_fn != nullptr)
|
||||
? StatusCode::Success
|
||||
: StatusCode::CoreHostEntryPointFailure;
|
||||
}
|
||||
|
||||
//
|
||||
// Turn on tracing for the corehost based on "COREHOST_TRACE" env.
|
||||
//
|
||||
void setup_tracing()
|
||||
{
|
||||
// Read trace environment variable
|
||||
pal::string_t trace_str;
|
||||
if (!pal::getenv(_X("COREHOST_TRACE"), &trace_str))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto trace_val = pal::xtoi(trace_str.c_str());
|
||||
if (trace_val > 0)
|
||||
{
|
||||
trace::enable();
|
||||
trace::info(_X("Tracing enabled"));
|
||||
}
|
||||
}
|
||||
|
||||
}; // end of anonymous namespace
|
||||
|
||||
#if defined(_WIN32)
|
||||
int __cdecl wmain(const int argc, const pal::char_t* argv[])
|
||||
#else
|
||||
int main(const int argc, const pal::char_t* argv[])
|
||||
#endif
|
||||
{
|
||||
setup_tracing();
|
||||
|
||||
pal::dll_t corehost;
|
||||
|
||||
#ifdef COREHOST_PACKAGE_SERVICING
|
||||
// No custom host asked, so load the corehost if serviced first.
|
||||
pal::string_t svc_dir;
|
||||
if (pal::getenv(_X("DOTNET_SERVICING"), &svc_dir))
|
||||
{
|
||||
pal::string_t path = svc_dir;
|
||||
append_path(&path, COREHOST_PACKAGE_NAME);
|
||||
append_path(&path, COREHOST_PACKAGE_VERSION);
|
||||
append_path(&path, COREHOST_PACKAGE_COREHOST_RELATIVE_DIR);
|
||||
|
||||
corehost_main_fn host_main;
|
||||
StatusCode code = load_host_lib(path, &corehost, &host_main);
|
||||
if (code != StatusCode::Success)
|
||||
{
|
||||
trace::info(_X("Failed to load host library from servicing dir: %s; Status=%08X"), path.c_str(), code);
|
||||
// Ignore all errors for the servicing case, and proceed to the next step.
|
||||
}
|
||||
else
|
||||
{
|
||||
trace::info(_X("Calling host entrypoint from library at servicing dir %s"), path.c_str());
|
||||
return host_main(argc, argv);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get current path to look for the library app locally.
|
||||
pal::string_t own_path;
|
||||
if (!pal::get_own_executable_path(&own_path) || !pal::realpath(&own_path))
|
||||
{
|
||||
trace::error(_X("Failed to locate current executable"));
|
||||
return StatusCode::CoreHostCurExeFindFailure;
|
||||
}
|
||||
|
||||
// Local load of the corehost library.
|
||||
auto own_dir = get_directory(own_path);
|
||||
|
||||
corehost_main_fn host_main;
|
||||
StatusCode code = load_host_lib(own_dir, &corehost, &host_main);
|
||||
switch (code)
|
||||
{
|
||||
// Success, call the entrypoint.
|
||||
case StatusCode::Success:
|
||||
trace::info(_X("Calling host entrypoint from library at own dir %s"), own_dir.c_str());
|
||||
return host_main(argc, argv);
|
||||
|
||||
// DLL missing is not fatal.
|
||||
case StatusCode::CoreHostLibMissingFailure:
|
||||
trace::info(_X("Calling statically linked entrypoint from own exe"));
|
||||
return corehost_main(argc, argv);
|
||||
|
||||
// Some other fatal error.
|
||||
default:
|
||||
trace::error(_X("Error loading the host library from own dir: %s; Status=%08X"), own_dir.c_str(), code);
|
||||
return code;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue