summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-07-17 16:50:40 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-07-17 23:35:14 -0700
commit25070b355b8a0394c1fbd9cf82c44752b5a8b8c3 (patch)
tree5e8edf1e5e3f58a8b11b1fcdd2fa851b2322df35
parent3b0b6deecf156916a9fb68dda9ca4b8a47d65aab (diff)
downloadtmwa-25070b355b8a0394c1fbd9cf82c44752b5a8b8c3.tar.gz
tmwa-25070b355b8a0394c1fbd9cf82c44752b5a8b8c3.tar.bz2
tmwa-25070b355b8a0394c1fbd9cf82c44752b5a8b8c3.tar.xz
tmwa-25070b355b8a0394c1fbd9cf82c44752b5a8b8c3.zip
Add dir annoyances
-rw-r--r--.travis.yml4
-rw-r--r--Makefile.in160
-rwxr-xr-xconfigure9
-rw-r--r--etc/tmwa/shared.conf1
-rw-r--r--include/tmwa/shared.hpp28
-rw-r--r--share/tmwa/shared.data1
-rw-r--r--src/conf/install.hpp30
-rw-r--r--src/io/dir.cpp54
-rw-r--r--src/io/dir.hpp50
-rw-r--r--src/io/fd.cpp4
-rw-r--r--src/io/fd.hpp8
-rw-r--r--src/io/read.cpp4
-rw-r--r--src/io/read.hpp3
-rw-r--r--src/io/write.cpp3
-rw-r--r--src/io/write.hpp3
-rw-r--r--src/mmo/core.cpp5
-rw-r--r--src/shared/lib.cpp80
-rw-r--r--src/strings/literal.hpp5
-rwxr-xr-xtools/maybe-mv2
-rwxr-xr-xtools/nightly68
-rw-r--r--version.make11
21 files changed, 490 insertions, 43 deletions
diff --git a/.travis.yml b/.travis.yml
index 8c2293e..fd6d110 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -48,7 +48,7 @@ script:
- mkdir build
- cd build
- git init
- - ../configure --dev CPPFLAGS=-DQUIET `! [[ $CXX =~ clang* ]] || echo --disable-abi6` $EXTRA_CONFIGURE_ARGS
+ - ../configure --build=x86_64-linux-gnu --dev CPPFLAGS=-DQUIET `! [[ $CXX =~ clang* ]] || echo --disable-abi6` $EXTRA_CONFIGURE_ARGS
- make -R -k -j2
- make -R -k -j2 test TESTER='valgrind --error-exitcode=1 --track-fds=yes'
@@ -56,7 +56,7 @@ script:
#after_script:
- make -R -k -j2 format
- git --git-dir=../.git --work-tree=.. diff --exit-code
- - make -R -k -j2 dist
+ - make -R -k -j2 dist bindist
### The rest of the file creates a build matrix
### containing gcc-4.6 through gcc-4.8 and clang-3.1 through clang-3.3
diff --git a/Makefile.in b/Makefile.in
index 9f02a8f..951bd51 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -12,8 +12,10 @@ BINDIR = @BINDIR@
SBINDIR = @SBINDIR@
LIBEXECDIR = @LIBEXECDIR@
SYSCONFDIR = @SYSCONFDIR@
+PACKAGESYSCONFDIR := ${SYSCONFDIR}/${PACKAGE}
SHAREDSTATEDIR = @SHAREDSTATEDIR@
LOCALSTATEDIR = @LOCALSTATEDIR@
+PACKAGELOCALSTATEDIR := ${LOCALSTATEDIR}/${PACKAGE}
LIBDIR = @LIBDIR@
INCLUDEDIR = @INCLUDEDIR@
OLDINCLUDEDIR = @OLDINCLUDEDIR@
@@ -33,8 +35,6 @@ DEBUGDIR = @DEBUGDIR@
BUILD = @BUILD@
HOST = @HOST@
-BISON = @BISON@
-FLEX = @FLEX@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LDLIBS = @LIBS@
@@ -49,6 +49,7 @@ ENABLE_ABI6 = @ENABLE_ABI6@
ENABLE_CYGWIN_HACKS = @ENABLE_CYGWIN_HACKS@
ENABLE_COMPAT_SYMLINKS = @ENABLE_COMPAT_SYMLINKS@
ENABLE_DEBUG = @ENABLE_DEBUG@
+ENABLE_RPATH = @ENABLE_RPATH@
TESTER =
TEST_ARGS =
@@ -170,22 +171,26 @@ SHELL=bash
# path lists
REAL_SOURCES := $(shell cd ${SRC_DIR}; find src/ -name '*.cpp')
-REAL_HEADERS := $(shell cd ${SRC_DIR}; find src/ -name '*.hpp' -o -name '*.tcc')
+REAL_HEADERS := $(shell cd ${SRC_DIR}; find include/ src/ -name '*.hpp' -o -name '*.tcc')
PIES := $(shell cd ${SRC_DIR}; find src/ -name '*.py')
SOURCES := ${REAL_SOURCES}
HEADERS := ${REAL_HEADERS}
PATTERN_ROOTS := $(patsubst src/%.cpp,%,${SOURCES})
PATTERN_MAINS := $(patsubst %/main,%,$(filter %/main,${PATTERN_ROOTS}))
+PATTERN_LIBS := $(patsubst %/lib,%,$(filter %/lib,${PATTERN_ROOTS}))
PATTERN_TESTS := $(patsubst %/test,%,$(filter %/test,${PATTERN_ROOTS}))
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})
+PDC_OBJECTS := $(patsubst %.d,%.pdc.o,${DEPENDS})
+PIC_OBJECTS := $(patsubst %.d,%.pic.o,${DEPENDS})
MAIN_SOURCES := $(filter %/main.cpp,${SOURCES})
+LIB_SOURCES := $(filter %/lib.cpp,${SOURCES})
TEST_SOURCES := $(filter %/test.cpp,${SOURCES})
BINARIES := $(patsubst src/%/main.cpp,bin/tmwa-%,${MAIN_SOURCES})
+LIBRARIES := $(patsubst src/%/lib.cpp,lib/libtmwa-%.so,${LIB_SOURCES})
TEST_BINARIES := $(patsubst src/%/test.cpp,bin/test-%,${TEST_SOURCES})
# tricky part
@@ -193,7 +198,7 @@ TEST_BINARIES := $(patsubst src/%/test.cpp,bin/test-%,${TEST_SOURCES})
# 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.
+# 3: For each lib.hpp header, substitute the corresponding .so library
# 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.
@@ -201,7 +206,7 @@ TEST_BINARIES := $(patsubst src/%/test.cpp,bin/test-%,${TEST_SOURCES})
define RECURSIVE_DEPS_IMPL
$(eval more_deps := $(value ${1}))
$(eval more_deps := $(patsubst src/%.hpp,%,${more_deps}))
-
+$(eval lib_deps += $(patsubst include/tmwa/%.hpp,lib/libtmwa-%.${SO_LONG},$(filter include/tmwa/%.hpp,${more_deps})))
$(eval more_deps := $(filter ${PATTERN_ROOTS},${more_deps}))
$(eval more_deps := $(filter-out ${cur_deps},${more_deps}))
$(eval cur_deps += ${more_deps})
@@ -215,6 +220,7 @@ endef
# 4: Expand to text. Note that *nothing* else actually produces anything!
define RECURSIVE_DEPS
$(eval cur_deps := ${1})
+$(eval lib_deps :=)
$(call RECURSIVE_DEPS_IMPL,${1})
${cur_deps}
@@ -249,6 +255,30 @@ CXXFLAGS += -fstack-protector
override CXXFLAGS += -fno-strict-aliasing
override CXXFLAGS += -fvisibility=hidden
+nothing=
+space=${nothing} ${nothing}
+define relpath
+$(subst ${space},/,$(foreach component,$(subst /,${space},$1),..))$2
+endef
+
+,=,
+ifeq (${ENABLE_RPATH},relative)
+rel_BINDIR := $(subst ${EPREFIX},,${BINDIR})
+rel_LIBDIR := $(subst ${EPREFIX},,${LIBDIR})
+ifneq (${EPREFIX}${rel_BINDIR},${BINDIR})
+$(error BINDIR must be within EPREFIX to use relative rpath)
+endif
+ifneq (${EPREFIX}${rel_LIBDIR},${LIBDIR})
+$(error LIBDIR must be within EPREFIX to use relative rpath)
+endif
+override LDFLAGS += -Wl,-rpath='$$ORIGIN/$(call relpath,${rel_BINDIR},${rel_LIBDIR})'
+endif
+
+ifeq (${ENABLE_RPATH},absolute)
+override LDFLAGS += -Wl,rpath=${LIBDIR}
+override LDFLAGS += $(patsubst -L%,-Wl$,rpath=%,$(filter -L%,${LDFLAGS}))
+endif
+
@@ -263,12 +293,15 @@ else
include ${DEPENDS}
endif
+include ${SRC_DIR}/version.make
+
+
thisdir := $(abspath .)
#$(foreach root,${PATTERN_ROOTS},$(info pre-root: ${root} := $(value ${root}))$(info ))
# can't do $(filter %.hpp yet)
$(foreach root,${PATTERN_ROOTS},$(eval ${root} := $(sort $(patsubst ${thisdir}/%,%,$(abspath $(patsubst ${SRC_DIR}/%,%,$(wildcard $(value ${root})) $(filter conf-raw/%.h,$(value ${root}))))))))
# have to redo what we undid to get it as a variable
-$(foreach root,${PATTERN_ROOTS},$(eval obj/${root}.ii obj/${root}.ll obj/${root}.bc obj/${root}.s obj/${root}.o obj/${root}.d : $(value ${root})) )
+$(foreach root,${PATTERN_ROOTS},$(eval obj/${root}.ii obj/${root}.ll obj/${root}.bc obj/${root}.s obj/${root}.pdc.o obj/${root}.pic.o obj/${root}.d : $(value ${root})) )
#$(foreach root,${PATTERN_ROOTS},$(info post-root: ${root} := $(value ${root}))$(info ))
# test.o implicitly (NOT explicitly) depends on all (nonexistent) test_*.hpp
@@ -276,17 +309,23 @@ $(foreach root,${PATTERN_ROOTS},$(eval obj/${root}.ii obj/${root}.ll obj/${root}
$(foreach test,${PATTERN_TESTS},$(eval ${test}/test += $(patsubst %,src/%.hpp,$(filter %_test,${PATTERN_ROOTS}))))
-$(foreach main,${PATTERN_MAINS},$(eval main-${main} := $(strip $(call RECURSIVE_DEPS,${main}/main))))
+$(foreach main,${PATTERN_MAINS},$(eval main-${main} := $(strip $(call RECURSIVE_DEPS,${main}/main))) $(eval main-${main}-libs := ${lib_deps}))
# actual rule deps
-$(foreach main,${PATTERN_MAINS},$(eval bin/tmwa-${main} : $(patsubst %,obj/%.o,$(value main-${main}))))
+$(foreach main,${PATTERN_MAINS},$(eval bin/tmwa-${main} : $(patsubst %,obj/%.pdc.o,$(value main-${main})) $(value main-${main}-libs)))
$(foreach main,${PATTERN_MAINS},$(eval bin/tmwa-${main}-gdb.py : $(filter ${PIES},$(patsubst %,src/%.py,$(value main-${main})))))
-#$(foreach main,${PATTERN_MAINS},$(info post-main: main-${main}: $(value main-${main})) $(info ))
+#$(foreach main,${PATTERN_MAINS},$(info post-main: main-${main}: $(value main-${main})) $(info post-main: main-${main}-libs: $(value main-${main}-libs)) $(info ))
+
+$(foreach lib,${PATTERN_LIBS},$(eval lib-${lib} := $(strip $(call RECURSIVE_DEPS,${lib}/lib))) $(eval lib-${lib}-libs := ${lib_deps}))
+# actual rule deps
+$(foreach lib,${PATTERN_LIBS},$(eval lib/libtmwa-${lib}.${SO_LONG} : $(patsubst %,obj/%.pic.o,$(value lib-${lib})) $(filter-out lib/libtmwa-${lib}.${SO_LONG},$(value lib-${lib}-libs))))
+$(foreach lib,${PATTERN_LIBS},$(eval lib/libtmwa-${lib}.${SO_LONG}-gdb.py : $(filter ${PIES},$(patsubst %,src/%.py,$(value lib-${lib})))))
+#$(foreach lib,${PATTERN_LIBS},$(info post-lib: lib-${lib}: $(value lib-${lib})) $(info post-lib: lib-${lib}-libs: $(value lib-${lib}-libs)) $(info ))
-$(foreach test,${PATTERN_TESTS},$(eval test-${test} := $(strip $(call RECURSIVE_DEPS,${test}/test))))
+$(foreach test,${PATTERN_TESTS},$(eval test-${test} := $(strip $(call RECURSIVE_DEPS,${test}/test))) $(eval test-${test}-libs := ${lib_deps}))
# actual rule deps
-$(foreach test,${PATTERN_TESTS},$(eval bin/test-${test} : $(patsubst %,obj/%.o,$(value test-${test}))))
+$(foreach test,${PATTERN_TESTS},$(eval bin/test-${test} : $(patsubst %,obj/%.pdc.o,$(value test-${test})) $(value test-${test}-libs)))
$(foreach test,${PATTERN_TESTS},$(eval bin/test-${test}-gdb.py : $(filter ${PIES},$(patsubst %,src/%.py,$(value test-${test})))))
-#$(foreach test,${PATTERN_TESTS},$(info post-test: test-${test}: $(value test-${test})) $(info ))
+#$(foreach test,${PATTERN_TESTS},$(info post-test: test-${test}: $(value test-${test})) $(info post-test: test-${test}-libs: $(value test-${test}-libs)) $(info ))
vpath %.cpp ${SRC_DIR}
@@ -306,17 +345,17 @@ s: ${ASSEMBLED}
o: ${OBJECTS}
clean-deps:
- -$c find obj -name '*.d' -delete
+ -$l find obj -name '*.d' -delete
clean-format:
- -$c find obj -name '*.formatted' -delete
+ -$l find obj -name '*.formatted' -delete
clean-obj:
- -$c find obj -name '*.o' -delete
+ -$l find obj -name '*.o' -delete
clean-conf:
- $c rm -rf conf-raw
+ $l rm -rf conf-raw
mostlyclean: clean-conf
- $c rm -rf obj
+ $l rm -rf obj
clean: mostlyclean
- $c rm -rf bin
+ $l rm -rf bin lib
distclean: clean gen-clean
gen-clean: ;
@@ -341,11 +380,13 @@ obj/%.bc: src/%.cpp
obj/%.s: src/%.cpp
$(MKDIR_FIRST)
$c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -S -o $@ $<
-obj/%.o: src/%.cpp
+obj/%.pdc.o: src/%.cpp
$(MKDIR_FIRST)
$c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $<
+obj/%.pic.o: src/%.cpp
+ $(MKDIR_FIRST)
+ $c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -fPIC -c -o $@ $<
-# I'm not convinced keeping the bin/ is a good idea
bin/%-gdb.py:
$(MKDIR_FIRST)
cat ${SRC_DIR}/src/main-gdb-head.py \
@@ -356,12 +397,24 @@ bin/%: bin/%-gdb.py
$(MKDIR_FIRST)
$l ${CXX} ${LDFLAGS} $(filter-out bin/%-gdb.py,$^) ${LDLIBS} -o $@
-${TEST_BINARIES}: obj/gtest-all.o
+lib/%.${SO_LONG}-gdb.py:
+ $(MKDIR_FIRST)
+ cat ${SRC_DIR}/src/main-gdb-head.py \
+ $^ \
+ ${SRC_DIR}/src/main-gdb-tail.py \
+ > $@
+lib/%.${SO_LONG}: lib/%.${SO_LONG}-gdb.py
+ $(MKDIR_FIRST)
+ $l ${CXX} -shared -Wl,-soname=$*.${SO_SHORT} ${LDFLAGS} $(filter-out lib/%-gdb.py,$^) ${LDLIBS} -o $@
+ $c ln -sf $*.${SO_LONG} lib/$*.${SO_SHORT}
+ $c ln -sf $*.${SO_SHORT} lib/$*.so
+
+${TEST_BINARIES}: obj/gtest-all.pdc.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
+$(filter %_test.pdc.o,${OBJECTS}) obj/gtest-all.pdc.o: override CPPFLAGS += -DGTEST_HAS_PTHREAD=0 -I${GTEST_DIR}
+obj/gtest-all.pdc.o: override WARNINGS :=
+obj/gtest-all.pdc.o: ${GTEST_DIR}/src/gtest-all.cc
$(MKDIR_FIRST)
$c ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $<
@@ -398,6 +451,17 @@ else
@echo - Not installing compatibility symlinks
endif
+install: install-lib
+install-lib:
+ @echo + Install libraries
+ ${install_dir} ${DESTDIR}${LIBDIR}
+ ${install_data} -t ${DESTDIR}${LIBDIR} \
+ $(patsubst %.so,%.${SO_LONG},${LIBRARIES})
+ for lib in $(patsubst lib/%.so,%,${LIBRARIES}); do \
+ ln -sf $$lib.${SO_LONG} ${DESTDIR}${LIBDIR}/$$lib.${SO_SHORT}; \
+ ln -sf $$lib.${SO_SHORT} ${DESTDIR}${LIBDIR}/$$lib.so; \
+ done
+
install: install-debug
install-debug:
ifeq (${ENABLE_DEBUG},yes)
@@ -405,10 +469,40 @@ ifeq (${ENABLE_DEBUG},yes)
${install_dir} ${DESTDIR}${DEBUGDIR}${BINDIR}
${install_data} -t ${DESTDIR}${DEBUGDIR}${BINDIR} \
$(patsubst %,%-gdb.py,${BINARIES})
+ ${install_dir} ${DESTDIR}${DEBUGDIR}${LIBDIR}
+ ${install_data} -t ${DESTDIR}${DEBUGDIR}${LIBDIR} \
+ $(patsubst %.so,%.${SO_LONG}-gdb.py,${LIBRARIES})
else
@echo - Not installing debug files
endif
+install: install-include
+install-include:
+ @echo + Install headers
+ ${install_dir} ${DESTDIR}${INCLUDEDIR}
+ ${install_data} -t ${DESTDIR}${INCLUDEDIR} \
+ $(addprefix ${SRC_DIR}/,$(filter include/%,${HEADERS}))
+
+install: install-state
+install-state:
+ @echo + Install statedir
+ ${install_dir} ${DESTDIR}${PACKAGELOCALSTATEDIR}
+ touch ${DESTDIR}${PACKAGELOCALSTATEDIR}/.keep
+
+install: install-data
+install-data:
+ @echo + Install data
+ ${install_dir} ${DESTDIR}${PACKAGEDATADIR}
+ ${install_data} -t ${DESTDIR}${PACKAGEDATADIR} \
+ ${SRC_DIR}/share/tmwa/*
+
+install: install-conf
+install-conf:
+ @echo + Install config files
+ ${install_dir} ${DESTDIR}${PACKAGESYSCONFDIR}
+ ${install_data} -t ${DESTDIR}${PACKAGESYSCONFDIR} \
+ ${SRC_DIR}/etc/tmwa/*
+
tags: ${SOURCES} ${HEADERS}
$l ctags --totals -h .tcc --langmap=C++:+.tcc --c-kinds=+px -f $@ $^
@@ -416,25 +510,23 @@ 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 $@
+ @echo '#define $* $(value $*)' | maybe-replace $@
bool_yes := true
bool_no := false
conf-raw/bool-%.h: FORCE
$(MKDIR_FIRST)
- echo '#define $* $(bool_$(value $*))' | maybe-replace $@
+ @echo '#define $* $(bool_$(value $*))' | maybe-replace $@
conf-raw/str-%.h: FORCE
$(MKDIR_FIRST)
- echo '#define $* "$(value $*)"_s' | maybe-replace $@
+ @echo '#define $* "$(value $*)"_s' | maybe-replace $@
FORCE: ;
.PHONY: FORCE
-override CPPFLAGS += -I .
+override CPPFLAGS += -I . -I ${SRC_DIR}/include
# distribution tarballs
# this only works from within a git checkout
@@ -455,8 +547,10 @@ dist/%-bundled.tar: dist/%-src.tar dist/%-attoconf-only.tar
cp dist/$*-src.tar $@
tar Af $@ dist/$*-attoconf-only.tar
dist/%-bin-${HOST}.tar: all
- ${MAKE} install DESTDIR=$(abspath dist/$*)
- tar cf $@ -C dist $*
+ ${MAKE} install DESTDIR=$(abspath dist/${HOST}/$*)
+ if test -n '${BUNDLED_LIBS}'; then cp ${BUNDLED_LIBS} dist/${HOST}/$*/${LIBDIR}/; fi
+ tar cf $@ -C dist/${HOST} $*
+ rm -r dist/${HOST}/
dist: dist/tmwa-${VERSION_FULL}-src.tar dist/tmwa-${VERSION_FULL}-bundled.tar
ifneq '' '${HOST}'
diff --git a/configure b/configure
index e75f860..504502a 100755
--- a/configure
+++ b/configure
@@ -48,8 +48,8 @@ class Configuration(Cxx, Install, ConfigHash, Templates):
def general(self):
super(Configuration, self).general()
home = os.path.expanduser('~')
- self.add_alias('--user', ['--prefix=%s' % home],
- help='alias for --prefix=$HOME', hidden=False)
+ self.add_alias('--user', ['--prefix=%s' % home, '--enable-rpath=relative'],
+ help='alias for --prefix=$HOME --enable-rpath=relative', hidden=False)
self.add_alias('--dev', ['--user', '--enable-warnings', '--enable-abi6'],
help=None, hidden=False)
@@ -78,12 +78,15 @@ class Configuration(Cxx, Install, ConfigHash, Templates):
self.add_bool_feature('cygwin-hacks', init='no',
check=lambda build, ENABLE_CYGWIN_HACKS: None,
help='Work around bugs in certain cygwin versions')
- self.add_bool_feature('compat-symlinks', init='yes',
+ self.add_bool_feature('compat-symlinks', init='no',
check=lambda build, ENABLE_COMPAT_SYMLINKS: None,
help='Install symlinks to avoid breaking old scripts')
self.add_bool_feature('debug', init='yes',
check=lambda build, ENABLE_DEBUG: None,
help='Install extra files useful for debugging')
+ self.add_option('--enable-rpath', init='none',
+ type=enum('none', 'relative', 'absolute'), check=lambda build, ENABLE_RPATH: None,
+ help='Use rpaths to find libraries', hidden=False)
def vars(self):
super(Configuration, self).vars()
diff --git a/etc/tmwa/shared.conf b/etc/tmwa/shared.conf
new file mode 100644
index 0000000..a05b6cb
--- /dev/null
+++ b/etc/tmwa/shared.conf
@@ -0,0 +1 @@
+// This file is used for common config between all servers
diff --git a/include/tmwa/shared.hpp b/include/tmwa/shared.hpp
new file mode 100644
index 0000000..c624e54
--- /dev/null
+++ b/include/tmwa/shared.hpp
@@ -0,0 +1,28 @@
+#pragma once
+// tmwa/shared.hpp - Public header to ensure install is working.
+//
+// Copyright © 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/>.
+
+#include <cstdbool>
+
+
+namespace tmwa
+{
+ __attribute__((visibility("default")))
+ void check_paths();
+} // namespace tmwa
diff --git a/share/tmwa/shared.data b/share/tmwa/shared.data
new file mode 100644
index 0000000..f30511f
--- /dev/null
+++ b/share/tmwa/shared.data
@@ -0,0 +1 @@
+// This file is used for common data between all servers
diff --git a/src/conf/install.hpp b/src/conf/install.hpp
new file mode 100644
index 0000000..42fd125
--- /dev/null
+++ b/src/conf/install.hpp
@@ -0,0 +1,30 @@
+#pragma once
+// conf/install.hpp - Import configuration variables related to install.
+//
+// Copyright © 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/>.
+
+// just mention "fwd.hpp" to make formatter happy
+
+#include "conf-raw/str-PACKAGESYSCONFDIR.h"
+#include "conf-raw/str-PACKAGELOCALSTATEDIR.h"
+#include "conf-raw/str-PACKAGEDATADIR.h"
+
+
+namespace tmwa
+{
+} // namespace tmwa
diff --git a/src/io/dir.cpp b/src/io/dir.cpp
new file mode 100644
index 0000000..2acb75a
--- /dev/null
+++ b/src/io/dir.cpp
@@ -0,0 +1,54 @@
+#include "dir.hpp"
+// io/dir.cpp - rooted file operations
+//
+// Copyright © 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/>.
+
+#include <fcntl.h>
+
+#include "../strings/zstring.hpp"
+
+#include "../poison.hpp"
+
+
+namespace tmwa
+{
+namespace io
+{
+ DirFd::DirFd()
+ : dirfd(FD::cast_dammit(AT_FDCWD))
+ {}
+
+ DirFd::DirFd(ZString path)
+ : dirfd(FD::open(path, O_DIRECTORY | O_RDONLY, 0))
+ {}
+
+ DirFd::DirFd(const DirFd& root, ZString path)
+ : dirfd(FD::openat(root.dirfd, path, O_DIRECTORY | O_RDONLY, 0))
+ {}
+
+ DirFd::~DirFd()
+ {
+ dirfd.close();
+ }
+
+ FD DirFd::open_fd(ZString name, int flags, int mode) const
+ {
+ return FD::openat(dirfd, name, flags, mode);
+ }
+} // namespace io
+} // namespace tmwa
diff --git a/src/io/dir.hpp b/src/io/dir.hpp
new file mode 100644
index 0000000..071f309
--- /dev/null
+++ b/src/io/dir.hpp
@@ -0,0 +1,50 @@
+#pragma once
+// io/dir.hpp - rooted file operations
+//
+// Copyright © 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/>.
+
+#include "fwd.hpp"
+
+#include "../strings/fwd.hpp"
+
+#include "fd.hpp"
+
+
+namespace tmwa
+{
+namespace io
+{
+ class DirFd
+ {
+ private:
+ FD dirfd;
+
+ public:
+ DirFd();
+ explicit
+ DirFd(ZString);
+ DirFd(const DirFd&, ZString);
+
+ DirFd(const DirFd&) = delete;
+ ~DirFd();
+ DirFd& operator = (const DirFd&) = delete;
+
+ FD open_fd(ZString name, int flags, int mode=FD::DEFAULT_MODE) const;
+ };
+} // namespace io
+} // namespace tmwa
diff --git a/src/io/fd.cpp b/src/io/fd.cpp
index 4c61a6f..c0b44e8 100644
--- a/src/io/fd.cpp
+++ b/src/io/fd.cpp
@@ -34,6 +34,10 @@ namespace io
{
return FD(::open(path.c_str(), flags, mode));
}
+ FD FD::openat(FD dirfd, ZString path, int flags, int mode)
+ {
+ return FD(::openat(dirfd.fd, path.c_str(), flags, mode));
+ }
FD FD::socket(int domain, int type, int protocol)
{
return FD(::socket(domain, type, protocol));
diff --git a/src/io/fd.hpp b/src/io/fd.hpp
index 6fb745d..d04d5bf 100644
--- a/src/io/fd.hpp
+++ b/src/io/fd.hpp
@@ -56,8 +56,13 @@ namespace io
FD stdout() { return FD(1); }
static
FD stderr() { return FD(2); }
+
+ static const int DEFAULT_MODE = 0666;
+
static
- FD open(ZString path, int flags, int mode=0666);
+ FD open(ZString path, int flags, int mode=DEFAULT_MODE);
+ static
+ FD openat(FD dirfd, ZString path, int flags, int mode=DEFAULT_MODE);
static
FD socket(int domain, int type, int protocol);
FD accept(struct sockaddr *addr, socklen_t *addrlen);
@@ -65,6 +70,7 @@ namespace io
int pipe(FD& r, FD& w);
static
int pipe2(FD& r, FD& w, int flags);
+
static
FD sysconf_SC_OPEN_MAX();
diff --git a/src/io/read.cpp b/src/io/read.cpp
index d057ca6..3ae5246 100644
--- a/src/io/read.cpp
+++ b/src/io/read.cpp
@@ -42,6 +42,10 @@ namespace io
: fd(FD::open(name, O_RDONLY | O_CLOEXEC)), start(0), end(0)
{
}
+ ReadFile::ReadFile(const DirFd& dir, ZString name)
+ : fd(dir.open_fd(name, O_RDONLY | O_CLOEXEC)), start(0), end(0)
+ {
+ }
ReadFile::~ReadFile()
{
fd.close();
diff --git a/src/io/read.hpp b/src/io/read.hpp
index 6a44de6..1ec26ca 100644
--- a/src/io/read.hpp
+++ b/src/io/read.hpp
@@ -22,6 +22,7 @@
#include "../strings/fwd.hpp"
+#include "dir.hpp"
#include "fd.hpp"
namespace tmwa
@@ -39,6 +40,8 @@ namespace io
ReadFile(FD fd);
explicit
ReadFile(ZString name);
+ ReadFile(const DirFd& dir, ZString name);
+
ReadFile& operator = (ReadFile&&) = delete;
ReadFile(ReadFile&&) = delete;
~ReadFile();
diff --git a/src/io/write.cpp b/src/io/write.cpp
index 3326d2c..833b173 100644
--- a/src/io/write.cpp
+++ b/src/io/write.cpp
@@ -41,6 +41,9 @@ namespace io
WriteFile::WriteFile(ZString name, bool linebuffered)
: fd(FD::open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)), lb(linebuffered), buflen(0)
{}
+ WriteFile::WriteFile(const DirFd& dir, ZString name, bool linebuffered)
+ : fd(dir.open_fd(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)), lb(linebuffered), buflen(0)
+ {}
WriteFile::~WriteFile()
{
if (fd != FD())
diff --git a/src/io/write.hpp b/src/io/write.hpp
index 11bc679..1ab05f3 100644
--- a/src/io/write.hpp
+++ b/src/io/write.hpp
@@ -24,6 +24,7 @@
#include "../strings/fwd.hpp"
+#include "dir.hpp"
#include "fd.hpp"
@@ -43,6 +44,8 @@ namespace io
WriteFile(FD fd, bool linebuffered=false);
explicit
WriteFile(ZString name, bool linebuffered=false);
+ WriteFile(const DirFd& dir, ZString name, bool linebuffered=false);
+
WriteFile(WriteFile&&) = delete;
WriteFile& operator = (WriteFile&&) = delete;
~WriteFile();
diff --git a/src/mmo/core.cpp b/src/mmo/core.cpp
index 2264ec6..f1a8d07 100644
--- a/src/mmo/core.cpp
+++ b/src/mmo/core.cpp
@@ -27,6 +27,8 @@
#include <csignal>
#include <cstdlib>
+#include <tmwa/shared.hpp>
+
#include "../strings/zstring.hpp"
#include "../strings/literal.hpp"
@@ -107,6 +109,9 @@ void sig_proc(int)
int main(int argc, char **argv)
{
using namespace tmwa;
+
+ check_paths();
+
// ZString args[argc]; is (deliberately!) not supported by clang yet
ZString *args = static_cast<ZString *>(alloca(argc * sizeof(ZString)));
for (int i = 0; i < argc; ++i)
diff --git a/src/shared/lib.cpp b/src/shared/lib.cpp
new file mode 100644
index 0000000..a9dc9b1
--- /dev/null
+++ b/src/shared/lib.cpp
@@ -0,0 +1,80 @@
+#include <tmwa/shared.hpp>
+// shared/lib.cpp - Public library to ensure install is working.
+//
+// Copyright © 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/>.
+
+#include "../conf/install.hpp"
+
+#include "../strings/literal.hpp"
+#include "../strings/astring.hpp"
+#include "../strings/zstring.hpp"
+
+#include "../io/cxxstdio.hpp"
+#include "../io/dir.hpp"
+#include "../io/read.hpp"
+#include "../io/write.hpp"
+
+#include "../poison.hpp"
+
+
+namespace tmwa
+{
+#define PRINT_VAR(var) PRINTF("%s = %s\n"_fmt, #var##_s, var)
+
+ static
+ void try_read(const io::DirFd& dirfd, ZString filename)
+ {
+ io::ReadFile rf(dirfd, filename);
+ if (!rf.is_open())
+ abort();
+ AString line;
+ if (!rf.getline(line))
+ abort();
+ }
+
+ static
+ void try_write(const io::DirFd& dirfd, ZString filename)
+ {
+ io::WriteFile wf(dirfd, filename);
+ if (!wf.is_open())
+ abort();
+ wf.put_line("Hello, World!"_s);
+ if (!wf.close())
+ abort();
+ }
+
+ void check_paths()
+ {
+ ZString portable_root(strings::really_construct_from_a_pointer, getenv("TMWA_PORTABLE") ?: "", nullptr);
+ bool portable = bool(portable_root);
+ if (!portable)
+ portable_root = "."_s;
+
+ io::DirFd root(portable_root);
+
+ io::DirFd etc(root, PACKAGESYSCONFDIR.xslice_t(portable));
+ io::DirFd var(root, PACKAGELOCALSTATEDIR.xslice_t(portable));
+ io::DirFd share(root, PACKAGEDATADIR.xslice_t(portable));
+
+ try_read(etc, "shared.conf"_s);
+ try_read(share, "shared.data"_s);
+ try_write(var, "shared.test"_s);
+
+ // io::FD::open();
+ }
+} // namespace tmwa
diff --git a/src/strings/literal.hpp b/src/strings/literal.hpp
index 5e27a9f..67bd317 100644
--- a/src/strings/literal.hpp
+++ b/src/strings/literal.hpp
@@ -32,11 +32,12 @@ namespace strings
class LString : public _crtp_string<LString, AString, LPair>
{
iterator _b, _e;
- // optional
- const RString *_base;
private:
LString(const char *b, const char *e);
friend LString operator "" _s(const char *, size_t);
+ // for tail slicing
+ LString(const char *b, const char *e, const RString *) : LString(b, e) {}
+ friend class _crtp_string<LString, AString, LPair>;
public:
iterator begin() const;
diff --git a/tools/maybe-mv b/tools/maybe-mv
index 996052f..56d8e9e 100755
--- a/tools/maybe-mv
+++ b/tools/maybe-mv
@@ -2,9 +2,7 @@
# Replace one file with another, but maybe don't update the timestamp
if cmp "$1" "$2"
then
- echo rm "$1"
rm "$1"
else
- echo mv "$1" "$2"
mv "$1" "$2"
fi
diff --git a/tools/nightly b/tools/nightly
new file mode 100755
index 0000000..7e72605
--- /dev/null
+++ b/tools/nightly
@@ -0,0 +1,68 @@
+#!/bin/bash -e
+
+WWW=${HOME}/www/
+
+ALL_CONFIGS=(
+ config64
+ config32
+)
+# need a special kernel for configx32
+
+
+config32() {
+ # No one knows what number this is supposed to be:
+ # - the lib directory is called i386-linux-gnu
+ # - the 32-bit files are called i486-linux-gnu
+ # - the cross-32 configury says i586
+ HOST=i586-linux-gnu
+ CXX='g++ -m32'
+ EXTRA_LIBS=(
+ /lib32/libc.so.6
+ /lib32/libm.so.6
+ /usr/lib32/libgcc_s.so.1
+ /usr/lib32/libstdc++.so.6
+ )
+}
+
+configx32() {
+ HOST=x86_64-linux-gnux32
+ CXX='g++ -mx32'
+ EXTRA_LIBS=(
+ /libx32/libc.so.6
+ /libx32/libm.so.6
+ /usr/libx32/libgcc_s.so.1
+ /usr/libx32/libstdc++.so.6
+ )
+}
+
+config64() {
+ HOST=x86_64-linux-gnu
+ CXX='g++ -m64'
+ EXTRA_LIBS=(
+ /lib/x86_64-linux-gnu/libc.so.6
+ /lib/x86_64-linux-gnu/libm.so.6
+ /lib/x86_64-linux-gnu/libgcc_s.so.1
+ /usr/lib/x86_64-linux-gnu/libstdc++.so.6
+ )
+}
+
+first=true
+
+for config in ${ALL_CONFIGS[@]}
+do
+ $config
+ mkdir -p build-$HOST
+ cd build-$HOST
+ ../configure --host=$HOST CXX="$CXX -Wno-deprecated-declarations" --prefix=/. --enable-rpath=relative
+ make -j3 all
+ make -j3 test
+ if $first
+ then
+ make -j3 dist
+ first=false
+ fi
+ make -j3 bindist BUNDLED_LIBS="${EXTRA_LIBS[*]}"
+ gzip -n -9 dist/*.tar
+ mv dist/*.tar.gz $WWW
+ cd ..
+done
diff --git a/version.make b/version.make
index f7d5511..73ecc83 100644
--- a/version.make
+++ b/version.make
@@ -1,4 +1,7 @@
+ABI_VERSION := 0
+
# These lines are automatically replaced in tarballs generated by 'make dist'
+# Note so you stop forgetting: export-subst attribute can't do tag-relative
VERSION_FULL := $(shell git --git-dir=${SRC_DIR}/.git describe --tags HEAD)
VERSION_HASH := $(shell git --git-dir=${SRC_DIR}/.git rev-parse HEAD)
@@ -40,8 +43,16 @@ VENDOR_SOURCE := https://github.com/themanaworld/tmwa
# Convenience
VERSION_STRING := TMWA ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} dev${VERSION_DEVEL} +${VENDOR_POINT} (${VENDOR_NAME})
+VERSION_DOTS := ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_DEVEL}.${VENDOR_POINT}
+
+# Shared libraries
+SO_SHORT := so.${ABI_VERSION}
+SO_LONG := ${SO_SHORT}.${VERSION_DOTS}
+# and thanks for all the fish
version:
@echo version '${VERSION_STRING}'
@echo based on commit ${VERSION_FULL} aka ${VERSION_HASH}
@echo source ${VENDOR_SOURCE}
+ @echo abi version ${ABI_VERSION}
+ @echo 'lib so -> ${SO_SHORT} -> ${SO_LONG}'