webassembly003 whisper.cpp的项目结构CMakeLists.txt

注:带星号的为非重要部分

基础配置

csharp 复制代码
cmake_minimum_required (VERSION 3.5)

project(whisper.cpp VERSION 1.5.0)

# Add path to modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
# 在\cmake文件夹下还有BuildTypes.cmake,DefaultTargetOptions.cmake,GitVars.cmake几个文件
# CMAKE_MODULE_PATH是供搜索第三方库用的路径变量,因此可在项目中引用自定义模块:
#include(BuildTypes) 在第13行
#include(DefaultTargetOptions) 在第425和478行,为指定的目标设置一些默认的编译特性和属性,以确保项目在编译和安装时的一致性和可靠性。
#include(GitVars) 在第12行
cmake 复制代码
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # 设置CMAKE_CURRENT_SOURCE_DIR变量,应该是可执行文件的输出目录

# 如果当前的源目录等于根源目录
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    set(WHISPER_STANDALONE ON)  # 标志 WHISPER_STANDALONE 设置为 ON
    include(GitVars)  # 引用 GitVars 模块
    include(BuildTypes)  # 引用 BuildTypes 模块

    # 配置封装到其他语言的项目版本相关,详见Note1
    if (EXISTS "${CMAKE_SOURCE_DIR}/bindings/ios/Makefile-tmpl")
        configure_file(${CMAKE_SOURCE_DIR}/bindings/ios/Makefile-tmpl ${CMAKE_SOURCE_DIR}/bindings/ios/Makefile @ONLY)
    endif()
    configure_file(${CMAKE_SOURCE_DIR}/bindings/javascript/package-tmpl.json ${CMAKE_SOURCE_DIR}/bindings/javascript/package.json @ONLY)
    
else() # 如果当前源目录不是根源目录
    set(WHISPER_STANDALONE OFF) # 则将 WHISPER_STANDALONE 标志设置为 OFF
endif()

DefaultTargetOptions

csharp 复制代码
# Set the default compile features and properties for a target.

if (NOT TARGET)
    message(FATAL_ERROR "TARGET not set before including DefaultTargetOptions")
endif()

target_compile_features(${TARGET}
    PRIVATE
        cxx_std_11
    )

set_target_properties(${TARGET}
    PROPERTIES
        EXPORT_COMPILE_COMMANDS ON
        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
        INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
)

GIT*

csharp 复制代码
find_package(Git)

# the commit's SHA1
execute_process(COMMAND
    "${GIT_EXECUTABLE}" describe --match=NeVeRmAtCh --always --abbrev=8
    WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
    OUTPUT_VARIABLE GIT_SHA1
    ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)

# the date of the commit
execute_process(COMMAND
    "${GIT_EXECUTABLE}" log -1 --format=%ad --date=local
    WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
    OUTPUT_VARIABLE GIT_DATE
    ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)

# the subject of the commit
execute_process(COMMAND
    "${GIT_EXECUTABLE}" log -1 --format=%s
    WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
    OUTPUT_VARIABLE GIT_COMMIT_SUBJECT
    ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)

BuildTypes*

csharp 复制代码
# Add new build types

# ReleaseGG - Release with enabled asserts

SET(CMAKE_CXX_FLAGS_RELEASEGG
    "-O3"
    CACHE STRING "Flags used by the c++ compiler during release builds with enabled asserts."
    FORCE )
SET(CMAKE_C_FLAGS_RELEASEGG
    "-O3"
    CACHE STRING "Flags used by the compiler during release builds with enabled asserts."
    FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_RELEASEGG
    ""
    CACHE STRING "Flags used for linking binaries during release builds with enabled asserts."
    FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEGG
    ""
    CACHE STRING "Flags used by the shared libraries linker during release builds with enabled asserts."
    FORCE )
MARK_AS_ADVANCED(
    CMAKE_CXX_FLAGS_RELEASEGG
    CMAKE_C_FLAGS_RELEASEGG
    CMAKE_EXE_LINKER_FLAGS_RELEASEGG
    CMAKE_SHARED_LINKER_FLAGS_RELEASEGG )

# RelWithDebInfoGG - RelWithDebInfo with enabled asserts

SET(CMAKE_CXX_FLAGS_RELWITHDEBINFOGG
    "-O2 -g"
    CACHE STRING "Flags used by the c++ compiler during release builds with debug symbols and enabled asserts."
    FORCE )
SET(CMAKE_C_FLAGS_RELWITHDEBINFOGG
    "-O2 -g"
    CACHE STRING "Flags used by the compiler during release builds with debug symbols and enabled asserts."
    FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFOGG
    ""
    CACHE STRING "Flags used for linking binaries during release builds with debug symbols and enabled asserts."
    FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFOGG
    ""
    CACHE STRING "Flags used by the shared libraries linker during release builds with debug symbols and enabled asserts."
    FORCE )
MARK_AS_ADVANCED(
    CMAKE_CXX_FLAGS_RELWITHDEBINFOGG
    CMAKE_C_FLAGS_RELWITHDEBINFOGG
    CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFOGG
    CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFOGG )

if (NOT XCODE AND NOT MSVC AND NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo" "ReleaseGG" "RelWithDebInfoGG")
endif()

WASM配置*

csharp 复制代码
# 检查是否使用 Emscripten 工具链进行交叉编译
if (EMSCRIPTEN)
    # 如果是 Emscripten,设置默认值为不构建共享库
    set(BUILD_SHARED_LIBS_DEFAULT OFF)

    # 添加选项,用于指定是否将 WASM 嵌入到生成的 whisper.js 文件中
    option(WHISPER_WASM_SINGLE_FILE "whisper: embed WASM inside the generated whisper.js" ON)
else()
    # 如果不是 Emscripten,进一步检查是否使用 MinGW 工具链
    if (MINGW)
        # 如果是 MinGW,设置默认值为不构建共享库
        set(BUILD_SHARED_LIBS_DEFAULT OFF)
    else()
        # 如果不是 Emscripten 且不是 MinGW,设置默认值为构建共享库
        set(BUILD_SHARED_LIBS_DEFAULT ON)
    endif()
endif()

options编译选项

cmake 复制代码
# 如果目标平台是苹果 (Apple)
if (APPLE)
    set(WHISPER_METAL_DEFAULT ON)  # 设置 WHISPER_METAL_DEFAULT 为 ON,Metal是苹果发布的一套操作GPU的编程API
else()
    set(WHISPER_METAL_DEFAULT OFF)# 否则设置 WHISPER_METAL_DEFAULT 为 OFF
endif()

# 定义构建共享库的选项,并设置默认值为 BUILD_SHARED_LIBS_DEFAULT
option(BUILD_SHARED_LIBS              "whisper: build shared libs" ${BUILD_SHARED_LIBS_DEFAULT})

# 编译器选项
# 编译器警告的选项
option(WHISPER_ALL_WARNINGS           "whisper: enable all compiler warnings"                   ON)# 定义启用所有编译器警告的选项
option(WHISPER_ALL_WARNINGS_3RD_PARTY "whisper: enable all compiler warnings in 3rd party libs" OFF)# 定义启用所有第三方库中编译器警告的选项
# 编译器自带的调试工具sanitizers选项:
option(WHISPER_SANITIZE_THREAD        "whisper: enable thread sanitizer"    OFF)# 定义启用线程 Sanitizer 的选项
option(WHISPER_SANITIZE_ADDRESS       "whisper: enable address sanitizer"   OFF)# 定义启用地址 Sanitizer 的选项 ASan 是一种结合编译器插桩和运行时的一种快速内存检测工具,主要用于检测代码中的部分 内存安全 问题
option(WHISPER_SANITIZE_UNDEFINED     "whisper: enable undefined sanitizer" OFF)# 定义启用未定义行为 Sanitizer 的选项

# 是否构建示例和测试
option(WHISPER_BUILD_TESTS            "whisper: build tests"    ${WHISPER_STANDALONE})# 定义构建测试的选项
option(WHISPER_BUILD_EXAMPLES         "whisper: build examples" ${WHISPER_STANDALONE})# 定义构建示例的选项

# 定义支持 libSDL2 的选项,Simple DirectMedia Layer是一个跨平台开发库,旨在通过OpenGL和Direct3D提供对音频、键盘、鼠标、操纵杆和图形硬件的低级别访问。https://github.com/libsdl-org/SDL
option(WHISPER_SDL2                   "whisper: support for libSDL2" OFF)

# 定义禁用 AVX 指令集的选项
option(WHISPER_NO_AVX                 "whisper: disable AVX"  OFF)
# 定义禁用 AVX2 指令集的选项
option(WHISPER_NO_AVX2                "whisper: disable AVX2" OFF)
# 定义禁用 FMA 指令集的选项, FMA指令集是128位元和256位元的流式單指令流多資料流擴充集( SSE )指令集
option(WHISPER_NO_FMA                 "whisper: disable FMA"  OFF)
# 定义禁用 F16c 指令集的选项,F16C指令就是AMD的CVT16指令,Intel换了一个名称,随后AMD也接收了这一称呼。Intel 首次在 2012 年的 Ivy Bridge 微架构处理器上使用。
option(WHISPER_NO_F16C                "whisper: disable F16c" OFF)

# 定义支持 OpenVINO 的选项
option(WHISPER_OPENVINO               "whisper: support for OpenVINO" OFF)

# 如果目标平台是苹果 (Apple)
if (APPLE)
    # 定义禁用 Accelerate framework 的选项
    option(WHISPER_NO_ACCELERATE         "whisper: disable Accelerate framework" OFF)

    # 定义使用 Metal 的选项,并设置默认值为 WHISPER_METAL_DEFAULT
    option(WHISPER_METAL                 "whisper: use Metal"                    ${WHISPER_METAL_DEFAULT})

    # 定义禁用 Metal 调试的选项
    option(WHISPER_METAL_NDEBUG          "whisper: disable Metal debugging"      OFF)

    # 定义启用 Core ML framework 的选项
    option(WHISPER_COREML                "whisper: enable Core ML framework"     OFF)

    # 定义允许使用非-CoreML的回退的选项
    option(WHISPER_COREML_ALLOW_FALLBACK "whisper: allow non-CoreML fallback"    OFF)
else()
    # 如果不是苹果,则定义使用 BLAS 库的选项
    option(WHISPER_BLAS                  "whisper: use BLAS libraries"  OFF)

    # 定义 BLAS 库的供应商选项
    option(WHISPER_BLAS_VENDOR           "whisper: BLAS library vendor" Generic)

    # 定义优先使用 OpenBLAS 的选项
    option(WHISPER_OPENBLAS              "whisper: prefer OpenBLAS"     OFF)

    # 定义支持 cuBLAS 的选项
    option(WHISPER_CUBLAS                "whisper: support for cuBLAS"  OFF)

    # 定义支持 hipBLAS 的选项
    option(WHISPER_HIPBLAS               "whisper: support for hipBLAS" OFF)

    # 定义使用 CLBlast 的选项
    option(WHISPER_CLBLAST               "whisper: use CLBlast"         OFF)
endif()

# 定义启用性能分析的选项
option(WHISPER_PERF "whisper: enable perf timings" OFF)
csharp 复制代码
# sanitizers

# 如果不是使用 MSVC 编译器
if (NOT MSVC)
    # 如果启用 Thread Sanitizer
    if (WHISPER_SANITIZE_THREAD)
        # 添加线程 Sanitizer 的编译选项
        set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fsanitize=thread")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
    endif()

    # 如果启用 Address Sanitizer
    if (WHISPER_SANITIZE_ADDRESS)
        # 添加地址 Sanitizer 的编译选项,并保留函数调用栈信息
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}     -fsanitize=address -fno-omit-frame-pointer")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
    endif()

    # 如果启用 Undefined Behavior Sanitizer
    if (WHISPER_SANITIZE_UNDEFINED)
        # 添加未定义行为 Sanitizer 的编译选项
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}     -fsanitize=undefined")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
    endif()
endif()

# 以下两行是注释掉的代码,未启用
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffast-math")
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")

dependencies依赖

csharp 复制代码
# 使用 find_package 查找 Threads 库,找到 Threads 库后,可以使用 Threads::Threads 在后续的目标中链接该库
find_package(Threads REQUIRED)

if (APPLE)*

csharp 复制代码
# on APPLE
if (APPLE)
    # include Accelerate framework
    if (NOT WHISPER_NO_ACCELERATE)
        find_library(ACCELERATE_FRAMEWORK Accelerate)

        if (ACCELERATE_FRAMEWORK)
            message(STATUS "Accelerate framework found")

            set(WHISPER_EXTRA_LIBS  ${WHISPER_EXTRA_LIBS}  ${ACCELERATE_FRAMEWORK})
            set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_USE_ACCELERATE)
        else()
            message(FATAL_ERROR "Accelerate framework not found")
        endif()
    endif()

    if (WHISPER_METAL)
        find_library(FOUNDATION_LIBRARY         Foundation              REQUIRED)
        find_library(METAL_FRAMEWORK            Metal                   REQUIRED)
        find_library(METALKIT_FRAMEWORK         MetalKit                REQUIRED)

        if (METAL_FRAMEWORK)
            message(STATUS "Metal framework found")

            set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS}
                ${FOUNDATION_LIBRARY}
                ${METAL_FRAMEWORK}
                ${METALKIT_FRAMEWORK}
                )
            set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_USE_METAL)

            if (WHISPER_METAL_NDEBUG)
                set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_METAL_NDEBUG)
            endif()
        else()
            message(FATAL_ERROR "Metal framework not found")
        endif()

        set(GGML_SOURCES_METAL ggml-metal.m ggml-metal.h)

        # copy ggml-metal.metal to bin directory
        configure_file(ggml-metal.metal bin/ggml-metal.metal COPYONLY)
    endif()

    if (WHISPER_COREML)
        find_library(FOUNDATION_FRAMEWORK Foundation)
        find_library(COREML_FRAMEWORK CoreML)

        if (COREML_FRAMEWORK)
            message(STATUS "CoreML framework found")

            set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DWHISPER_USE_COREML)
        else()
            message(FATAL_ERROR "CoreML framework not found")
        endif()

        if (WHISPER_COREML_ALLOW_FALLBACK)
            set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DWHISPER_COREML_ALLOW_FALLBACK)
        endif()
    endif()
endif()

if (WHISPER_OPENBLAS)*

csharp 复制代码
if (WHISPER_OPENBLAS)
    set(WHISPER_BLAS_VENDOR "OpenBLAS")
    set(WHISPER_BLAS ON)
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})
        else ()
            message(FATAL_ERROR "BLAS library was not found. Environment variable OPENBLAS_PATH not defined.")
        endif ()
    else ()
        set(BLA_STATIC 1)
        set(BLA_VENDOR ${WHISPER_BLAS_VENDOR})
        set(BLA_SIZEOF_INTEGER 8)
        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)
            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()
            message(FATAL_ERROR "BLAS library was not found")
        endif()
    endif ()
endif ()

if (WHISPER_CUBLAS)
    cmake_minimum_required(VERSION 3.17)

    find_package(CUDAToolkit)

    if (CUDAToolkit_FOUND)
        message(STATUS "cuBLAS found")

        enable_language(CUDA)

        set(GGML_SOURCES_CUDA ggml-cuda.cu ggml-cuda.h)

        add_compile_definitions(GGML_USE_CUBLAS)

        if (WHISPER_STATIC)
            set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} CUDA::cudart_static CUDA::cublas_static CUDA::cublasLt_static)
        else()
            set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} CUDA::cudart CUDA::cublas CUDA::cublasLt)
        endif()

    else()
        message(FATAL_ERROR "cuBLAS not found")
    endif()
endif()


if (WHISPER_HIPBLAS)
    list(APPEND CMAKE_PREFIX_PATH /opt/rocm)
    if (NOT ${CMAKE_C_COMPILER_ID} MATCHES "Clang")
        message(WARNING "Only LLVM is supported for HIP, hint: CC=/opt/rocm/llvm/bin/clang")
    endif()
    if (NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
        message(WARNING "Only LLVM is supported for HIP, hint: CXX=/opt/rocm/llvm/bin/clang++")
    endif()

    find_package(hip)
    find_package(hipblas)
    find_package(rocblas)

    if (${hipblas_FOUND} AND ${hip_FOUND})
        message(STATUS "HIP and hipBLAS found")
        add_compile_definitions(GGML_USE_HIPBLAS GGML_USE_CUBLAS)
        add_library(ggml-rocm OBJECT ggml-cuda.cu ggml-cuda.h)
        set_property(TARGET ggml-rocm PROPERTY POSITION_INDEPENDENT_CODE ON)
        set_source_files_properties(ggml-cuda.cu PROPERTIES LANGUAGE CXX)
        target_link_libraries(ggml-rocm PRIVATE hip::device PUBLIC hip::host roc::rocblas roc::hipblas)

        if (WHISPER_STATIC)
            message(FATAL_ERROR "Static linking not supported for HIP/ROCm")
        endif()
        set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} ggml-rocm)
    else()
        message(FATAL_ERROR "hipBLAS or HIP not found. Try setting CMAKE_PREFIX_PATH=/opt/rocm")
    endif()
endif()

if (WHISPER_CLBLAST)
    find_package(CLBlast)
    if (CLBlast_FOUND)
        message(STATUS "CLBlast found")

        set(GGML_SOURCES_OPENCL ggml-opencl.cpp ggml-opencl.h)

        add_compile_definitions(GGML_USE_CLBLAST)

        set(WHISPER_EXTRA_LIBS ${WHISPER_EXTRA_LIBS} clblast)
    else()
        message(FATAL_ERROR "CLBlast not found")
    endif()
endif()

if( WHISPER_OPENVINO )
    find_package(OpenVINO REQUIRED COMPONENTS Runtime)
endif()

编译器选项

构建类型,如 Debug、Release*

csharp 复制代码
# compiler flags

# 如果没有设置 CMAKE_BUILD_TYPE(用于指定构建类型,如 Debug、Release)且没有配置 CMAKE_CONFIGURATION_TYPES(多配置构建的情况下),则进行以下设置
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    # 设置构建类型为 Release,并将其缓存
    set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
    # 设置 CMAKE_BUILD_TYPE 的可选值为 "Debug"、"Release"、"RelWithDebInfo"
    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo")
endif ()

warning*

csharp 复制代码
if (WHISPER_ALL_WARNINGS)
    if (NOT MSVC)
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
            -Wall                           \
            -Wextra                         \
            -Wpedantic                      \
            -Wshadow                        \
            -Wcast-qual                     \
            -Wstrict-prototypes             \
            -Wpointer-arith                 \
            -Wno-unused-function            \
        ")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
            -Wall                           \
            -Wextra                         \
            -Wpedantic                      \
            -Wcast-qual                     \
        ")
    else()
        # todo : msvc
    endif()
endif()

MSVC*

csharp 复制代码
if (NOT MSVC)
    # 如果不是使用 MSVC 编译器,则添加编译选项 -Werror=vla,将变长数组 (VLA) 的警告视为错误
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=vla")

    # 下面两行是注释掉的代码,可以用于进一步设置编译选项(未启用)
    #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-math-errno -ffinite-math-only -funsafe-math-optimizations")
endif()


# 输出 CMAKE_SYSTEM_PROCESSOR 的信息到状态消息
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")

硬件设置(AVX之类的)

csharp 复制代码
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64")
    message(STATUS "ARM detected")
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64le")
    message(STATUS "PowerPC detected")
else()
    message(STATUS "x86 detected")
    if (MSVC)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")
        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /utf-8")
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8")
        if(NOT WHISPER_NO_AVX2)
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
            set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /arch:AVX2")
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:AVX2")
        else()
            if(NOT WHISPER_NO_AVX)
                set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX")
                set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /arch:AVX")
                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:AVX")
            endif()
        endif()
    else()
        if (EMSCRIPTEN)
            set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -pthread")
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
        else()
            if(NOT WHISPER_NO_AVX)
                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx")
            endif()
            if(NOT WHISPER_NO_AVX2)
                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2")
            endif()
            if(NOT WHISPER_NO_FMA)
                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfma")
            endif()
            if(NOT WHISPER_NO_F16C)
                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mf16c")
            endif()
        endif()
    endif()
endif()

配置 可移植操作系统接口POSIX 兼容性

  • POSIX:可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX )
csharp 复制代码
#
# POSIX conformance
#

# clock_gettime came in POSIX.1b (1993)
# CLOCK_MONOTONIC came in POSIX.1-2001 / SUSv3 as optional
# posix_memalign came in POSIX.1-2001 / SUSv3
# M_PI is an XSI extension since POSIX.1-2001 / SUSv3, came in XPG1 (1985)
add_compile_definitions(_XOPEN_SOURCE=600) # 通过 add_compile_definitions 命令(Note2),将预处理宏 _XOPEN_SOURCE 的定义设置为 600。这个宏用于启用或禁用一些特定于 UNIX 系统的功能。在这里,设置为 600 表示支持 POSIX.1-2001 / SUSv3 标准及更早的版本。

# Somehow in OpenBSD whenever POSIX conformance is specified
# some string functions rely on locale_t availability,
# which was introduced in POSIX.1-2008, forcing us to go higher
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") # OpenBSD 系统,Linux 和 BSD 都是免费的,开源的,类Unix系统。OpenBSD的目标系统类型是服务器、NAS、工作站和嵌入式系统。
    remove_definitions(-D_XOPEN_SOURCE=600)# 移除先前的 -D_XOPEN_SOURCE=600 定义
    add_compile_definitions(_XOPEN_SOURCE=700)# 设置 _XOPEN_SOURCE 的定义为 700
endif()

# Data types, macros and functions related to controlling CPU affinity
# are available on Linux through GNU extensions in libc
if (CMAKE_SYSTEM_NAME MATCHES "Linux")# Linux 系统
    add_compile_definitions(_GNU_SOURCE)# 添加 _GNU_SOURCE 的编译定义,这个宏是为了启用 GNU C 库(glibc)中的一些特定功能和扩展,包括与 CPU 亲和性相关的数据类型、宏和函数。
endif()

# RLIMIT_MEMLOCK came in BSD, is not specified in POSIX.1,
# and on macOS its availability depends on enabling Darwin extensions
# similarly on DragonFly, enabling BSD extensions is necessary
if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # 如果系统是 Darwin(Apple现在的主要操作系统,无论是macOS、iOS还是iPadOS,甚至是HomePod和Apple TV(TvOS)都是建立在Darwin的基础上),则添加 _DARWIN_C_SOURCE 的编译定义
    add_compile_definitions(_DARWIN_C_SOURCE)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "DragonFly")# 如果系统是 DragonFly,则添加 _DARWIN_C_SOURCE 的编译定义
    add_compile_definitions(_DARWIN_C_SOURCE)
endif()

# alloca is a non-standard interface that is not visible on BSDs when
# POSIX conformance is specified, but not all of them provide a clean way
# to enable it in such cases
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")# 如果系统是 FreeBSD,则添加 __BSD_VISIBLE 的编译定义
    add_compile_definitions(__BSD_VISIBLE)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")# 如果系统是 NetBSD,则添加 _NETBSD_SOURCE 的编译定义
    add_compile_definitions(_NETBSD_SOURCE)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")# 如果系统是 OpenBSD,则添加 _BSD_SOURCE 的编译定义
    add_compile_definitions(_BSD_SOURCE)
endif()
csharp 复制代码
# perf性能测试相关,暂时不是很重要
if (WHISPER_PERF)
    set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_PERF)
endif()

Core ML framework和OPENVINO*

csharp 复制代码
#
# whisper.coreml - Core ML support
#
if (WHISPER_COREML)
    set(TARGET whisper.coreml)

    add_library(${TARGET}
        coreml/whisper-encoder.h
        coreml/whisper-encoder.mm
        coreml/whisper-encoder-impl.h
        coreml/whisper-encoder-impl.m
        )

    include(DefaultTargetOptions)

    target_include_directories(${TARGET} PUBLIC
        .
        )

    target_link_libraries(${TARGET} PRIVATE ${FOUNDATION_FRAMEWORK} ${COREML_FRAMEWORK})

    set_target_properties(${TARGET} PROPERTIES
        COMPILE_FLAGS "-fobjc-arc"
        )
endif()

if (WHISPER_OPENVINO)
    set(TARGET whisper.openvino)

    add_library(${TARGET} OBJECT
        openvino/whisper-openvino-encoder.h
        openvino/whisper-openvino-encoder.cpp
        )

    target_include_directories(${TARGET} PUBLIC
        .
        )

    set_property(TARGET ${TARGET} PROPERTY POSITION_INDEPENDENT_CODE ON)
    set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DWHISPER_USE_OPENVINO)

    target_link_libraries(${TARGET} PRIVATE openvino::runtime)
endif()

whisper库

csharp 复制代码
#
# whisper - this is the main library of the project
#

set(TARGET whisper)
# 生成库文件
add_library(${TARGET}
    ggml.h
    ggml.c
    ggml-alloc.h
    ggml-alloc.c
    ggml-backend.h
    ggml-backend.c
    ggml-quants.h
    ggml-quants.c
    ${GGML_SOURCES_METAL}
    ${GGML_SOURCES_CUDA}
    ${GGML_SOURCES_OPENCL}
    whisper.h
    whisper.cpp
    )

include(DefaultTargetOptions)

target_include_directories(${TARGET} PUBLIC
    .
    )# 为TARGET添加头文件搜索路径
  • 非重要代码
csharp 复制代码
if (WHISPER_COREML)
    target_link_libraries(${TARGET} PRIVATE whisper.coreml)
endif()

if (WHISPER_OPENVINO)
    target_link_libraries(${TARGET} PRIVATE whisper.openvino)
endif()

if (MSVC)
    target_link_libraries(${TARGET} PRIVATE ${WHISPER_EXTRA_LIBS} ${CMAKE_THREAD_LIBS_INIT})

    set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -D_CRT_SECURE_NO_WARNINGS)
else()
    target_link_libraries(${TARGET} PRIVATE m ${WHISPER_EXTRA_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
  • 构建共享库
csharp 复制代码
# 根据构建类型设置库目标的链接和编译定义
if (BUILD_SHARED_LIBS) # 默认为ON
    # 设置目标链接的库
    target_link_libraries(${TARGET} PUBLIC
        ${CMAKE_DL_LIBS} # ${CMAKE_DL_LIBS} is the Name of library containing dlopen and dlclose,在 Unix/Linux 系统中用于动态加载共享库的函数.
        )

    # 为库目标添加编译定义(宏定义,见Note3)
    target_compile_definitions(${TARGET} PUBLIC
        WHISPER_SHARED
        GGML_SHARED
        )

    # 设置库目标的私有编译定义
    target_compile_definitions(${TARGET} PRIVATE
        WHISPER_BUILD
        GGML_BUILD
        )

    if (WHISPER_METAL)# 如果使用 苹果的Metal,则将 ggml-metal.m.metal 文件添加到资源
        # TODO: 我认为这应该使 ggml-metal.m "看到" "bin" 目录下的 ggml-metal.metal 文件
        #       但由于某种原因,在这里的工作方式与 llama.cpp 中的不同
        set_target_properties(${TARGET} PROPERTIES RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/ggml-metal.metal")
    endif()
endif()
  • 非重要代码
csharp 复制代码
if (GGML_SOURCES_CUDA)
    message(STATUS "GGML CUDA sources found, configuring CUDA architecture")
    set_property(TARGET whisper PROPERTY CUDA_ARCHITECTURES OFF)
    set_property(TARGET whisper PROPERTY CUDA_SELECT_NVCC_ARCH_FLAGS "Auto")
endif()

if (EMSCRIPTEN)
    set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS "-msimd128")
endif()

# 使用了 target_compile_definitions 命令,将 WHISPER_EXTRA_FLAGS 中的内容添加到目标(${TARGET})的公共编译定义中。公共编译定义是指在编译目标时可见于整个项目的定义,通常是宏定义。
target_compile_definitions(${TARGET} PUBLIC
    ${WHISPER_EXTRA_FLAGS}
    )

install

csharp 复制代码
# 设置目标属性,指定库的公共头文件
set_target_properties(${TARGET} PROPERTIES PUBLIC_HEADER "whisper.h")

# 包含GNUInstallDirs模块,该模块定义了一些标准的安装目录变量
include(GNUInstallDirs)

# 安装目标文件到指定目录
install(
    TARGETS ${TARGET}           # 目标名称
    LIBRARY DESTINATION lib     # 库文件的安装目录
    ARCHIVE DESTINATION lib/static  # 静态库文件的安装目录
    RUNTIME DESTINATION bin     # 可执行文件的安装目录
    RESOURCE DESTINATION bin    # 资源文件的安装目录
    PUBLIC_HEADER DESTINATION include  # 公共头文件的安装目录
)

绑定和测试*

csharp 复制代码
#
# bindings
#

add_subdirectory(bindings)

#
# programs, examples and tests
#

if (WHISPER_BUILD_TESTS AND NOT CMAKE_JS_VERSION)
    enable_testing()
    add_subdirectory(tests)
endif ()

if (WHISPER_BUILD_EXAMPLES)
    add_subdirectory(examples)
endif()

构建的过程

/bin/cmake/linux/bin/cmake --build /home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug --target bench -- -j 8
gmake[1]: 进入目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
gmake[2]: 进入目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
gmake[3]: 进入目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
Scanning dependencies of target whisper # 构建 `whisper` 库
gmake[3]: 离开目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
gmake[3]: 进入目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
[ 12%] Building C object CMakeFiles/whisper.dir/ggml.c.o
[ 25%] Building C object CMakeFiles/whisper.dir/ggml-alloc.c.o
[ 37%] Building C object CMakeFiles/whisper.dir/ggml-backend.c.o
[ 50%] Building C object CMakeFiles/whisper.dir/ggml-quants.c.o
[ 62%] Building CXX object CMakeFiles/whisper.dir/whisper.cpp.o
/home/pdd/le/whisper.cpp-1.5.0/whisper.cpp: In function 'ggml_backend* whisper_backend_init(const whisper_context_params&)':
/home/pdd/le/whisper.cpp-1.5.0/whisper.cpp:1059:75: warning: unused parameter 'params' [-Wunused-parameter]
 1059 | static ggml_backend_t whisper_backend_init(const whisper_context_params & params) {
      |                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/home/pdd/le/whisper.cpp-1.5.0/whisper.cpp: At global scope:
/home/pdd/le/whisper.cpp-1.5.0/whisper.cpp:205:29: warning: 'ggml_tensor* ggml_mul_mat_pad(ggml_context*, ggml_tensor*, ggml_tensor*, int)' defined but not used [-Wunused-function]
  205 | static struct ggml_tensor * ggml_mul_mat_pad(struct ggml_context * ctx, struct ggml_tensor * x, struct ggml_tensor * y, int pad = 32) {
      |                             ^~~~~~~~~~~~~~~~
[ 75%] Linking CXX shared library libwhisper.so # 链接 `whisper` 库(`libwhisper.so`)
gmake[3]: 离开目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
[ 75%] Built target whisper
gmake[3]: 进入目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
Scanning dependencies of target bench
gmake[3]: 离开目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
gmake[3]: 进入目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
[ 87%] Building CXX object examples/bench/CMakeFiles/bench.dir/bench.cpp.o
[100%] Linking CXX executable ../../bin/bench 
gmake[3]: 离开目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
[100%] Built target bench # 创建 `bench` 可执行文件
gmake[2]: 离开目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"
gmake[1]: 离开目录"/home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug"

Build finished

CG

Note1:configure_file

configure_file 是 CMake 中用于在构建过程中生成文件的命令。它的主要作用是将源文件的内容复制到目标文件中,并在复制的过程中进行一些文本替换,替换操作依赖于 CMake 变量和配置。

语法如下:

cmake 复制代码
configure_file(<input> <output> [@ONLY] [ESCAPE_QUOTES] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF|CR]])

其中:

  • <input> 是源文件的路径。
  • <output> 是目标文件的路径。
  • @ONLY 可选参数表示仅在 @ 符号引导的变量上执行替换。不提供 @ONLY 时,所有变量都将替换。
  • ESCAPE_QUOTES 可选参数表示在替换时转义引号。
  • NEWLINE_STYLE 可选参数指定换行符的风格,可以是 UNIXDOSWIN32LFCRLFCR

例子:

cmake 复制代码
# CMakeLists.txt

set(VERSION_MAJOR 1)
set(VERSION_MINOR 0)

configure_file(config.h.in config.h @ONLY)
c 复制代码
// config.h.in

#define VERSION_MAJOR @VERSION_MAJOR@
#define VERSION_MINOR @VERSION_MINOR@

在这个例子中,config.h.in 是一个模板文件,其中使用了 @VERSION_MAJOR@@VERSION_MINOR@ 这样的占位符。通过 configure_file 命令,CMake 将替换这些占位符为相应的变量的值,并生成 config.h 文件。在这个过程中,@ONLY 表示仅替换由 @ 符号引导的变量。这个生成的 config.h 文件可以被项目的源代码使用。

此外,configure_file 还允许在配置时执行一些 CMake 脚本,进一步扩展了其功能。通过这种方式,可以在构建时生成一些特定于构建配置的文件,例如根据不同平台生成不同的配置文件。

csharp 复制代码
// https://github1s.com/ggerganov/whisper.cpp/blob/v1.5.0/bindings/javascript/package-tmpl.json
{
  "name": "whisper.cpp",
  "version": "@PROJECT_VERSION@",
  "description": "Whisper speech recognition",
  "main": "whisper.js",
  "scripts": {
    "test": "echo \"todo: add tests\" && exit 0"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ggerganov/whisper.cpp"
  },
  "keywords": [
    "openai",
    "whisper",
    "speech-to-text",
    "speech-recognition",
    "transformer"
  ],
  "author": "Georgi Gerganov",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/ggerganov/whisper.cpp/issues"
  },
  "homepage": "https://github.com/ggerganov/whisper.cpp#readme"
}
// https://github1s.com/ggerganov/whisper.cpp/blob/v1.5.0/bindings/javascript/package.json
{
  "name": "whisper.cpp",
  "version": "1.5.0",
  "description": "Whisper speech recognition",
  "main": "whisper.js",
  "scripts": {
    "test": "echo \"todo: add tests\" && exit 0"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ggerganov/whisper.cpp"
  },
  "keywords": [
    "openai",
    "whisper",
    "speech-to-text",
    "speech-recognition",
    "transformer"
  ],
  "author": "Georgi Gerganov",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/ggerganov/whisper.cpp/issues"
  },
  "homepage": "https://github.com/ggerganov/whisper.cpp#readme"
}

Note2:add_compile_definitions

add_compile_definitions 是 CMake 中用于向目标添加编译定义(宏定义)的命令。它用于在编译时向源代码中注入预定义的宏,从而影响代码的编译行为。在上下文中,这些宏通常用于控制特定平台或编译器的特定行为。

语法如下:

cmake 复制代码
add_compile_definitions(definition1 [definition2 ...])
  • definition1, definition2, ...: 要添加的编译定义,可以是一个或多个。

例如,如果要向编译过程中添加一个名为 ENABLE_FEATURE_X 的宏定义,可以使用如下命令:

cmake 复制代码
add_compile_definitions(ENABLE_FEATURE_X)

在你提供的代码片段中,add_compile_definitions 用于添加一些特定平台的编译定义,以启用或禁用某些非标准的接口或特性。这样,可以根据操作系统的类型为代码选择性地启用或禁用特定的功能或扩展。

Note3:target_compile_definitions

  • source.cpp:
cpp 复制代码
#include <iostream>

#ifdef DEBUG_MODE
#define LOG(message) std::cout << "[DEBUG] " << message << std::endl;
#else
#define LOG(message) std::cout << "[RELEASE] " << message << std::endl;
#endif

int main() {
    LOG("Hello, world!");

    return 0;
}
  • CMakeLists.txt
cmake 复制代码
# CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
project(MyProject)

# 添加可执行文件目标
add_executable(my_executable my_source.cpp)

# 在目标上添加 DEBUG_MODE 宏定义
target_compile_definitions(my_executable PUBLIC DEBUG_MODE)
相关推荐
昨日之日20067 天前
Moonshine - 新型开源ASR(语音识别)模型,体积小,速度快,比OpenAI Whisper快五倍 本地一键整合包下载
人工智能·whisper·语音识别
新缸中之脑16 天前
基于Distil-Whisper的实时ASR【自动语音识别】
人工智能·whisper·语音识别
敢敢のwings21 天前
如何在Windows平台下基于Whisper来训练自己的数据
windows·whisper·1024程序员节
z千鑫22 天前
【OpenAI】第六节(语音生成与语音识别技术)从 ChatGPT 到 Whisper 的全方位指南
人工智能·chatgpt·whisper·gpt-3·openai·语音识别·codemoss能用ai
bug智造25 天前
Whisper 音视频转写
whisper·音视频
客院载论1 个月前
论文学习——基于Whisper迁移学习的阿尔兹海默症检测方法——音频特征和语义特征的结合
学习·whisper·迁移学习
htsitr1 个月前
实时语音转文字(基于NAudio+Whisper+VOSP+Websocket)
whisper
盼海1 个月前
安装openai-whisper 失败
python·whisper
aiAIman1 个月前
主流显卡和 CPU 进行 Whisper 转录性能 RTF 转录时间估算
人工智能·python·语言模型·whisper
碳治郎AI1 个月前
【AIGC】OpenAI 宣布推出Whisper large-v3-turbo 语音转录模型 速度提高了8倍
人工智能·whisper·aigc