From 25070b355b8a0394c1fbd9cf82c44752b5a8b8c3 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Thu, 17 Jul 2014 16:50:40 -0700 Subject: Add dir annoyances --- .travis.yml | 4 +- Makefile.in | 160 ++++++++++++++++++++++++++++++++++++++---------- configure | 9 ++- etc/tmwa/shared.conf | 1 + include/tmwa/shared.hpp | 28 +++++++++ share/tmwa/shared.data | 1 + src/conf/install.hpp | 30 +++++++++ src/io/dir.cpp | 54 ++++++++++++++++ src/io/dir.hpp | 50 +++++++++++++++ src/io/fd.cpp | 4 ++ src/io/fd.hpp | 8 ++- src/io/read.cpp | 4 ++ src/io/read.hpp | 3 + src/io/write.cpp | 3 + src/io/write.hpp | 3 + src/mmo/core.cpp | 5 ++ src/shared/lib.cpp | 80 ++++++++++++++++++++++++ src/strings/literal.hpp | 5 +- tools/maybe-mv | 2 - tools/nightly | 68 ++++++++++++++++++++ version.make | 11 ++++ 21 files changed, 490 insertions(+), 43 deletions(-) create mode 100644 etc/tmwa/shared.conf create mode 100644 include/tmwa/shared.hpp create mode 100644 share/tmwa/shared.data create mode 100644 src/conf/install.hpp create mode 100644 src/io/dir.cpp create mode 100644 src/io/dir.hpp create mode 100644 src/shared/lib.cpp create mode 100755 tools/nightly 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 +// +// 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 . + +#include + + +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 +// +// 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 . + +// 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 +// +// 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 . + +#include + +#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 +// +// 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 . + +#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 #include +#include + #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(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 +// shared/lib.cpp - Public library to ensure install is working. +// +// Copyright © 2014 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 . + +#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 { 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; 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}' -- cgit v1.2.3-60-g2f50