Skip to content
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
45 changes: 45 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ option(GGML_XTHEADVECTOR "ggml: enable xtheadvector" OFF)
option(GGML_VXE "ggml: enable vxe" ${GGML_NATIVE})

option(GGML_CPU_ALL_VARIANTS "ggml: build all variants of the CPU backend (requires GGML_BACKEND_DL)" OFF)
option(GGML_CPU_STATIC "ggml: build CPU backend as static library even with GGML_BACKEND_DL" OFF)
set(GGML_CPU_ARM_ARCH "" CACHE STRING "ggml: CPU architecture for ARM")
set(GGML_CPU_POWERPC_CPUTYPE "" CACHE STRING "ggml: CPU type for PowerPC")

Expand All @@ -186,6 +187,14 @@ set(GGML_SCHED_MAX_COPIES "4" CACHE STRING "ggml: max input copies for pipeline
option(GGML_CPU "ggml: enable CPU backend" ON)
option(GGML_SCHED_NO_REALLOC "ggml: disallow reallocations in ggml-alloc (for debugging)" OFF)

# When non-empty, ggml libs land on disk as `lib<prefix>ggml-*.{a,so,dll}` and the
# runtime backend loader looks for the same prefix. CMake target names and the
# `find_package(ggml CONFIG)` package name are unchanged. Defaults to
# `qvac-speech-` on the speech branch to match the loader's compiled-in default
# in `ggml-backend-reg.cpp`.
set(GGML_LIB_OUTPUT_PREFIX "qvac-speech-" CACHE STRING
"ggml: prefix for built ggml library filenames")

# 3rd party libs / backends
option(GGML_ACCELERATE "ggml: enable Accelerate framework" ON)
option(GGML_BLAS "ggml: use BLAS" ${GGML_BLAS_DEFAULT})
Expand Down Expand Up @@ -294,6 +303,41 @@ include(GNUInstallDirs)

add_subdirectory(src)

if (NOT GGML_LIB_OUTPUT_PREFIX STREQUAL "")
function(_ggml_apply_lib_output_prefix target)
if (NOT TARGET ${target})
return()
endif()
get_target_property(_lop_type ${target} TYPE)
if (_lop_type STREQUAL "INTERFACE_LIBRARY" OR
_lop_type STREQUAL "OBJECT_LIBRARY")
return()
endif()
get_target_property(_lop_old ${target} OUTPUT_NAME)
if (NOT _lop_old OR _lop_old STREQUAL "_lop_old-NOTFOUND")
set(_lop_old ${target})
endif()
set_target_properties(${target} PROPERTIES
OUTPUT_NAME "${GGML_LIB_OUTPUT_PREFIX}${_lop_old}")
endfunction()

foreach (_lop_target ggml ggml-base)
_ggml_apply_lib_output_prefix(${_lop_target})
endforeach()
if (DEFINED GGML_AVAILABLE_BACKENDS)
foreach (_lop_target ${GGML_AVAILABLE_BACKENDS})
_ggml_apply_lib_output_prefix(${_lop_target})
endforeach()
endif()

if (TARGET ggml-base)
target_compile_definitions(ggml-base PRIVATE
GGML_BACKEND_DL_PROJECT_PREFIX="${GGML_LIB_OUTPUT_PREFIX}")
endif()

message(STATUS "ggml: lib output prefix '${GGML_LIB_OUTPUT_PREFIX}'")
endif()

#
# tests and examples
#
Expand Down Expand Up @@ -324,6 +368,7 @@ set(GGML_PUBLIC_HEADERS
include/ggml-cpp.h
include/ggml-cuda.h
include/ggml-opt.h
include/ggml-opencl.h
include/ggml-metal.h
include/ggml-rpc.h
include/ggml-virtgpu.h
Expand Down
24 changes: 19 additions & 5 deletions cmake/ggml-config.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -104,33 +104,47 @@ set_and_check(GGML_LIB_DIR "@PACKAGE_GGML_LIB_INSTALL_DIR@")
if(NOT TARGET ggml::ggml)
find_package(Threads REQUIRED)

find_library(GGML_LIBRARY ggml
find_library(GGML_LIBRARY NAMES "${GGML_LIB_OUTPUT_PREFIX}ggml" ggml
REQUIRED
HINTS ${GGML_LIB_DIR}
NO_CMAKE_FIND_ROOT_PATH)

add_library(ggml::ggml UNKNOWN IMPORTED)
set_target_properties(ggml::ggml
PROPERTIES
IMPORTED_LOCATION "${GGML_LIBRARY}")
IMPORTED_LOCATION "${GGML_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${GGML_INCLUDE_DIR}")

find_library(GGML_BASE_LIBRARY ggml-base
find_library(GGML_BASE_LIBRARY NAMES "${GGML_LIB_OUTPUT_PREFIX}ggml-base" ggml-base
REQUIRED
HINTS ${GGML_LIB_DIR}
NO_CMAKE_FIND_ROOT_PATH)

add_library(ggml::ggml-base UNKNOWN IMPORTED)
set_property(TARGET ggml::ggml-base PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${GGML_INCLUDE_DIR}")
set_target_properties(ggml::ggml-base
PROPERTIES
IMPORTED_LOCATION "${GGML_BASE_LIBRARY}")

if(GGML_MAX_NAME)
set_property(TARGET ggml::ggml-base APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS "GGML_MAX_NAME=${GGML_MAX_NAME}")
endif()

set(_ggml_all_targets "")
if (NOT GGML_BACKEND_DL)
# In hybrid mode (GGML_BACKEND_DL + GGML_CPU_STATIC), only the CPU backend
# is static and must still be exported to downstream consumers.
if (NOT GGML_BACKEND_DL OR GGML_CPU_STATIC)
foreach(_ggml_backend ${GGML_AVAILABLE_BACKENDS})
string(REGEX MATCH "^ggml-cpu" is_cpu_variant "${_ggml_backend}")
if (GGML_BACKEND_DL AND GGML_CPU_STATIC AND NOT is_cpu_variant)
continue()
endif()
string(REPLACE "-" "_" _ggml_backend_pfx "${_ggml_backend}")
string(TOUPPER "${_ggml_backend_pfx}" _ggml_backend_pfx)

find_library(${_ggml_backend_pfx}_LIBRARY ${_ggml_backend}
find_library(${_ggml_backend_pfx}_LIBRARY
NAMES "${GGML_LIB_OUTPUT_PREFIX}${_ggml_backend}" "${_ggml_backend}"
REQUIRED
HINTS ${GGML_LIB_DIR}
NO_CMAKE_FIND_ROOT_PATH)
Expand Down
22 changes: 16 additions & 6 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,10 @@ endif()

# ggml

if (GGML_BACKEND_DL AND NOT BUILD_SHARED_LIBS)
message(FATAL_ERROR "GGML_BACKEND_DL requires BUILD_SHARED_LIBS")
# GGML_BACKEND_DL works with static core when PIC is enabled below.

if (GGML_CPU_STATIC AND GGML_CPU_ALL_VARIANTS)
message(FATAL_ERROR "GGML_CPU_STATIC is incompatible with GGML_CPU_ALL_VARIANTS")
endif()

add_library(ggml-base
Expand Down Expand Up @@ -221,6 +223,10 @@ if (GGML_SCHED_NO_REALLOC)
target_compile_definitions(ggml-base PUBLIC GGML_SCHED_NO_REALLOC)
endif()

if (DEFINED GGML_MAX_NAME)
target_compile_definitions(ggml-base PUBLIC GGML_MAX_NAME=${GGML_MAX_NAME})
endif()

add_library(ggml
ggml-backend-dl.cpp
ggml-backend-reg.cpp)
Expand All @@ -245,10 +251,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
endif()

function(ggml_add_backend_library backend)
if (GGML_BACKEND_DL)
if (GGML_BACKEND_DL AND NOT (GGML_CPU_STATIC AND ${backend} MATCHES "^ggml-cpu"))
add_library(${backend} MODULE ${ARGN})
# write the shared library to the output directory
set_target_properties(${backend} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
set_target_properties(${backend} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
target_compile_definitions(${backend} PRIVATE GGML_BACKEND_DL)
add_dependencies(ggml ${backend})
if (GGML_BACKEND_DIR)
Expand All @@ -265,7 +272,7 @@ function(ggml_add_backend_library backend)
target_link_libraries(${backend} PRIVATE ggml-base)
target_include_directories(${backend} PRIVATE ..)

if (${BUILD_SHARED_LIBS})
if (BUILD_SHARED_LIBS OR GGML_BACKEND_DL)
target_compile_definitions(${backend} PRIVATE GGML_BACKEND_BUILD)
target_compile_definitions(${backend} PUBLIC GGML_BACKEND_SHARED)
endif()
Expand Down Expand Up @@ -301,6 +308,9 @@ function(ggml_add_backend backend)
string(TOUPPER "GGML_USE_${backend}" backend_use)
target_compile_definitions(ggml PUBLIC ${backend_use})
endif()
if (GGML_CPU_STATIC AND "${backend}" STREQUAL "CPU")
target_compile_definitions(ggml PUBLIC GGML_USE_CPU)
endif()
endif()
endfunction()

Expand Down Expand Up @@ -484,7 +494,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "visionOS")
target_compile_definitions(ggml-base PUBLIC _DARWIN_C_SOURCE)
endif()

if (BUILD_SHARED_LIBS)
if (BUILD_SHARED_LIBS OR GGML_BACKEND_DL)
foreach (target ggml-base ggml)
set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_compile_definitions(${target} PRIVATE GGML_BUILD)
Expand Down
11 changes: 9 additions & 2 deletions src/ggml-backend-reg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,9 @@ static fs::path backend_filename_prefix() {
#endif
#else
#ifdef _WIN32
return fs::u8path("ggml-");
return fs::u8path("qvac-speech-ggml-");
#else
return fs::u8path("libggml-");
return fs::u8path("libqvac-speech-ggml-");
#endif
#endif
}
Expand Down Expand Up @@ -553,6 +553,13 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent,
}
}
}
// Android app packaging can flatten native libraries into one directory.
// If loading from the requested subdirectory fails, retry by filename only
// and leave lookup to dlopen's default search path resolution.
fs::path filename = backend_filename_prefix().native() + name_path.native() + backend_filename_extension().native();
if (auto reg = get_reg().load_backend(filename, silent)) {
return reg;
}
return nullptr;
}

Expand Down
15 changes: 5 additions & 10 deletions src/ggml-opencl/ggml-opencl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4353,15 +4353,6 @@ static ggml_backend_i ggml_backend_opencl_i = {
};

ggml_backend_t ggml_backend_opencl_init(void) {
// qvac-parakeet patch: bail out cleanly when the OpenCL backend
// discovery saw zero usable devices. Upstream calls
// ggml_backend_reg_dev_get() unconditionally, which asserts on an
// empty device list. Parakeet's host code expects a nullable result
// from ggml_backend_opencl_init() (it falls back to CPU when the
// returned backend is null); the assertion makes that fallback path
// unreachable on hosts where ggml-opencl can't find any GPU it
// accepts (Adreno-only environments without an Adreno device,
// headless CI runners, etc.).
ggml_backend_reg_t reg = ggml_backend_opencl_reg();
if (ggml_backend_reg_dev_count(reg) == 0) {
return nullptr;
Expand Down Expand Up @@ -6272,7 +6263,11 @@ static size_t ggml_backend_opencl_reg_device_count(ggml_backend_reg_t reg) {
}

static ggml_backend_dev_t ggml_backend_opencl_reg_device_get(ggml_backend_reg_t reg, size_t index) {
GGML_ASSERT(index < ggml_backend_opencl_reg_device_count(reg));
size_t n = ggml_backend_opencl_reg_device_count(reg);
if (n == 0) {
return nullptr;
}
GGML_ASSERT(index < n);

return &g_ggml_backend_opencl_devices[index];

Expand Down
Loading