-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMakefile
More file actions
255 lines (227 loc) · 10.9 KB
/
Copy pathMakefile
File metadata and controls
255 lines (227 loc) · 10.9 KB
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
# Gem Programming Language Interpreter Makefile
# Compiler settings
CC = gcc
CFLAGS = -O3 -flto -DNDEBUG
LDFLAGS = -lm
# Directories
SRC_DIR = src
STL_DIR = stl
BIN_DIR = bin
DOCS_DIR = docs
# Source files
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
STL_FILES = $(wildcard $(STL_DIR)/*.gem)
# Generated files
EMBEDDED_STL_HEADER = $(SRC_DIR)/embedded_stl.h
VERSION_HEADER = $(SRC_DIR)/version.h
VERSION_CONF = version.conf
# Load version from configuration file
include $(VERSION_CONF)
# Calculate derived version strings
ifeq ($(strip $(VERSION_SUFFIX)),)
VERSION_STRING := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
VERSION_DISPLAY := v$(VERSION_STRING)
else
VERSION_STRING := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)-$(VERSION_SUFFIX)
VERSION_DISPLAY := v$(VERSION_STRING)
endif
# Default target - compile with standard library
all: $(BIN_DIR)/gemc
# Generate version header from version configuration
$(VERSION_HEADER): $(VERSION_CONF)
@echo "Generating version header..."
@echo "// Auto-generated file - do not edit manually" > $(VERSION_HEADER)
@echo "// Generated from $(VERSION_CONF)" >> $(VERSION_HEADER)
@echo "" >> $(VERSION_HEADER)
@echo "#ifndef VERSION_H" >> $(VERSION_HEADER)
@echo "#define VERSION_H" >> $(VERSION_HEADER)
@echo "" >> $(VERSION_HEADER)
@echo "#define VERSION_MAJOR $(VERSION_MAJOR)" >> $(VERSION_HEADER)
@echo "#define VERSION_MINOR $(VERSION_MINOR)" >> $(VERSION_HEADER)
@echo "#define VERSION_PATCH $(VERSION_PATCH)" >> $(VERSION_HEADER)
@echo "#define VERSION_SUFFIX \"$(VERSION_SUFFIX)\"" >> $(VERSION_HEADER)
@echo "" >> $(VERSION_HEADER)
@echo "#define VERSION_STRING \"$(VERSION_STRING)\"" >> $(VERSION_HEADER)
@echo "#define VERSION_DISPLAY \"$(VERSION_DISPLAY)\"" >> $(VERSION_HEADER)
@echo "" >> $(VERSION_HEADER)
@echo "// Helper macros for version comparisons" >> $(VERSION_HEADER)
@echo "#define VERSION_NUMBER ((VERSION_MAJOR * 10000) + (VERSION_MINOR * 100) + VERSION_PATCH)" >> $(VERSION_HEADER)
@echo "" >> $(VERSION_HEADER)
@echo "#endif // VERSION_H" >> $(VERSION_HEADER)
@echo "Generated $(VERSION_HEADER) with version $(VERSION_STRING)"
# Update documentation files with current version
update-docs: $(VERSION_HEADER)
@echo "Updating documentation with version $(VERSION_STRING)..."
@if [ -f "$(DOCS_DIR)/index.html" ]; then \
sed -i.bak 's/<span class="version">v[^<]*<\/span>/<span class="version">$(VERSION_DISPLAY)<\/span>/g' $(DOCS_DIR)/index.html; \
sed -i.bak 's/<span class="version-badge">v[^<]*<\/span>/<span class="version-badge">$(VERSION_DISPLAY)<\/span>/g' $(DOCS_DIR)/index.html; \
sed -i.bak 's/Gem Programming Language v[^<]*/Gem Programming Language $(VERSION_DISPLAY)/g' $(DOCS_DIR)/index.html; \
rm -f $(DOCS_DIR)/index.html.bak; \
echo "Updated $(DOCS_DIR)/index.html"; \
fi
@if [ -f "$(DOCS_DIR)/changeblog.html" ]; then \
sed -i.bak 's/Gem Programming Language v[^<]*/Gem Programming Language $(VERSION_DISPLAY)/g' $(DOCS_DIR)/changeblog.html; \
rm -f $(DOCS_DIR)/changeblog.html.bak; \
echo "Updated $(DOCS_DIR)/changeblog.html"; \
fi
# Generate embedded STL header from STL files
$(EMBEDDED_STL_HEADER): $(STL_FILES)
@echo "Generating embedded STL header..."
@echo "// Auto-generated file - do not edit manually" > $(EMBEDDED_STL_HEADER)
@echo "// Generated from STL files in $(STL_DIR)/ directory" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@echo "#ifndef EMBEDDED_STL_H" >> $(EMBEDDED_STL_HEADER)
@echo "#define EMBEDDED_STL_H" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@echo "#ifdef WITH_STL" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@for stl_file in $(STL_FILES); do \
module_name=$$(basename "$$stl_file" .gem); \
module_name_upper=$$(echo "$$module_name" | tr '[:lower:]' '[:upper:]'); \
echo "Processing $$stl_file -> $$module_name"; \
echo "// Embedded STL module: $$module_name" >> $(EMBEDDED_STL_HEADER); \
printf "static const char STL_%s_MODULE[] = \n" "$$module_name_upper" >> $(EMBEDDED_STL_HEADER); \
first_line=true; \
while IFS= read -r line; do \
escaped_line=$$(printf '%s' "$$line" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g'); \
if [ "$$first_line" = true ]; then \
printf '"%s\\n"\n' "$$escaped_line" >> $(EMBEDDED_STL_HEADER); \
first_line=false; \
else \
printf '"%s\\n"\n' "$$escaped_line" >> $(EMBEDDED_STL_HEADER); \
fi; \
done < "$$stl_file"; \
echo ";" >> $(EMBEDDED_STL_HEADER); \
echo "" >> $(EMBEDDED_STL_HEADER); \
done
@echo "// STL module lookup table" >> $(EMBEDDED_STL_HEADER)
@echo "typedef struct {" >> $(EMBEDDED_STL_HEADER)
@echo " const char* name;" >> $(EMBEDDED_STL_HEADER)
@echo " const char* source;" >> $(EMBEDDED_STL_HEADER)
@echo "} EmbeddedSTLModule;" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@echo "static const EmbeddedSTLModule EMBEDDED_STL_MODULES[] = {" >> $(EMBEDDED_STL_HEADER)
@for stl_file in $(STL_FILES); do \
module_name=$$(basename "$$stl_file" .gem); \
module_name_upper=$$(echo "$$module_name" | tr '[:lower:]' '[:upper:]'); \
echo " {\"$$module_name\", STL_$${module_name_upper}_MODULE}," >> $(EMBEDDED_STL_HEADER); \
done
@echo " {NULL, NULL} // Sentinel" >> $(EMBEDDED_STL_HEADER)
@echo "};" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@echo "// Function to get embedded STL module source" >> $(EMBEDDED_STL_HEADER)
@echo "static const char* getEmbeddedSTLModule(const char* moduleName) {" >> $(EMBEDDED_STL_HEADER)
@echo " for (int i = 0; EMBEDDED_STL_MODULES[i].name != NULL; i++) {" >> $(EMBEDDED_STL_HEADER)
@echo " if (strcmp(EMBEDDED_STL_MODULES[i].name, moduleName) == 0) {" >> $(EMBEDDED_STL_HEADER)
@echo " return EMBEDDED_STL_MODULES[i].source;" >> $(EMBEDDED_STL_HEADER)
@echo " }" >> $(EMBEDDED_STL_HEADER)
@echo " }" >> $(EMBEDDED_STL_HEADER)
@echo " return NULL;" >> $(EMBEDDED_STL_HEADER)
@echo "}" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@echo "#endif // WITH_STL" >> $(EMBEDDED_STL_HEADER)
@echo "" >> $(EMBEDDED_STL_HEADER)
@echo "#endif // EMBEDDED_STL_H" >> $(EMBEDDED_STL_HEADER)
@echo "Generated $(EMBEDDED_STL_HEADER) with embedded STL modules"
# Compile with standard library (default)
$(BIN_DIR)/gemc: $(SRC_FILES) $(EMBEDDED_STL_HEADER) $(VERSION_HEADER)
@mkdir -p $(BIN_DIR)
@echo "Building Gem interpreter with standard library..."
$(CC) $(SRC_FILES) -o $(BIN_DIR)/gemc $(CFLAGS) $(LDFLAGS) -DWITH_STL -DSTL_PATH='"$(STL_DIR)"'
@echo "Built: $(BIN_DIR)/gemc (with standard library) - version $(VERSION_STRING)"
# Compile without standard library
$(BIN_DIR)/gemch: $(SRC_FILES) $(VERSION_HEADER)
@mkdir -p $(BIN_DIR)
@echo "Building Gem interpreter without standard library..."
$(CC) $(SRC_FILES) -o $(BIN_DIR)/gemch $(CFLAGS) $(LDFLAGS)
@echo "Built: $(BIN_DIR)/gemch (without standard library) - version $(VERSION_STRING)"
# WASM build targets
EMCC = emcc
WASM_CFLAGS = -O3 -s WASM=1 -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s EXPORT_NAME="GemModule" -s ENVIRONMENT=web -s EXPORTED_FUNCTIONS='["_gem_init","_gem_cleanup","_gem_clear_output","_gem_get_output","_gem_add_to_output","_gem_interpret","_gem_get_version","_gem_is_initialized"]'
WASM_SRC_FILES = $(filter-out $(SRC_DIR)/main.c, $(SRC_FILES))
# Build WASM version with standard library
$(DOCS_DIR)/gem.js: $(WASM_SRC_FILES) $(EMBEDDED_STL_HEADER) $(VERSION_HEADER)
@echo "Building Gem interpreter for WebAssembly with standard library..."
$(EMCC) $(WASM_SRC_FILES) -o $(DOCS_DIR)/gem.js $(WASM_CFLAGS) -DWITH_STL -DSTL_PATH='"$(STL_DIR)"'
@echo "Built: $(DOCS_DIR)/gem.js and $(DOCS_DIR)/gem.wasm (with standard library) - version $(VERSION_STRING)"
# Build WASM version without standard library
$(DOCS_DIR)/gem-no-stl.js: $(WASM_SRC_FILES) $(VERSION_HEADER)
@echo "Building Gem interpreter for WebAssembly without standard library..."
$(EMCC) $(WASM_SRC_FILES) -o $(DOCS_DIR)/gem-no-stl.js $(WASM_CFLAGS)
@echo "Built: $(DOCS_DIR)/gem-no-stl.js and $(DOCS_DIR)/gem-no-stl.wasm (without standard library) - version $(VERSION_STRING)"
# Convenience targets
gemc: $(BIN_DIR)/gemc
gemch: $(BIN_DIR)/gemch
wasm: $(DOCS_DIR)/gem.js
wasm-no-stl: $(DOCS_DIR)/gem-no-stl.js
# Alternative target for --no-stl flag
no-stl: $(BIN_DIR)/gemch
# Update version and rebuild everything
version-update: clean $(VERSION_HEADER) update-docs all
@echo "Version update complete: $(VERSION_STRING)"
# Show current version
version:
@echo "Current version: $(VERSION_STRING)"
@echo "Display version: $(VERSION_DISPLAY)"
# Clean build artifacts
clean:
rm -rf $(BIN_DIR)
rm -f $(EMBEDDED_STL_HEADER)
rm -f $(VERSION_HEADER)
rm -f $(DOCS_DIR)/gem.js $(DOCS_DIR)/gem.wasm
rm -f $(DOCS_DIR)/gem-no-stl.js $(DOCS_DIR)/gem-no-stl.wasm
# Install to system (optional)
install: $(BIN_DIR)/gemc
cp $(BIN_DIR)/gemc /usr/local/bin/
# Uninstall from system (optional)
uninstall:
rm -f /usr/local/bin/gemc
# Run tests (if any)
test: $(BIN_DIR)/gemc
@echo "Running tests..."
@if [ -d "tests" ]; then \
for test_file in tests/*.gem; do \
if [ -f "$$test_file" ]; then \
echo "Running $$test_file..."; \
./$(BIN_DIR)/gemc "$$test_file"; \
fi; \
done; \
else \
echo "No test directory found"; \
fi
# Help target
help:
@echo "Gem Programming Language Interpreter Build System"
@echo "Current version: $(VERSION_STRING)"
@echo ""
@echo "Targets:"
@echo " all - Build gemc with standard library (default)"
@echo " gemc - Build gemc with standard library"
@echo " gemch - Build gemch without standard library"
@echo " wasm - Build WebAssembly version with standard library"
@echo " wasm-no-stl - Build WebAssembly version without standard library"
@echo " no-stl - Alias for gemch (without standard library)"
@echo " version - Show current version information"
@echo " version-update- Update version and rebuild everything"
@echo " update-docs - Update documentation files with current version"
@echo " clean - Remove build artifacts"
@echo " install - Install gemc to /usr/local/bin"
@echo " uninstall - Remove gemc from /usr/local/bin"
@echo " test - Run test files (if any)"
@echo " help - Show this help message"
@echo ""
@echo "Build output:"
@echo " Binaries are built in the $(BIN_DIR)/ directory"
@echo " WASM files are built in the $(DOCS_DIR)/ directory"
@echo ""
@echo "Version management:"
@echo " Edit $(VERSION_CONF) to change version"
@echo " Run 'make version-update' to apply changes everywhere"
@echo ""
@echo "Examples:"
@echo " make # Build with standard library ($(BIN_DIR)/gemc)"
@echo " make wasm # Build WebAssembly version ($(DOCS_DIR)/gem.js)"
@echo " make version # Show current version"
@echo " make version-update# Update version and rebuild"
@echo " make clean # Clean build artifacts"
.PHONY: gemc gemch clean install uninstall test help no-stl version version-update update-docs wasm wasm-no-stl