aboutsummaryrefslogtreecommitdiff
path: root/Makefile
blob: a9ccedc6faf038d6973fe85010f27475fad7e052 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
PREFIX=$(HOME)/.local
VERSION=0.0.1
CC=cc
CCONFIG=-std=c2x -fPIC \
		-fno-signed-zeros -fno-finite-math-only -fno-trapping-math \
		-fvisibility=hidden -fdollars-in-identifiers \
		-DGC_THREADS
LTO=
LDFLAGS=-L/usr/local/lib
INCLUDE_DIRS=-I/usr/local/include
CWARN=-Wall -Wextra -Wno-format -Wshadow \
	  -Wno-pedantic \
	  -Wno-pointer-arith \
	  -Wtype-limits -Wunused-result -Wnull-dereference \
	  -Walloca -Wcast-align \
	  -Wdangling-else -Wdate-time -Wdisabled-optimization -Wdouble-promotion \
	  -Wexpansion-to-defined -Wno-float-equal \
	  -Wframe-address -Winline -Winvalid-pch \
	  -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn \
	  -Wnull-dereference -Woverlength-strings -Wpacked \
	  -Wredundant-decls -Wshadow \
	  -Wno-stack-protector -Wswitch-default \
	  -Wundef -Wunused -Wunused-but-set-variable \
	  -Wunused-const-variable -Wunused-local-typedefs -Wunused-macros -Wvariadic-macros \
	  -Wwrite-strings

ifeq ($(shell $(CC) -v 2>&1 | grep -c "gcc version"), 1)
	LTO += -flto=auto -fno-fat-lto-objects -Wl,-flto
	CWARN += -Werror -Wsign-conversion -Walloc-zero -Wduplicated-branches -Wduplicated-cond -Wjump-misses-init \
			 -Wlogical-op -Wpacked-not-aligned -Wshadow=compatible-local -Wshadow=global -Wshadow=local \
			 -Wsuggest-attribute=const -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure \
			 -Wsync-nand -Wtrampolines -Wvector-operation-performance -Wcast-align=strict
	CCONFIG += -fsanitize=signed-integer-overflow -fno-sanitize-recover -fno-signaling-nans
else
	CWARN += -Wno-missing-field-initializers
endif

OS := $(shell uname -s)

OSFLAGS != case $(OS) in *BSD|Darwin) echo '-D_BSD_SOURCE';; Linux) echo '-D_GNU_SOURCE';; *) echo '-D_DEFAULT_SOURCE';; esac
EXTRA=
G=-ggdb
O=-Og
CFLAGS=$(CCONFIG) $(INCLUDE_DIRS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LTO)
CFLAGS_PLACEHOLDER="$$(printf '\033[2m<flags...>\033[m\n')" 
LDLIBS=-lgc -lcord -lm -lunistring -lgmp -lbacktrace
LIBTOMO_FLAGS=-shared

ifeq ($(OS),OpenBSD)
	LDLIBS += -lexecinfo
endif

ifeq ($(OS),Darwin)
	INCLUDE_DIRS += -I/opt/homebrew/include
	LDFLAGS += -L/opt/homebrew/lib
	LIB_FILE=libtomo.dylib
	LIBTOMO_FLAGS += -Wl,-install_name,@rpath/libtomo.dylib
else
	LIB_FILE=libtomo.so
	LIBTOMO_FLAGS += -Wl,-soname,libtomo.so
endif

COMPILER_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c))
STDLIB_OBJS=$(patsubst %.c,%.o,$(wildcard src/stdlib/*.c))
TESTS=$(patsubst test/%.tm,test/results/%.tm.testresult,$(wildcard test/*.tm))

all: build/$(LIB_FILE) build/tomo

build/tomo: $(STDLIB_OBJS) $(COMPILER_OBJS)
	@mkdir -p build
	@echo $(CC) $(CFLAGS_PLACEHOLDER) $(LDFLAGS) $^ $(LDLIBS) -o $@
	@$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@

build/$(LIB_FILE): $(STDLIB_OBJS)
	@mkdir -p build
	@echo $(CC) $^ $(CFLAGS_PLACEHOLDER) $(OSFLAGS) $(LDFLAGS) $(LDLIBS) $(LIBTOMO_FLAGS) -o $@
	@$(CC) $^ $(CFLAGS) $(OSFLAGS) $(LDFLAGS) $(LDLIBS) $(LIBTOMO_FLAGS) -o $@

tags:
	ctags src/*.[ch] src/stdlib/*.[ch]

%.o: %.c src/ast.h src/environment.h src/types.h
	@echo $(CC) $(CFLAGS_PLACEHOLDER) -c $< -o $@
	@$(CC) $(CFLAGS) -c $< -o $@

%: %.tm
	tomo -e $<

test/results/%.tm.testresult: test/%.tm build/tomo
	@mkdir -p test/results
	@printf '\033[33;1;4m%s\033[m\n' $<
	@set -o pipefail; \
	if ! VERBOSE=0 COLOR=1 LC_ALL=C CC=gcc ./build/tomo -O 1 $< 2>&1 | tee $@; then \
		rm -f $@; \
		false; \
	fi

test: $(TESTS)
	@printf '\033[32;7m ALL TESTS PASSED! \033[m\n'

clean:
	rm -rf build/* $(COMPILER_OBJS) $(STDLIB_OBJS) test/*.tm.testresult test/.build lib/*/.build examples/.build examples/*/.build

%: %.md
	pandoc --lua-filter=docs/.pandoc/bold-code.lua -s $< -t man -o $@

examples:
	./build/tomo -qIL examples/log examples/ini examples/vectors examples/http examples/wrap examples/colorful
	./build/tomo -e examples/game/game.tm examples/http-server/http-server.tm \
		examples/tomodeps/tomodeps.tm examples/tomo-install/tomo-install.tm
	./build/tomo examples/learnxiny.tm

deps: check-gcc
	./install_dependencies.sh

check-gcc:
	@GCC_VERSION=$$(gcc --version | awk '{print $$3;exit}'); \
	if [ "$$(printf '%s\n' "$$GCC_VERSION" "12.0.0" | sort -V | head -n 1)" = "12.0.0" ]; then \
		printf "\033[32;1mGCC version is good!\033[m\n"; \
		exit 0; \
	else \
		printf "\033[31;1mGCC version is lower than the required 12.0.0!\033[m\n" >&2; \
		exit 1; \
	fi

install-files: build/tomo build/$(LIB_FILE)
	@if ! echo "$$PATH" | tr ':' '\n' | grep -qx "$(PREFIX)/bin"; then \
		printf "\033[31;1mError: '$(PREFIX)' is not in your \$$PATH variable!\033[m\n" >&2; \
		printf "\033[31;1mSpecify a different prefix with 'make PREFIX=... install'\033[m\n" >&2; \
		printf "\033[31;1mor add the following line to your .profile:\033[m\n" >&2; \
		printf "\n\033[1mexport PATH=\"$(PREFIX):\$$PATH\"\033[m\n\n" >&2; \
		exit 1; \
	fi
	mkdir -p -m 755 "$(PREFIX)/man/man1" "$(PREFIX)/bin" "$(PREFIX)/include/tomo" "$(PREFIX)/lib" "$(PREFIX)/share/tomo/modules"
	cp -v src/stdlib/*.h "$(PREFIX)/include/tomo/"
	cp -v build/$(LIB_FILE) "$(PREFIX)/lib/"
	rm -f "$(PREFIX)/bin/tomo"
	cp -v build/tomo "$(PREFIX)/bin/"
	cp -v docs/tomo.1 "$(PREFIX)/man/man1/"

install-libs: build/tomo
	./build/tomo -qIL lib/patterns lib/time lib/commands lib/shell lib/random lib/base64 lib/pthreads lib/uuid lib/core

install: install-files install-libs

uninstall:
	rm -rvf "$(PREFIX)/bin/tomo" "$(PREFIX)/include/tomo" "$(PREFIX)/lib/$(LIB_FILE) "$(PREFIX)/share/tomo"; \

.SUFFIXES:
.PHONY: all clean install install-files install-libs uninstall test tags examples deps check-gcc