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

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

基础配置

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行
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 设置为 ONinclude(GitVars)  # 引用 GitVars 模块include(BuildTypes)  # 引用 BuildTypes 模块# 配置封装到其他语言的项目版本相关,详见Note1if (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

# 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}PRIVATEcxx_std_11)set_target_properties(${TARGET}PROPERTIESEXPORT_COMPILE_COMMANDS ONRUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
)

GIT*

find_package(Git)# the commit's SHA1
execute_process(COMMAND"${GIT_EXECUTABLE}" describe --match=NeVeRmAtCh --always --abbrev=8WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"OUTPUT_VARIABLE GIT_SHA1ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)# the date of the commit
execute_process(COMMAND"${GIT_EXECUTABLE}" log -1 --format=%ad --date=localWORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"OUTPUT_VARIABLE GIT_DATEERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)# the subject of the commit
execute_process(COMMAND"${GIT_EXECUTABLE}" log -1 --format=%sWORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"OUTPUT_VARIABLE GIT_COMMIT_SUBJECTERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)

BuildTypes*

# Add new build types# ReleaseGG - Release with enabled assertsSET(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_RELEASEGGCMAKE_C_FLAGS_RELEASEGGCMAKE_EXE_LINKER_FLAGS_RELEASEGGCMAKE_SHARED_LINKER_FLAGS_RELEASEGG )# RelWithDebInfoGG - RelWithDebInfo with enabled assertsSET(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_RELWITHDEBINFOGGCMAKE_C_FLAGS_RELWITHDEBINFOGGCMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFOGGCMAKE_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配置*

# 检查是否使用 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编译选项

# 如果目标平台是苹果 (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_DEFAULToption(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)
# sanitizers# 如果不是使用 MSVC 编译器
if (NOT MSVC)# 如果启用 Thread Sanitizerif (WHISPER_SANITIZE_THREAD)# 添加线程 Sanitizer 的编译选项set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fsanitize=thread")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")endif()# 如果启用 Address Sanitizerif (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 Sanitizerif (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依赖

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

if (APPLE)*

# on APPLE
if (APPLE)# include Accelerate frameworkif (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 directoryconfigure_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)*

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*

# 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*

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 : msvcendif()
endif()

MSVC*

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之类的)

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 )
#
# 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()
# perf性能测试相关,暂时不是很重要
if (WHISPER_PERF)set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_PERF)
endif()

Core ML framework和OPENVINO*

  • Core ML 是一个 Apple 框架,允许开发人员轻松集成 机器学习 (ML) 模型到应用中。Core ML 可在 iOS、iPadOS、 watchOS、macOS 和 Apple tvOS。Core ML 引入了公共文件格式 (.mlmodel) 适用于广泛的 ML 方法,包括深度神经网络(卷积 和循环)、树集成(提升树、随机森林、决策树)、 和广义线性模型。Core ML 模型可直接集成到 Xcode 中的 App。 Core ML 通过利用 Apple 硬件并最大限度地减少内存占用和功耗,针对各种型号类型的设备端性能进行了优化。 Core ML 旨在通过利用其 CPU、GPU 和神经网络引擎来优化设备性能,同时将内存和功耗降至最低。应用程序使用 CoreML 应用程序编程接口 (API) 在每个用户拥有的所有设备上进行预测和微调模型。可以转换为Core ML的模型格式有Caffe、Keras、XGBoost、 Scikit-learn 、MXNet 、 LibSVM 和 Torch7。
  • 英特尔的OpenVINO™ 工具套件:一款可轻松实现“一次写入,处处部署”的开源工具套件
#
# whisper.coreml - Core ML support
#
if (WHISPER_COREML)set(TARGET whisper.coreml)add_library(${TARGET}coreml/whisper-encoder.hcoreml/whisper-encoder.mmcoreml/whisper-encoder-impl.hcoreml/whisper-encoder-impl.m)include(DefaultTargetOptions)target_include_directories(${TARGET} PUBLIC.)target_link_libraries(${TARGET} PRIVATE ${FOUNDATION_FRAMEWORK} ${COREML_FRAMEWORK})set_target_properties(${TARGET} PROPERTIESCOMPILE_FLAGS "-fobjc-arc")
endif()if (WHISPER_OPENVINO)set(TARGET whisper.openvino)add_library(${TARGET} OBJECTopenvino/whisper-openvino-encoder.hopenvino/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库

#
# whisper - this is the main library of the project
#set(TARGET whisper)
# 生成库文件
add_library(${TARGET}ggml.hggml.cggml-alloc.hggml-alloc.cggml-backend.hggml-backend.cggml-quants.hggml-quants.c${GGML_SOURCES_METAL}${GGML_SOURCES_CUDA}${GGML_SOURCES_OPENCL}whisper.hwhisper.cpp)include(DefaultTargetOptions)target_include_directories(${TARGET} PUBLIC.)# 为TARGET添加头文件搜索路径
  • 非重要代码
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()
  • 构建共享库
# 根据构建类型设置库目标的链接和编译定义
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} PUBLICWHISPER_SHAREDGGML_SHARED)# 设置库目标的私有编译定义target_compile_definitions(${TARGET} PRIVATEWHISPER_BUILDGGML_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()
  • 非重要代码
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

# 设置目标属性,指定库的公共头文件
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  # 公共头文件的安装目录
)

绑定和测试*

#
# 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

  • 有关cmake和CMakeLists.txt

Note1:configure_file

configure_file 是 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

例子:

# CMakeLists.txtset(VERSION_MAJOR 1)
set(VERSION_MINOR 0)configure_file(config.h.in config.h @ONLY)
// 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 脚本,进一步扩展了其功能。通过这种方式,可以在构建时生成一些特定于构建配置的文件,例如根据不同平台生成不同的配置文件。

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

语法如下:

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

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

add_compile_definitions(ENABLE_FEATURE_X)

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

Note3:target_compile_definitions

  • source.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;
#endifint main() {LOG("Hello, world!");return 0;
}
  • CMakeLists.txt
# CMakeLists.txtcmake_minimum_required(VERSION 3.12)
project(MyProject)# 添加可执行文件目标
add_executable(my_executable my_source.cpp)# 在目标上添加 DEBUG_MODE 宏定义
target_compile_definitions(my_executable PUBLIC DEBUG_MODE)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/632451.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Uboot-5(U-Boot源码分析1-启动第一阶段)

来源&#xff1a;朱有鹏老师的嵌入式linux核心教程 1、start.S引入 1.1、u-boot.lds中找到start.S入口 (1)、在C语言中整个项目的入口就是main函数&#xff08;这是C语言规定的&#xff09;&#xff0c;所以譬如说一个有10000个.c文件的项目&#xff0c;第一个要分析的文件就…

Go 中 slice 的 In 功能实现探索

文章目录 遍历二分查找map key性能总结 之前在知乎看到一个问题&#xff1a;为什么 Golang 没有像 Python 中 in 一样的功能&#xff1f;于是&#xff0c;搜了下这个问题&#xff0c;发现还是有不少人有这样的疑问。 补充&#xff1a;本文写于 2019 年。GO 现在已经支持泛型&am…

腾讯云 腾讯云服务器 - 腾讯云 产业智变·云启未来

腾讯云服务器CVM提供安全可靠的弹性计算服务&#xff0c;腾讯云明星级云服务器&#xff0c;弹性计算实时扩展或缩减计算资源&#xff0c;支持包年包月、按量计费和竞价实例计费模式&#xff0c;CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格&#xff0c;提供9个9的数…

【工作记录】基于springboot3+springsecurity6实现多种登录方式(一)

前言 springboot3已经推出有一段时间了&#xff0c;近期公司里面的小项目使用的都是springboot3版本的&#xff0c;安全框架还是以springsecurity为主&#xff0c;毕竟亲生的。 本文针对基于springboot3和springsecurity实现用户登录认证访问以及异常处理做个记录总结&#x…

Linux miniGUI移植分析

框架介绍 常用GUI程序对比 https://www.cnblogs.com/zyly/p/17378659.html MiniGUI分为底层的GAL&#xff08;图形抽象层&#xff09;和IAL&#xff08;输入抽象层&#xff09;&#xff0c;向上为基于标准POSIX接口中pthread库的Mini-Thread架构和基于Server/Client的Mini-L…

JSONObject - 用最通俗的讲解,教你玩转 JSON 数据的解析和修改

目录 一、JSONObject 1.1、为什么要使用他&#xff1f; 1.2、应用 1.2.1、依赖 1.2.2、JSON 数据示例 1.2.3、JSON 数据的构建 1.2.4、JSON 数据的解析 一、JSONObject 1.1、为什么要使用他&#xff1f; 在还没有接触过这个东西的时候&#xff0c;一直是通过 ObjectMap…

Spring 核心之 IOC 容器学习二

基于 Annotation 的 IOC 初始化 Annotation 的前世今生 从 Spring2.0 以后的版本中&#xff0c;Spring 也引入了基于注解(Annotation)方式的配置&#xff0c;注解(Annotation)是 JDK1.5 中引入的一个新特性&#xff0c;用于简化 Bean 的配置&#xff0c;可以取代 XML 配置文件…

深度学习记录--归—化输入特征

归化 归化输入(normalizing inputs),对特征值进行一定的处理&#xff0c;可以加速神经网络训练速度 步骤 零均值化 通过x值更新让均值稳定在零附近&#xff0c;即为零均值化 归化方差 适当减小变量方差 解释 归化可以让原本狭长的数据图像变得规整&#xff0c;梯度下降的…

Electron中苹果支付 Apple Pay inAppPurchase 内购支付

正在开发中&#xff0c;开发好了&#xff0c;写一个完整详细的过程&#xff0c;保证无脑集成即可 一、先创建一个App 一般情况下&#xff0c;在你看这篇文章的时候&#xff0c;说明你已经开发的app差不多了。 但是要上架app到Mac App Store&#xff0c;则要在appstoreconnect…

WPF中Image控件Source的多种指定方式

XAML中 1、直接绝对路径直接给Source 2、将图片放到项目里面&#xff0c;设置图片为资源&#xff1b;Source写法为&#xff1a; &#xff08;1&#xff09;Source"pack://application:,,,/label里面的Content;component/folder/test.png" &#xff08;2&…

HBase学习六:LSM树算法

1、简介 HBase是基于LSM树架构实现的,天生适合写多读少的应用场景。 LSM树本质上和B+树一样,是一种磁盘数据的索引结构。但和B+树不同的是,LSM树的索引对写入请求更友好。因为无论是何种写入请求,LSM树都会将写入操作处理为一次顺序写,而HDFS擅长的正是顺序写(且HDFS不…

鸿蒙应用开发横空出世:是否应该换赛道

鸿蒙应用开发横空出世:互联网寒冬的希望? 大家好,我是demo.最近相信大家最近也收到了这样的消息,网上大肆宣传明年未来的趋势是鸿蒙应用开发,这里呢我也确实被这些信息所覆盖.最近几年确实互联网行业不是很景气,许多公司大量裁员,很多人都因此丢了工作.大龄程序员一直是互联网…

5408. 保险箱

5408. 保险箱 - AcWing题库 #include <iostream> #include <string> #include <algorithm> #include <cstring> using namespace std;const int N 1e5 10; string x, y; int f[N][3], n; int main() {cin >> n >> x >> y;memset(…

Linux第31步_了解STM32MP157的TF-A

了解STM32MP157的TF-A&#xff0c;为后期移植服务。 一、指令集 ARMV8提供了两种指令集:AAarch64和AArch32&#xff0c;根据字面意思就是64位和32位。 ARMV7提供的指令集是AArch32。 二、TF-A 指令集是AArch64的芯片&#xff0c;TF-A有&#xff1a;bl1、bl2、bl31、bl32 和…

drive souls to hell

​ a man forgot to put his phone on silent (/ˈsaɪlənt/), and it rang so loud in the church during preaching, the pastor scolded him,the worshippers admonished him after the sermon for interrupting ,his wife kept to lecturing on his carelessness all the …

用Python判断节假日,以及节假日的SQL数据文件

为什么要判断节假日&#xff1f; 在我们的日常生活中&#xff0c;节假日是一个重要的组成部分。无论是个人计划还是商业活动&#xff0c;了解特定日期是否为节假日都是非常有用的。在Python中&#xff0c;我们可以使用一些内置的日期和时间模块来判断一个日期是否是法定节假日…

再见了RDM,Redis官方GUI才是最好的!

1 简介 直观高效的 Redis GUI 管理工具&#xff0c;它可以对 Redis 的内存、连接数、命中率以及正常运行时间进行监控&#xff0c;并且可以在界面上使用 CLI 和连接的 Redis 进行交互&#xff08;RedisInsight 内置对 Redis 模块支持&#xff09;&#xff0c;官方下载地址。 使…

Power Designer 连接 PostgreSQL 逆向工程生成pd表结构操作步骤以及过程中出现的问题解决

一、使用PowerDesigner16.5 链接pg数据库 1.1、启动PD.选择Create Model…。 1.2、选择Model types / Physical Data Model Physical Diagram&#xff1a;选择pgsql直接【ok】 1.3、选择connect 在工具栏选择Database-Connect… 快捷键&#xff1a;ctrlshiftN.如下图&#xff…

查询数据库表字段具有某些特征的表

目录 引言举例总结 引言 当我们把一个项目做完以后&#xff0c;客户要求我们把系统中所有的电话&#xff0c;证件号等进行加密处理时&#xff0c;我们难道要一个表一表去查看那些字段是电话和证件号码吗&#xff1f; 这种办法有点费劲&#xff0c;下面我们来探索如何找到想要的…

CVE-2024-0195-SpiderFlow爬虫平台远程命令执行漏洞分析

项目下载地址 spider-flow: 新一代爬虫平台&#xff0c;以图形化方式定义爬虫流程&#xff0c;不写代码即可完成爬虫。https://gitee.com/ssssssss-team/spider-flow 在平台spiderflow的页面中有一个自定义函数&#xff0c;看到函数应是非常的敏感了。 可以做一些猜想与尝试&…