Skip to content

Commit

Permalink
Makefile and build scripts optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
kmicki committed Jul 9, 2022
1 parent 04af8ab commit 5500cb6
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 126 deletions.
3 changes: 2 additions & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"-std=c++2a",
"-pthread",
"-lncurses"
]
],
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
Expand Down
9 changes: 1 addition & 8 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -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}"
},
Expand All @@ -27,7 +21,6 @@
{
"type": "cppbuild",
"label": "Build Debug",
"dependsOn": "Prepare build",
"command": "/usr/sbin/make",
"args": [ "debug" ],
"options": {
Expand Down
270 changes: 224 additions & 46 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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)
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 $@
15 changes: 0 additions & 15 deletions build.sh

This file was deleted.

11 changes: 0 additions & 11 deletions buildinstall.sh

This file was deleted.

7 changes: 0 additions & 7 deletions buildupdate.sh

This file was deleted.

Loading

0 comments on commit 5500cb6

Please sign in to comment.