summaryrefslogtreecommitdiff
path: root/misc/ollama/files/patch-FreeBSD-compatibility
blob: 046ca9b3417c107e9cb4c665cef1ae3319a1335c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
-- patch based on https://github.com/ollama/ollama/issues/1102#issuecomment-2270042340

new file mode 100644
--- gpu/gpu_bsd.go.orig	2024-08-18 20:03:12 UTC
+++ gpu/gpu_bsd.go
@@ -0,0 +1,122 @@
+//go:build dragonfly || freebsd || netbsd || openbsd
+
+package gpu
+
+import "github.com/ollama/ollama/format"
+//import sysctl "github.com/lorenzosaino/go-sysctl" // sysctl: this is Linux-only, see https://github.com/lorenzosaino/go-sysctl/issues/7
+import sysctl "github.com/blabber/go-freebsd-sysctl/sysctl" // sysctl: this is FreeBSD-only basic library
+import (
+	"log/slog"
+)
+
+/*
+#cgo CFLAGS: -I/usr/local/include
+#cgo LDFLAGS: -L/usr/local/lib -lvulkan
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <vulkan/vulkan.h>
+
+bool hasVulkanSupport(uint64_t *memSize) {
+  VkInstance instance;
+
+	VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+	appInfo.pApplicationName = "Ollama";
+	appInfo.apiVersion = VK_API_VERSION_1_0;
+
+	VkInstanceCreateInfo createInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+	createInfo.pApplicationInfo = &appInfo;
+
+	// Create a Vulkan instance
+	if (vkCreateInstance(&createInfo, NULL, &instance) != VK_SUCCESS)
+		return false;
+
+	// Fetch the first physical Vulkan device. Note that numDevices is overwritten with the number of devices found
+	uint32_t numDevices = 1;
+	VkPhysicalDevice device;
+	vkEnumeratePhysicalDevices(instance, &numDevices, &device);
+	if (numDevices == 0) {
+		vkDestroyInstance(instance, NULL);
+		return false;
+	}
+
+	// Fetch the memory information for this device.
+	VkPhysicalDeviceMemoryProperties memProperties;
+	vkGetPhysicalDeviceMemoryProperties(device, &memProperties);
+
+	// Add up all the heaps.
+	VkDeviceSize totalMemory = 0;
+	for (uint32_t i = 0; i < memProperties.memoryHeapCount; ++i) {
+		if (memProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
+			*memSize += memProperties.memoryHeaps[i].size;
+		}
+	}
+
+	vkDestroyInstance(instance, NULL);
+	return true;
+}
+*/
+import "C"
+
+func GetGPUInfo() GpuInfoList {
+	var gpuMem C.uint64_t
+	if C.hasVulkanSupport(&gpuMem) {
+		// Vulkan supported
+		return []GpuInfo{
+			{
+				Library: 				"vulkan",
+				ID:							"0",
+				MinimumMemory: 	512 * format.MebiByte,
+				memInfo: 	memInfo{
+					FreeMemory: uint64(gpuMem),
+					TotalMemory: uint64(gpuMem),
+				},
+			},
+		}
+	}
+
+	// CPU fallback
+	cpuMem, _ := GetCPUMem()
+	return []GpuInfo{
+		{
+			Library: "cpu",
+			memInfo: cpuMem,
+		},
+	}
+}
+
+func GetCPUInfo() GpuInfoList {
+	mem, _ := GetCPUMem()
+	return []GpuInfo{
+		{
+			Library: "cpu",
+			Variant: GetCPUCapability(),
+			memInfo: mem,
+		},
+	}
+}
+
+func GetCPUMem() (memInfo, error) {
+	// all involved sysctl variables
+	sysctl_vm_page_size, _ := sysctl.GetInt64("vm.stats.vm.v_page_size") // memory page size
+	sysctl_hw_physmem, _ := sysctl.GetInt64("hw.physmem") // physical memory in bytes
+	sysctl_vm_free_count, _ := sysctl.GetInt64("vm.stats.vm.v_free_count") // free page count
+	sysctl_vm_swap_total, _ := sysctl.GetInt64("vm.swap_total") // total swap size in bytes
+
+	// individual values
+	total_memory := uint64(sysctl_hw_physmem)
+	free_memory := uint64(sysctl_vm_free_count) * uint64(sysctl_vm_page_size)
+	free_swap := uint64(sysctl_vm_swap_total) // wrong to use the total swap size here, should be vm.swap_free, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=280909
+
+	slog.Debug("gpu_bsd.go::GetCPUMem::GetCPUMem", "total_memory", total_memory, "free_memory", free_memory, "free_swap", free_swap)
+
+	return memInfo{
+		TotalMemory: uint64(total_memory),
+		FreeMemory: uint64(free_memory),
+		FreeSwap: uint64(free_swap),
+	}, nil
+}
+
+func (l GpuInfoList) GetVisibleDevicesEnv() (string, string) {
+	return "", ""
+}
--- gpu/gpu_test.go.orig	1979-11-30 08:00:00 UTC
+++ gpu/gpu_test.go
@@ -11,7 +11,7 @@ func TestBasicGetGPUInfo(t *testing.T) {
 func TestBasicGetGPUInfo(t *testing.T) {
 	info := GetGPUInfo()
 	assert.NotEmpty(t, len(info))
-	assert.Contains(t, "cuda rocm cpu metal", info[0].Library)
+	assert.Contains(t, "cuda rocm cpu metal vulkan", info[0].Library)
 	if info[0].Library != "cpu" {
 		assert.Greater(t, info[0].TotalMemory, uint64(0))
 		assert.Greater(t, info[0].FreeMemory, uint64(0))
@@ -24,6 +24,8 @@ func TestCPUMemInfo(t *testing.T) {
 	switch runtime.GOOS {
 	case "darwin":
 		t.Skip("CPU memory not populated on darwin")
+	case "dragonfly", "freebsd", "netbsd", "openbsd":
+	  t.Skip("CPU memory is not populated on *BSD")
 	case "linux", "windows":
 		assert.Greater(t, info.TotalMemory, uint64(0))
 		assert.Greater(t, info.FreeMemory, uint64(0))
--- llm/generate/gen_bsd.sh.orig	2024-08-06 16:29:05 UTC
+++ llm/generate/gen_bsd.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# This script is intended to run inside the go generate
+# working directory must be ./llm/generate/
+
+set -ex
+set -o pipefail
+echo "Starting BSD generate script"
+. $(dirname $0)/gen_common.sh
+init_vars
+#git_module_setup
+apply_patches
+
+COMMON_BSD_DEFS="-DCMAKE_SYSTEM_NAME=$(uname -s)"
+CMAKE_TARGETS="--target llama --target ggml"
+
+COMMON_CPU_DEFS="${COMMON_BSD_DEFS} -DCMAKE_SYSTEM_PROCESSOR=${ARCH} -DBUILD_SHARED_LIBS=off"
+
+# Static build for linking into the Go binary
+init_vars
+CMAKE_DEFS="${COMMON_CPU_DEFS} -DGGML_VULKAN=on -DGGML_ACCELERATE=off -DGGML_AVX=off -DGGML_AVX2=off -DGGML_AVX512=off -DGGML_FMA=off -DGGML_F16C=off ${CMAKE_DEFS}"
+BUILD_DIR="../build/bsd/${ARCH}_static"
+echo "Building static library"
+build
+
+init_vars
+CMAKE_DEFS="${COMMON_CPU_DEFS} -DGGML_AVX=off -DGGML_AVX2=off -DGGML_AVX512=off -DGGML_FMA=off -DGGML_F16C=off ${CMAKE_DEFS}"
+BUILD_DIR="../build/bsd/${ARCH}/cpu"
+echo "Building LCD CPU"
+build
+compress
+
+init_vars
+CMAKE_DEFS="${COMMON_CPU_DEFS} -DGGML_AVX=on -DGGML_AVX2=off -DGGML_AVX512=off -DGGML_FMA=off -DGGML_F16C=off ${CMAKE_DEFS}"
+BUILD_DIR="../build/bsd/${ARCH}/cpu_avx"
+echo "Building AVX CPU"
+build
+compress
+
+init_vars
+CMAKE_DEFS="${COMMON_CPU_DEFS} -DGGML_AVX=on -DGGML_AVX2=on -DGGML_AVX512=off -DGGML_FMA=on -DGGML_F16C=on ${CMAKE_DEFS}"
+BUILD_DIR="../build/bsd/${ARCH}/cpu_avx2"
+echo "Building AVX2 CPU"
+build
+compress
+
+init_vars
+CMAKE_DEFS="${COMMON_CPU_DEFS} -DGGML_VULKAN=on ${CMAKE_DEFS}"
+BUILD_DIR="../build/bsd/${ARCH}/vulkan"
+echo "Building Vulkan GPU"
+build
+compress
+
+cleanup
+echo "go generate completed.  LLM runners: $(cd ${BUILD_DIR}/..; echo *)"
--- llm/generate/generate_bsd.go.orig	2024-08-06 07:41:26 UTC
+++ llm/generate/generate_bsd.go
@@ -0,0 +1,5 @@
+//go:build dragonfly || freebsd || netbsd || openbsd
+
+package generate
+
+//go:generate bash ./gen_bsd.sh
--- llm/llm.go.orig	1979-11-30 08:00:00 UTC
+++ llm/llm.go
@@ -8,6 +8,10 @@ package llm
 // #cgo windows,arm64 LDFLAGS: -static-libstdc++ -static-libgcc -static -L${SRCDIR}/build/windows/arm64_static -L${SRCDIR}/build/windows/arm64_static/src -L${SRCDIR}/build/windows/arm64_static/ggml/src
 // #cgo linux,amd64 LDFLAGS: -L${SRCDIR}/build/linux/x86_64_static -L${SRCDIR}/build/linux/x86_64_static/src -L${SRCDIR}/build/linux/x86_64_static/ggml/src
 // #cgo linux,arm64 LDFLAGS: -L${SRCDIR}/build/linux/arm64_static -L${SRCDIR}/build/linux/arm64_static/src -L${SRCDIR}/build/linux/arm64_static/ggml/src
+// #cgo dragonfly,amd64 LDFLAGS: ${SRCDIR}/build/bsd/x86_64_static/src/libllama.a -lstdc++ -lm
+// #cgo freebsd,amd64 LDFLAGS: -L${SRCDIR}/build/bsd/x86_64_static/src -lllama -L${SRCDIR}/build/bsd/x86_64_static/ggml/src -lggml -lstdc++ -lm -lomp
+// #cgo netbsd,amd64 LDFLAGS: ${SRCDIR}/build/bsd/x86_64_static/src/libllama.a -lstdc++ -lm
+// #cgo openbsd,amd64 LDFLAGS: ${SRCDIR}/build/bsd/x86_64_static/src/libllama.a -lstdc++ -lm
 // #include <stdlib.h>
 // #include "llama.h"
 import "C"
--- llm/llm_bsd.go.orig	2024-08-06 07:41:26 UTC
+++ llm/llm_bsd.go
@@ -0,0 +1,13 @@
+//go:build dragonfly || freebsd || netbsd || openbsd
+
+package llm
+
+import (
+	"embed"
+	"syscall"
+)
+
+//go:embed build/bsd/*/*/bin/*
+var libEmbed embed.FS
+
+var LlamaServerSysProcAttr = &syscall.SysProcAttr{}
--- scripts/build_bsd.sh.orig	2024-08-06 07:41:26 UTC
+++ scripts/build_bsd.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -e
+
+case "$(uname -s)" in
+  DragonFly)
+    ;;
+  FreeBSD)
+    ;;
+  NetBSD)
+    ;;
+  OpenBSD)
+    ;;
+  *)
+    echo "$(uname -s) is not supported"
+    exit 1
+    ;;
+esac
+
+export VERSION=${VERSION:-$(git describe --tags --first-parent --abbrev=7 --long --dirty --always | sed -e "s/^v//g")}
+export GOFLAGS="'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=$VERSION\" \"-X=github.com/ollama/ollama/server.mode=release\"'"
+
+mkdir -p dist
+rm -rf llm/llama.cpp/build
+
+go generate ./...
+CGO_ENABLED=1 go build -trimpath -o dist/ollama-bsd
--- scripts/build_freebsd.sh.orig	2024-08-06 07:41:26 UTC
+++ scripts/build_freebsd.sh
@@ -0,0 +1 @@
+build_bsd.sh
\ No newline at end of file