summaryrefslogtreecommitdiff
path: root/Makefile.in
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-02-01 14:57:23 -0800
committerBen Longbons <b.r.longbons@gmail.com>2014-02-01 14:57:23 -0800
commit7c77cbd24c03aceff65feae5082221b62eaeea6e (patch)
treefc92065d844ba74c6ef38d0da1f9868aa17e6f79 /Makefile.in
parent3d8b6671b394ef6c4c5df3065a6123a5d6cacb93 (diff)
downloadtmwa-7c77cbd24c03aceff65feae5082221b62eaeea6e.tar.gz
tmwa-7c77cbd24c03aceff65feae5082221b62eaeea6e.tar.bz2
tmwa-7c77cbd24c03aceff65feae5082221b62eaeea6e.tar.xz
tmwa-7c77cbd24c03aceff65feae5082221b62eaeea6e.zip
Get rid of makefile indirection
Diffstat (limited to 'Makefile.in')
-rw-r--r--Makefile.in418
1 files changed, 408 insertions, 10 deletions
diff --git a/Makefile.in b/Makefile.in
index 1030212..64b0c27 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -48,14 +48,412 @@ ENABLE_DEBUG = @ENABLE_DEBUG@
-# This file is reverse included. Don't forward in that case.
-ifeq '${MAKEFILE_LIST}' ' Makefile'
-.DEFAULT_GOAL=.default-target-wrapper
-# The documentation for ${MAKECMDGOALS} says "Note that this variable
-# should be used only in special circumstances."
-# If you do not understand *exactly* why I do this instead of
-# %::;${MAKE}, stay away from this code. You have been warned.
-.default-target-wrapper ${MAKECMDGOALS}: .all-target-wrapper ; @:
-.all-target-wrapper:
- ${MAKE} -rRf ${SRC_DIR}/real.make ${MAKECMDGOALS}
+## real.make - The One Makefile that builds them all.
+##
+## Copyright © 2012-2014 Ben Longbons <b.r.longbons@gmail.com>
+##
+## This file is part of The Mana World (Athena server)
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# With the One Makefile, you never have to remember to update the list of
+# objects you need to link your programs. It is designed to behave (almost)
+# exactly the way you expect a Makefile to act - which cannot be said of
+# automake, cmake, or qmake.
+#
+# The One Makefile lives under the name 'real.make', because it is
+# reponsible for doing all the actual building, but it is not the file
+# that the user actually calls (using make) directly. The reason for this
+# is that the One Makefile requires a certain environment that it cannot
+# arrange for on its own.
+#
+# Specifically:
+# The -r and -R flags must be passed.
+# A list of variables must be included, but regenerating Makefile from
+# Makefile.in is time-consuming, so real.make actually *includes* the
+# file that called it.
+#
+# For an example of how to do this safely, look at the Makefile.in shipped
+# by TMWA. Of course, you could use any other mechanism to generate a
+# Makefile, as long as it supplies the appropriate list of variables.
+
+
+# TODO:
+# 1. Implement support for static libraries
+# This should be trivial.
+# 2. Implement support for shared libraries
+# This requires building two different .o files and such.
+# 3. Implement support for mixed C and C++ source trees
+# This just requires writing more patsubst in various places
+# At that point, they should *probably* be refactored out into functions.
+# However, it would be hard to allow linking some binaries as pure C.
+# Unless maybe we should use .c.o and .cpp.o ?
+# 4. See if something can be done about all the mkdirs.
+# 5. Remove the few (obvious) bits that are hard-coded for TMWA.
+# 6. Handle testing better. I'm guessing I should actually compile just
+# one foo_test.cpp file into each executable test ...
+# 7. Refactor into several files after all. We need extensibility!
+#
+# IWBNMI:
+# 1. Add 'make check' and 'make installcheck'.
+# 2. 'make distclean' should remove "anything that ./configure created".
+# 3. 'make dist' should be implemented. Git only or not?
+# 4. 'make install' should install documentation.
+# 5. Split 'make install-exec' and 'make install-data'. Beware etc and var!
+# 6. '--program-prefix' and '--program-suffix' (easy). What about sed?
+# 7. Support DESTDIR during 'make install' (URGENT).
+# 8. 'make distcheck' using the 'make dist' tarball?
+# 9. Add rules for gettext.
+# 10. Support per-target build flags? (requires renaming)
+
+ifeq ($(findstring s,$(firstword ${MAKEFLAGS})),)
+ifndef MAKE_RESTARTS
+# TODO: should I write this in tengwar?
+# The major problem is that it's usually encoded in the PUA
+# and thus requires a font specification.
+# There *is* a formal request and tentative allocation in the SMP,
+# but it has been languishing for 15 years.
+# TODO: regardless of the preceding, look up the words for 'build' and 'link'.
+# (Does there exist a word that could mean "makefile"?
+# Maybe something like 'instructional scroll')
+
+# Note: the space is necessary
+$(info )
+$(info Welcome to the One Makefile)
+$(info Copyright 2012-2014 Ben Longbons)
+$(info )
+$(info One Makefile to build them all,)
+$(info One Makefile to find them,)
+$(info One Makefile to bring them all)
+$(info and in the darkness link them.)
+$(info )
+else
+$(info The Road goes ever on and on ...)
+endif
+endif
+
+.SUFFIXES:
+# make 3.81 doesn't support 'undefine' and Debian hasn't shipped it yet
+# even though all the related bugs have already been fixed.
+$(foreach var,$(filter-out .% MAKE% SUFFIXES,${.VARIABLES}),$(if $(filter default,$(origin ${var})),$(eval ${var} =)))
+
+export PATH:=$(realpath ${SRC_DIR}/tools):${PATH}
+
+# bash is needed for 'set -o pipefail' below - I have had real bugs there!
+# It's just not worth the bother to see if another shell works when it
+# needs to *and* fails when it needs to. Just use bash.
+SHELL=bash
+
+# path lists
+LEXERS := $(shell cd ${SRC_DIR}; find src/ -name '*.lpp')
+PARSERS := $(shell cd ${SRC_DIR}; find src/ -name '*.ypp')
+GEN_SOURCES := \
+ $(patsubst %.lpp,%.cpp,${LEXERS}) \
+ $(patsubst %.ypp,%.cpp,${PARSERS})
+GEN_HEADERS := \
+ $(patsubst %.ypp,%.hpp,${PARSERS})
+REAL_SOURCES := $(shell cd ${SRC_DIR}; find src/ -name '*.cpp')
+REAL_HEADERS := $(shell cd ${SRC_DIR}; find src/ -name '*.hpp' -o -name '*.tcc')
+REAL_SOURCES := $(filter-out ${GEN_SOURCES},${REAL_SOURCES})
+REAL_HEADERS := $(filter-out ${GEN_HEADERS},${REAL_HEADERS})
+SOURCES := ${GEN_SOURCES} ${REAL_SOURCES}
+HEADERS := ${GEN_HEADERS} ${REAL_HEADERS}
+DEPENDS := $(patsubst src/%.cpp,obj/%.d,${SOURCES})
+PREPROCESSED := $(patsubst %.d,%.ii,${DEPENDS})
+IRS := $(patsubst %.d,%.ll,${DEPENDS})
+BITCODES := $(patsubst %.d,%.bc,${DEPENDS})
+ASSEMBLED := $(patsubst %.d,%.s,${DEPENDS})
+OBJECTS := $(patsubst %.d,%.o,${DEPENDS})
+GEN_DEPENDS := $(patsubst src/%.cpp,obj/%.d,${GEN_SOURCES})
+GEN_PREPROCESSED := $(patsubst %.d,%.ii,${GEN_DEPENDS})
+GEN_IRS := $(patsubst %.d,%.ll,${GEN_DEPENDS})
+GEN_BITCODES := $(patsubst %.d,%.bc,${GEN_DEPENDS})
+GEN_ASSEMBLED := $(patsubst %.d,%.s,${GEN_DEPENDS})
+GEN_OBJECTS := $(patsubst %.d,%.o,${GEN_DEPENDS})
+MAIN_SOURCES := $(filter %/main.cpp,${SOURCES})
+BINARIES := $(patsubst src/%/main.cpp,bin/tmwa-%,${MAIN_SOURCES})
+
+TEST_DEPENDS := $(patsubst src/%/test.cpp,obj/%/autolist.d,$(filter %/test.cpp,${SOURCES}))
+DEPENDS += ${TEST_DEPENDS}
+TEST_BINARIES := $(patsubst obj/%/autolist.d,bin/test-%,${TEST_DEPENDS})
+
+# tricky part
+
+# We can't put comments in a macro so here goes:
+# 1: Include the contents of the current %.d file ($1).
+# 2: For each header, substitute the corresponding %.o's dependency file.
+# 3: Blank, reserved for header->libtmwa-common.a if that gets implemented.
+# 4: Remove all non-deps - clutter and lonely headers.
+# 5: Prevent infinite loops later by filtering out deps we've already seen.
+# 6: Merge new deps into the existing dep list.
+# 7: Recurse over all new deps (see 5).
+define RECURSIVE_DEPS_IMPL
+$(eval more_deps := $(shell cat $(patsubst %/test.d,%/autolist.d,${1})))
+$(eval more_deps := $(patsubst src/%.hpp,obj/%.d,${more_deps}))
+
+$(eval more_deps := $(filter ${DEPENDS},${more_deps}))
+$(eval more_deps := $(filter-out ${cur_deps},${more_deps}))
+$(eval cur_deps += ${more_deps})
+$(foreach dep,${more_deps},$(call RECURSIVE_DEPS_IMPL,${dep}))
+endef
+
+# 1: Initialize the dep list ($1 is a %.d).
+# 2: Call the real function on it.
+# 3: Blank for clarity.
+# 4: Expand to text. Note that *nothing* else actually produces anything!
+define RECURSIVE_DEPS
+$(eval cur_deps := ${1})
+$(call RECURSIVE_DEPS_IMPL,${1})
+
+${cur_deps}
+endef
+
+# Apply the rules to all the main.cpp files
+$(foreach exe,${BINARIES},$(eval ${exe}: $(strip $(patsubst %.d,%.o,$(call RECURSIVE_DEPS,$(patsubst bin/tmwa-%,obj/%/main.d,${exe}))))))
+$(foreach exe,${TEST_BINARIES},$(eval ${exe}: $(strip $(patsubst %.d,%.o,$(call RECURSIVE_DEPS,$(patsubst bin/test-%,obj/%/test.d,${exe}))))))
+
+# utility functions for the rules
+MKDIR_FIRST = @mkdir -p ${@D}
+
+# Stuff sensitive to attoconf
+CXXFLAGS += ${WARNINGS}
+ifeq (${ENABLE_WARNINGS},yes)
+WARNINGS := -include ${SRC_DIR}/src/warnings.hpp
+endif
+${GEN_DEPENDS} ${GEN_PREPROCESSED} ${GEN_IRS} ${GEN_BITCODES} ${GEN_ASSEMBLED} ${GEN_OBJECTS}: override WARNINGS :=
+# can't just override for generated objects,
+# because a generated header might be used for a non-generated object.
+override CPPFLAGS += -I ${SRC_DIR}/$(patsubst obj/%,src/%,${@D})
+
+# related to gdb bug 15801
+ifeq (${ENABLE_ABI6},yes)
+CXXFLAGS += -fabi-version=6
+endif
+
+# This needs to edit CXX instead of CXXFLAGS in order to make
+# the %.ii rule work.
+ifeq (${ENABLE_CYGWIN_HACKS},yes)
+override CXX += -std=gnu++0x
+else
+override CXX += -std=c++0x
endif
+
+CXXFLAGS += -fstack-protector
+override CXXFLAGS += -fno-strict-aliasing
+override CXXFLAGS += -fvisibility=hidden
+
+# actual rules
+vpath %.ypp ${SRC_DIR}
+vpath %.lpp ${SRC_DIR}
+vpath %.cpp ${SRC_DIR}
+vpath %.hpp ${SRC_DIR}
+vpath %.tcc ${SRC_DIR}
+vpath tools/% ${SRC_DIR}
+
+.DELETE_ON_ERROR:
+.DEFAULT_GOAL := all
+# main goals
+all: ${BINARIES}
+cpp: ${GEN_SOURCES} ${GEN_HEADERS}
+ii: ${PREPROCESSED}
+ll: ${IRS}
+bc: ${BITCODES}
+s: ${ASSEMBLED}
+o: ${OBJECTS}
+
+mostlyclean:
+ rm -rf obj conf-raw
+clean: mostlyclean
+ rm -rf bin
+distclean: clean gen-clean
+gen-clean:
+ rm -f ${GEN_SOURCES} ${GEN_HEADERS}
+
+%.cpp: %.lpp
+ $(MKDIR_FIRST)
+ ${FLEX} -o $@ $<
+%.cpp %.hpp: %.ypp
+ $(MKDIR_FIRST)
+ ${BISON} -d -o $*.cpp $<
+ifndef MAKE_RESTARTS
+# prevent errors if missing header
+obj/%.d: src/%.cpp
+ $(MKDIR_FIRST)
+ set -o pipefail; \
+ ${CXX} ${CPPFLAGS} -DGENERATING_DEPENDENCIES ${CXXFLAGS} -MG -MP -MM $< \
+ -MT '$(patsubst %.d,%.ii,$@) $(patsubst %.d,%.ll,$@) $(patsubst %.d,%.bc,$@) $(patsubst %.d,%.s,$@) $(patsubst %.d,%.o,$@) $@' \
+ | sed -e ':again; s:/[^/. ]*/\.\./:/:; t again' \
+ -e 's: ${SRC_DIR}/: :g' \
+ > $@
+endif
+# the above SRC_DIR replacement is not really safe, but it works okayish.
+obj/%.ii: src/%.cpp
+ $(MKDIR_FIRST)
+ ${CXX} ${CPPFLAGS} -E -o $@ $<
+obj/%.ll: src/%.cpp
+ $(MKDIR_FIRST)
+ ${CXX} ${CPPFLAGS} ${CXXFLAGS} -S -emit-llvm -o $@ $<
+obj/%.bc: src/%.cpp
+ $(MKDIR_FIRST)
+ ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -emit-llvm -o $@ $<
+obj/%.s: src/%.cpp
+ $(MKDIR_FIRST)
+ ${CXX} ${CPPFLAGS} ${CXXFLAGS} -S -o $@ $<
+obj/%.o: src/%.cpp
+ $(MKDIR_FIRST)
+ ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $<
+
+obj/%/autolist.d: $(filter-out %/autolist.d,${DEPENDS})
+ echo $@: $(filter %_test.d,$^) > $@
+include ${DEPENDS}
+
+# I'm not convinced keeping the bin/ is a good idea
+# TODO - for development, regenerate -gdb.py even if the binary
+# doesn't need to be rebuilt. For release, the version forces rebuild.
+bin/%:
+ $(MKDIR_FIRST)
+ ${CXX} ${LDFLAGS} $^ ${LDLIBS} -o $@
+ cat ${SRC_DIR}/src/main-gdb-head.py \
+ $(wildcard $(patsubst obj/%.o,${SRC_DIR}/src/%.py,$^)) \
+ ${SRC_DIR}/src/main-gdb-tail.py \
+ > $@-gdb.py
+
+${TEST_BINARIES}: obj/gtest-all.o
+
+# This isn't perfect.
+$(filter %_test.o,${OBJECTS}) obj/gtest-all.o: override CPPFLAGS += -DGTEST_HAS_PTHREAD=0 -I${GTEST_DIR}
+obj/gtest-all.o: override WARNINGS :=
+obj/gtest-all.o: ${GTEST_DIR}/src/gtest-all.cc
+ $(MKDIR_FIRST)
+ ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $<
+
+test: $(patsubst bin/%,.run-%,${TEST_BINARIES})
+.run-%: bin/%
+ $<
+
+install := install --backup=${ENABLE_BACKUPS_DURING_INSTALL}
+install_exe := ${install}
+install_dir := ${install} -d
+install_data := ${install} -m 0644
+install_symlink := ln --backup=${ENABLE_BACKUPS_DURING_INSTALL} -sf
+
+install:
+ @echo = Done installing
+
+install: install-bin
+install-bin:
+ @echo + Installing binaries
+ ${install_dir} ${DESTDIR}${BINDIR}
+ ${install_exe} -t ${DESTDIR}${BINDIR} \
+ ${BINARIES}
+install-bin: install-bin-compat
+install-bin-compat:
+ifeq (${ENABLE_COMPAT_SYMLINKS},yes)
+ @echo + Installing compatibility symlinks
+ ${install_dir} ${DESTDIR}${BINDIR}
+ ${install_symlink} tmwa-login ${DESTDIR}${BINDIR}/login-server
+ ${install_symlink} tmwa-char ${DESTDIR}${BINDIR}/char-server
+ ${install_symlink} tmwa-map ${DESTDIR}${BINDIR}/map-server
+ ${install_symlink} tmwa-admin ${DESTDIR}${BINDIR}/ladmin
+ ${install_symlink} tmwa-monitor ${DESTDIR}${BINDIR}/eathena-monitor
+else
+ @echo - Not installing compatibility symlinks
+endif
+
+install: install-debug
+install-debug:
+ifeq (${ENABLE_DEBUG},yes)
+ @echo + Installing debug files
+ ${install_dir} ${DESTDIR}${DEBUGDIR}${BINDIR}
+ ${install_data} -t ${DESTDIR}${DEBUGDIR}${BINDIR} \
+ $(patsubst %,%-gdb.py,${BINARIES})
+else
+ @echo - Not installing debug files
+endif
+
+tags: ${SOURCES} ${HEADERS}
+ ctags --totals -h .tcc --langmap=C++:+.tcc --c-kinds=+px -f $@ $^
+
+Makefile: ${SRC_DIR}/Makefile.in
+ @echo Makefile.in updated, reconfiguring ...
+ ./config.status
+
+include ${SRC_DIR}/version.make
+
+# TODO - fix pattern priority bug so I can make these .hpp
+#
+# This is complicated and still isn't optimal.
+conf-raw/int-%.h: FORCE
+ $(MKDIR_FIRST)
+ echo '#define $* $(value $*)' | maybe-replace $@
+bool_yes := true
+bool_no := false
+conf-raw/bool-%.h: FORCE
+ $(MKDIR_FIRST)
+ echo '#define $* $(bool_$(value $*))' | maybe-replace $@
+conf-raw/str-%.h: FORCE
+ $(MKDIR_FIRST)
+ echo '#define $* "$(value $*)"' | maybe-replace $@
+FORCE: ;
+override CPPFLAGS += -I .
+
+# distribution tarballs
+# this only works from within a git checkout
+dist/%/version.make:
+ $(MKDIR_FIRST)
+ git show HEAD:version.make > $@
+ sed 's/^VERSION_FULL := .*/#&\nVERSION_FULL := ${VERSION_FULL}/' -i $@
+ sed 's/^VERSION_HASH := .*/#&\nVERSION_HASH := ${VERSION_HASH}/' -i $@
+dist/%-src.tar: dist/%/version.make
+ git archive --prefix=$*/ -o $@ HEAD
+ ( cd dist && tar uf $*-src.tar --mtime="$$(git log -n1 --pretty=%cd)" --mode=664 --owner=root --group=root $*/version.make )
+ rm dist/$*/version.make
+ rmdir dist/$*/
+dist/%-attoconf-only.tar:
+ $(MKDIR_FIRST)
+ git --git-dir=deps/attoconf/.git archive --prefix=$*/deps/attoconf/ HEAD -o $@
+dist/%-bundled.tar: dist/%-src.tar dist/%-attoconf-only.tar
+ cp dist/$*-src.tar $@
+ tar Af $@ dist/$*-attoconf-only.tar
+
+dist: dist/tmwa-${VERSION_FULL}-src.tar dist/tmwa-${VERSION_FULL}-bundled.tar
+.PHONY: dist
+
+# lpp and ypp are (currently) very slow, so do them first (parallel)
+format: format-lpp format-ypp format-cpp format-hpp
+format-cpp: $(patsubst src/%,obj/%.formatted,${REAL_SOURCES})
+format-hpp: $(patsubst src/%,obj/%.formatted,${REAL_HEADERS})
+format-lpp: $(patsubst src/%,obj/%.formatted,${LEXERS})
+format-ypp: $(patsubst src/%,obj/%.formatted,${PARSERS})
+obj/%.cpp.formatted: src/%.cpp tools/indenter
+ $(MKDIR_FIRST)
+ apply-filter 'indenter -cpp' $<
+ touch $@
+obj/%.hpp.formatted: src/%.hpp tools/indenter
+ $(MKDIR_FIRST)
+ apply-filter 'indenter -cpp' $<
+ touch $@
+obj/%.tcc.formatted: src/%.tcc tools/indenter
+ $(MKDIR_FIRST)
+ apply-filter 'indenter -cpp' $<
+ touch $@
+obj/%.lpp.formatted: src/%.lpp tools/indenter
+ $(MKDIR_FIRST)
+ apply-filter 'indenter -lpp' $<
+ touch $@
+obj/%.ypp.formatted: src/%.ypp tools/indenter
+ $(MKDIR_FIRST)
+ apply-filter 'indenter -ypp' $<
+ touch $@
+.PHONY: format format-cpp format-hpp format-lpp format-ypp