From: Przemysław Pawełczyk Date: Fri, 29 Mar 2024 13:53:26 +0000 (+0100) Subject: build : use pkg-config for OpenBLAS (#1778) X-Git-Tag: upstream/1.7.4~869 X-Git-Url: https://git.djapps.eu/?a=commitdiff_plain;h=1e8f28c42a1472ae7c49d0502ea06e2f5bc29a69;p=pkg%2Fggml%2Fsources%2Fwhisper.cpp build : use pkg-config for OpenBLAS (#1778) * make : use pkg-config for finding CFLAGS & LDFLAGS needed by OpenBLAS That way building on *nix like environments (including MSYS2 on Windows) with WHISPER_OPENBLAS=1 works out of the box. Fix handling of WHISPER_OPENBLAS, so that empty value or 0 won't be misinterpreted by make as enabled. Mind that it's not intended to detect CMake false constants (OFF NO FALSE N). make is not CMake. By default OpenBLAS with 64-bit interface is used, but that can be changed with `WHISPER_OPENBLAS_INTERFACE64=0` if 32-bit one is desired. If OpenBLAS headers and library are respectively in include/ and lib/ subdirectories of given path, then you can specify it, e.g. `OPENBLAS_PATH=/usr/local/openblas`, and this will take precedence over any pkg-config file. If there is no pkg-config file (.pc) for OpenBLAS and OPENBLAS_PATH is empty, then headers are assumed to be in /usr/include/openblas and library as assumed to be called 'openblas64' (or 'openblas' if `WHISPER_OPENBLAS_INTERFACE64=0`). If different headers location should be used, then it can be done, e.g. `WHISPER_BLAS_CFLAGS=-I/usr/local/include/openblas`. If different library should be used, it can be specified, e.g. `WHISPER_BLAS_LIB=openblasp64` (pthreads version as seen on Fedora), or you can provide LDFLAGS needed to link with OpenBLAS directly: `WHISPER_BLAS_LDFLAGS="-L/usr/local/lib/openblas -lopenblas64"`. Current solution is flexible enough to handle most cases out there without needlessly hardcoding possible OpenBLAS installation details. * cmake : fix how pkg-config is used for finding include dirs and libraries needed by OpenBLAS That way building on *nix like environments (including MSYS2 on Windows) with -DWHISPER_OPENBLAS=ON should work out of the box as long as you have CMake 3.25 or newer. Make OPENBLAS_PATH environment variable supported not only on Windows. It sets OpenBLAS include dir to ${OPENBLAS_PATH}/include and library to ${WHISPER_BLAS_LIB} (name without prefixes and suffixes) in ${OPENBLAS_PATH}/lib and avoids further package finding. By default OpenBLAS with 64-bit interface is used (equivalent to setting `-DWHISPER_BLAS_LIB=openblas64`), but that can be changed with `-DWHISPER_OPENBLAS_INTERFACE64=OFF` (equivalent to setting `-DWHISPER_BLAS_LIB=openblas`) if 32-bit one is desired. Turn on BLA_STATIC for FindBLAS only when WHISPER_STATIC is enabled. BLA_STATIC may not work as expected for pkg-config based operation. Get rid of supporting BLAS_HOME environment variable. If OPENBLAS_PATH is insufficient in your case, there is no pkg-config file to rely on, then you can manually specify include dir, e.g. `-DBLAS_INCLUDE_DIRS=/usr/local/include/openblas`, and library, e.g. `-DBLAS_LIBRARIES=/usr/local/lib/libopenblas.so`. * make / cmake : use OpenBLAS with 32-bit interface by default. OpenBLAS w/o INTERFACE64=1 vel USE_64BITINT=1 seems to be more common. * cmake : hardcode "lib" prefix for OpenBLAS lib filename (even on Windows) * cmake : hardcode OpenBLAS library name when building in MSVC (Windows) Most *nix like environments (including MSYS2 on Windows) have OpenBLAS packages that allow coexistence of OpenBLAS builds with 32-bit and 64-bit interface (w/o and w/ OPENBLAS_USE64BITINT defined) and they differ by not having or having "64" suffix in their library filenames. That's not the case for OpenBLAS prebuilt libraries for Windows. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 8aff0f83..c7562025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ else() option(WHISPER_BLAS "whisper: use BLAS libraries" OFF) option(WHISPER_BLAS_VENDOR "whisper: BLAS library vendor" Generic) option(WHISPER_OPENBLAS "whisper: prefer OpenBLAS" OFF) + option(WHISPER_OPENBLAS_INTERFACE64 "whisper: use OpenBLAS w/ 64-bit interface" OFF) option(WHISPER_CUDA "whisper: support for CUDA" OFF) option(WHISPER_CUBLAS "whisper: support for CUDA (deprecated)" OFF) option(WHISPER_HIPBLAS "whisper: support for hipBLAS" OFF) @@ -207,30 +208,82 @@ endif() if (WHISPER_OPENBLAS) set(WHISPER_BLAS_VENDOR "OpenBLAS") set(WHISPER_BLAS ON) + # BLA_PKGCONFIG_BLAS is supported since CMake 3.25. + # FindBLAS.cmake pkg-config logic seems incomplete, because when + # BLA_SIZEOF_INTEGER is 8, then it should search for blas64 instead of blas. + # blas.pc/blas64.pc are not always provided, so let's be more specific + # and go with openblas.pc/openblas64.pc if WHISPER_OPENBLAS is on. + if (WHISPER_OPENBLAS_INTERFACE64) + set(WHISPER_BLAS_LIB "openblas64") + else () + set(WHISPER_BLAS_LIB "openblas") + endif () + set(BLA_PKGCONFIG_BLAS ${WHISPER_BLAS_LIB}) + # OpenBLAS prebuilt libraries for Windows do not have "64" suffix in filename. + # (But .pc file has "64" suffix in filename for USE_64BITINT=1 Windows build.) + if (MSVC) + set(WHISPER_BLAS_LIB "openblas") + endif () endif() if (WHISPER_BLAS) - if (WIN32) - if(DEFINED ENV{OPENBLAS_PATH}) - set(BLAS_LIBRARIES $ENV{OPENBLAS_PATH}/lib/libopenblas.dll.a) - message(STATUS "Libraries ${BLAS_LIBRARIES}") - set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_USE_OPENBLAS) - include_directories($ENV{OPENBLAS_PATH}/include) - set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} ${BLAS_LIBRARIES}) + if (NOT "$ENV{OPENBLAS_PATH}" STREQUAL "") + if (WHISPER_STATIC) + set(WHISPER_BLAS_LIB_PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX}) + set(WHISPER_BLAS_LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX}) else () - message(FATAL_ERROR "BLAS library was not found. Environment variable OPENBLAS_PATH not defined.") + if (CMAKE_IMPORT_LIBRARY_SUFFIX) + set(WHISPER_BLAS_LIB_PREFIX ${CMAKE_IMPORT_LIBRARY_PREFIX}) + set(WHISPER_BLAS_LIB_SUFFIX ${CMAKE_IMPORT_LIBRARY_SUFFIX}) + else () + set(WHISPER_BLAS_LIB_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) + set(WHISPER_BLAS_LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + endif () + endif () + # OpenBLAS prebuilt libraries hardcode "lib" prefix in filename even on Windows + if (WHISPER_OPENBLAS) + set(WHISPER_BLAS_LIB_PREFIX "lib") endif () + message(STATUS "BLAS compatible library path provided") + set(BLAS_LIBRARIES "$ENV{OPENBLAS_PATH}/lib/${WHISPER_BLAS_LIB_PREFIX}${WHISPER_BLAS_LIB}${WHISPER_BLAS_LIB_SUFFIX}") + message(STATUS "Libraries ${BLAS_LIBRARIES}") + set(BLAS_INCLUDE_DIRS "$ENV{OPENBLAS_PATH}/include") + message(STATUS "Include dirs ${BLAS_INCLUDE_DIRS}") + if (NOT EXISTS "${BLAS_LIBRARIES}") + message(FATAL_ERROR "BLAS library was not found. Environment variable OPENBLAS_PATH misdefined.") + endif () + set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_USE_OPENBLAS) + include_directories(${BLAS_INCLUDE_DIRS}) + set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} ${BLAS_LIBRARIES}) else () - set(BLA_STATIC 1) + if (WHISPER_STATIC) + # FindBLAS.cmake pkg-config logic seems incomplete, because when + # BLA_STATIC is on, then it should use pkg_check_modules_static + # instead of pkg_check_modules. + # Some manual variable overriding may be necessary if you don't + # achieve desired results. + set(BLA_STATIC 1) + endif () set(BLA_VENDOR ${WHISPER_BLAS_VENDOR}) - set(BLA_SIZEOF_INTEGER 8) + if (WHISPER_OPENBLAS_INTERFACE64) + set(BLA_SIZEOF_INTEGER 8) + else () + set(BLA_SIZEOF_INTEGER 4) + endif() set(BLA_PREFER_PKGCONFIG 1) find_package(BLAS) if(BLAS_FOUND) message(STATUS "BLAS compatible library found") message(STATUS "Libraries ${BLAS_LIBRARIES}") - find_path(BLAS_INCLUDE_DIRS cblas.h /usr/include/openblas /usr/local/include/openblas $ENV{BLAS_HOME}/include) + if (NOT DEFINED BLAS_INCLUDE_DIRS) + if (PKGC_BLAS_FOUND) + set(BLAS_INCLUDE_DIRS "${PKGC_BLAS_INCLUDE_DIRS}") + else () + find_path(BLAS_INCLUDE_DIRS cblas.h /usr/include/openblas) + endif() + endif() + message(STATUS "Include dirs ${BLAS_INCLUDE_DIRS}") set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_USE_OPENBLAS) include_directories(${BLAS_INCLUDE_DIRS}) set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} ${BLAS_LIBRARIES}) diff --git a/Makefile b/Makefile index 4cf76c6a..e255c521 100644 --- a/Makefile +++ b/Makefile @@ -210,9 +210,28 @@ ifndef WHISPER_NO_METAL endif endif -ifdef WHISPER_OPENBLAS - CFLAGS += -DGGML_USE_OPENBLAS -I/usr/local/include/openblas -I/usr/include/openblas - LDFLAGS += -lopenblas +ifneq ($(filter-out 0,$(WHISPER_OPENBLAS)),) # OpenBLAS + WHISPER_OPENBLAS_INTERFACE64 ?= 0 # use 32-bit interface by default + ifneq ($(filter-out 0,$(WHISPER_OPENBLAS_INTERFACE64)),) + WHISPER_BLAS_LIB := openblas64 + else + WHISPER_BLAS_LIB := openblas + endif + ifneq ($(OPENBLAS_PATH),) + WHISPER_BLAS_CFLAGS := -I$(OPENBLAS_PATH)/include + WHISPER_BLAS_LDFLAGS := -L$(OPENBLAS_PATH)/lib -l$(WHISPER_BLAS_LIB) + else + WHISPER_BLAS_LIB_PC_EXISTS := $(shell pkg-config --exists $(WHISPER_BLAS_LIB) && echo 1) + ifneq ($(filter-out 0,$(WHISPER_BLAS_LIB_PC_EXISTS)),) + WHISPER_BLAS_CFLAGS := $(shell pkg-config --cflags $(WHISPER_BLAS_LIB)) + WHISPER_BLAS_LDFLAGS := $(shell pkg-config --libs $(WHISPER_BLAS_LIB)) + else + WHISPER_BLAS_CFLAGS := -I/usr/include/openblas + WHISPER_BLAS_LDFLAGS := -l$(WHISPER_BLAS_LIB) + endif + endif + CFLAGS += $(WHISPER_BLAS_CFLAGS) -DGGML_USE_OPENBLAS + LDFLAGS += $(WHISPER_BLAS_LDFLAGS) endif ifdef WHISPER_CUBLAS