From 5500cb661c0e22c57156e78e06d2a5f98460ccf0 Mon Sep 17 00:00:00 2001 From: kmicki <1463619+kmicki@users.noreply.github.com> Date: Fri, 8 Jul 2022 12:37:06 +0200 Subject: [PATCH] Makefile and build scripts optimization --- .vscode/c_cpp_properties.json | 3 +- .vscode/tasks.json | 9 +- Makefile | 270 +++++++++++++++++++++++++------ build.sh | 15 -- buildinstall.sh | 11 -- buildupdate.sh | 7 - createpkg.sh | 24 --- pkg/install.sh | 2 + prepare.sh => scripts/prepare.sh | 18 +-- 9 files changed, 233 insertions(+), 126 deletions(-) delete mode 100755 build.sh delete mode 100755 buildinstall.sh delete mode 100755 buildupdate.sh delete mode 100755 createpkg.sh rename prepare.sh => scripts/prepare.sh (75%) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 81185b8..49a5d86 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,8 @@ "-std=c++2a", "-pthread", "-lncurses" - ] + ], + "configurationProvider": "ms-vscode.makefile-tools" } ], "version": 4 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4b21f3f..e3010f4 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,17 +1,11 @@ { "version": "2.0.0", "tasks": [ - { - "type": "shell", - "label": "Prepare build", - "command": "${workspaceFolder}/prepare.sh" - }, { "type": "cppbuild", "label": "Build", - "dependsOn": "Prepare build", "command": "/usr/sbin/make", - "args": [], + "args": [ "release" ], "options": { "cwd": "${workspaceFolder}" }, @@ -27,7 +21,6 @@ { "type": "cppbuild", "label": "Build Debug", - "dependsOn": "Prepare build", "command": "/usr/sbin/make", "args": [ "debug" ], "options": { diff --git a/Makefile b/Makefile index 4216eb8..b8157a8 100644 --- a/Makefile +++ b/Makefile @@ -1,81 +1,259 @@ -BINDIR = bin -DEBUGDIR = $(BINDIR)/debug -RELEASEDIR = $(BINDIR)/release -EXENAME = sdgyrodsu +## Build a project and combine built executable into binary package together with additional files +## Restrictions: +## - one generated binary file (executable) +## - single extension of compiled source files +## - compilation with gcc or compatible -OBJDIR = obj -OBJDEBUGDIR = $(OBJDIR)/debug -OBJRELEASEDIR = $(OBJDIR)/release +# Configuration -RELEASEPATH = $(RELEASEDIR)/$(EXENAME) -DEBUGPATH = $(DEBUGDIR)/$(EXENAME) +# Main directories +# dir with source files SRCDIR = src +# dir with header files +HEADERDIR = inc +# main dir for object files +OBJDIR = obj +# main dir for binaries +BINDIR = bin +# dir with files to be included in the binary package +PKGDIR = pkg +# dir for binary package +PKGBINDIR = pkgbin + +# Names +# main name for release build artifacts +RELEASE = release +# main name for debug build artifacts +DEBUG = debug +# main name for the application/executable +EXENAME = sdgyrodsu +# main name for the binary package +PKGNAME = SteamDeckGyroDSUSetup + +# Extensions +# extension of source files SRCEXT = cpp +# extension of object files OBJEXT = o -HEADERDIR = inc +# Compiler +# Compiler executable +CC = g++ +# C++ standard parameter CPPSTD = c++2a +# Additional parameters for all builds +ADDPARS = +# Additional parameters for release build +ADDRELEASEPARS = -O3 +# Additional parameters for debug build +ADDDEBUGPARS = +# Additional libraries parameters ADDLIBS = -pthread -lncurses -COMMONPARS = -std=$(CPPSTD) $(ADDLIBS) -I $(HEADERDIR) -RELEASEPARS = $(COMMONPARS) -O3 -DEBUGPARS = $(COMMONPARS) +# Install -CC = g++ +# Install script name (has to be in $PKGDIR) +INSTALLSCRIPT = install.sh + +# Prepare + +# Prepare script file path, used to install dependencies with missing files in the system +PREPARESCRIPT = scripts/prepare.sh + +# Dependency check (Steam Deck) +# Some libraries have to be reinstalled on Steam Deck because haeder files are missing + +# Check files - these files existence will be checked to determine if +# the corresponding dependency is properly installed +DEPENDCHECKFILES := $(firstword $(wildcard /usr/include/c++/*/vector)) /usr/include/errno.h /usr/include/linux/can/error.h /usr/include/ncurses.h -sources := $(wildcard $(SRCDIR)/*.cpp) $(wildcard $(SRCDIR)/*/*.cpp) $(wildcard $(SRCDIR)/*/*/*.cpp) $(wildcard $(SRCDIR)/*/*/*/*.cpp) -debugobjects := $(subst $(SRCDIR)__, $(OBJDEBUGDIR)/,$(subst /,__,$(sources:.$(SRCEXT)=.$(OBJEXT)))) -releaseobjects := $(subst $(SRCDIR)__, $(OBJRELEASEDIR)/,$(subst /,__,$(sources:.$(SRCEXT)=.$(OBJEXT)))) +# Dependencies - names of packages to install with pacman -S +# if the corresponding check file is not found +DEPENDENCIES := gcc glibc linux-api-headers ncurses + +# Functions + +rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) + +# Generated variables + +# Subdirectories + +# dir for debug build's objects +OBJDEBUGDIR = $(OBJDIR)/$(DEBUG) +# dir for release build's objects +OBJRELEASEDIR = $(OBJDIR)/$(RELEASE) +# dir for debug build's binaries +DEBUGDIR = $(BINDIR)/$(DEBUG) +# dir for release build's binaries +RELEASEDIR = $(BINDIR)/$(RELEASE) +# dir for binary package contents +PKGPREPDIR = $(PKGBINDIR)/$(PKGNAME) + +# File paths + +# path for debug build's executable +DEBUGPATH = $(DEBUGDIR)/$(EXENAME) +# path for release build's executable +RELEASEPATH = $(RELEASEDIR)/$(EXENAME) +# inary package file name +PKGBIN = $(PKGNAME).zip +# path for binary package +PKGBINPATH = $(PKGBINDIR)/$(PKGBIN) + +# Compilator parameters + +# common parameters for a compilator +COMMONPARS = -std=$(CPPSTD) $(GENLIBS) -I $(HEADERDIR) $(ADDPARS) +# parameters for release build +RELEASEPARS = $(COMMONPARS) $(ADDRELEASEPARS) +# parameters for debug build +DEBUGPARS = $(COMMONPARS) $(ADDDEBUGPARS) + +# Source files +SOURCES := $(call rwildcard,$(SRCDIR),*.$(SRCEXT)) + +# List of objects created in debug build +DEBUGOBJECTS := $(subst $(SRCDIR)__, $(OBJDEBUGDIR)/,$(subst /,__,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))) + +# List of objects created in release build +RELEASEOBJECTS := $(subst $(SRCDIR)__, $(OBJRELEASEDIR)/,$(subst /,__,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))) + +# List of additional files for a binary package +PACKAGEFILES := $(wildcard $(PKGDIR)/*) + +# Binary package files in a destination directory +PKGBINFILES := $(PKGPREPDIR)/$(EXENAME) $(subst $(PKGDIR)/,$(PKGPREPDIR)/,$(PACKAGEFILES)) .SILENT: -.PHONY: release -release: $(RELEASEPATH) +# Phony Targets +.PHONY: release # Release build - generate executable $BINDIR/$RELEASE/$EXENAME +.PHONY: debug # Debug build - generate executable $BINDIR/$DEBUG/$EXENAME +.PHONY: prepare # Prepare dependencies for build (for Steam Deck, see DEPENDENCIES above) +.PHONY: preparepkg # Prepare binary package files (copy release executable and files from $PKGDIR into $PKGBINDIR/$PKGNAME) +.PHONY: createpkg # Create zipped binary package (zip prepared binary package files into $PKGBINDIR/$PKGNAME.zip) +.PHONY: clean # Clean binaries and objects (both release and debug build, inside $BINDIR and $OBJDIR) +.PHONY: dbgclean # Clean binaries and objects from debug build (inside $BINDIR/$DEBUG and $OBJDIR/$DEBUG) +.PHONY: relclean # Clean binaries and objects from release build (inside $BINDIR/$RELEASE and $OBJDIR/$RELEASE) +.PHONY: pkgclean # Clean binary package artifacts (prepared files and zipped package) +.PHONY: pkgbinclean # Clean zipped binary package +.PHONY: pkgprepclean # Clean files prepared for binary package +.PHONY: cleanall # Clean all artifacts (deletes $BINDIR, $OBJDIR, $PKGBINDIR) +.PHONY: install # Run install script in prepared binary package files -.PHONY: debug -debug: $(DEBUGPATH) +# Prepare -$(RELEASEPATH): $(OBJRELEASEDIR) $(RELEASEDIR) $(releaseobjects) - echo "Linking into $@" - $(CC) $(filter %.$(OBJEXT),$^) $(RELEASEPARS) -o $@ +prepare: $(DEPENDCHECKFILES) -$(DEBUGPATH): $(OBJDEBUGDIR) $(DEBUGDIR) $(debugobjects) - echo "Linking into $@" - $(CC) $(filter %.$(OBJEXT),$^) $(DEBUGPARS) -o $@ +$(DEPENDCHECKFILES) &: + @echo "Prepare dependencies" + deps=( $(DEPENDENCIES) ) && files=( $(DEPENDCHECKFILES) ) && ./$(PREPARESCRIPT) "$${#deps[@]}" "$${deps[@]}" "$${#files[@]}" "$${files[@]}" -.SECONDEXPANSION: +# Build +# See also second expansion at the end -$(debugobjects): $(OBJDEBUGDIR)/%.$(OBJEXT): $$(subst __,/,$(SRCDIR)/%.$(SRCEXT)) \ -$$(shell g++ -M -I $(HEADERDIR)/ $$(subst __,/,$$(subst .$(OBJEXT),.$(SRCEXT),$$(subst $(OBJDEBUGDIR)/,$(SRCDIR)/,$$@))) | sed 's/.*\.o://' | sed 's/ \\//g' | tr '\n' ' ') - echo "Building $< into $@" - $(CC) $< -c $(DEBUGPARS) -o $@ +release: $(RELEASEPATH) -$(releaseobjects): $(OBJRELEASEDIR)/%.$(OBJEXT): $$(subst __,/,$(SRCDIR)/%.$(SRCEXT)) \ -$$(shell g++ -M -I $(HEADERDIR)/ $$(subst __,/,$$(subst .$(OBJEXT),.$(SRCEXT),$$(subst $(OBJRELEASEDIR)/,$(SRCDIR)/,$$@))) | sed 's/.*\.o://' | sed 's/ \\//g' | tr '\n' ' ') - echo "Building $< into $@" - $(CC) $< -c $(RELEASEPARS) -o $@ +$(RELEASEPATH): $(DEPENDCHECKFILES) $(RELEASEOBJECTS) | $(RELEASEDIR) + @echo "Linking into $@" + $(CC) $(filter %.o,$^) $(RELEASEPARS) $(ADDLIBS) -o $@ -$(OBJRELEASEDIR) $(OBJDEBUGDIR): | $(OBJDIR) - mkdir $@ +debug: $(DEBUGPATH) -$(OBJDIR): - mkdir $@ +$(DEBUGPATH): $(DEPENDCHECKFILES) $(DEBUGOBJECTS) | $(DEBUGDIR) + @echo "Linking into $@" + $(CC) $(filter %.o,$^) $(DEBUGPARS) $(ADDLIBS) -o $@ -$(RELEASEDIR) $(DEBUGDIR): | $(BINDIR) - mkdir $@ +# Binary package -$(BINDIR): - mkdir $@ +preparepkg: $(PKGBINFILES) + +$(PKGBINFILES) &: $(RELEASEPATH) $(PACKAGEFILES) | $(PKGBINDIR) $(PKGPREPDIR) + @echo "Preparing binary package files in $(PKGPREPDIR)" + rm -rf $(PKGPREPDIR)/* + cp $(RELEASEPATH) $(PKGPREPDIR)/ + cp $(PKGDIR)/* $(PKGPREPDIR)/ + +createpkg: $(PKGBINPATH) + +$(PKGBINPATH): $(PKGBINFILES) + @echo "Zipping package files into a binary package $@" + rm -f $(PKGBINPATH) + cd $(PKGBINDIR) && zip -r $(PKGBIN) $(PKGNAME) -clean: dbgclean relclean +# Clean + +clean: dbgclean relclean relclean: + @echo "Removing release build and objects" rm -f $(OBJRELEASEDIR)/*.$(OBJEXT) rm -f $(RELEASEPATH) dbgclean: + @echo "Removing debug build and objects" rm -f $(OBJDEBUGDIR)/*.$(OBJEXT) - rm -f $(DEBUGPATH) \ No newline at end of file + rm -f $(DEBUGPATH) + +pkgclean: pkgprepclean pkgbinclean + +pkgprepclean: + @echo "Removing package files" + rm -rf $(PKGPREPDIR) + +pkgbinclean: + @echo "Removing binary package" + rm -f $(PKGBINPATH) + +cleanall: clean pkgclean + @echo "Removing object,binary and binary package directories" + rm -rf $(PKGBINDIR) $(OBJDIR) $(BINDIR) + +# Install + +install: $(PKGBINFILES) + @echo "Installing" + cd $(PKGPREPDIR) && ./$(INSTALLSCRIPT) + +# Directories + +$(OBJRELEASEDIR) $(OBJDEBUGDIR): | $(OBJDIR) + @echo "Creating directory $@" + mkdir $@ + +$(RELEASEDIR) $(DEBUGDIR): | $(BINDIR) + @echo "Creating directory $@" + mkdir $@ + +$(PKGPREPDIR): | $(PKGBINDIR) + @echo "Creating directory $@" + mkdir $@ + +$(OBJDIR) $(BINDIR) $(PKGDIR) $(PKGBINDIR): + @echo "Creating directory $@" + mkdir $@ + +# Build - second expansion + +.SECONDEXPANSION: + +# Auxiliary function that uses compiler to generate list of headers the source file depends on +getheaders=$(shell $(CC) -M -I $(HEADERDIR)/ $(subst __,/,$(subst .$(OBJEXT),.$(SRCEXT),$(subst $(OBJRELEASEDIR)/,$(SRCDIR)/,$1))) 2>/dev/null | sed 's/.*\.o://' | sed 's/ \\//g' | tr '\n' ' ') + +# Release +# Build object files + +$(RELEASEOBJECTS): $(OBJRELEASEDIR)/%.$(OBJEXT): $$(subst __,/,$(SRCDIR)/%.$(SRCEXT)) $$(call getheaders,$$@) $$(DEPENDCHECKFILES) | $(OBJRELEASEDIR) + @echo "Building $< into $@" + $(CC) $< -c $(RELEASEPARS) -o $@ + +# Debug +# Build object files + +$(DEBUGOBJECTS): $(OBJDEBUGDIR)/%.$(OBJEXT): $$(subst __,/,$(SRCDIR)/%.$(SRCEXT)) $$(call getheaders,$$@) $$(DEPENDCHECKFILES) | $(OBJDEBUGDIR) + @echo "Building $< into $@" + $(CC) $< -c $(DEBUGPARS) -o $@ \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index 1159f2b..0000000 --- a/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -./prepare.sh - -echo "Building source..." -#g++ -std=c++2a -O3 $(find inc -type d -printf '-I %p\n') $(find src -type f -iregex '.*\.cpp' -printf '%p\n') -pthread -lncurses -o bin/release/sdgyrodsu -make - -result=$? - -if [ "$result" -ne 0 ]; then - echo -e "\e[1mError: source was not built.\e[0m" - exit $result -else - echo -e "\e[1mBuilding complete.\e[0m" -fi - diff --git a/buildinstall.sh b/buildinstall.sh deleted file mode 100755 index bae8193..0000000 --- a/buildinstall.sh +++ /dev/null @@ -1,11 +0,0 @@ -./build.sh - -sudo groupadd usbaccess -sudo gpasswd -a $USER usbaccess -sudo cp pkg/51-deck-controls.rules /etc/udev/rules.d/ - -mkdir -p $HOME/sdgyrodsu -cp bin/sdgyrodsu $HOME/sdgyrodsu/ -cp pkg/sdgyrodsu.service $HOME/.config/systemd/user/ -systemctl --user enable --now sdgyrodsu.service - diff --git a/buildupdate.sh b/buildupdate.sh deleted file mode 100755 index a006334..0000000 --- a/buildupdate.sh +++ /dev/null @@ -1,7 +0,0 @@ -./build.sh - -systemctl --user stop sdgyrodsu.service -rm $HOME/sdgyrodsu/sdgyrodsu -cp bin/sdgyrodsu $HOME/sdgyrodsu/ -systemctl --user enable --now sdgyrodsu.service - diff --git a/createpkg.sh b/createpkg.sh deleted file mode 100755 index f06fb47..0000000 --- a/createpkg.sh +++ /dev/null @@ -1,24 +0,0 @@ -./build.sh - -result=$? - -if [ "$result" -ne 0 ]; then - exit $result -fi - -mkdir -p bin/pkg -rm -rf bin/pkg/* - -cp bin/release/* bin/pkg/ -cp pkg/* bin/pkg/ - -mkdir -p pkgbin/ -rm -rf pkgbin/* -mkdir -p pkgbin/SteamDeckGyroDSUSetup -cp bin/pkg/* pkgbin/SteamDeckGyroDSUSetup/ -rm -rf bin/pkg - -cd pkgbin -zip -r SteamDeckGyroDSUSetup.zip SteamDeckGyroDSUSetup -rm -rf SteamDeckGyroDSUSetup - diff --git a/pkg/install.sh b/pkg/install.sh index 59319fc..8d5fa31 100755 --- a/pkg/install.sh +++ b/pkg/install.sh @@ -1,3 +1,5 @@ +cd "$(dirname "$(readlink -f "$0")")" + echo "Checking 'usbaccess' user group..." if cat /etc/group | grep -q 'usbaccess'; then echo "'usbaccess' group exits." diff --git a/prepare.sh b/scripts/prepare.sh similarity index 75% rename from prepare.sh rename to scripts/prepare.sh index 4d39ad5..212109c 100755 --- a/prepare.sh +++ b/scripts/prepare.sh @@ -1,16 +1,11 @@ # Required packages -declare -a dependencies=("gcc" "glibc" "linux-api-headers" "ncurses" "usbutils") +dependencies=( "${@:2:$1}" ); shift "$(( $1 + 1 ))" # Some header file for each package. # SteamOS has all required packages installed by default but for some reason header files are missing. # This will be checked before building. -declare -a checks=( - "/usr/include/c++/*/vector" - "/usr/include/errno.h" - "/usr/include/linux/can/error.h" - "/usr/include/ncurses.h" - "/usr/bin/lsusb" -) +checks=( "${@:2:$1}" ); shift "$(( $1 + 1 ))" + declare -a reinstall common_reinstall=false @@ -48,13 +43,8 @@ if [ "$common_reinstall" == true ]; then fi echo "Required dependencies reinstalled." else - echo "All dependencies' header files installed." + echo "All dependencies' header files already installed." fi -echo -e "Create \e[1mbin\e[0m directory..." -mkdir -p bin >/dev/null -mkdir -p bin/release >/dev/null -mkdir -p bin/debug >/dev/null - exit 0