Skip to content
Open
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
49 changes: 14 additions & 35 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ on:
pull_request:
branches: [ main ]

# ggml is built from source via FetchContent (see CMakeLists), so no system ggml
# is required on any platform. Static build => self-contained binary artifacts.
jobs:
build:
name: build on ${{ matrix.os }} (${{ matrix.arch }})
Expand All @@ -16,53 +18,30 @@ jobs:
include:
- os: ubuntu-latest
arch: x86_64
- os: ubuntu-24.04-arm64
- os: ubuntu-24.04-arm
arch: arm64
- os: macos-latest
arch: arm64
- os: windows-latest
arch: x86_64

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libsdl2-dev build-essential cmake

- name: Install dependencies (macOS)
if: runner.os == 'macOS'
run: |
brew install sdl2 cmake

- name: Install dependencies (Windows)
if: runner.os == 'Windows'
run: |
vcpkg install sdl2:x64-windows
vcpkg integrate install
- uses: actions/checkout@v4

- name: Configure CMake
run: >
cmake -S . -B build
-DCMAKE_BUILD_TYPE=Release
${{ runner.os == 'Windows' && '-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake' || '' }}
${{ runner.os == 'macOS' && '-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"' || '' }}
- name: Configure
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF

- name: Build
run: cmake --build build --config Release -j

- name: Upload Artifacts
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
with:
name: voxtral-${{ runner.os }}-${{ matrix.arch }}
path: |
build/voxtral*
build/examples/stream/voxtral-stream*
!build/**/*.dir
!build/**/*.obj
!build/**/*.o
build/voxtral
build/voxtral.exe
build/voxtral-quantize
build/voxtral-quantize.exe
build/Release/voxtral.exe
build/Release/voxtral-quantize.exe
if-no-files-found: ignore
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

124 changes: 61 additions & 63 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,84 +9,64 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

option(VOXTRAL_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF)
option(VOXTRAL_NATIVE_OPT "Enable native CPU tuning flags" ON)
option(VOXTRAL_AUTO_DETECT_CPU "Auto-detect CPU features and set ggml flags" ON)
option(VOXTRAL_AUTO_DETECT_BLAS "Auto-enable ggml BLAS if found" ON)
# Homebrew uses the system ggml formula; everywhere else ggml is built from source
# via FetchContent (no vendored submodule). Backends are discovered at runtime via
# the ggml registry, so no backend flags are needed here.
option(VOXTRAL_USE_SYSTEM_GGML "Link a system ggml instead of building it from source" OFF)

if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

find_package(Threads REQUIRED)

set(GGML_BUILD_TESTS OFF CACHE BOOL "Disable ggml tests" FORCE)
set(GGML_BUILD_EXAMPLES OFF CACHE BOOL "Disable ggml examples" FORCE)

if(VOXTRAL_AUTO_DETECT_CPU AND NOT CMAKE_CROSSCOMPILING)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|i[3-6]86")
include(CheckCXXSourceRuns)

function(voxtral_check_cpu_supports feature outvar)
set(_src "
#if !(defined(__x86_64__) || defined(__i386__) || defined(_M_X64) || defined(_M_IX86))
int main() { return 1; }
#endif
#if defined(__GNUC__) || defined(__clang__)
int main() { return __builtin_cpu_supports(\"${feature}\") ? 0 : 1; }
#else
int main() { return 1; }
#endif
")
check_cxx_source_runs("${_src}" ${outvar})
endfunction()

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
voxtral_check_cpu_supports("avx" VOXTRAL_CPU_HAS_AVX)
voxtral_check_cpu_supports("avx2" VOXTRAL_CPU_HAS_AVX2)
voxtral_check_cpu_supports("fma" VOXTRAL_CPU_HAS_FMA)
voxtral_check_cpu_supports("f16c" VOXTRAL_CPU_HAS_F16C)
voxtral_check_cpu_supports("bmi2" VOXTRAL_CPU_HAS_BMI2)
voxtral_check_cpu_supports("avx512f" VOXTRAL_CPU_HAS_AVX512)

set(VOXTRAL_CPU_FEATURES_DETECTED ON)
endif()
if(VOXTRAL_USE_SYSTEM_GGML)
find_package(ggml CONFIG REQUIRED)
set(VOXTRAL_GGML_TARGETS ggml::ggml ggml::ggml-base)
# Imported targets omit the include dir with dynamically-loaded backends.
set(VOXTRAL_GGML_INCLUDES ${GGML_INCLUDE_DIR})
else()
include(FetchContent)
set(GGML_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GGML_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
if(APPLE)
# Embed Metal shaders so the binary needs no external default.metallib.
set(GGML_METAL_EMBED_LIBRARY ON CACHE BOOL "" FORCE)
endif()
FetchContent_Declare(ggml
GIT_REPOSITORY https://github.com/ggml-org/ggml.git
GIT_TAG 5cecdad692d868e28dbd2f7c468504770108f30c)
FetchContent_MakeAvailable(ggml)
set(VOXTRAL_GGML_TARGETS ggml)
set(VOXTRAL_GGML_INCLUDES "")
endif()

if(VOXTRAL_CPU_FEATURES_DETECTED)
# Use explicit ISA flags instead of -march=native when auto-detecting.
set(GGML_NATIVE OFF CACHE BOOL "ggml: optimize the build for the current system" FORCE)
set(GGML_AVX ${VOXTRAL_CPU_HAS_AVX} CACHE BOOL "ggml: enable AVX" FORCE)
set(GGML_AVX2 ${VOXTRAL_CPU_HAS_AVX2} CACHE BOOL "ggml: enable AVX2" FORCE)
set(GGML_FMA ${VOXTRAL_CPU_HAS_FMA} CACHE BOOL "ggml: enable FMA" FORCE)
set(GGML_F16C ${VOXTRAL_CPU_HAS_F16C} CACHE BOOL "ggml: enable F16C" FORCE)
set(GGML_BMI2 ${VOXTRAL_CPU_HAS_BMI2} CACHE BOOL "ggml: enable BMI2" FORCE)
set(GGML_AVX512 ${VOXTRAL_CPU_HAS_AVX512} CACHE BOOL "ggml: enable AVX512F" FORCE)
endif()

if(VOXTRAL_AUTO_DETECT_BLAS)
if(NOT DEFINED CACHE{GGML_BLAS})
find_package(BLAS QUIET)
if(BLAS_FOUND)
set(GGML_BLAS ON CACHE BOOL "ggml: use BLAS" FORCE)
endif()
endif()
endif()

add_subdirectory(ggml)

add_library(voxtral_lib
src/voxtral.cpp)

# On Windows with BUILD_SHARED_LIBS=ON, export symbols automatically so the
# import library (voxtral_lib.lib) is generated for dependents like `voxtral`.
if(WIN32 AND BUILD_SHARED_LIBS)
set_target_properties(voxtral_lib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()

target_include_directories(voxtral_lib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include)
${CMAKE_CURRENT_SOURCE_DIR}/include
${VOXTRAL_GGML_INCLUDES})

target_link_libraries(voxtral_lib
PUBLIC
ggml
Threads::Threads
m
dl)
${VOXTRAL_GGML_TARGETS}
Threads::Threads)

if(NOT WIN32)
target_link_libraries(voxtral_lib PUBLIC m)
endif()

if(CMAKE_DL_LIBS)
target_link_libraries(voxtral_lib PUBLIC ${CMAKE_DL_LIBS})
endif()

if(VOXTRAL_WARNINGS_AS_ERRORS)
if (MSVC)
Expand All @@ -97,14 +77,27 @@ if(VOXTRAL_WARNINGS_AS_ERRORS)
endif()

if(VOXTRAL_NATIVE_OPT AND NOT MSVC)
target_compile_options(voxtral_lib PRIVATE -march=native -mtune=native)
if(APPLE)
message(STATUS "VOXTRAL_NATIVE_OPT: skipping -march/-mtune=native on Apple toolchains")
else()
target_compile_options(voxtral_lib PRIVATE -march=native -mtune=native)
endif()
endif()

add_executable(voxtral src/main.cpp)
target_link_libraries(voxtral PRIVATE voxtral_lib)

add_executable(voxtral-quantize src/voxtral-quantize.cpp)
target_link_libraries(voxtral-quantize PRIVATE ggml Threads::Threads m dl)
target_link_libraries(voxtral-quantize PRIVATE ${VOXTRAL_GGML_TARGETS} Threads::Threads)
target_include_directories(voxtral-quantize PRIVATE ${VOXTRAL_GGML_INCLUDES})

if(NOT WIN32)
target_link_libraries(voxtral-quantize PRIVATE m)
endif()

if(CMAKE_DL_LIBS)
target_link_libraries(voxtral-quantize PRIVATE ${CMAKE_DL_LIBS})
endif()

if(VOXTRAL_WARNINGS_AS_ERRORS)
if (MSVC)
Expand All @@ -115,9 +108,14 @@ if(VOXTRAL_WARNINGS_AS_ERRORS)
endif()

if(VOXTRAL_NATIVE_OPT AND NOT MSVC)
target_compile_options(voxtral-quantize PRIVATE -march=native -mtune=native)
if(NOT APPLE)
target_compile_options(voxtral-quantize PRIVATE -march=native -mtune=native)
endif()
endif()

# Install the CLI tools (used by `cmake --install` and the Homebrew formula).
install(TARGETS voxtral voxtral-quantize RUNTIME DESTINATION bin)

find_package(Python3 COMPONENTS Interpreter)
if(Python3_Interpreter_FOUND)
add_custom_target(voxtral_convert
Expand Down
30 changes: 30 additions & 0 deletions Formula/voxtral.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Homebrew formula for voxtral.cpp.
#
# brew tap andrijdavid/voxtral https://github.com/andrijdavid/voxtral.cpp
# brew install --HEAD voxtral
#
# Builds against the system ggml (no bundled submodule), like the homebrew-core
# whisper-cpp formula.
class Voxtral < Formula
desc "C++ implementation of the Voxtral speech-to-text model (ggml)"
homepage "https://github.com/andrijdavid/voxtral.cpp"
license "MIT"
# Add `url` + `sha256` for a tagged release tarball; HEAD-only for now.
head "https://github.com/andrijdavid/voxtral.cpp.git", branch: "main"

depends_on "cmake" => :build
depends_on "ggml"

def install
system "cmake", "-S", ".", "-B", "build",
"-DVOXTRAL_USE_SYSTEM_GGML=ON",
"-DCMAKE_INSTALL_RPATH=#{rpath}",
*std_cmake_args
system "cmake", "--build", "build"
system "cmake", "--install", "build"
end

test do
assert_match "usage", shell_output("#{bin}/voxtral --help")
end
end
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Andrij David

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading