Files
RASCSI/cpp/Makefile
T
Eric Helgeson 7bef2d72ae rewrite Web UI in Go
Introduce a server-rendered Go control panel for managing PiSCSI devices, disk images, saved configurations, archives, uploads, system settings, embedded themes and translations, PWA assets, a mock daemon, installation and systemd support, generated protobuf bindings, tests, and CI builds for supported Raspberry Pi targets.

This is built for feature parity with the Python Web UI, with a few notable differences: piscsi-web runs as a non-privileged user, there is no user authentication, the upload form uses a plain stream with no Javascript, the ability to set 'pretty hostname' is removed, and reserved ID memos are removed too.

Update piscsi core to use /var/lib/piscsi/images as its default and resolve relative image folders from the server working directory. Allow valid folders outside the user's home directory, and align the tests, protocol comments, service example, and man pages with the new behavior.

Ship a script and makefile target for migrating user data from old to new file system locations.
2026-08-01 12:30:27 +02:00

307 lines
11 KiB
Makefile

.DEFAULT_GOAL: all
## Optional build flags:
## CROSS_COMPILE : Specify which compiler toolchain to use.
## To cross compile set this accordingly, e.g. to:
## arm-linux-gnueabihf-
CROSS_COMPILE ?=
CXX = $(CROSS_COMPILE)g++
## DEFAULT_IMAGE_FOLDER : Default directory for PiSCSI disk images.
## Override at build time, e.g.
## make DEFAULT_IMAGE_FOLDER=/srv/piscsi/images
DEFAULT_IMAGE_FOLDER ?= /var/lib/piscsi/images
## DEBUG=1 : A Debug build includes the debugger symbols
## and disables compiler optimization. Typically,
## this is only used by developers.
DEBUG ?= 0
ifeq ($(DEBUG), 1)
# Debug compiler flags
CXXFLAGS += -O0 -g -Wall -Wextra -DDEBUG
else
# Release compiler flags
CXXFLAGS += -O3 -Wall -Werror -Wextra -DNDEBUG
endif
ifeq ("$(shell uname -s)","Linux")
# -Wno-psabi might not work on non-Linux platforms
CXXFLAGS += -Wno-psabi
endif
CXXFLAGS += -std=c++20 -iquote . -D_FILE_OFFSET_BITS=64 -DFMT_HEADER_ONLY -DSPDLOG_FMT_EXTERNAL -DPISCSI_DEFAULT_IMAGE_FOLDER=\"$(DEFAULT_IMAGE_FOLDER)\" -MD -MP
## EXTRA_FLAGS : Can be used to pass special purpose flags
CXXFLAGS += $(EXTRA_FLAGS)
## CONNECT_TYPE=FULLSPEC : Specify the type of PiSCSI board type
## that you are using. The typical options are
## STANDARD or FULLSPEC. The default is FULLSPEC
## * THIS IS TYPICALLY THE ONLY COMPILE OPTION YOU
## * NEED TO SPECIFY
# If its not specified, build for FULLSPEC configuration
CONNECT_TYPE ?= FULLSPEC
ifdef CONNECT_TYPE
CXXFLAGS += -DCONNECT_TYPE_$(CONNECT_TYPE)
endif
PISCSI = piscsi
SCSICTL = scsictl
SCSIDUMP = scsidump
SCSIMON = scsimon
PISCSI_TEST = piscsi_test
SCSILOOP = scsiloop
SYSTEMD_CONF = /etc/systemd/system/piscsi.service
RSYSLOG_CONF = /etc/rsyslog.d/piscsi.conf
RSYSLOG_LOG = /var/log/piscsi.log
USR_LOCAL_BIN = /usr/local/bin
MAN_PAGE_DIR = /usr/local/man/man1
DOC_DIR = ../doc
COVERAGE_DIR = coverage
COVERAGE_FILE = piscsi.dat
OS_FILES = ../os_integration
OBJDIR := obj
BINDIR := bin
BIN_ALL = \
$(BINDIR)/$(PISCSI) \
$(BINDIR)/$(SCSICTL) \
$(BINDIR)/$(SCSIMON) \
$(BINDIR)/$(SCSILOOP)
# scsidump requires initiator support
ifeq ($(CONNECT_TYPE), FULLSPEC)
BIN_ALL += $(BINDIR)/$(SCSIDUMP)
endif
SRC_PROTOC = ../proto/piscsi_interface.proto
SRC_GENERATED = $(GENERATED_DIR)/piscsi_interface.pb.cpp
SRC_PROTOBUF = \
shared/protobuf_util.cpp
SRC_SHARED = \
shared/piscsi_version.cpp \
shared/piscsi_util.cpp \
shared/network_util.cpp
SRC_PISCSI_CORE = $(shell find ./piscsi -name '*.cpp' | grep -v piscsi.cpp)
SRC_PISCSI_CORE += $(shell find ./controllers -name '*.cpp')
SRC_PISCSI_CORE += $(shell find ./devices -name '*.cpp')
SRC_PISCSI_CORE += $(shell find ./hal -name '*.cpp')
SRC_PISCSI = piscsi/piscsi.cpp
SRC_SCSIMON = scsimon/scsimon.cpp
SRC_SCSIMON += $(shell find ./scsimon -name '*.cpp' | grep -v scsimon.cpp)
SRC_SCSIMON += $(shell find ./hal -name '*.cpp')
SRC_SCSICTL_CORE = $(shell find ./scsictl -name '*.cpp' | grep -v scsictl.cpp)
SRC_SCSICTL = scsictl/scsictl.cpp
SRC_SCSIDUMP = scsidump/scsidump.cpp
SRC_SCSIDUMP += $(shell find ./scsidump -name '*.cpp' | grep -v scsidump.cpp)
SRC_SCSIDUMP += $(shell find ./hal -name '*.cpp')
SRC_PISCSI_TEST = $(shell find ./test -name '*.cpp')
SRC_PISCSI_TEST += $(shell find ./scsidump -name '*.cpp' | grep -v scsidump.cpp)
SRC_SCSILOOP = scsiloop/scsiloop.cpp
SRC_SCSILOOP += $(shell find ./scsiloop -name '*.cpp' | grep -v scsiloop.cpp)
SRC_SCSILOOP += $(shell find ./hal -name '*.cpp')
vpath %.h ./shared ./controllers ./devices ./scsimon ./hal \
./hal/pi_defs ./piscsi ./scsictl ./scsidump ./scsiloop
vpath %.cpp ./shared ./controllers ./devices ./scsimon ./hal \
./hal/pi_defs ./piscsi ./scsictl ./scsidump ./scsiloop ./test
vpath %.o ./$(OBJDIR)
vpath ./$(BINDIR)
OBJ_PISCSI_CORE := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PISCSI_CORE:%.cpp=%.o)))
OBJ_PISCSI := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PISCSI:%.cpp=%.o)))
OBJ_SCSICTL_CORE := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSICTL_CORE:%.cpp=%.o)))
OBJ_SCSICTL := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSICTL:%.cpp=%.o)))
OBJ_SCSIDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIDUMP:%.cpp=%.o)))
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
OBJ_PISCSI_TEST := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PISCSI_TEST:%.cpp=%.o)))
OBJ_SCSILOOP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSILOOP:%.cpp=%.o)))
OBJ_SHARED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SHARED:%.cpp=%.o)))
OBJ_PROTOBUF := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PROTOBUF:%.cpp=%.o)))
OBJ_GENERATED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_GENERATED:%.cpp=%.o)))
BINARIES = $(USR_LOCAL_BIN)/$(SCSICTL) \
$(USR_LOCAL_BIN)/$(PISCSI) \
$(USR_LOCAL_BIN)/$(SCSIMON) \
$(USR_LOCAL_BIN)/$(SCSILOOP)
ifeq ($(CONNECT_TYPE), FULLSPEC)
BINARIES += $(USR_LOCAL_BIN)/$(SCSIDUMP)
endif
MAN_PAGES = $(MAN_PAGE_DIR)/piscsi.1 \
$(MAN_PAGE_DIR)/scsictl.1 \
$(MAN_PAGE_DIR)/scsimon.1 \
$(MAN_PAGE_DIR)/scsiloop.1
ifeq ($(CONNECT_TYPE), FULLSPEC)
MAN_PAGES += $(MAN_PAGE_DIR)/scsidump.1
endif
GENERATED_DIR := generated
# For the unit tests, the following functions will be "wrapped" by the linker, meaning the
# __wrap_xxxx() function will be called instead of the real function. These linker flags
# should only be used for testing purposes!
TEST_WRAPS = -Wl,--wrap=fopen64
# The following will include all of the auto-generated dependency files (*.d)
# if they exist. This will trigger a rebuild of a source file if a header changes
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_PISCSI_CORE) $(OBJ_SCSICTL_CORE) $(OBJ_PISCSI) $(OBJ_SCSICTL) $(OBJ_SCSIDUMP) $(OBJ_SCSIMON) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_PISCSI_TEST) $(OBJ_SCSILOOP))
-include $(ALL_DEPS)
$(OBJDIR) $(BINDIR):
@echo "-- Creating directory $@"
mkdir -p $@
$(OBJDIR)/%.o: %.cpp | $(OBJDIR)
$(CXX) $(CXXFLAGS) -c $< -o $@
$(SRC_GENERATED) : $(SRC_PROTOC)
@echo "-- Generating protobuf-based source files"
mkdir -p $(GENERATED_DIR)
protoc --cpp_out=$(GENERATED_DIR) --proto_path=../proto $(SRC_PROTOC)
mv $(GENERATED_DIR)/piscsi_interface.pb.cc $@
$(OBJ_GENERATED) : $(SRC_GENERATED) | $(OBJDIR)
$(CXX) $(CXXFLAGS) -c $< -o $@
## Build Targets:
## all : Rebuild all of the executable files and re-generate
## the text versions of the manpages
## docs : Re-generate the text versions of the man pages
## test : Build and run unit tests
## coverage : Build and run unit tests and create coverage SonarQube files.
## lcov : Build and run unit tests and create coverage HTML files.
## Note that you have to run 'make clean' before switching
## between coverage and non-coverage builds.
.DEFAULT_GOAL := all
.PHONY: all docs test coverage lcov
all: $(SRC_GENERATED) $(BIN_ALL) docs
test: $(SRC_GENERATED) $(BINDIR)/$(PISCSI_TEST)
$(BINDIR)/$(PISCSI_TEST)
coverage: CXXFLAGS += --coverage
coverage: test
lcov: CXXFLAGS += --coverage
lcov: test
lcov -q -c -d . --include '*/cpp/*' -o $(COVERAGE_FILE) --exclude '*/test/*' --exclude '*/interfaces/*' --exclude '*/piscsi_interface.pb*'
genhtml -q -o $(COVERAGE_DIR) --legend $(COVERAGE_FILE)
docs: $(DOC_DIR)/piscsi_man_page.txt $(DOC_DIR)/scsictl_man_page.txt $(DOC_DIR)/scsimon_man_page.txt $(DOC_DIR)/scsidump_man_page.txt $(DOC_DIR)/scsiloop_man_page.txt
$(OBJ_PISCSI_CORE) $(OBJ_PISCSI) $(OBJ_SCSICTL_CORE) $(OBJ_SCSICTL) $(OBJ_PROTOBUF) $(OBJ_PISCSI_TEST) : $(SRC_GENERATED)
$(BINDIR)/$(PISCSI): $(OBJ_GENERATED) $(OBJ_PISCSI_CORE) $(OBJ_PISCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_GENERATED) | $(BINDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJ_PISCSI_CORE) $(OBJ_PISCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_GENERATED) -lpthread -lpcap -lprotobuf
$(BINDIR)/$(SCSICTL): $(OBJ_GENERATED) $(OBJ_SCSICTL_CORE) $(OBJ_SCSICTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_GENERATED) | $(BINDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJ_SCSICTL_CORE) $(OBJ_SCSICTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_GENERATED) -lpthread -lprotobuf
$(BINDIR)/$(SCSIDUMP): $(OBJ_SCSIDUMP) $(OBJ_SHARED) | $(BINDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJ_SCSIDUMP) $(OBJ_SHARED)
$(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) $(OBJ_SHARED) | $(BINDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJ_SCSIMON) $(OBJ_SHARED)
$(BINDIR)/$(SCSILOOP): $(OBJ_SHARED) $(OBJ_SCSILOOP) | $(BINDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJ_SHARED) $(OBJ_SCSILOOP)
$(BINDIR)/$(PISCSI_TEST): $(OBJ_GENERATED) $(OBJ_PISCSI_CORE) $(OBJ_SCSICTL_CORE) $(OBJ_PISCSI_TEST) $(OBJ_SCSICTL_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_GENERATED) | $(BINDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TEST_WRAPS) -o $@ $(OBJ_PISCSI_CORE) $(OBJ_SCSICTL_CORE) $(OBJ_PISCSI_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_GENERATED) -lpthread -lpcap -lprotobuf -lgmock -lgtest
# Phony rules for building individual utilities
.PHONY: $(PISCSI) $(SCSICTL) $(SCSIDUMP) $(SCSIMON) $(PISCSI_TEST) $(SCSILOOP)
$(PISCSI) : $(BINDIR)/$(PISCSI)
$(SCSICTL) : $(BINDIR)/$(SCSICTL)
$(SCSIDUMP) : $(BINDIR)/$(SCSIDUMP)
$(SCSIMON) : $(BINDIR)/$(SCSIMON)
$(PISCSI_TEST): $(BINDIR)/$(PISCSI_TEST)
$(SCSILOOP) : $(BINDIR)/$(SCSILOOP)
## clean : Remove all of the object files, intermediate
## compiler files and executable files
.PHONY: clean
clean:
rm -rf $(OBJDIR) $(BINDIR) $(GENERATED_DIR) $(COVERAGE_DIR) $(COVERAGE_FILE)
## install : Copies all of the man pages to the correct location
## Copies the binaries to a global install location
## Configures the Systemd and RSyslog services to auto-run PiSCSI
## * This target needs to be run with sudo (ex: sudo make install)
## * Before running this, you need to stop the piscsi service if
## * it is already running:
## * sudo systemctl stop piscsi
## * After running this, you will need to reboot or run:
## * sudo systemctl daemon-reload
## * sudo systemctl restart rsyslog
## * sudo systemctl enable piscsi
## * sudo systemctl start piscsi
.PHONY: install
install: \
$(MAN_PAGES) \
$(BINARIES) \
$(SYSTEMD_CONF) \
$(RSYSLOG_CONF) \
$(RSYSLOG_LOG)
@echo "-- Done installing!"
$(USR_LOCAL_BIN)% : $(BINDIR)/%
@echo "-- Copying $@"
cp $< $@
$(MAN_PAGE_DIR)/%.1 : $(DOC_DIR)/%.1 | $(MAN_PAGE_DIR)/
@echo "-- Copying $@"
cp $< $@
$(DOC_DIR)/%_man_page.txt : $(DOC_DIR)/%.1
@echo "!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!" > $@
@echo "!! ------ The native file is $(notdir $<). Re-run 'make docs' after updating\n\n" >> $@
MANWIDTH=80 man -l $< | col -bx >> $@
$(SYSTEMD_CONF) : $(OS_FILES)/$(notdir $(SYSTEMD_CONF))
@echo "-- Copying $@"
cp $< $@
$(RSYSLOG_CONF) : $(OS_FILES)/$(notdir $(RSYSLOG_CONF))
@echo "-- Copying $@"
cp $< $@
$(RSYSLOG_LOG) :
@echo "-- Creating $@"
touch /var/log/piscsi.log
chown root:adm /var/log/piscsi.log
$(MAN_PAGE_DIR)/:
echo "-- Creating directory $@"
mkdir -p $@
## help : Lists information about how to use the makefile
# The help rule is based upon the approach from:
# https://swcarpentry.github.io/make-novice/08-self-doc/index.html
.PHONY: help
help : Makefile
@sed -n 's/^##//p' $<
## Debug : Same as 'all'. Useful when using a debugger.
.PHONY: Debug
Debug: all