X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=Makefile;h=f0b3cabfc15faad1eec6b6951e3a2cc3396599fa;hp=4f42a7fe7fa392b2d9e0d6679b5b710bbabbc1ac;hb=f971f89e1e239a74fd34f9f5369993b25d5432ed;hpb=fe3d8e44e6b6b153860af46a9c3b3d604e01bb9e diff --git a/Makefile b/Makefile index 4f42a7f..dc49416 100644 --- a/Makefile +++ b/Makefile @@ -1,107 +1,204 @@ -DESTDIR := -PREFIX := /usr/local -BINDIR := $(PREFIX)/bin -DATADIR := $(PREFIX)/share -MANDIR := $(DATADIR)/man - -UNAME ?= $(shell uname) -CYGWIN = $(findstring CYGWIN, $(UNAME)) -MINGW = $(findstring MINGW32, $(UNAME)) - -CC ?= clang -CFLAGS += -Wall -Wextra -I. -pedantic-errors -#turn on tons of warnings if clang is present -# but also turn off the STUPID ONES -ifeq ($(CC), clang) - CFLAGS += \ - -Weverything \ - -Wno-padded \ - -Wno-format-nonliteral \ - -Wno-disabled-macro-expansion \ - -Wno-conversion \ - -Wno-missing-prototypes \ - -Wno-float-equal \ - -Wno-cast-align +# Compilation options: +# * LTO - Link time optimization [default=0] +# * ASAN - Address sanitizer [default=0] +# * UBSAN - Undefined behavior sanitizer [default=0] +# * DEBUG - Debug build [default=0] +# * UNUSED - Remove unused references [default=1] +# * SRCDIR - Out of tree builds [default=./] +LTO ?= 0 +ASAN ?= 0 +UBSAN ?= 0 +DEBUG ?= 0 +UNUSED ?= 1 +SRCDIR ?= ./ + +# Determine if we're building for Windows or not so we can set the right file +# extensions for the binaries and exclude the testsuite because it doesn't build +# for that platform. +ifeq ($(OS),Windows_NT) + GMQCC := gmqcc.exe + QCVM := qcvm.exe +else + GMQCC := gmqcc + QCVM := qcvm + TESTSUITE := testsuite endif -ifeq ($(track), no) - CFLAGS += -DNOTRACK + +# C++ compiler +CXX ?= clang++ + +# Build artifact directories +OBJDIR := .build/objs +DEPDIR := .build/deps + +# Collect all the source files for GMQCC. +GSRCS := ast.cpp +GSRCS += code.cpp +GSRCS += conout.cpp +GSRCS += fold.cpp +GSRCS += ftepp.cpp +GSRCS += intrin.cpp +GSRCS += ir.cpp +GSRCS += lexer.cpp +GSRCS += main.cpp +GSRCS += opts.cpp +GSRCS += parser.cpp +GSRCS += stat.cpp +GSRCS += utf8.cpp +GSRCS += util.cpp + +# Collect all the source files for QCVM. +QSRCS := exec.cpp +QSRCS += stat.cpp +QSRCS += util.cpp + +# Collect all the source files for TESTSUITE. +TSRCS := conout.cpp +TSRCS += opts.cpp +TSRCS += stat.cpp +TSRCS += test.cpp +TSRCS += util.cpp + +# +# Compilation flags +# +CXXFLAGS := -Wall +CXXFLAGS += -Wextra +CXXFLAGS += -Wno-parentheses +CXXFLAGS += -Wno-class-memaccess +CXXFLAGS += -Wno-implicit-fallthrough +CXXFLAGS += -std=c++11 + +# Disable some unneeded features. +CXXFLAGS += -fno-exceptions +CXXFLAGS += -fno-rtti +CXXFLAGS += -fno-asynchronous-unwind-tables + +# Give each function and data it's own section so the linker can remove unused +# references to each, producing smaller, tighter binaries. +ifeq ($(UNUSED),1) + CXXFLAGS += -ffunction-sections + CXXFLAGS += -fdata-sections endif -OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o file.o utf8lib.o -OBJ_T = test.o util.o conout.o file.o -OBJ_C = main.o lexer.o parser.o file.o -OBJ_X = exec-standalone.o util.o conout.o file.o - -ifneq ("$(CYGWIN)", "") - #nullify the common variables that - #most *nix systems have (for windows) - PREFIX := - BINDIR := - DATADIR := - MANDIR := - QCVM = qcvm.exe - GMQCC = gmqcc.exe - TESTSUITE = testsuite.exe -else -ifneq ("$(MINGW)", "") - #nullify the common variables that - #most *nix systems have (for windows) - PREFIX := - BINDIR := - DATADIR := - MANDIR := - QCVM = qcvm.exe - GMQCC = gmqcc.exe - TESTSUITE = testsuite.exe +# Enable link-time optimizations if requested. +ifeq ($(LTO),1) + CXXFLAGS += -flto +endif + +ifeq ($(DEBUG),1) + # Ensure there is a frame-pointer in debug builds. + CXXFLAGS += -fno-omit-frame-pointer + + # Disable all optimizations in debug builds. + CXXFLAGS += -O0 + + # Enable debug symbols. + CXXFLAGS += -g else - QCVM = qcvm - GMQCC = gmqcc - TESTSUITE = testsuite + # Disable all the stack protection features in release builds. + CXXFLAGS += -fno-stack-protector + CXXFLAGS += -fno-stack-check + + # Disable frame pointer in release builds when AddressSanitizer isn't present. + ifeq ($(ASAN),1) + CXXFLAGS += -fno-omit-frame-pointer + else + CXXFLAGS += -fomit-frame-pointer + endif + + # Highest optimization flag in release builds. + CXXFLAGS += -O3 +endif + +# Sanitizer selection +ifeq ($(ASAN),1) + CXXFLAGS += -fsanitize=address endif +ifeq ($(UBSAN),1) + CXXFLAGS += -fsanitize=undefined endif -#standard rules -default: all -%.o: %.c - $(CC) -c $< -o $@ $(CFLAGS) +# +# Dependency flags +# +DEPFLAGS := -MMD +DEPFLAGS += -MP -exec-standalone.o: exec.c - $(CC) -c $< -o $@ $(CFLAGS) -DQCVM_EXECUTOR=1 +# +# Linker flags +# +LDFLAGS := -$(QCVM): $(OBJ_X) - $(CC) -o $@ $^ $(CFLAGS) -lm +# Remove unreferenced sections +ifeq ($(UNUSED),1) + LDFLAGS += -Wl,--gc-sections +endif -$(GMQCC): $(OBJ_C) $(OBJ_D) - $(CC) -o $@ $^ $(CFLAGS) +# Enable link-time optimizations if request. +ifeq ($(LTO),1) + LDFLAGS += -flto +endif -$(TESTSUITE): $(OBJ_T) - $(CC) -o $@ $^ $(CFLAGS) +# Sanitizer selection +ifeq ($(ASAN),1) + LDFLAGS += -fsanitize=address +endif +ifeq ($(UBSAN),1) + LDFLAGS += -fsanitize=undefined +endif + +# Strip the binaries when not a debug build +ifneq (,$(findstring, -g,$(CXXFLAGS))) + STRIP := true +else + STRIP := strip +endif all: $(GMQCC) $(QCVM) $(TESTSUITE) -check: all - @ ./$(TESTSUITE) +# Build artifact directories. +$(DEPDIR): + @mkdir -p $(DEPDIR) +$(OBJDIR): + @mkdir -p $(OBJDIR) + +$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d | $(OBJDIR) $(DEPDIR) + $(CXX) -MT $@ $(DEPFLAGS) -MF $(DEPDIR)/$*.Td $(CXXFLAGS) -c -o $@ $< + @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d + +$(GMQCC): $(filter %.o,$(GSRCS:%.cpp=$(OBJDIR)/%.o)) + $(CXX) $^ $(LDFLAGS) -o $@ + $(STRIP) $@ + +$(QCVM): $(filter %.o,$(QSRCS:%.cpp=$(OBJDIR)/%.o)) + $(CXX) $^ $(LDFLAGS) -o $@ + $(STRIP) $@ + +$(TESTSUITE): $(filter %.o,$(TSRCS:%.cpp=$(OBJDIR)/%.o)) + $(CXX) $^ $(LDFLAGS) -o $@ + $(STRIP) $@ + +# Determine if the tests should be run. +RUNTESTS := true +ifdef TESTSUITE + RUNTESTS := ./$(TESTSUITE) +endif + +test: $(QCVM) $(TESTSUITE) + @$(RUNTESTS) clean: - rm -f *.o $(GMQCC) $(QCVM) $(TESTSUITE) *.dat - -# deps -$(OBJ_D) $(OBJ_C) $(OBJ_X): gmqcc.h opts.def -main.o: lexer.h -parser.o: ast.h lexer.h -lexer.o: lexer.h -ast.o: ast.h ir.h -ir.o: ir.h - -#install rules -install: install-gmqcc install-qcvm install-doc -install-gmqcc: $(GMQCC) - install -d -m755 $(DESTDIR)$(BINDIR) - install -m755 $(GMQCC) $(DESTDIR)$(BINDIR)/gmqcc -install-qcvm: $(QCVM) - install -d -m755 $(DESTDIR)$(BINDIR) - install -m755 $(QCVM) $(DESTDIR)$(BINDIR)/qcvm -install-doc: - install -d -m755 $(DESTDIR)$(MANDIR)/man1 - install -m755 doc/gmqcc.1 $(DESTDIR)$(MANDIR)/man1/ - install -m755 doc/qcvm.1 $(DESTDIR)$(MANDIR)/man1/ + rm -rf $(DEPDIR) $(OBJDIR) + +.PHONY: test clean $(DEPDIR) $(OBJDIR) + +# Dependencies +$(filter %.d,$(GSRCS:%.cpp=$(DEPDIR)/%.d)): +include $(wildcard $@) + +$(filter %.d,$(QSRCS:%.cpp=$(DEPDIR)/%.d)): +include $(wildcard $@) + +$(filter %.d,$(TSRCS:%.cpp=$(DEPDIR)/%.d)): +include $(wildcard $@)