From b7b5c7742696ec7a7961c0d5d31857537a5c51a2 Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Wed, 7 Aug 2024 15:23:57 +0200 Subject: [PATCH 1/2] [ESI] Add option to build runtime as a static library --- lib/Dialect/ESI/runtime/CMakeLists.txt | 47 ++++++++++++---- .../ESI/runtime/cpp/include/esi/Accelerator.h | 7 ++- .../ESI/runtime/cpp/lib/Accelerator.cpp | 55 +++++++++++++------ 3 files changed, 79 insertions(+), 30 deletions(-) diff --git a/lib/Dialect/ESI/runtime/CMakeLists.txt b/lib/Dialect/ESI/runtime/CMakeLists.txt index 1bf82fa04c98..9b36819a418f 100644 --- a/lib/Dialect/ESI/runtime/CMakeLists.txt +++ b/lib/Dialect/ESI/runtime/CMakeLists.txt @@ -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") @@ -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) @@ -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. @@ -119,9 +132,17 @@ IF(MSVC) 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 ) @@ -143,9 +164,11 @@ target_link_libraries(ESICppRuntime PUBLIC nlohmann_json::nlohmann_json ) if(NOT MSVC) - target_link_libraries(ESICppRuntime PRIVATE - dl - ) + if(NOT ESI_STATIC_RUNTIME) + target_link_libraries(ESICppRuntime PRIVATE + dl + ) + endif() target_link_options(ESICppRuntime PRIVATE -pthread ) @@ -165,10 +188,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 .* diff --git a/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h b/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h index 34567c466f88..c3a1cd9da9e6 100644 --- a/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h +++ b/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h @@ -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 -connect(Context &ctxt, std::string backend, std::string connection); +std::unique_ptr 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( Context &, std::string)>; -void registerBackend(std::string name, BackendCreate create); +void registerBackend(const std::string &name, BackendCreate create); // Helper struct to template diff --git a/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp b/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp index 019d734b0023..f5249d0020bb 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp @@ -175,25 +175,48 @@ static void loadBackend(std::string backend) { namespace registry { namespace internal { -static std::map backendRegistry; -void registerBackend(std::string name, BackendCreate create) { - if (backendRegistry.count(name)) - throw std::runtime_error("Backend already exists in registry"); - backendRegistry[name] = create; +class BackendRegistry { +public: + static void registerBackend(const std::string &name, BackendCreate create) { + auto ®istry = get().backendRegistry; + if (registry.count(name)) + throw std::runtime_error("Backend already exists in registry"); + registry[name] = create; + } + + static std::unique_ptr + connect(Context &ctxt, const std::string &backend, + const std::string &connection) { + auto ®istry = get().backendRegistry; + 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 = registry.find(backend); + if (f == registry.end()) + throw std::runtime_error("Backend '" + backend + "' not found"); + } + return f->second(ctxt, connection); + } + +private: + static BackendRegistry &get() { + static BackendRegistry instance; + return instance; + } + + std::map backendRegistry; +}; + +void registerBackend(const std::string &name, BackendCreate create) { + BackendRegistry::registerBackend(name, create); } } // namespace internal -std::unique_ptr -connect(Context &ctxt, std::string backend, std::string connection) { - auto f = internal::backendRegistry.find(backend); - if (f == internal::backendRegistry.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()) - throw std::runtime_error("Backend '" + backend + "' not found"); - } - return f->second(ctxt, connection); +std::unique_ptr connect(Context &ctxt, + const std::string &backend, + const std::string &connection) { + return internal::BackendRegistry::connect(ctxt, backend, connection); } } // namespace registry From 9206566b2bbf530c8d48e03c34c3cae4bf09e78a Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Thu, 8 Aug 2024 06:20:45 +0000 Subject: [PATCH 2/2] review comments --- lib/Dialect/ESI/runtime/CMakeLists.txt | 9 ++-- .../ESI/runtime/cpp/lib/Accelerator.cpp | 44 +++++++------------ 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/lib/Dialect/ESI/runtime/CMakeLists.txt b/lib/Dialect/ESI/runtime/CMakeLists.txt index 9b36819a418f..fdda1847c2da 100644 --- a/lib/Dialect/ESI/runtime/CMakeLists.txt +++ b/lib/Dialect/ESI/runtime/CMakeLists.txt @@ -131,7 +131,6 @@ IF(MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1) ENDIF(MSVC) -# The core API. For now, compile the backends into it directly. if(ESI_STATIC_RUNTIME) add_library(ESICppRuntime STATIC ${ESICppRuntimeSources} @@ -164,11 +163,9 @@ target_link_libraries(ESICppRuntime PUBLIC nlohmann_json::nlohmann_json ) if(NOT MSVC) - if(NOT ESI_STATIC_RUNTIME) - target_link_libraries(ESICppRuntime PRIVATE - dl - ) - endif() + target_link_libraries(ESICppRuntime PRIVATE + dl + ) target_link_options(ESICppRuntime PRIVATE -pthread ) diff --git a/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp b/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp index f5249d0020bb..0aae47341b6e 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/Accelerator.cpp @@ -177,46 +177,36 @@ namespace internal { class BackendRegistry { public: - static void registerBackend(const std::string &name, BackendCreate create) { - auto ®istry = get().backendRegistry; - if (registry.count(name)) - throw std::runtime_error("Backend already exists in registry"); - registry[name] = create; - } - - static std::unique_ptr - connect(Context &ctxt, const std::string &backend, - const std::string &connection) { - auto ®istry = get().backendRegistry; - 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 = registry.find(backend); - if (f == registry.end()) - throw std::runtime_error("Backend '" + backend + "' not found"); - } - return f->second(ctxt, connection); - } - -private: - static BackendRegistry &get() { + static std::map &get() { static BackendRegistry instance; - return instance; + return instance.backendRegistry; } +private: std::map backendRegistry; }; void registerBackend(const std::string &name, BackendCreate create) { - BackendRegistry::registerBackend(name, create); + auto ®istry = BackendRegistry::get(); + if (registry.count(name)) + throw std::runtime_error("Backend already exists in registry"); + registry[name] = create; } } // namespace internal std::unique_ptr connect(Context &ctxt, const std::string &backend, const std::string &connection) { - return internal::BackendRegistry::connect(ctxt, backend, connection); + auto ®istry = 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 = registry.find(backend); + if (f == registry.end()) + throw std::runtime_error("Backend '" + backend + "' not found"); + } + return f->second(ctxt, connection); } } // namespace registry