|
1 | | -require 'mkmf' |
| 1 | +require "mkmf" |
| 2 | +require "tsort" |
2 | 3 |
|
3 | | -# need to use c++ compiler flags |
4 | | -$CXXFLAGS << ' -std=c++17' |
| 4 | +# TODO: options such as CoreML |
5 | 5 |
|
6 | | -$LDFLAGS << ' -lstdc++' |
| 6 | +cmake = find_executable("cmake") || abort |
7 | 7 |
|
8 | | -# Set to true when building binary gems |
9 | | -if enable_config('static-stdlib', false) |
10 | | - $LDFLAGS << ' -static-libgcc -static-libstdc++' |
11 | | -end |
12 | | - |
13 | | -if enable_config('march-tune-native', false) |
14 | | - $CFLAGS << ' -march=native -mtune=native' |
15 | | - $CXXFLAGS << ' -march=native -mtune=native' |
16 | | -end |
| 8 | +have_library("gomp") rescue nil |
17 | 9 |
|
18 | | -if ENV['WHISPER_METAL'] |
19 | | - $GGML_METAL ||= true |
20 | | - $DEPRECATE_WARNING ||= true |
21 | | -end |
| 10 | +prefix = File.join("build", "whisper.cpp.dot") |
| 11 | +system cmake, "-S", "sources", "-B", "build", "--graphviz", prefix, "-D", "BUILD_SHARED_LIBS=OFF", exception: true |
22 | 12 |
|
23 | | -$UNAME_S = `uname -s`.chomp |
24 | | -$UNAME_P = `uname -p`.chomp |
25 | | -$UNAME_M = `uname -m`.chomp |
26 | | - |
27 | | -if $UNAME_S == 'Darwin' |
28 | | - unless ENV['GGML_NO_METAL'] |
29 | | - $GGML_METAL ||= true |
| 13 | +static_lib_shape = nil |
| 14 | +nodes = {} |
| 15 | +depends = {} |
| 16 | +class << depends |
| 17 | + include TSort |
| 18 | + alias tsort_each_node each_key |
| 19 | + def tsort_each_child(node, &block) |
| 20 | + fetch(node, []).each(&block) |
30 | 21 | end |
31 | | - $GGML_NO_OPENMP ||= true |
32 | | -end |
33 | | - |
34 | | -if $GGML_METAL |
35 | | - $GGML_METAL_EMBED_LIBRARY = true |
36 | | -end |
37 | | - |
38 | | -$MK_CPPFLAGS = '-Iggml/include -Iggml/src -Iggml/src/ggml-cpu -Iinclude -Isrc -Iexamples -DGGML_USE_CPU' |
39 | | -$MK_CFLAGS = '-std=c11 -fPIC' |
40 | | -$MK_CXXFLAGS = '-std=c++17 -fPIC' |
41 | | -$MK_NVCCFLAGS = '-std=c++17' |
42 | | -$MK_LDFLAGS = '' |
43 | | - |
44 | | -$OBJ_GGML = [] |
45 | | -$OBJ_WHISPER = [] |
46 | | -$OBJ_COMMON = [] |
47 | | -$OBJ_SDL = [] |
48 | | - |
49 | | -$MK_CPPFLAGS << ' -D_XOPEN_SOURCE=600' |
50 | | - |
51 | | -if $UNAME_S == 'Linux' |
52 | | - $MK_CPPFLAGS << ' -D_GNU_SOURCE' |
53 | | -end |
54 | | - |
55 | | -if $UNAME_S == 'Darwin' |
56 | | - $MK_CPPFLAGS << ' -D_DARWIN_C_SOURCE' |
57 | | -end |
58 | | - |
59 | | -if ENV['WHISPER_DEBUG'] |
60 | | - $MK_CFLAGS << ' -O0 -g' |
61 | | - $MK_CXXFLAGS << ' -O0 -g' |
62 | | - $MK_LDFLAGS << ' -g' |
63 | | - $MK_NVCCFLAGS << ' -O0 -g' |
64 | | -else |
65 | | - $MK_CPPFLAGS << ' -DNDEBUG' |
66 | | - $MK_CFLAGS << ' -O3' |
67 | | - $MK_CXXFLAGS << ' -O3' |
68 | | - $MK_NVCCFLAGS << ' -O3' |
69 | | -end |
70 | | - |
71 | | -$WARN_FLAGS = |
72 | | - ' -Wall' << |
73 | | - ' -Wextra' << |
74 | | - ' -Wpedantic' << |
75 | | - ' -Wcast-qual' << |
76 | | - ' -Wno-unused-function' |
77 | | - |
78 | | -$MK_CFLAGS << |
79 | | - $WARN_FLAGS << |
80 | | - ' -Wshadow' << |
81 | | - ' -Wstrict-prototypes' << |
82 | | - ' -Wpointer-arith' << |
83 | | - ' -Wmissing-prototypes' << |
84 | | - ' -Werror=implicit-int' << |
85 | | - ' -Werror=implicit-function-declaration' |
86 | | - |
87 | | -$MK_CXXFLAGS << |
88 | | - $WARN_FLAGS << |
89 | | - ' -Wmissing-declarations' << |
90 | | - ' -Wmissing-noreturn' |
91 | | - |
92 | | -unless `#{cc_command} #{$LDFLAGS} -Wl,-v 2>&1`.chomp.include? 'dyld-1015.7' |
93 | | - $MK_CPPFLAGS << ' -DHAVE_BUGGY_APPLE_LINKER' |
94 | | -end |
95 | | - |
96 | | -if %w[Linux Darwin FreeBSD NetBSD OpenBSD Haiku].include? $UNAME_S |
97 | | - $MK_CFLAGS << ' -pthread' |
98 | | - $MK_CXXFLAGS << ' -pthread' |
99 | | -end |
100 | | - |
101 | | -unless $_WIN32 |
102 | | - $DSO_EXT = '.so' |
103 | | -else |
104 | | - $DSO_EXT = '.dll' |
105 | 22 | end |
106 | | - |
107 | | -unless ENV['RISCV'] |
108 | | - if %w[x86_64 i686 amd64].include? $UNAME_M |
109 | | - $HOST_CXXFLAGS ||= '' |
110 | | - |
111 | | - $MK_CFLAGS << ' -march=native -mtune=native' |
112 | | - $HOST_CXXFLAGS << ' -march=native -mtune=native' |
113 | | - end |
114 | | -else |
115 | | - $MK_CFLAGS << ' -march=rv64gcv -mabi=lp64d' |
116 | | - $MK_CXXFLAGS << ' -march=rv64gcv -mabi=lp64d' |
117 | | -end |
118 | | - |
119 | | -unless ENV['GGML_NO_ACCELERATE'] |
120 | | - if $UNAME_S == 'Darwin' |
121 | | - $MK_CPPFLAGS << ' -DGGML_USE_ACCELERATE -DGGML_USE_BLAS -DGGML_BLAS_USE_ACCELERATE' |
122 | | - $MK_CPPFLAGS << ' -DACCELERATE_NEW_LAPACK' |
123 | | - $MK_CPPFLAGS << ' -DACCELERATE_LAPACK_ILP64' |
124 | | - $MK_LDFLAGS << ' -framework Accelerate' |
125 | | - $OBJ_GGML << 'ggml/src/ggml-blas/ggml-blas.o' |
126 | | - end |
127 | | -end |
128 | | - |
129 | | -if ENV['GGML_OPENBLAS'] |
130 | | - $MK_CPPFLAGS << " -DGGML_USE_BLAS #{`pkg-config --cflags-only-I openblas`.chomp}" |
131 | | - $MK_CFLAGS << " #{`pkg-config --cflags-only-other openblas)`.chomp}" |
132 | | - $MK_LDFLAGS << " #{`pkg-config --libs openblas`}" |
133 | | - $OBJ_GGML << 'ggml/src/ggml-blas/ggml-blas.o' |
134 | | -end |
135 | | - |
136 | | -if ENV['GGML_OPENBLAS64'] |
137 | | - $MK_CPPFLAGS << " -DGGML_USE_BLAS #{`pkg-config --cflags-only-I openblas64`.chomp}" |
138 | | - $MK_CFLAGS << " #{`pkg-config --cflags-only-other openblas64)`.chomp}" |
139 | | - $MK_LDFLAGS << " #{`pkg-config --libs openblas64`}" |
140 | | - $OBJ_GGML << 'ggml/src/ggml-blas/ggml-blas.o' |
141 | | -end |
142 | | - |
143 | | -if $GGML_METAL |
144 | | - $MK_CPPFLAGS << ' -DGGML_USE_METAL' |
145 | | - $MK_LDFLAGS << ' -framework Foundation -framework Metal -framework MetalKit' |
146 | | - $OBJ_GGML << 'ggml/src/ggml-metal/ggml-metal.o' |
147 | | - |
148 | | - if ENV['GGML_METAL_NDEBUG'] |
149 | | - $MK_CPPFLAGS << ' -DGGML_METAL_NDEBUG' |
150 | | - end |
151 | | - |
152 | | - if $GGML_METAL_EMBED_LIBRARY |
153 | | - $MK_CPPFLAGS << ' -DGGML_METAL_EMBED_LIBRARY' |
154 | | - $OBJ_GGML << 'ggml/src/ggml-metal/ggml-metal-embed.o' |
| 23 | +File.open(File.join("build", "whisper.cpp.dot")).each_line do |line| |
| 24 | + case line |
| 25 | + when /\[\s*label\s*=\s*"Static Library"\s*,\s*shape\s*=\s*(?<shape>\w+)\s*\]/ |
| 26 | + static_lib_shape = $~[:shape] |
| 27 | + when /\A\s*"(?<node>\w+)"\s*\[\s*label\s*=\s*"(?<label>\S+)"\s*,\s*shape\s*=\s*(?<shape>\w+)\s*\]\s*;\s*\z/ |
| 28 | + node = $~[:node] |
| 29 | + label = $~[:label] |
| 30 | + shape = $~[:shape] |
| 31 | + nodes[node] = [label, shape] |
| 32 | + when /\A\s*"(?<depender>\w+)"\s*->\s*"(?<dependee>\w+)"/ |
| 33 | + depender = $~[:depender] |
| 34 | + dependee = $~[:dependee] |
| 35 | + depends[depender] ||= [] |
| 36 | + depends[depender] << dependee |
155 | 37 | end |
156 | 38 | end |
157 | | - |
158 | | -$OBJ_GGML << |
159 | | - 'ggml/src/ggml.o' << |
160 | | - 'ggml/src/ggml-alloc.o' << |
161 | | - 'ggml/src/ggml-backend.o' << |
162 | | - 'ggml/src/ggml-backend-reg.o' << |
163 | | - 'ggml/src/ggml-opt.o' << |
164 | | - 'ggml/src/ggml-quants.o' << |
165 | | - 'ggml/src/ggml-threading.o' << |
166 | | - 'ggml/src/ggml-cpu/ggml-cpu.o' << |
167 | | - 'ggml/src/ggml-cpu/ggml-cpu-cpp.o' << |
168 | | - 'ggml/src/ggml-cpu/ggml-cpu-aarch64.o' << |
169 | | - 'ggml/src/ggml-cpu/ggml-cpu-hbm.o' << |
170 | | - 'ggml/src/ggml-cpu/ggml-cpu-quants.o' << |
171 | | - 'ggml/src/ggml-cpu/ggml-cpu-traits.o' << |
172 | | - 'ggml/src/ggml-cpu/unary-ops.o' << |
173 | | - 'ggml/src/ggml-cpu/binary-ops.o' << |
174 | | - 'ggml/src/ggml-cpu/vec.o' << |
175 | | - 'ggml/src/ggml-cpu/ops.o' |
176 | | - |
177 | | -$OBJ_WHISPER << |
178 | | - 'src/whisper.o' << |
179 | | - 'examples/common.o' << |
180 | | - 'examples/common-whisper.o' |
181 | | - |
182 | | -$objs = $OBJ_GGML + $OBJ_WHISPER + $OBJ_COMMON + $OBJ_SDL |
183 | | -$objs << |
184 | | - "ruby_whisper.o" << |
185 | | - "ruby_whisper_context.o" << |
186 | | - "ruby_whisper_transcribe.o" << |
187 | | - "ruby_whisper_params.o" << |
188 | | - "ruby_whisper_error.o" << |
189 | | - "ruby_whisper_segment.o" << |
190 | | - "ruby_whisper_model.o" |
191 | | - |
192 | | -$CPPFLAGS = "#{$MK_CPPFLAGS} #{$CPPFLAGS}" |
193 | | -$CFLAGS = "#{$CPPFLAGS} #{$MK_CFLAGS} #{$GF_CFLAGS} #{$CFLAGS}" |
194 | | -$BASE_CXXFLAGS = "#{$MK_CXXFLAGS} #{$CXXFLAGS}" |
195 | | -$CXXFLAGS = "#{$BASE_CXXFLAGS} #{$HOST_CXXFLAGS} #{$GF_CXXFLAGS} #{$CPPFLAGS}" |
196 | | -$NVCCFLAGS = "#{$MK_NVCCFLAGS} #{$NVCCFLAGS}" |
197 | | -$LDFLAGS = "#{$MK_LDFLAGS} #{$LDFLAGS}" |
198 | | - |
199 | | -create_makefile('whisper') |
200 | | - |
201 | | -File.open 'Makefile', 'a' do |file| |
202 | | - file.puts 'include scripts/get-flags.mk' |
203 | | - file.puts 'include cpu.mk' |
204 | | - |
205 | | - if $GGML_METAL |
206 | | - file.puts 'include metal.mk' |
207 | | - |
208 | | - if $GGML_METAL_EMBED_LIBRARY |
209 | | - file.puts 'include metal-embed.mk' |
210 | | - end |
211 | | - end |
| 39 | +libs = depends.tsort.filter_map {|node| |
| 40 | + label, shape = nodes[node] |
| 41 | + shape == static_lib_shape ? label : nil |
| 42 | +}.collect {|lib| "lib#{lib}.a"} |
| 43 | + .reverse |
| 44 | + .join(" ") |
| 45 | + |
| 46 | +$CFLAGS << " -std=c11 -fPIC" |
| 47 | +$CXXFLAGS << " -std=c++17 -O3 -DNDEBUG" |
| 48 | +$INCFLAGS << " -Isources/include -Isources/ggml/include -Isources/examples" |
| 49 | +$LOCAL_LIBS << " #{libs}" |
| 50 | +$cleanfiles << " build #{libs}" |
| 51 | + |
| 52 | +create_makefile "whisper" do |conf| |
| 53 | + conf << <<~EOF |
| 54 | + $(TARGET_SO): #{libs} |
| 55 | + #{libs}: cmake-targets |
| 56 | + cmake-targets: |
| 57 | + #{"\t"}#{cmake} -S sources -B build -D BUILD_SHARED_LIBS=OFF -D CMAKE_ARCHIVE_OUTPUT_DIRECTORY=#{__dir__} -D CMAKE_POSITION_INDEPENDENT_CODE=ON |
| 58 | + #{"\t"}#{cmake} --build build --config Release --target common whisper |
| 59 | + #{"\t"} |
| 60 | + EOF |
212 | 61 | end |
0 commit comments