diff --git a/.github/workflows/bindings-ruby.yml b/.github/workflows/bindings-ruby.yml index 63f7f615..680862fb 100644 --- a/.github/workflows/bindings-ruby.yml +++ b/.github/workflows/bindings-ruby.yml @@ -1,55 +1,11 @@ name: Bindings Tests (Ruby) + on: push: - paths: - - bindings/ruby/** - - src/**/*.c - - src/**/*.cpp - - src/**/*.h - - src/**/*.m - - src/**/*.metal - - include/**/*.c - - include/**/*.cpp - - include/**/*.h - - include/**/*.m - - include/**/*.metal - - ggml/**/*.c - - ggml/**/*.cpp - - ggml/**/*.h - - ggml/**/*.m - - ggml/**/*.metal - - scripts/get-flags.mk - - examples/common.h - - examples/common.cpp - - examples/common-whisper.h - - examples/common-whisper.cpp - - examples/stb_vorbis.c - - examples/miniaudio.h + branches: + - master pull_request: - paths: - - bindings/ruby/** - - src/**/*.c - - src/**/*.cpp - - src/**/*.h - - src/**/*.m - - src/**/*.metal - - include/**/*.c - - include/**/*.cpp - - include/**/*.h - - include/**/*.m - - include/**/*.metal - - ggml/**/*.c - - ggml/**/*.cpp - - ggml/**/*.h - - ggml/**/*.m - - ggml/**/*.metal - - scripts/get-flags.mk - - examples/common.h - - examples/common.cpp - - examples/common-whisper.h - - examples/common-whisper.cpp - - examples/stb_vorbis.c - - examples/miniaudio.h + types: [opened, synchronize, reopened] jobs: ubuntu-22: @@ -60,6 +16,6 @@ jobs: steps: - uses: ruby/setup-ruby@v1 with: - ruby-version: '3.1' + ruby-version: '3.2' - uses: actions/checkout@v4 - run: rake test diff --git a/bindings/ruby/.gitignore b/bindings/ruby/.gitignore index e04a90a9..e93e6fac 100644 --- a/bindings/ruby/.gitignore +++ b/bindings/ruby/.gitignore @@ -1,3 +1,6 @@ LICENSE pkg/ lib/whisper.* +ext/sources/* +!ext/sources/CMakeGraphVizOptions.cmake +ext/mkmf.log diff --git a/bindings/ruby/Rakefile b/bindings/ruby/Rakefile index 0d52e88a..bc6f8433 100644 --- a/bindings/ruby/Rakefile +++ b/bindings/ruby/Rakefile @@ -3,11 +3,15 @@ require "bundler/gem_tasks" require "rake/testtask" require_relative "extsources" +SOURCES_DIR = "ext/sources" + SOURCES = FileList[] EXTSOURCES.each do |src| basename = src.pathmap("%f") - dest = basename == "LICENSE" ? basename : src.pathmap("%{../..,ext}p") + dest = basename == "LICENSE" ? basename + : src.pathmap("%{\\.\\./\\.\\.,#{SOURCES_DIR}}p") + .pathmap("%{\\.\\./javascript,#{SOURCES_DIR}/bindings/javascript}p") dir = dest.pathmap("%d") file src directory dir @@ -18,7 +22,6 @@ EXTSOURCES.each do |src| end CLEAN.include SOURCES -CLEAN.include FileList["ext/**/*.o", "ext/**/*.metal", "ext/**/*.tmp", "ext/whisper.{so,bundle,dll}"] SRC = FileList["ext/*.{c,cpp,h}"] @@ -36,6 +39,20 @@ file "ext/Makefile" => SRC + ["ext/extconf.rb"] + SOURCES do |t| ruby "extconf.rb" end end +if File.exist? "ext/Makefile" + task :make_clean do + cd "ext" do + sh "make", "clean" + end + end + task clean: :make_clean + task :make_distclean do + cd "ext" do + sh "make", "distclean" + end + end + task clobber: :make_distclean +end file SO_FILE => "ext/Makefile" do |t| chdir "ext" do diff --git a/bindings/ruby/ext/extconf.rb b/bindings/ruby/ext/extconf.rb index d9d6fc06..f8e44799 100644 --- a/bindings/ruby/ext/extconf.rb +++ b/bindings/ruby/ext/extconf.rb @@ -1,212 +1,61 @@ -require 'mkmf' +require "mkmf" +require "tsort" -# need to use c++ compiler flags -$CXXFLAGS << ' -std=c++17' +# TODO: options such as CoreML -$LDFLAGS << ' -lstdc++' +cmake = find_executable("cmake") || abort -# Set to true when building binary gems -if enable_config('static-stdlib', false) - $LDFLAGS << ' -static-libgcc -static-libstdc++' -end +have_library("gomp") rescue nil -if enable_config('march-tune-native', false) - $CFLAGS << ' -march=native -mtune=native' - $CXXFLAGS << ' -march=native -mtune=native' -end +prefix = File.join("build", "whisper.cpp.dot") +system cmake, "-S", "sources", "-B", "build", "--graphviz", prefix, "-D", "BUILD_SHARED_LIBS=OFF", exception: true -if ENV['WHISPER_METAL'] - $GGML_METAL ||= true - $DEPRECATE_WARNING ||= true -end - -$UNAME_S = `uname -s`.chomp -$UNAME_P = `uname -p`.chomp -$UNAME_M = `uname -m`.chomp - -if $UNAME_S == 'Darwin' - unless ENV['GGML_NO_METAL'] - $GGML_METAL ||= true - end - $GGML_NO_OPENMP ||= true -end - -if $GGML_METAL - $GGML_METAL_EMBED_LIBRARY = true -end - -$MK_CPPFLAGS = '-Iggml/include -Iggml/src -Iggml/src/ggml-cpu -Iinclude -Isrc -Iexamples -DGGML_USE_CPU' -$MK_CFLAGS = '-std=c11 -fPIC' -$MK_CXXFLAGS = '-std=c++17 -fPIC' -$MK_NVCCFLAGS = '-std=c++17' -$MK_LDFLAGS = '' - -$OBJ_GGML = [] -$OBJ_WHISPER = [] -$OBJ_COMMON = [] -$OBJ_SDL = [] - -$MK_CPPFLAGS << ' -D_XOPEN_SOURCE=600' - -if $UNAME_S == 'Linux' - $MK_CPPFLAGS << ' -D_GNU_SOURCE' -end - -if $UNAME_S == 'Darwin' - $MK_CPPFLAGS << ' -D_DARWIN_C_SOURCE' -end - -if ENV['WHISPER_DEBUG'] - $MK_CFLAGS << ' -O0 -g' - $MK_CXXFLAGS << ' -O0 -g' - $MK_LDFLAGS << ' -g' - $MK_NVCCFLAGS << ' -O0 -g' -else - $MK_CPPFLAGS << ' -DNDEBUG' - $MK_CFLAGS << ' -O3' - $MK_CXXFLAGS << ' -O3' - $MK_NVCCFLAGS << ' -O3' -end - -$WARN_FLAGS = - ' -Wall' << - ' -Wextra' << - ' -Wpedantic' << - ' -Wcast-qual' << - ' -Wno-unused-function' - -$MK_CFLAGS << - $WARN_FLAGS << - ' -Wshadow' << - ' -Wstrict-prototypes' << - ' -Wpointer-arith' << - ' -Wmissing-prototypes' << - ' -Werror=implicit-int' << - ' -Werror=implicit-function-declaration' - -$MK_CXXFLAGS << - $WARN_FLAGS << - ' -Wmissing-declarations' << - ' -Wmissing-noreturn' - -unless `#{cc_command} #{$LDFLAGS} -Wl,-v 2>&1`.chomp.include? 'dyld-1015.7' - $MK_CPPFLAGS << ' -DHAVE_BUGGY_APPLE_LINKER' -end - -if %w[Linux Darwin FreeBSD NetBSD OpenBSD Haiku].include? $UNAME_S - $MK_CFLAGS << ' -pthread' - $MK_CXXFLAGS << ' -pthread' -end - -unless $_WIN32 - $DSO_EXT = '.so' -else - $DSO_EXT = '.dll' -end - -unless ENV['RISCV'] - if %w[x86_64 i686 amd64].include? $UNAME_M - $HOST_CXXFLAGS ||= '' - - $MK_CFLAGS << ' -march=native -mtune=native' - $HOST_CXXFLAGS << ' -march=native -mtune=native' - end -else - $MK_CFLAGS << ' -march=rv64gcv -mabi=lp64d' - $MK_CXXFLAGS << ' -march=rv64gcv -mabi=lp64d' -end - -unless ENV['GGML_NO_ACCELERATE'] - if $UNAME_S == 'Darwin' - $MK_CPPFLAGS << ' -DGGML_USE_ACCELERATE -DGGML_USE_BLAS -DGGML_BLAS_USE_ACCELERATE' - $MK_CPPFLAGS << ' -DACCELERATE_NEW_LAPACK' - $MK_CPPFLAGS << ' -DACCELERATE_LAPACK_ILP64' - $MK_LDFLAGS << ' -framework Accelerate' - $OBJ_GGML << 'ggml/src/ggml-blas/ggml-blas.o' +static_lib_shape = nil +nodes = {} +depends = {} +class << depends + include TSort + alias tsort_each_node each_key + def tsort_each_child(node, &block) + fetch(node, []).each(&block) end end - -if ENV['GGML_OPENBLAS'] - $MK_CPPFLAGS << " -DGGML_USE_BLAS #{`pkg-config --cflags-only-I openblas`.chomp}" - $MK_CFLAGS << " #{`pkg-config --cflags-only-other openblas)`.chomp}" - $MK_LDFLAGS << " #{`pkg-config --libs openblas`}" - $OBJ_GGML << 'ggml/src/ggml-blas/ggml-blas.o' -end - -if ENV['GGML_OPENBLAS64'] - $MK_CPPFLAGS << " -DGGML_USE_BLAS #{`pkg-config --cflags-only-I openblas64`.chomp}" - $MK_CFLAGS << " #{`pkg-config --cflags-only-other openblas64)`.chomp}" - $MK_LDFLAGS << " #{`pkg-config --libs openblas64`}" - $OBJ_GGML << 'ggml/src/ggml-blas/ggml-blas.o' -end - -if $GGML_METAL - $MK_CPPFLAGS << ' -DGGML_USE_METAL' - $MK_LDFLAGS << ' -framework Foundation -framework Metal -framework MetalKit' - $OBJ_GGML << 'ggml/src/ggml-metal/ggml-metal.o' - - if ENV['GGML_METAL_NDEBUG'] - $MK_CPPFLAGS << ' -DGGML_METAL_NDEBUG' - end - - if $GGML_METAL_EMBED_LIBRARY - $MK_CPPFLAGS << ' -DGGML_METAL_EMBED_LIBRARY' - $OBJ_GGML << 'ggml/src/ggml-metal/ggml-metal-embed.o' +File.open(File.join("build", "whisper.cpp.dot")).each_line do |line| + case line + when /\[\s*label\s*=\s*"Static Library"\s*,\s*shape\s*=\s*(?\w+)\s*\]/ + static_lib_shape = $~[:shape] + when /\A\s*"(?\w+)"\s*\[\s*label\s*=\s*"(?