-
Notifications
You must be signed in to change notification settings - Fork 13
Description
I just learned about your project yesterday, but I ran into problems compiling it in Windows.
Ultimately, the project compiled successfully.
I hope this solution is useful.
Description:
Currently, the project fails to compile on Windows when trying to build a portable version with dynamic backend loading (-DGGML_BACKEND_DL=1). There are two main issues:
CMake Error: target_link_libraries fails because it tries to link MODULE_LIBRARY targets (like ggml-cuda) directly.
Linker Error (LNK2019): ggml_backend_cpu_set_n_threads is not exported by ggml.dll in DL mode, causing unresolved external symbols.
Proposed Fixes:
- CMakeLists.txt modification:
Update the link_ggml_backends macro to check the target type before linking. Only link if it's not a MODULE_LIBRARY:
# Shared compile options and ggml linkage
macro(link_ggml_backends target)
target_include_directories(${target} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_include_directories(${target} SYSTEM PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/ggml/include
)
if(MSVC)
target_compile_options(${target} PRIVATE /W4 /wd4100 /wd4505)
else()
target_compile_options(${target} PRIVATE -Wall -Wextra -Wshadow -Wconversion
-Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion)
endif()
target_link_libraries(${target} PRIVATE ggml)
if(TARGET ggml-base)
target_link_libraries(${target} PRIVATE ggml-base)
endif()
foreach(backend blas cuda metal vulkan)
if(TARGET ggml-${backend})
get_target_property(CURRENT_BACKEND_TYPE ggml-${backend} TYPE)
if (NOT CURRENT_BACKEND_TYPE STREQUAL "MODULE_LIBRARY")
target_link_libraries(${target} PRIVATE ggml-${backend})
endif()
string(TOUPPER ${backend} BACKEND_UPPER)
target_compile_definitions(${target} PRIVATE ACESTEP_HAVE_${BACKEND_UPPER})
if(backend STREQUAL "cuda")
find_package(CUDAToolkit QUIET)
if(CUDAToolkit_FOUND)
target_link_libraries(${target} PRIVATE CUDA::cudart)
endif()
endif()
endif()
endforeach()
endmacro()- backend.h modification:
To support CPU thread management in DL mode without linking errors, replace direct ggml_backend_cpu_set_n_threads calls with the Registry/Device API:
// Remove #include "ggml-cpu.h"
// Use this inside backend_init:
int n_threads = (int)std::thread::hardware_concurrency() / 2;
if (n_threads < 1) n_threads = 1;
// [GGML] If best backend is already CPU, reuse it (avoid 2 CPU instances
// where only one gets the thread count)
char params[64];
snprintf(params, sizeof(params), "n_threads=%d", n_threads);
bool best_is_cpu = (strcmp(ggml_backend_name(bp.backend), "CPU") == 0);
if (best_is_cpu) {
bp.cpu_backend = bp.backend;
} else {
ggml_backend_dev_t cpu_dev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU);
if (cpu_dev) {
bp.cpu_backend = ggml_backend_dev_init(cpu_dev, params);
}
if (!bp.cpu_backend) {
bp.cpu_backend = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, NULL);
}
if (!bp.cpu_backend) {
fprintf(stderr, "[Load] FATAL: failed to init CPU backend\n");
exit(1);
}
}This approach allows distributing a single set of binaries that dynamically load CUDA, Vulkan, or specific CPU variants (AVX2/AVX512) on the user's machine.
Note: These changes were developed using Gemini and verified through extensive local testing on Windows (MSVC 19.44, CUDA 12.4). The resulting binaries are fully portable and correctly initialize the CUDA/Vulkan/CPU backends at runtime.