1+ # prepare env file and tmp dir
2+ $(shell mkdir -p .tmp/out && touch .env && git init -q)
3+
4+ # import custom makefiles
5+ -include Makefile.project
6+
17# import and use env vars if exist
28-include .env.project
3- - include .env
9+ include .env
410export
511
6- # prepare env file and tmp dir
7- $(shell mkdir -p ./.tmp && touch .env)
8-
912# check required project vars
1013ifndef PROJECT_DISPLAY_NAME
11- $(error PROJECT_DISPLAY_NAME is not set)
14+ PROJECT_DISPLAY_NAME := Example App
15+ $(shell echo "\nPROJECT_DISPLAY_NAME=$(PROJECT_DISPLAY_NAME)" >> .env.project)
16+ $(info Created `PROJECT_DISPLAY_NAME` variable in `.env.project` file!)
1217endif
1318
19+ ifndef PROJECT_VERSION
20+ PROJECT_VERSION := 0.0.1
21+ $(shell echo "\nPROJECT_VERSION=$(PROJECT_VERSION)" >> .env.project)
22+ $(info Created `PROJECT_VERSION` variable in `.env.project` file!)
23+ endif
24+
25+ -include .env.project
26+
1427# project default vars
1528ifdef PROJECT_EXTRA_BUILD_ARGS
1629PROJECT_EXTRA_BUILD_ARGS +=
1730endif
1831
19- PROJECT_VERSION ?= 0.0.1
32+ .DEFAULT_GOAL = info
2033PROJECT_SHORT_NAME ?= $(PROJECT_DISPLAY_NAME )
2134PROJECT_SHORT_NAME := $(shell echo $(PROJECT_SHORT_NAME ) | sed 's/ //g' | sed 's/-/ /g' | tr '[:upper:]' '[:lower:]')
22- PROJECT_COMMIT_SHORT ? = $(shell echo " $$(git rev-parse --short HEAD )$$([ -n "$$( git status -s ) " ] && echo -n "-modified" ) ")
35+ PROJECT_COMMIT_SHORT : = $(shell git rev-parse --is-inside-work-tree > /dev/null 2>&1 && git rev-parse --verify HEAD > /dev/null 2>&1 && (commit= $$(git rev-parse --short HEAD ) ; status= $$(git status -s ) ; if [ -n "$$status" ]; then echo $$commit-modified; else echo $$commit; fi) || echo "no-commit ")
2336PROJECT_BUILD_ARGS ?= "$(PROJECT_EXTRA_BUILD_ARGS ) -X main.Version=$(PROJECT_VERSION ) -X main.Commit=$(PROJECT_COMMIT_SHORT ) -X \"main.DisplayName=$(PROJECT_DISPLAY_NAME ) \" -X main.ShortName=$(PROJECT_SHORT_NAME ) "
37+ PROJECT_BUILDALL_OS ?= linux darwin windows
38+ PROJECT_BUILDALL_ARCH ?= arm amd64 386 arm64
2439
2540# general default vars
2641PORT ?= 8080
2742HOST ?= 0.0.0.0
2843GOOS ?= $(shell go env GOOS)
2944GOARCH ?= $(shell go env GOARCH)
30- GOCACHE ?= $(shell if [ -d "~/.cache/go-build" ]; then realpath "~/.cache/go-build"; else mkdir -p .tmp/.cache/go-build && realpath ".tmp/.cache/go-build"; fi)
31-
45+ GOCACHE ?= $(shell if [ -d "$$(go env GOCACHE ) " ]; then realpath "$$(go env GOCACHE ) "; else mkdir -p .tmp/.cache/go-build && realpath ".tmp/.cache/go-build"; fi)
3246
3347# #@ These environment variables control various project configurations, including build, run, and deployment settings.
3448# #@ They are loaded from the `.env.projects` file, which is overwritten the `.env` file variables.
3549# #@
3650# #@ Makefile vars
3751# #@
38- # #@ PROJECT_DISPLAY_NAME: projects full name, required
52+ # #@ PROJECT_DISPLAY_NAME: projects full name,
53+ # #@: default adds 'Example App' to '.env.project'
3954# #@ PROJECT_VERSION: semver like project version,
40- # #@: default is 0.0.1
55+ # #@: default adds ' 0.0.1' to '.env.project'
4156# #@ PROJECT_SHORT_NAME: short spaceless lowercase name,
4257# #@: default is $PROJECT_DISPLAY_NAME
4358# #@ PROJECT_COMMIT_SHORT: commit short hash,
@@ -46,6 +61,10 @@ GOCACHE ?= $(shell if [ -d "~/.cache/go-build" ]; then realpath "~/.cache/go-bui
4661# #@: default is project base vars + $PROJECT_EXTRA_BUILD_ARGS
4762# #@ PROJECT_EXTRA_BUILD_ARGS: additional build args,
4863# #@: default is empty
64+ # #@ PROJECT_BUILDALL_OS: defines 'buildall' os targets
65+ # #@: default is 'linux darwin windows'
66+ # #@ PROJECT_BUILDALL_ARCH: defines 'buildall' arch targets
67+ # #@: default is 'arm amd64 386 arm64'
4968# #@
5069# #@ Docker vars
5170# #@
@@ -70,7 +89,7 @@ GOCACHE ?= $(shell if [ -d "~/.cache/go-build" ]; then realpath "~/.cache/go-bui
7089# #@: default build system arch
7190# #@ GOCACHE: container go cache dir,
7291# #@: default global go cache if is dir
73- # #@: else creates ./. tmp/.cache/go-build
92+ # #@: else creates .tmp/.cache/go-build
7493
7594# #@
7695# #@ Misc commands
@@ -105,10 +124,10 @@ info: ##@ prints a project info message
105124vars : # #@ prints some vars for debugging
106125 @echo " \nProject\n"
107126 @env | grep " ^PROJECT_" || true
108- @echo " \nDocker\n"
109- @env | grep " ^DOCKER_" || true
110127 @echo " \nGo\n"
111128 @env | grep " ^GO" || true
129+ @echo " \nDocker\n"
130+ @env | grep " ^DOCKER_" || true
112131 @echo " \nGeneral\n"
113132 @echo " ARGS: '$( ARGS) '"
114133 @echo " PORT: '$( PORT) '"
@@ -120,7 +139,7 @@ env: ##@ prints env vars for debugging
120139
121140.PHONY : clean
122141clean : # #@ cleans up generated files and docker cache
123- @rm -fr ./. tmp ./out ./ bin
142+ @rm -fr .tmp bin
124143 @if command -v go 2>&1 > /dev/null; then \
125144 echo " cleanup go..." ; \
126145 go clean; \
@@ -152,26 +171,55 @@ build: ##@ uses go to build the app with build args
152171
153172.PHONY : buildall
154173buildall : # #@ cross-compilation for all GOOS/GOARCH combinations
155- @echo " Run test build-system build..."
156- @make -s build || { echo " Test system-build build failed!" ; exit 1; }
157- @echo " Prepare out dir..."
158- @mkdir -p out .tmp/out-bak
159- @mv out/* .tmp/out-bak || true
160- @echo " Start build processes..."
161- @go tool dist list | while IFS=/ read -r GOOS GOARCH; do \
174+ @echo " Prepare..."
175+ @echo " Selected operating systems: $( PROJECT_BUILDALL_OS) "
176+ @echo " Selected architectures: $( PROJECT_BUILDALL_ARCH) "
177+ @set -- $(PROJECT_BUILDALL_OS ) && \
178+ OS_ARRAY=$$@ && \
179+ set -- $(PROJECT_BUILDALL_ARCH ) && \
180+ ARCH_ARRAY=$$@ && \
181+ set -- $$(go tool dist list | tr '\n' ' ' ) && \
182+ TARGET_ARRAY=$$@ && \
183+ FILTERED_TARGETS=" " && \
184+ for target in $$ TARGET_ARRAY; do \
185+ target_os=$$(echo $$target | cut -d '/' -f1 ) ; \
186+ target_arch=$$(echo $$target | cut -d '/' -f2 ) ; \
187+ if [ -z " $$ PROJECT_BUILDALL_OS" ] || echo " $$ OS_ARRAY" | grep -qw " $$ target_os" ; then \
188+ if [ -z " $$ PROJECT_BUILDALL_ARCH" ] || echo " $$ ARCH_ARRAY" | grep -qw " $$ target_arch" ; then \
189+ FILTERED_TARGETS=" $$ FILTERED_TARGETS $$ target" ; \
190+ fi ; \
191+ fi ; \
192+ done && \
193+ FILTERED_TARGETS=$$ {FILTERED_TARGETS#? } && \
194+ if [ -z " $$ FILTERED_TARGETS" ]; then \
195+ echo " Error: No matching targets found for the selected OS and architectures" ; \
196+ echo " - os: $$ PROJECT_BUILDALL_OS" ; \
197+ echo " - arch: $$ PROJECT_BUILDALL_ARCH" ; \
198+ echo " - targets: $$ TARGET_ARRAY" ; \
199+ exit 1; \
200+ fi && \
201+ echo " \nBuild for targets:\n$$ FILTERED_TARGETS" && \
202+ rm -rf .tmp/out-bak && \
203+ mv .tmp/out .tmp/out-bak || true && \
204+ echo " \nRun test build-system build..." && \
205+ make -s build || { echo " Test system-build build failed!" ; exit 1; } && \
206+ echo " Start build processes..." && \
207+ for target in $$ FILTERED_TARGETS; do \
208+ GOOS=$$(echo $$target | cut -d'/' -f1 ) && \
209+ GOARCH=$$(echo $$target | cut -d'/' -f2 ) && \
162210 ( \
163211 go build \
164212 -ldflags=$(PROJECT_BUILD_ARGS ) \
165- -o out/$(PROJECT_SHORT_NAME ) -$$ GOOS-$$ GOARCH && \
166- chmod +x out/$(PROJECT_SHORT_NAME ) -$$ GOOS-$$ GOARCH \
167- ) || { echo " Build failed for ' $$ GOOS'/' $$ GOARCH' !" ; exit 1; } \
213+ -o .tmp/ out/$(PROJECT_SHORT_NAME ) -$$ GOOS-$$ GOARCH && \
214+ chmod +x .tmp/ out/$(PROJECT_SHORT_NAME ) -$$ GOOS-$$ GOARCH \
215+ ) && echo " - $$ GOOS/ $$ GOARCH build! " || { echo " Build failed for $$ GOOS/ $$ GOARCH!" ; exit 1; } & \
168216 done && \
169217 wait
170218 @echo " All build processes finished."
171219
172220.PHONY : gi
173221gi : # #@ installs the build binary globally
174- @sudo cp ./ bin /usr/local/bin/$(PROJECT_SHORT_NAME )
222+ @sudo cp bin /usr/local/bin/$(PROJECT_SHORT_NAME )
175223
176224.PHONY : gu
177225gu : # #@ uninstalls the build binary globally
@@ -193,10 +241,11 @@ test: ##@ runs all GO tests recursively without coverage
193241 go test ./...
194242
195243.PHONY : cover
196- cover : # #@ generates a cover. html test coverage report
244+ cover : # #@ generates a raw and html test coverage report
197245 @echo " Run go tests recursively..."
198246 go test -coverprofile .tmp/cover.out ./...
199247 go tool cover -html=.tmp/cover.out -o .tmp/cover.html
248+ @echo " cover.out and cover.html generated in .tmp!"
200249
201250.PHONY : init
202251init : # #@ infos, deps install, test and build
@@ -205,23 +254,20 @@ init: ##@ infos, deps install, test and build
205254 @make -s test
206255 @make -s build
207256
208- .PHONY : air
209- air : # #@ air watch mode and also installs air
257+ .PHONY : dev
258+ dev : # #@ runs the app in watch mode
259+ @echo " Install air if needed and run it..."
210260 @go install github.com/air-verse/air@v1
211261 @air
212262
213263# #@
214- # #@ Docker envs
264+ # #@ Docker targets
215265# #@
216266
217- .PHONY : dev
218- dev : # #@ starts a air dev docker container
219- @docker rm -f dev-local-$(PROJECT_SHORT_NAME ) > /dev/null 2>&1
220-
221- docker compose run --build --rm -it --name dev-local-$(PROJECT_SHORT_NAME) -P local
222-
223- .PHONY : bash
224- bash : # #@ runs a bash shell in the dev container
225- @docker rm -f dev-local-$(PROJECT_SHORT_NAME ) -bash > /dev/null 2>&1
226-
227- docker compose run --build --rm -it --name dev-local-$(PROJECT_SHORT_NAME ) -bash --entrypoint bash -P local
267+ .PHONY : docker
268+ docker : # #@ runs a shell in the container
269+ @docker rm -f dev-$(PROJECT_SHORT_NAME ) || > /dev/null 2>&1
270+ docker compose run -P --rm -it --build \
271+ --name dev-$(PROJECT_SHORT_NAME ) \
272+ --entrypoint bash \
273+ local
0 commit comments