Skip to content
Draft
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
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ endif()
project(level-zero VERSION 1.34.0)
include(GNUInstallDirs)

option(BUILD_STATIC "Build the Level Zero front end as a static library" OFF)
option(BUILD_STATIC_NO_DLL "Embed the Level Zero loader implementation in the static library" OFF)

if(BUILD_STATIC_NO_DLL)
set(BUILD_STATIC ON CACHE BOOL "Build the Level Zero front end as a static library" FORCE)
endif()

find_package(Git)
if(Git_FOUND)
if(MSVC)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ When the `-DBUILD_STATIC=1` is executed, the dynamic loader and layers are not b

Testing with the static loader requires a build of the dynamic loader or an installation of the dynamic loader to exist in the library path.

To embed the loader implementation in the static archive and avoid a runtime dependency on `ze_loader.dll`, configure with `-DBUILD_STATIC_NO_DLL=1`. This automatically enables the static build. The resulting archive still loads vendor Level Zero driver libraries and may load optional validation or tracing layers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts to clarify, since the term static build now has two meanings. Old static was effectively a stub only, and the new is a full static. We can debate terms, but we should be clear about the shift in static definition in the docs and definitions. Also I would be clear that a 'full static' doesn't include the validation / tracing layers as they will remain .dll files to be loaded upon user environmental request.

I'd avoid the term 'may load optional' is it reads like it's not deterministic. But in reality it is very deterministic upon user request. Full sentence suggestion:

"The resulting full static archive will still load vendor Level Zero driver libraries and will load the optional validation and tracing layers if requested from environmental variables or API calls"


# Debug Trace

> **Deprecated:** `ZE_ENABLE_LOADER_DEBUG_TRACE` is deprecated and will be removed in a future release.
Expand Down
6 changes: 3 additions & 3 deletions scripts/templates/libapi.cpp.mako
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ${th.make_func_name(n, tags, obj)}(
{
%if re.match("Init", obj['name']):
%if re.match("zes", n):
#ifdef L0_STATIC_LOADER_BUILD
#if defined(L0_STATIC_LOADER_BUILD) || defined(L0_STATIC_LOADER_BUILD_NO_DLL)
if (!${x}_lib::context) {
${x}_lib::context = new ${x}_lib::context_t;
}
Expand Down Expand Up @@ -95,7 +95,7 @@ ${th.make_func_name(n, tags, obj)}(
%else:
%if re.match("InitDrivers", obj['name']):
${x}_result_t result = ${X}_RESULT_SUCCESS;
#ifdef L0_STATIC_LOADER_BUILD
#if defined(L0_STATIC_LOADER_BUILD) || defined(L0_STATIC_LOADER_BUILD_NO_DLL)
if (!${x}_lib::context) {
${x}_lib::context = new ${x}_lib::context_t;
}
Expand Down Expand Up @@ -136,7 +136,7 @@ ${th.make_func_name(n, tags, obj)}(
return result;
%else:
static ${x}_result_t result = ${X}_RESULT_SUCCESS;
#ifdef L0_STATIC_LOADER_BUILD
#if defined(L0_STATIC_LOADER_BUILD) || defined(L0_STATIC_LOADER_BUILD_NO_DLL)
if (!${x}_lib::context) {
${x}_lib::context = new ${x}_lib::context_t;
}
Expand Down
11 changes: 9 additions & 2 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ if (BUILD_STATIC)
""
${CMAKE_CURRENT_BINARY_DIR}/ZeLoaderVersion.rc
)
add_definitions(-DL0_STATIC_LOADER_BUILD="1")
if(BUILD_STATIC_NO_DLL)
message(STATUS "Embedding loader implementation in static library")
add_definitions(-DL0_STATIC_LOADER_BUILD_NO_DLL="1")
else()
add_definitions(-DL0_STATIC_LOADER_BUILD="1")
endif()
else()
message(STATUS "Building loader as dynamic library")
add_library(${TARGET_LOADER_NAME}
Expand All @@ -34,8 +39,10 @@ if(MSVC AND L0_DLL_INTEGRITY_CHECKS)
endif()

add_subdirectory(lib)
if (NOT BUILD_STATIC)
if (NOT BUILD_STATIC OR BUILD_STATIC_NO_DLL)
add_subdirectory(loader)
endif()
if (NOT BUILD_STATIC)
add_subdirectory(layers)
endif()
add_subdirectory(drivers)
Expand Down
2 changes: 1 addition & 1 deletion source/lib/linux/lib_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace ze_lib
{
#ifndef L0_STATIC_LOADER_BUILD
#if !defined(L0_STATIC_LOADER_BUILD) && !defined(L0_STATIC_LOADER_BUILD_NO_DLL)
void __attribute__((constructor)) createLibContext() {
context = new context_t;
}
Expand Down
4 changes: 2 additions & 2 deletions source/lib/windows/lib_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
*/

#include "../ze_lib.h"
#ifndef L0_STATIC_LOADER_BUILD
#if !defined(L0_STATIC_LOADER_BUILD) && !defined(L0_STATIC_LOADER_BUILD_NO_DLL)
#include "../loader/ze_loader_internal.h"
#endif

namespace ze_lib
{
#ifndef L0_STATIC_LOADER_BUILD
#if !defined(L0_STATIC_LOADER_BUILD) && !defined(L0_STATIC_LOADER_BUILD_NO_DLL)
/*
* DllMain is called by the OS when the DLL is loaded or unloaded.
* When modifying the code here, be aware of the restrictions on what can be done
Expand Down
20 changes: 19 additions & 1 deletion source/lib/ze_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ namespace ze_lib
loaderTeardownCallbackReceived = true;
}
#endif
#ifdef L0_STATIC_LOADER_BUILD_NO_DLL
void context_at_exit_destructor()
{
if (ze_lib::context) {
delete ze_lib::context;
ze_lib::context = nullptr;
}
}
bool delayContextDestruction = false;
std::once_flag embeddedContextAtExitOnce;
#endif
/**
* @brief Removes a teardown callback from the context's callback registry.
*
Expand Down Expand Up @@ -100,6 +111,13 @@ namespace ze_lib
{
ze_result_t result;
ze_api_version_t version = ZE_API_VERSION_CURRENT;
#ifdef L0_STATIC_LOADER_BUILD_NO_DLL
std::call_once(embeddedContextAtExitOnce, []() {
if (!delayContextDestruction) {
std::atexit(context_at_exit_destructor);
}
});
#endif
#ifdef L0_STATIC_LOADER_BUILD
std::string loaderLibraryPath;
auto loaderLibraryPathEnv = getenv_string("ZEL_LIBRARY_PATH");
Expand Down Expand Up @@ -738,4 +756,4 @@ zelDisableTracingLayer()
return ZE_RESULT_SUCCESS;
}

} //extern "c"
} //extern "c"
4 changes: 2 additions & 2 deletions source/lib/ze_libapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ zeInit(
)
{
static ze_result_t result = ZE_RESULT_SUCCESS;
#ifdef L0_STATIC_LOADER_BUILD
#if defined(L0_STATIC_LOADER_BUILD) || defined(L0_STATIC_LOADER_BUILD_NO_DLL)
if (!ze_lib::context) {
ze_lib::context = new ze_lib::context_t;
}
Expand Down Expand Up @@ -249,7 +249,7 @@ zeInitDrivers(
)
{
ze_result_t result = ZE_RESULT_SUCCESS;
#ifdef L0_STATIC_LOADER_BUILD
#if defined(L0_STATIC_LOADER_BUILD) || defined(L0_STATIC_LOADER_BUILD_NO_DLL)
if (!ze_lib::context) {
ze_lib::context = new ze_lib::context_t;
}
Expand Down
2 changes: 1 addition & 1 deletion source/lib/zes_libapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ zesInit(
///< ::zes_init_flags_t values.
)
{
#ifdef L0_STATIC_LOADER_BUILD
#if defined(L0_STATIC_LOADER_BUILD) || defined(L0_STATIC_LOADER_BUILD_NO_DLL)
if (!ze_lib::context) {
ze_lib::context = new ze_lib::context_t;
}
Expand Down
2 changes: 1 addition & 1 deletion source/loader/windows/loader_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ namespace loader
return TRUE;
}
#endif
}
}
28 changes: 28 additions & 0 deletions source/loader/ze_loader_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,28 @@
#include "ze_loader_internal.h"
#include "../lib/ze_lib.h"

#ifdef L0_STATIC_LOADER_BUILD_NO_DLL
#include <cstdlib>
#include <mutex>

namespace {
void destroyEmbeddedLoaderContext() {
delete loader::context;
loader::context = nullptr;
}

void ensureEmbeddedLoaderContext() {
static std::once_flag contextOnce;
std::call_once(contextOnce, []() {
if (loader::context == nullptr) {
loader::context = new loader::context_t;
}
std::atexit(destroyEmbeddedLoaderContext);
});
}
} // namespace
#endif

#if defined(__cplusplus)
extern "C" {
#endif
Expand All @@ -24,6 +46,9 @@ extern "C" {
ZE_DLLEXPORT ze_result_t ZE_APICALL
zeLoaderInit()
{
#ifdef L0_STATIC_LOADER_BUILD_NO_DLL
ensureEmbeddedLoaderContext();
#endif
return loader::context->init();
}

Expand Down Expand Up @@ -109,6 +134,9 @@ zelLoaderGetVersionsInternal(
size_t *num_elems, //Pointer to num versions to get.
zel_component_version_t *versions) //Pointer to array of versions. If set to NULL, num_elems is returned
{
#ifdef L0_STATIC_LOADER_BUILD_NO_DLL
ensureEmbeddedLoaderContext();
#endif
if(nullptr == versions){
*num_elems = loader::context->compVersions.size();
return ZE_RESULT_SUCCESS;
Expand Down
12 changes: 9 additions & 3 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ endif()

# For static builds, we need to include the loader source files directly
# since they are not built into the library when BUILD_STATIC=1
if(BUILD_STATIC)
if(BUILD_STATIC AND NOT BUILD_STATIC_NO_DLL)
target_sources(tests PRIVATE
${PROJECT_SOURCE_DIR}/source/loader/ze_loader.cpp
${PROJECT_SOURCE_DIR}/source/loader/ze_loader_api.cpp
Expand Down Expand Up @@ -61,12 +61,18 @@ if(BUILD_STATIC)
)
endif()

# Add the same definitions as the source CMakeLists.txt
endif()

if(BUILD_STATIC)
target_compile_definitions(tests PRIVATE
L0_LOADER_VERSION="${PROJECT_VERSION_MAJOR}"
L0_VALIDATION_LAYER_SUPPORTED_VERSION="${PROJECT_VERSION_MAJOR}"
L0_STATIC_LOADER_BUILD="1"
)
if(BUILD_STATIC_NO_DLL)
target_compile_definitions(tests PRIVATE L0_STATIC_LOADER_BUILD_NO_DLL="1")
else()
target_compile_definitions(tests PRIVATE L0_STATIC_LOADER_BUILD="1")
endif()
endif()

target_include_directories(tests PRIVATE ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/source/inc)
Expand Down
Loading