From 7c77cbd24c03aceff65feae5082221b62eaeea6e Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Sat, 1 Feb 2014 14:57:23 -0800 Subject: Get rid of makefile indirection --- real.make | 418 -------------------------------------------------------------- 1 file changed, 418 deletions(-) delete mode 100644 real.make (limited to 'real.make') diff --git a/real.make b/real.make deleted file mode 100644 index dd22b2d..0000000 --- a/real.make +++ /dev/null @@ -1,418 +0,0 @@ -## real.make - The One Makefile that builds them all. -## -## Copyright © 2012-2013 Ben Longbons -## -## 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 . - -# 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-2013 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 - -ifeq ($(findstring r, $(firstword ${MAKEFLAGS})),) -$(error Missing -r - please do not invoke this makefile directly.) -endif - -ifeq ($(findstring R, $(firstword ${MAKEFLAGS})),) -$(error Missing -R - please do not invoke this makefile directly.) -endif - -ifneq "$(notdir ${MAKEFILE_LIST})" "real.make" -$(error not used as sole toplevel makefile!) -endif - -include Makefile # for variables - this is handled VERY carefully - -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 -- cgit v1.2.3-70-g09d2