summaryrefslogtreecommitdiffstats
path: root/Makefile
blob: b37ecfe1a006ae06a62fb6ae9e974f2a7ef18ccc (plain)
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
CC            = cc
CXX           = c++
CFLAGS        = -march=native -O2 -std=c11 -Wall -Wextra
CXXFLAGS      = -march=native -O2 -O2 -Wall -Wextra
INCLUDES      = -I. -Ideps/include

LLAMA_TAG     = b10107
LLAMA_URL     = https://github.com/ggml-org/llama.cpp/archive/refs/tags/$(LLAMA_TAG).tar.gz
LLAMA_TAR     = deps/llama-$(LLAMA_TAG).tar.gz
LLAMA_SRC_DIR = deps/llama.cpp-src
LLAMA_BUILD   = $(LLAMA_SRC_DIR)/build

STATIC_LIBS   = deps/lib/libllama.a \
                deps/lib/libggml.a \
                deps/lib/libggml-cpu.a \

# System flags required for static linking llama on OpenBSD
SYS_LIBS      = -static -pthread -lm -lc++ -lc++abi

TARGET        = lexd
SRC           = llm.c main.c
OBJS          = $(SRC:.c=.o)

# Standard tools and target directory
BINDIR        = /usr/local/bin
RCDIR         = /etc/rc.d
VARDIR        = /var/$(TARGET)
INSTALL       = install
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_SCRIPT  = $(INSTALL) -m 555
MKDIR_P       = mkdir -p

# Service user configuration
SERVICE_USER    = _lexd
SERVICE_GROUP   = _lexd

.PHONY: all clean distclean

all: $(TARGET)

# Explicit link order: libllama -> libggml-cpu -> libggml -> libggml-base
$(TARGET): deps/lib/libllama.a $(OBJS)
	$(CXX) $(CXXFLAGS) $(OBJS) \
		-Wl,--start-group \
		deps/lib/libllama.a \
		deps/lib/libggml-cpu.a \
		deps/lib/libggml.a \
		deps/lib/libggml-base.a \
		-Wl,--end-group \
		$(SYS_LIBS) -o $@

# BSD suffix rule: compiles any .c file into .o
.c.o:
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

# Rebuild objects if the shared header changes
$(OBJS): llm.h

# Download llama source and build statically
deps/lib/libllama.a deps/lib/libggml.a deps/lib/libggml-cpu.a:
	@mkdir -p deps/lib deps/include
	@echo "===> Downloading llama.cpp $(LLAMA_TAG) source..."
	ftp -o $(LLAMA_TAR) $(LLAMA_URL)

	@echo "===> Extracting source archive..."
	tar -xzf $(LLAMA_TAR) -C deps
	rm -rf $(LLAMA_SRC_DIR)
	mv deps/llama.cpp-$(LLAMA_TAG) $(LLAMA_SRC_DIR)
	rm -f $(LLAMA_TAR)
	
	@echo "===> Compiling llama static archives..."
	cmake -S $(LLAMA_SRC_DIR) -B $(LLAMA_BUILD) \
		-DCMAKE_BUILD_TYPE=Release \
		-DBUILD_SHARED_LIBS=OFF \
		-DGGML_OPENMP=OFF \
		-DGGML_VULKAN=OFF \
		-DLLAMA_BUILD_APP=OFF \
		-DLLAMA_BUILD_COMMON=OFF \
		-DLLAMA_BUILD_TESTS=OFF \
        -DLLAMA_BUILD_UI=OFF \
		-DLLAMA_BUILD_EXAMPLES=OFF \
		-DLLAMA_BUILD_SERVER=OFF \
		-DLLAMA_BUILD_TOOLS=OFF

	cmake --build $(LLAMA_BUILD) --config Release -j$$(sysctl -n hw.ncpu)

	@echo "===> Installing .a files and headers into deps/..."
	find $(LLAMA_BUILD) -type f -name "*.a" -exec cp {} deps/lib/ \;
	cp -R $(LLAMA_SRC_DIR)/include/* deps/include/
	cp -R $(LLAMA_SRC_DIR)/ggml/include/* deps/include/

	@echo "===> Cleaning up build directory..."
	rm -rf $(LLAMA_SRC_DIR)

install-user:
	@if ! id -u $(SERVICE_USER) >/dev/null 2>&1; then \
		echo "===> Creating service user..."; \
		groupadd $(SERVICE_GROUP) 2>/dev/null || true; \
		useradd -g $(SERVICE_GROUP) -s /sbin/nologin -m -c "lexd daemon user" $(SERVICE_USER); \
	fi

install: $(TARGET) install-user
	@$(MKDIR_P) $(BINDIR)
	@echo "===> Installing executable to $(BINDIR)/$(TARGET)..."
	@$(INSTALL_PROGRAM) $(TARGET) $(BINDIR)/$(TARGET)
	@echo "===> Installing RC script to $(DESTDIR)$(RCDIR)/$(TARGET)..."
	@$(MKDIR_P) $(RCDIR)
	@$(INSTALL_SCRIPT) $(TARGET).rc $(RCDIR)/$(TARGET)
	@echo "===> Creating data directory $(VARDIR)..."
	@$(MKDIR_P) $(VARDIR)
	@chown $(SERVICE_USER):$(SERVICE_GROUP) $(VARDIR)
	@chmod 750 $(VARDIR)
	@echo "===> Installation complete."

uninstall:
	@echo "===> Stopping service..."
	@-rcctl stop $(TARGET) 2>/dev/null || true
	@rm -f $(BINDIR)/$(TARGET)
	@rm -f $(RCDIR)/$(TARGET)
	@echo "Uninstall complete."
	@echo "Note: The data directory and service accounts were preserved."
	@echo "To remove all remaining data, run:"
	@echo "  # rm -rf $(VARDIR)"
	@echo "  # userdel -r $(SERVICE_USER)"
	@echo "  # groupdel $(SERVICE_GROUP)"

clean:
	rm -f $(TARGET) $(OBJS)
	
distclean: clean
	rm -rf deps