Skip to content
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

[ESI] Add option to build runtime as a static library #7455

Merged
merged 2 commits into from
Aug 8, 2024
Merged
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
40 changes: 31 additions & 9 deletions lib/Dialect/ESI/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ cmake_minimum_required(VERSION 3.20)
project(ESIRuntime LANGUAGES CXX)
include(FetchContent)

set(ESI_STATIC_RUNTIME OFF CACHE BOOL "Build the ESI runtime as a static library.")
if(ESI_STATIC_RUNTIME)
message("-- Building ESI runtime as a static library.")
endif()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
Expand All @@ -44,6 +49,10 @@ if (NOT TARGET nlohmann_json)
FetchContent_MakeAvailable(json)
endif()

if(ESI_STATIC_RUNTIME)
set(ZLIB_USE_STATIC_LIBS ON)
endif()

# We need zlib to uncompress the manifest.
find_package(ZLIB)
if(ZLIB_FOUND)
Expand All @@ -57,7 +66,11 @@ else()
)
FetchContent_MakeAvailable(ZLIB)
set(ZLIB_INCLUDE_DIR ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
set(ZLIB_LIBRARY zlib)
if(ESI_STATIC_RUNTIME)
set(ZLIB_LIBRARY zlibstatic)
else()
set(ZLIB_LIBRARY zlib)
endif()
endif()

# In a Python wheel build, we need to install libraries to different places.
Expand Down Expand Up @@ -118,10 +131,17 @@ IF(MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1)
ENDIF(MSVC)

# The core API. For now, compile the backends into it directly.
add_library(ESICppRuntime SHARED
${ESICppRuntimeSources}
)
if(ESI_STATIC_RUNTIME)
add_library(ESICppRuntime STATIC
${ESICppRuntimeSources}
)
else()
add_library(ESICppRuntime SHARED
${ESICppRuntimeSources}
)
endif()
add_library(esiaccel::ESICppRuntime ALIAS ESICppRuntime)

target_include_directories(ESICppRuntime PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/cpp/include
)
Expand Down Expand Up @@ -165,10 +185,12 @@ install(TARGETS ESICppRuntime
COMPONENT ESIRuntime
)

install(IMPORTED_RUNTIME_ARTIFACTS ESICppRuntime
RUNTIME_DEPENDENCY_SET ESICppRuntime_RUNTIME_DEPS
COMPONENT ESIRuntime
)
if(NOT ESI_STATIC_RUNTIME)
install(IMPORTED_RUNTIME_ARTIFACTS ESICppRuntime
RUNTIME_DEPENDENCY_SET ESICppRuntime_RUNTIME_DEPS
COMPONENT ESIRuntime
)
endif()
install(RUNTIME_DEPENDENCY_SET ESICppRuntime_RUNTIME_DEPS
DESTINATION ${LIB_DIR}
PRE_EXCLUDE_REGEXES .*
Expand Down
7 changes: 4 additions & 3 deletions lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,16 @@ namespace registry {

// Connect to an ESI accelerator given a backend name and connection specifier.
// Alternatively, instantiate the backend directly (if you're using C++).
std::unique_ptr<AcceleratorConnection>
connect(Context &ctxt, std::string backend, std::string connection);
std::unique_ptr<AcceleratorConnection> connect(Context &ctxt,
const std::string &backend,
const std::string &connection);

namespace internal {

/// Backends can register themselves to be connected via a connection string.
using BackendCreate = std::function<std::unique_ptr<AcceleratorConnection>(
Context &, std::string)>;
void registerBackend(std::string name, BackendCreate create);
void registerBackend(const std::string &name, BackendCreate create);

// Helper struct to
template <typename TAccelerator>
Expand Down
33 changes: 23 additions & 10 deletions lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,22 +175,35 @@ static void loadBackend(std::string backend) {
namespace registry {
namespace internal {

static std::map<std::string, BackendCreate> backendRegistry;
void registerBackend(std::string name, BackendCreate create) {
if (backendRegistry.count(name))
class BackendRegistry {
public:
static std::map<std::string, BackendCreate> &get() {
static BackendRegistry instance;
mortbopet marked this conversation as resolved.
Show resolved Hide resolved
return instance.backendRegistry;
}

private:
std::map<std::string, BackendCreate> backendRegistry;
};

void registerBackend(const std::string &name, BackendCreate create) {
auto &registry = BackendRegistry::get();
if (registry.count(name))
throw std::runtime_error("Backend already exists in registry");
backendRegistry[name] = create;
registry[name] = create;
}
} // namespace internal

std::unique_ptr<AcceleratorConnection>
connect(Context &ctxt, std::string backend, std::string connection) {
auto f = internal::backendRegistry.find(backend);
if (f == internal::backendRegistry.end()) {
std::unique_ptr<AcceleratorConnection> connect(Context &ctxt,
const std::string &backend,
const std::string &connection) {
auto &registry = internal::BackendRegistry::get();
auto f = registry.find(backend);
if (f == registry.end()) {
// If it's not already found in the registry, try to load it dynamically.
loadBackend(backend);
f = internal::backendRegistry.find(backend);
if (f == internal::backendRegistry.end())
f = registry.find(backend);
if (f == registry.end())
throw std::runtime_error("Backend '" + backend + "' not found");
}
return f->second(ctxt, connection);
Expand Down
Loading