Migrate to latest project structure

This commit is contained in:
Bob Polis 2025-01-08 12:37:42 +01:00
parent 3893978f18
commit 71b674ff42
11 changed files with 522 additions and 111 deletions

305
Makefile
View File

@ -1,29 +1,40 @@
include premake.make include premake.make
BIN := $(shell basename $$(pwd)) # git commit hash and version for this build
COMMIT != git log 2>/dev/null | sed -e '1s/^commit //;q' COMMIT-HASH != git log 2>/dev/null | sed -e '1s/^commit //;q'
COMMIT := "static const char* commit = \"$(COMMIT-HASH)\";"
VERSION := "static const char* version = \"$(MAJOR).$(MINOR).$(PATCH)\";"
MANSECTION ?= 1 # some important install locations
MANPAGE := $(BIN).$(MANSECTION)
SRCS := $(notdir $(wildcard src/*.cpp))
OBJS := $(SRCS:.cpp=.o)
DEPS := $(SRCS:.cpp=.dep)
BUILDDIR := build/intermediates/
PREFIX ?= /usr/local PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin BINDIR ?= $(PREFIX)/bin
MANDIR ?= $(PREFIX)/man/man
CONFIGDIR ?= $(PREFIX)/etc CONFIGDIR ?= $(PREFIX)/etc
DATADIR ?= $(PREFIX)/share INCLUDEDIR ?= $(PREFIX)/include
DOCDIR ?= $(DATADIR)/$(BIN)/doc LIBDIR ?= $(PREFIX)/lib
MANDIR ?= $(PREFIX)/man
DATADIR ?= $(PREFIX)/share/$(PROJ)
DOCDIR ?= $(DATADIR)/doc
# setup naming and versioning for library product
ifeq ($(UNAME_S), Darwin)
LINKERNAME := $(PROJ).dylib
SONAME := $(PROJ).$(MAJOR).dylib
REALNAME := $(LINKERNAME)
else ifeq ($(UNAME_S), OpenBSD)
REALNAME := $(PROJ).so.$(MAJOR).$(MINOR)
else ifeq ($(UNAME_S), Linux)
LINKERNAME := $(PROJ).so
SONAME := $(LINKERNAME).$(MAJOR)
REALNAME := $(SONAME).$(MINOR).$(PATCH)
endif
STATICLIB := $(PROJ).a
# select default compiler
CXX ?= g++ CXX ?= g++
RM := /bin/rm -rf
INSTALL := /usr/bin/install -c
# setup compiler flags and build config
CXXFLAGS += -Wshadow -Wall -Wpedantic -Wextra -Wno-unused-parameter CXXFLAGS += -Wshadow -Wall -Wpedantic -Wextra -Wno-unused-parameter
CXXFLAGS += -g3 -std=c++17 CXXFLAGS += -g3 -fPIC
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CXXFLAGS += -DDEBUG -O0 CXXFLAGS += -DDEBUG -O0
CONFIG := debug CONFIG := debug
@ -31,49 +42,253 @@ else
CXXFLAGS += -DNDEBUG -O3 CXXFLAGS += -DNDEBUG -O3
CONFIG := release CONFIG := release
endif endif
OUTDIR := build/$(CONFIG)/
vpath %.cpp src # setup build locations
vpath %.dep $(BUILDDIR) OUTDIR := build/$(CONFIG)
vpath %.o $(BUILDDIR) BUILDDIR := build/obj
BIN := $(OUTDIR)/$(PROJ)
.PHONY: all clean install prebuild test dist-clean # define sources and derived files
# allow for extra sources defined in premake.make
SRCS += $(notdir $(wildcard src/*.cpp))
OBJS := $(addprefix $(BUILDDIR)/, $(SRCS:.cpp=.o))
DEPS := $(addprefix $(BUILDDIR)/, $(SRCS:.cpp=.dep))
HDRS ?= $(filter-out src/precomp.hpp, $(wildcard src/*.hpp))
MANS := $(addprefix $(PREFIX)/, $(wildcard man/man*/*))
all: prebuild $(OUTDIR)$(BIN) # if project supports plugins, link to libdl where needed
ifdef PLUGINS
ifeq ($(UNAME_S),Darwin)
LDLIBS += -ldl
else ifeq ($(UNAME_S),Linux)
LDLIBS += -ldl
endif
endif
prebuild: src/commit.inc # pattern rules ===========================================================
@mkdir -p $(BUILDDIR) $(OUTDIR)
sed -i.bak -e '1s/".*"/"$(COMMIT)"/' src/commit.inc
@rm src/commit.inc.bak
src/commit.inc: $(BUILDDIR)/%.o: src/%.cpp
echo 'const char* commit = "";' > $@ ifeq ($(PRECOMPILE), 1)
$(CXX) $(CXXFLAGS) -o $@ -include precomp.hpp -MMD -MP -MT $@ -MF $(BUILDDIR)/$*.dep -c $<
else
$(CXX) $(CXXFLAGS) -o $@ -MMD -MP -MT $@ -MF $(BUILDDIR)/$*.dep -c $<
endif
$(OUTDIR)$(BIN): $(OBJS) %.dep: ;
$(CXX) -o $(OUTDIR)$(BIN) $(LDFLAGS) $(addprefix $(BUILDDIR),$(OBJS)) $(LDLIBS)
@ln -sf $(OUTDIR)$(BIN) $(BIN)
%.o %.dep: %.cpp $(MANDIR)/man1/%: man/man1/%
$(CXX) $(CXXFLAGS) -MMD -MP -MT $@ -MF $*.dep -c $< install -m 0644 $< $@
@mv $@ $*.dep $(BUILDDIR)
-include $(addprefix $(BUILDDIR), $(DEPS)) $(MANDIR)/man3/%: man/man3/%
install -m 0644 $< $@
$(MANDIR)/man5/%: man/man5/%
install -m 0644 $< $@
# =========================================================== pattern rules
# targets =================================================================
.PHONY: all commit-hash version plugins test clean dist-clean install-plugins \
install install-data uninstall-data uninstall-plugins uninstall
# main target
ifeq ($(PRODUCT), tool)
all: $(BUILDDIR) $(OUTDIR) commit-hash version plugins $(BIN)
else ifeq ($(PRODUCT), lib)
all: $(BUILDDIR) $(OUTDIR) commit-hash version plugins $(OUTDIR)/$(REALNAME) $(OUTDIR)/$(STATICLIB)
endif
$(BUILDDIR):
mkdir -p $@
$(OUTDIR):
mkdir -p $@
# product build rules
ifeq ($(PRODUCT), tool) # -------------------------------------------- tool
ifeq ($(PRECOMPILE), 1)
$(BIN): precomp.hpp.gch $(OBJS)
else
$(BIN): $(OBJS)
endif
$(CXX) -o $(BIN) $(LDFLAGS) $(OBJS) $(LDLIBS)
@ln -sf $(BIN) $(PROJ)
endif # -------------------------------------------------------------- tool
ifeq ($(PRODUCT), lib) # ---------------------------------------------- lib
ifeq ($(PRECOMPILE), 1)
$(OUTDIR)/$(REALNAME): precomp.hpp.gch $(OBJS)
else
$(OUTDIR)/$(REALNAME): $(OBJS)
endif
ifeq ($(UNAME_S),Darwin)
$(CXX) -dynamiclib -o $(OUTDIR)/$(REALNAME) -install_name $(LIBDIR)/$(REALNAME) \
-current_version $(MAJOR) -compatibility_version $(MINOR) $(LDFLAGS) $(OBJS) $(LDLIBS)
else ifeq ($(UNAME_S),OpenBSD)
$(CXX) -g -shared -Wl,-soname,$(REALNAME) -o $(OUTDIR)/$(REALNAME) $(LDFLAGS) $(OBJS) $(LDLIBS)
else ifeq ($(UNAME_S),Linux)
$(CXX) -g -shared -Wl,-soname,$(SONAME) -o $(OUTDIR)/$(REALNAME) $(LDFLAGS) $(OBJS) $(LDLIBS)
endif
$(OUTDIR)/$(STATICLIB): $(OBJS)
ar r $(OUTDIR)/$(STATICLIB) $(OBJS)
ifeq ($(GENERATELIBHEADER),1)
$(OUTDIR)/$(PROJ).hpp: $(HDRS)
@echo updating $(OUTDIR)/$(PROJ).hpp
@cp /dev/null $(OUTDIR)/$(PROJ).hpp
@for h in $(HDRS); \
do \
sed '/@exclude/d' $$h >> $(OUTDIR)/$(PROJ).hpp; \
done
endif
endif # --------------------------------------------------------------- lib
# get generated dependencies, if any
-include $(DEPS)
commit-hash:
@if ! echo $(COMMIT) | diff -q src/commit.inc - >/dev/null 2>&1 ;\
then \
echo $(COMMIT) > src/commit.inc ;\
fi
version:
@if ! echo $(VERSION) | diff -q src/version.inc - >/dev/null 2>&1 ;\
then \
echo $(VERSION) > src/version.inc ;\
fi
$(BUILDDIR)/version.o: src/version.inc src/commit.inc
precomp.hpp.gch: src/precomp.hpp
$(CXX) $< $(CXXFLAGS) -o $@
plugins:
ifdef PLUGINS
@for plug in $(PLUGINS) ;\
do \
$(MAKE) -C $$plug ;\
done
endif
test: test:
$(MAKE) -C tests && tests/tests $(MAKE) -C tests && tests/tests
clean: clean:
$(RM) $(BUILDDIR) rm -rf $(BUILDDIR) tests/build tests/tests tests/src/commit.inc tests/src/version.inc
$(MAKE) -C tests clean ifdef PLUGINS
@for plug in $(PLUGINS) ;\
do \
$(MAKE) -C $$plug clean ;\
done
endif
dist-clean: dist-clean: clean
$(RM) build $(BIN) src/commit.inc rm -rf build $(PROJ) src/commit.inc src/version.inc precomp.hpp.gch
$(MAKE) -C tests clean
install: $(MANDIR)/man1:
$(INSTALL) -d $(BINDIR) install -m 0755 -d $@
$(INSTALL) $(OUTDIR)$(BIN) $(BINDIR)
$(INSTALL) -d $(MANDIR)$(MANSECTION)
$(INSTALL) -m 0644 $(MANPAGE) $(MANDIR)$(MANSECTION)
$(MANDIR)/man3:
install -m 0755 -d $@
$(MANDIR)/man5:
install -m 0755 -d $@
$(DATADIR):
install -m 0755 -d $@
# (un)install targets
ifdef DATAFILES
install-data: $(DATADIR)
install -m 0644 $(DATAFILES) $(DATADIR)
else
install-data:
endif
uninstall-data:
rm -rf $(DATADIR)
install-plugins:
ifdef PLUGINS
@for plug in $(PLUGINS) ;\
do \
$(MAKE) -C $$plug install ;\
done
endif
uninstall-plugins:
ifdef PLUGINS
@for plug in $(PLUGINS) ;\
do \
$(MAKE) -C $$plug uninstall ;\
done
endif
ifeq ($(PRODUCT), tool) # -------------------------------------------- tool
$(BINDIR):
install -m 0755 -d $@
install: $(MANDIR)/man1 $(MANDIR)/man3 $(MANDIR)/man5 $(BINDIR) $(MANS) install-data install-plugins
install -m 0755 $(BIN) $(BINDIR)
uninstall: uninstall-data uninstall-plugins
rm -f $(BINDIR)/$(PROJ) $(MANS)
endif # -------------------------------------------------------------- tool
ifeq ($(PRODUCT), lib) # ---------------------------------------------- lib
$(LIBDIR):
install -m 0755 -d $@
$(INCLUDEDIR):
install -m 0755 -d $@
$(INCLUDEDIR)/$(PROJ):
install -m 0755 -d $@
ifeq ($(GENERATELIBHEADER), 1)
install: $(MANDIR)/man1 $(MANDIR)/man3 $(MANDIR)/man5 $(LIBDIR) $(INCLUDEDIR) $(MANS) $(OUTDIR)/$(PROJ).hpp install-data install-plugins
install -m 0644 $(OUTDIR)/$(PROJ).hpp $(INCLUDEDIR)
else
install: $(MANDIR)/man1 $(MANDIR)/man3 $(MANDIR)/man5 $(LIBDIR) $(INCLUDEDIR) $(MANS) $(INCLUDEDIR)/$(PROJ) install-data install-plugins
install -m 0644 $(HDRS) $(INCLUDEDIR)/$(PROJ)
endif
install -m 0644 $(OUTDIR)/$(REALNAME) $(LIBDIR)
install -m 0644 $(OUTDIR)/$(STATICLIB) $(LIBDIR)
ifeq ($(UNAME_S), Darwin)
cd $(LIBDIR) && ln -sf $(REALNAME) $(SONAME)
else ifeq ($(UNAME_S), Linux)
ifeq ($(USER), root)
ldconfig
else
cd $(LIBDIR) && ln -sf $(REALNAME) $(SONAME)
endif
cd $(LIBDIR) && ln -sf $(SONAME) $(LINKERNAME)
else ifeq ($(UNAME_S), OpenBSD)
ldconfig -R
endif
uninstall: uninstall-data uninstall-plugins
rm -rf $(INCLUDEDIR)/$(PROJ).hpp $(INCLUDEDIR)/$(PROJ) $(MANS) $(LIBDIR)/$(STATICLIB) $(LIBDIR)/$(REALNAME) $(LIBDIR)/$(SONAME) $(LIBDIR)/$(LINKERNAME)
ifeq ($(UNAME_S), Linux)
ldconfig
else ifeq ($(UNAME_S), OpenBSD)
ldconfig -R
endif
endif # --------------------------------------------------------------- lib
# ================================================================= targets
# project-specific targets go in here
-include postmake.make -include postmake.make

59
man/man1/termage.1 Normal file
View File

@ -0,0 +1,59 @@
.Dd $Mdocdate$
.Dt termage 1
.Os
.Sh NAME
.Nm termage
.Nd one line about what it does
.\" .Sh LIBRARY
.\" For sections 2, 3, and 9 only.
.\" Not used in OpenBSD.
.Sh SYNOPSIS
.Nm
.Fl h
.Nm
.Fl \-version
.Nm
.Op Ar
.Sh DESCRIPTION
The
.Nm
utility processes files ...
When no file arguments are given,
.Nm
will read from the standard input.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl h, \-help
Print help text and exit.
.It Fl \-version
Print version info and exit.
.El
.\" .Sh CONTEXT
.\" For section 9 functions only.
.\" .Sh IMPLEMENTATION NOTES
.\" Not used in OpenBSD.
.\" .Sh RETURN VALUES
.\" For sections 2, 3, and 9 function return values only.
.\" .Sh ENVIRONMENT
.\" For sections 1, 6, 7, and 8 only.
.\" .Sh FILES
.Sh EXIT STATUS
.\" For sections 1, 6, and 8 only.
.Nm
exits 0 on success, and 1 if an error occurs.
.\" .Sh EXAMPLES
.\" .Sh DIAGNOSTICS
.\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only.
.\" .Sh ERRORS
.\" For sections 2, 3, 4, and 9 errno settings only.
.\" .Sh SEE ALSO
.\" .Xr foobar 1
.\" .Sh STANDARDS
.\" .Sh HISTORY
.Sh AUTHORS
Bob Polis
.\" .Sh CAVEATS
.\" .Sh BUGS
.\" .Sh SECURITY CONSIDERATIONS
.\" Not used in OpenBSD.

View File

@ -1,2 +1,31 @@
# Define linker flags here, like: -lsqlite3 -lpthread
LDLIBS := -lscterm -lnetpbm -lscerror -lscstring LDLIBS := -lscterm -lnetpbm -lscerror -lscstring
MANSECTION := 1
# Dir name becomes product name.
PROJ := $(shell basename $$(pwd))
# Find out what platform we're on, e.g. Darwin, Linux, OpenBSD.
UNAME_S := $(shell uname -s)
# We will build a tool, not a library.
PRODUCT := tool
# Single source of truth for version.
MAJOR := 1
MINOR := 0
PATCH := 1
# Specify desired C++ standard for this project.
CXXFLAGS += -std=c++17
# Set to 1 if you want a precompiled header for the C++ Standard Library.
PRECOMPILE := 0
# List of extra files to be installed in DATADIR (/usr/local/share/$(PROJ) by default)
DATAFILES :=
# Define plugin sub-projects here. Assumption here is a directory "plugins"
# containing plugin sub-projects, each in its own directory.
# Rename and/or repeat accordingly.
PLUGINS := $(wildcard plugins/*)
MAKE += --no-print-directory

View File

@ -5,24 +5,16 @@
#include <getopt.h> #include <getopt.h>
#include <netpbm/pam.h> #include <netpbm/pam.h>
#include <libscstring.hpp> #include <libscstring.hpp>
#include "commit.inc" #include "version.hpp"
#include "pixels.hpp" #include "pixels.hpp"
#include "conversion.hpp" #include "conversion.hpp"
void print_help() { static void print_help() {
std::cout << "usage: termage [-h|--version] <imagefile>\n"; std::cout << "usage: termage [-h|--version] <imagefile>\n";
std::cout << " -h, --help show this help text and exit\n"; std::cout << " -h, --help show this help text and exit\n";
std::cout << " --version show version number and exit\n"; std::cout << " --version show version number and exit\n";
} }
void print_version() {
std::cout << "termage version 1.0";
if (commit[0] != '\0') {
std::cout << ", build " << commit;
}
std::cout << std::endl;
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
try { try {
pm_init("termage", 0); pm_init("termage", 0);
@ -39,7 +31,7 @@ int main(int argc, char* argv[]) {
// handle long-only options here // handle long-only options here
switch (opt_val) { switch (opt_val) {
case 1: case 1:
print_version(); std::cout << termage_version() << '\n';
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
break; break;

127
src/precomp.hpp Normal file
View File

@ -0,0 +1,127 @@
// C++98 (first official C++ standard)
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cerrno>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cwchar>
#include <cwctype>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if (__cplusplus >= 201103L) // C++11
#include <array>
#include <atomic>
#include <cfenv>
#include <chrono>
#include <cinttypes>
#include <codecvt> // deprecated in C++17, removed in C++26
#include <condition_variable>
#include <cstdint>
#include <cuchar>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <unordered_set>
#endif // C++11
#if (__cplusplus >= 201402L) // C++14
#include <shared_mutex>
#endif // C++14
#if (__cplusplus >= 201703L) // C++17
#include <any>
#include <charconv>
#include <execution>
#include <filesystem>
#include <memory_resource>
#include <optional>
#include <string_view>
#include <variant>
#endif // C++17
#if (__cplusplus >= 202002L) // C++20
#include <barrier>
#include <bit>
#include <compare>
#include <concepts>
#include <coroutine>
#include <format>
#include <latch>
#include <numbers>
#include <ranges>
#include <semaphore>
#include <source_location>
#include <span>
//#include <stop_token> not yet supported by clang 16
//#include <syncstream> not yet supported by clang 17
#include <version>
#endif // C++20
#if (__cplusplus >= 202302L) // C++23
#include <expected>
#include <flat_map>
#include <flat_set>
#include <generator>
#include <mdspan>
#include <print>
#include <spanstream>
#include <stacktrace>
#include <stdfloat>
#endif // C++23
#if (__cplusplus > 202302L) // C++26
#include <debugging>
#include <hazard_pointer>
#include <inplace_vector>
#include <linalg>
#include <rcu>
#include <text_encoding>
#endif // C++26

19
src/version.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "version.hpp"
#include <sstream>
std::string termage_version() {
#include "version.inc"
#include "commit.inc"
std::ostringstream oss;
oss << "termage version " << version;
#ifdef DEBUG
oss << " DEBUG";
#endif
oss << '\n';
if (commit[0] != '\0') {
oss << "build " << commit << ", ";
}
oss << __DATE__ << ", " << __TIME__ << '\n';
oss << "(c) Bob Polis, all rights reserved";
return oss.str();
}

8
src/version.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef _TERMAGE_VERSION_H_
#define _TERMAGE_VERSION_H_
#include <string>
std::string termage_version();
#endif // _TERMAGE_VERSION_H_

View File

@ -1,51 +0,0 @@
include ../premake.make
LDLIBS += -lboost_unit_test_framework
BIN := $(shell basename $$(pwd))
SRCS := $(notdir $(wildcard src/*.cpp))
SRCS += $(notdir $(filter-out ../src/main.cpp,$(wildcard ../src/*.cpp)))
OBJS := $(SRCS:.cpp=.o)
DEPS := $(SRCS:.cpp=.d)
BUILDDIR := build/intermediates/
CXX ?= g++
RM := /bin/rm -rf
CXXFLAGS += -Wshadow -Wall -Wpedantic -Wextra -Wno-unused-parameter
CXXFLAGS += -g3 -std=c++20 -I../src
ifeq ($(DEBUG),1)
CXXFLAGS += -D DEBUG -O0
CONFIG := debug
else
CXXFLAGS += -D NDEBUG -O3
CONFIG := release
endif
OUTDIR := build/$(CONFIG)/
vpath %.cpp src ../src
vpath %.d $(BUILDDIR)
vpath %.o $(BUILDDIR)
.PHONY: all clean prebuild
all: prebuild $(OUTDIR)$(BIN)
prebuild:
@mkdir -p $(BUILDDIR) $(OUTDIR)
$(OUTDIR)$(BIN): $(OBJS)
$(CXX) $(addprefix $(BUILDDIR),$(OBJS)) $(LDFLAGS) $(LDLIBS) -o $(OUTDIR)$(BIN)
@ln -sf $(OUTDIR)$(BIN) $(BIN)
%.o %.d: %.cpp
$(CXX) $(CXXFLAGS) -MMD -MP -MT $@ -MF $*.d -c $<
@mv $@ $*.d $(BUILDDIR)
-include $(addprefix $(BUILDDIR), $(DEPS))
clean:
$(RM) build $(BIN)
-include postmake.make

1
tests/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

6
tests/postmake.make Normal file
View File

@ -0,0 +1,6 @@
$(BUILDDIR)/%.o: ../src/%.cpp
ifeq ($(PRECOMPILE), 1)
$(CXX) $(CXXFLAGS) -o $@ -include precomp.hpp -MMD -MP -MT $@ -MF $(BUILDDIR)/$*.dep -c $<
else
$(CXX) $(CXXFLAGS) -o $@ -MMD -MP -MT $@ -MF $(BUILDDIR)/$*.dep -c $<
endif

5
tests/premake.make Normal file
View File

@ -0,0 +1,5 @@
include ../premake.make
LDLIBS += -lboost_unit_test_framework
CXXFLAGS += -I../src
SRCS := $(notdir $(filter-out ../src/main.cpp,$(wildcard ../src/*.cpp)))
PRODUCT := tool

1
tests/src/precomp.hpp Symbolic link
View File

@ -0,0 +1 @@
../../src/precomp.hpp