1# libfirm Makefile
2#
3# This is currently experimental and not fully supported, but we plan to replace
4# the jambuild with this at some point in the future.
5#
6# Most variable names are similar to the names used by autoconf...
7-include config.mak
8
9# Some build configuration defaults
10top_srcdir   ?= .
11top_builddir ?= build
12variant      ?= debug
13
14srcdir       ?= $(top_srcdir)
15builddir     ?= $(top_builddir)/$(variant)
16gendir       ?= $(top_builddir)/gen
17docdir       ?= $(top_builddir)/doc
18
19# This hides the noisy commandline outputs. Show them with "make V=1"
20ifneq ($(V),1)
21Q ?= @
22endif
23
24# Tools
25CC ?= cc
26DOXYGEN ?= doxygen
27LINK ?= $(CC)
28AR ?= ar
29ifeq ("$(shell uname)", "Darwin")
30DLLEXT ?= .dylib
31LINKDLLFLAGS = -dynamiclib -install_name $(abspath $@)
32else
33DLLEXT ?= .so
34LINKDLLFLAGS = -shared
35endif
36
37# Variants
38CFLAGS_debug       = -O0 -g3 -DDEBUG_libfirm
39CFLAGS_profile     = -O3 -pg -DNDEBUG -fno-inline
40CFLAGS_coverage    = -O0 --coverage -DDEBUG_libfirm
41CFLAGS_optimize    = -O3 -fomit-frame-pointer -DNDEBUG
42LINKFLAGS_debug    =
43LINKFLAGS_profile  = -pg
44LINKFLAGS_coverage = --coverage
45
46# General flags
47CPPFLAGS  ?=
48CFLAGS    += $(CFLAGS_$(variant)) -std=c99 -fPIC -DHAVE_FIRM_REVISION_H
49CFLAGS    += -Wall -W -Wextra -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings
50LINKFLAGS += $(LINKFLAGS_$(variant)) -lm
51VPATH = $(srcdir) $(gendir)
52
53all: firm
54.PHONY: all
55
56# disable make builtin suffix rules
57.SUFFIXES:
58
59# libFirm
60libfirm_SOURCES     = $(subst $(srcdir)/,,$(wildcard $(srcdir)/ir/*/*.c))
61libfirm_GEN_SOURCES =
62libfirm_DIRS        = $(sort $(dir $(libfirm_SOURCES))) include/libfirm include/libfirm/adt
63libfirm_GEN_DIRS    = $(sort $(dir $(libfirm_GEN_SOURCES)))
64libfirm_INCLUDEDIRS = $(addprefix $(srcdir)/, $(libfirm_DIRS)) $(addprefix $(gendir)/, $(libfirm_GEN_DIRS))
65libfirm_a           = $(builddir)/libfirm.a
66libfirm_dll         = $(builddir)/libfirm$(DLLEXT)
67libfirm_CPPFLAGS    = $(foreach dir,$(libfirm_INCLUDEDIRS),-I$(dir))
68libfirm_OBJECTS     = $(libfirm_SOURCES:%.c=$(builddir)/%.o) $(libfirm_GEN_SOURCES:%.c=$(builddir)/%.o)
69libfirm_DEPS        = $(libfirm_OBJECTS:%.o=%.d)
70libfirm_BUILDDIRS   = $(sort $(dir $(libfirm_OBJECTS))) $(addprefix $(gendir)/, $(libfirm_GEN_DIRS))
71
72.PHONY: firm
73firm: $(libfirm_dll) $(libfirm_a)
74
75# backends
76backends = amd64 arm ia32 mips sparc TEMPLATE
77
78EMITTER_GENERATOR = $(srcdir)/ir/be/scripts/generate_emitter.pl
79REGALLOC_IF_GENERATOR = $(srcdir)/ir/be/scripts/generate_regalloc_if.pl
80OPCODES_GENERATOR = $(srcdir)/ir/be/scripts/generate_new_opcodes.pl
81
82define backend_template
83$(1)_SOURCES = $$(subst $$(srcdir)/,,$$(wildcard $$(srcdir)/ir/be/$(1)/*.c))
84$(1)_GEN_HEADERS =
85
86$(1)_SPEC = ir/be/$(1)/$(1)_spec.pl
87
88$$(gendir)/ir/be/$(1)/gen_$(1)_emitter.h $$(gendir)/ir/be/$(1)/gen_$(1)_emitter.c: $$($(1)_SPEC) $$(EMITTER_GENERATOR)
89	@echo GEN $$@
90	$(Q)$$(EMITTER_GENERATOR) $$< $$(gendir)/ir/be/$(1)
91$(1)_GEN_SOURCES += ir/be/$(1)/gen_$(1)_emitter.c
92$(1)_GEN_HEADERS += $$(gendir)/ir/be/$(1)/gen_$(1)_emitter.h
93
94$$(gendir)/ir/be/$(1)/gen_$(1)_regalloc_if.h $$(gendir)/ir/be/$(1)/gen_$(1)_regalloc_if.c: $$($(1)_SPEC) $$(REGALLOC_IF_GENERATOR)
95	@echo GEN $$@
96	$(Q)$$(REGALLOC_IF_GENERATOR) $$< $$(gendir)/ir/be/$(1)
97$(1)_GEN_SOURCES += ir/be/$(1)/gen_$(1)_regalloc_if.c
98$(1)_GEN_HEADERS += $$(gendir)/ir/be/$(1)/gen_$(1)_regalloc_if.h
99
100$$(gendir)/ir/be/$(1)/gen_$(1)_new_nodes.h $$(gendir)/ir/be/$(1)/gen_$(1)_new_nodes.c: $$($(1)_SPEC) $$(OPCODES_GENERATOR)
101	@echo GEN $$@
102	$(Q)$$(OPCODES_GENERATOR) $$< $$(gendir)/ir/be/$(1)
103$(1)_GEN_SOURCES += ir/be/$(1)/gen_$(1)_new_nodes.c
104$(1)_GEN_HEADERS += $$(gendir)/ir/be/$(1)/gen_$(1)_new_nodes.h
105
106# We need to inform make of the headers it doesn't know yet...
107$(1)_OBJECTS = $$($(1)_SOURCES:%.c=$$(builddir)/%.o) $$($(1)_GEN_SOURCES:%.c=$$(builddir)/%.o)
108$$($(1)_OBJECTS): $$($(1)_GEN_HEADERS)
109
110libfirm_GEN_SOURCES += $$($(1)_GEN_SOURCES)
111libfirm_SOURCES += $$($1_SOURCES)
112endef
113
114$(foreach backend,$(backends),$(eval $(call backend_template,$(backend))))
115
116# generators
117IR_SPEC_GENERATED_INCLUDES := \
118	$(gendir)/include/libfirm/nodes.h \
119	$(gendir)/ir/ir/gen_proj_names.h  \
120	$(gendir)/ir/ir/gen_irnode.h
121IR_SPEC_GENERATOR := $(srcdir)/scripts/gen_ir.py
122IR_SPEC_GENERATOR_DEPS := $(IR_SPEC_GENERATOR) $(srcdir)/scripts/jinjautil.py $(srcdir)/scripts/irops.py $(srcdir)/scripts/filters.py
123IR_SPEC := $(srcdir)/scripts/ir_spec.py
124libfirm_BUILDDIRS += $(gendir)/include/libfirm
125
126libfirm_GEN_SOURCES += \
127	ir/ir/gen_irnode.c \
128	ir/ir/gen_irio.c
129$(builddir)/ir/ir/gen_irnode.o: $(gendir)/ir/ir/gen_irnode.c
130$(builddir)/ir/ir/gen_irio.o: $(gendir)/ir/ir/gen_irio.c
131
132$(gendir)/ir/ir/% : scripts/templates/% $(IR_SPEC_GENERATOR_DEPS) $(IR_SPEC)
133	@echo GEN $@
134	$(Q)$(IR_SPEC_GENERATOR) $(IR_SPEC) "$<" > "$@"
135
136$(gendir)/include/libfirm/% : scripts/templates/% $(IR_SPEC_GENERATOR_DEPS) $(IR_SPEC)
137	@echo GEN $@
138	$(Q)$(IR_SPEC_GENERATOR) $(IR_SPEC) "$<" > "$@"
139
140libfirm_GEN_DIRS += ir/ir include/libfirm
141
142$(libfirm_a): $(libfirm_OBJECTS)
143	@echo AR $@
144	$(Q)rm -f $@
145	$(Q)$(AR) -crs $@ $^
146
147$(libfirm_dll): $(libfirm_OBJECTS)
148	@echo LINK $@
149	$(Q)$(LINK) $(LINKDLLFLAGS) $^ -o $@ $(LINKFLAGS)
150
151# Determine if we can use cparser-beta for quickcheck
152QUICKCHECK_DEFAULT := $(shell which cparser-beta 2> /dev/null || echo true) -fsyntax-only
153QUICKCHECK ?= $(QUICKCHECK_DEFAULT)
154QUICKCHECK_FLAGS ?= -m32 -Wno-compat-option -Wno-shadow -Wno-shadow-local -Wunreachable-code
155
156$(builddir)/%.o: %.c $(IR_SPEC_GENERATED_INCLUDES)
157	@echo CC $@
158	$(Q)$(QUICKCHECK) $(QUICKCHECK_FLAGS) $(CFLAGS) $(CPPFLAGS) $(libfirm_CPPFLAGS) $(QUICKCHECK_FLAGS) $<
159	$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(libfirm_CPPFLAGS) -MP -MMD -c -o $@ $<
160
161$(docdir)/libfirm.tag: doc/Doxyfile doc/logo.png $(IR_SPEC_GENERATED_INCLUDES) $(wildcard include/libfirm/*.h) $(wildcard include/libfirm/adt/*.h)
162	@echo Doxygen $@
163	$(Q)$(DOXYGEN) $<
164
165.PHONY: doc
166doc: $(docdir)/libfirm.tag
167
168.PHONY: clean
169clean:
170	@echo CLEAN
171	$(Q)rm -fr $(builddir) $(gendir) $(docdir)
172
173.PHONY: install
174PREFIX ?= /usr/local
175INSTALL ?= install
176INSTALLPREFIX = $(DESTDIR)$(PREFIX)
177install: $(libfirm_a) $(libfirm_dll)
178	$(INSTALL) -d "$(INSTALLPREFIX)/include/libfirm"
179	$(INSTALL) -m0644 include/libfirm/*.h "$(INSTALLPREFIX)/include/libfirm"
180	$(INSTALL) -m0644 "$(gendir)"/include/libfirm/*.h "$(INSTALLPREFIX)/include/libfirm"
181	$(INSTALL) -d "$(INSTALLPREFIX)/include/libfirm/adt"
182	$(INSTALL) -m0644 include/libfirm/adt/*.h "$(INSTALLPREFIX)/include/libfirm/adt"
183	$(INSTALL) -d "$(INSTALLPREFIX)/lib"
184	$(INSTALL) -m0644 $^ "$(INSTALLPREFIX)/lib"
185
186# Ensure all output directories are created
187UNUSED1 := $(shell mkdir -p $(libfirm_BUILDDIRS))
188
189REVISION ?= $(shell git --git-dir $(top_srcdir)/.git describe --abbrev=40 --always --dirty --match '')
190
191# Update revision.h if necessary
192REVISIONH = $(gendir)/firm_revision.h
193libfirm_INCLUDEDIRS += $(gendir)
194UNUSED2 := $(shell \
195	REV="\#define libfirm_VERSION_REVISION \"$(REVISION)\""; \
196	echo "$$REV" | cmp -s - "$(REVISIONH)" 2> /dev/null || echo "$$REV" > "$(REVISIONH)" \
197)
198
199# Unit tests
200UNITTESTS_SOURCES = $(subst $(srcdir)/unittests/,,$(wildcard $(srcdir)/unittests/*.c))
201UNITTESTS         = $(UNITTESTS_SOURCES:%.c=$(builddir)/%.exe)
202UNITTESTS_OK      = $(UNITTESTS_SOURCES:%.c=$(builddir)/%.ok)
203
204$(builddir)/%.exe: $(srcdir)/unittests/%.c $(libfirm_a)
205	@echo LINK $<
206	$(Q)$(LINK) $(CFLAGS) $(CPPFLAGS) $(libfirm_CPPFLAGS) "$<" $(libfirm_a) -lm -o "$@"
207
208$(builddir)/%.ok: $(builddir)/%.exe
209	@echo EXEC $<
210	$(Q)$< && touch "$@"
211
212.PRECIOUS: $(UNITTESTS)
213.PHONY: test
214test: $(UNITTESTS_OK)
215
216.PHONY: gen
217gen: $(IR_SPEC_GENERATED_INCLUDES) $(libfirm_GEN_SOURCES)
218
219-include $(libfirm_DEPS)
220