diff --git a/Makefile b/Makefile index bf3731a7..30ca2c30 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,9 @@ GNUMAKEFLAGS := --no-print-directory SUBMAKEFLAGS := CLOE_ROOT := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) -CLOE_LAUNCH := PYTHONPATH="${CLOE_ROOT}/cli" python3 -m cloe_launch +CLOE_LAUNCH := PYTHONPATH="$(CLOE_ROOT)/cli" python3 -m cloe_launch -include ${CLOE_ROOT}/Makefile.help +include $(CLOE_ROOT)/Makefile.help # Set the clang-format command line to use: CLANG_FORMAT := $(shell command -v clang-format 2>/dev/null) @@ -31,8 +31,8 @@ CONAN_OPTIONS := # Lockfile for cloe-deployment: DEPLOY_LOCKFILE_SOURCE := tests/conanfile_deployment.py -DEPLOY_BUILD_LOCKFILE := ${DEPLOY_DIR}/conan.lock -DEPLOY_LOCKFILE_OPTION := --lockfile="${CLOE_ROOT}/${DEPLOY_BUILD_LOCKFILE}" +DEPLOY_BUILD_LOCKFILE := $(DEPLOY_DIR)/conan.lock +DEPLOY_LOCKFILE_OPTION := --lockfile="$(CLOE_ROOT)/$(DEPLOY_BUILD_LOCKFILE)" .DEFAULT_GOAL := help .PHONY: help @@ -47,12 +47,12 @@ help:: # Setup targets --------------------------------------------------------------- include Makefile.setup -${DEPLOY_BUILD_LOCKFILE}: - mkdir -p "${DEPLOY_DIR}" - conan lock create --lockfile-out "${DEPLOY_BUILD_LOCKFILE}" --build -- "${DEPLOY_LOCKFILE_SOURCE}" +$(DEPLOY_BUILD_LOCKFILE): + mkdir -p "$(DEPLOY_DIR)" + conan lock create --lockfile-out "$(DEPLOY_BUILD_LOCKFILE)" --build -- "$(DEPLOY_LOCKFILE_SOURCE)" .PHONY: lockfile -lockfile: ${DEPLOY_BUILD_LOCKFILE} +lockfile: $(DEPLOY_BUILD_LOCKFILE) # Workspace targets ----------------------------------------------------------- help:: @@ -63,23 +63,23 @@ help:: .PHONY: docs docs: $(call print_header, "Generating Doxygen documentation...") - ${MAKE} -C docs doxygen + $(MAKE) -C docs doxygen $(call print_header, "Generating Sphinx documentation...") - ${MAKE} -C docs html + $(MAKE) -C docs html help:: - $(call print_help_target, export-cli, "export ${_yel}cloe-launch-profile${_rst} Conan recipe") - $(call print_help_target, deploy-cli, "install ${_yel}cloe-launch${_rst} with ${_dim}${PIPX}${_rst}") + $(call print_help_target, export-cli, "export $(_yel)cloe-launch-profile$(_rst) Conan recipe") + $(call print_help_target, deploy-cli, "install $(_yel)cloe-launch$(_rst) with $(_dim)$(PIPX)$(_rst)") echo .PHONY: export-cli export-cli: - ${MAKE} -C cli export + $(MAKE) -C cli export .PHONY: deploy-cli deploy-cli: $(call print_header, "Deploying cloe-launch binary with pip...") - ${MAKE} -C cli install + $(MAKE) -C cli install help:: $(call print_help_target, lockfile, "create a lockfile for cloe deployment packages") @@ -87,36 +87,36 @@ help:: $(call print_help_target, status-all, "show status of each of the Conan packages") $(call print_help_target, export-all, "export all package sources to Conan cache") $(call print_help_target, build-all, "build individual packages locally in-source") - $(call print_help_target, deploy-all, "deploy Cloe to INSTALL_DIR [=${INSTALL_DIR}]") + $(call print_help_target, deploy-all, "deploy $(_yel)cloe$(_rst) to $(_grn)INSTALL_DIR$(_rst)=$(_dim)$(INSTALL_DIR)$(_rst)") $(call print_help_target, clean-all, "clean entire repository of temporary files") $(call print_help_target, purge-all, "remove all cloe packages (in any version) from Conan cache") echo .PHONY: build-all build-all: lockfile - ${MAKE} all-select CONAN_OPTIONS="${CONAN_OPTIONS} ${DEPLOY_LOCKFILE_OPTION}" + $(MAKE) all-select CONAN_OPTIONS="$(CONAN_OPTIONS) $(DEPLOY_LOCKFILE_OPTION)" .PHONY: status-all -status-all: ${DEPLOY_BUILD_LOCKFILE} - @for pkg in ${ALL_PKGS}; do \ - ${MAKE} LOCKFILE_SOURCE="" LOCKFILE_OPTION=${DEPLOY_LOCKFILE_OPTION} -C $${pkg} status || true; \ +status-all: $(DEPLOY_BUILD_LOCKFILE) + @for pkg in $(ALL_PKGS); do \ + $(MAKE) LOCKFILE_SOURCE="" LOCKFILE_OPTION=$(DEPLOY_LOCKFILE_OPTION) -C $${pkg} status || true; \ done .PHONY: export-all export-all: $(call print_header, "Exporting all cloe Conan packages...") - ${MAKE} export-select export-cli export + $(MAKE) export-select export-cli export .PHONY: deploy-all deploy-all: - $(call print_header, "Deploying binaries to ${INSTALL_DIR}...") - conan install ${CONAN_OPTIONS} --install-folder ${DEPLOY_DIR} -g deploy . - mkdir -p ${INSTALL_DIR} - cp -r ${DEPLOY_DIR}/cloe-*/* ${INSTALL_DIR}/ + $(call print_header, "Deploying binaries to $(INSTALL_DIR)...") + conan install $(CONAN_OPTIONS) --install-folder $(DEPLOY_DIR) -g deploy . + mkdir -p $(INSTALL_DIR) + cp -r $(DEPLOY_DIR)/cloe-*/* $(INSTALL_DIR)/ .PHONY: clean-all clean-all: - ${MAKE} clean clean-select + $(MAKE) clean clean-select .PHONY: purge-all purge-all: @@ -127,7 +127,7 @@ purge-all: .PHONY: package-all package-all: - conan install ${CONAN_OPTIONS} --install-folder ${DEPLOY_DIR} --build=missing --build=outdated ${DEPLOY_LOCKFILE_SOURCE} + conan install $(CONAN_OPTIONS) --install-folder $(DEPLOY_DIR) --build=missing --build=outdated $(DEPLOY_LOCKFILE_SOURCE) # Development targets --------------------------------------------------------- help:: @@ -143,19 +143,19 @@ format: # continues to work as expected. # # See: https://www.moxio.com/blog/43/ignoring-bulk-change-commits-with-git-blame - find . -type f -not -path '*/\.git/*' -and \( -name '*.cpp' -o -name '*.hpp' \) -exec ${CLANG_FORMAT} ${CLANG_FORMAT_ARGS} -i {} \; + find . -type f -not -path '*/\.git/*' -and \( -name '*.cpp' -o -name '*.hpp' \) -exec $(CLANG_FORMAT) $(CLANG_FORMAT_ARGS) -i {} \; .PHONY: todos todos: - ${AG} TODO - ${AG} FIXME - ${AG} XXX + $(AG) TODO + $(AG) FIXME + $(AG) XXX # Hidden development targets -------------------------------------------------- .PHONY: grep-uuids grep-uuids: - ${AG} "\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b" + $(AG) "\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b" grep-conan-requires: @rg -t py '^.*requires\(f?["](.+/[0-9]+\.[^)]+)["].*\).*$$' -r '$$1' -I --no-heading --no-line-number | sort | uniq diff --git a/Makefile.all b/Makefile.all index 2e294a6f..c6756f0e 100644 --- a/Makefile.all +++ b/Makefile.all @@ -53,12 +53,12 @@ ALL_PKGS := \ osi \ oak \ engine \ - ${PLUGIN_PKGS} + $(PLUGIN_PKGS) WITHOUT_PKGS := -UNSELECT_PKGS := ${WITHOUT_PKGS} +UNSELECT_PKGS := $(WITHOUT_PKGS) WITH_PKGS := -SELECT_PKGS := $(call uniq, $(filter-out ${UNSELECT_PKGS}, ${ALL_PKGS}) ${WITH_PKGS}) -.PHONY: ${ALL_PKGS} +SELECT_PKGS := $(call uniq, $(filter-out $(UNSELECT_PKGS), $(ALL_PKGS)) $(WITH_PKGS)) +.PHONY: $(ALL_PKGS) ## VENDOR PACKAGE SELECTION ## @@ -66,10 +66,10 @@ SELECT_PKGS := $(call uniq, $(filter-out ${UNSELECT_PKGS}, ${ALL_PKGS}) ${WITH_P ## ALL_VENDOR := $(wildcard vendor/*) WITHOUT_VENDOR := -UNSELECT_VENDOR := ${WITHOUT_VENDOR} +UNSELECT_VENDOR := $(WITHOUT_VENDOR) WITH_VENDOR := -SELECT_VENDOR := $(call uniq, $(filter-out ${UNSELECT_VENDOR}, ${ALL_VENDOR}) ${WITH_VENDOR}) -.PHONY: ${ALL_VENDOR} +SELECT_VENDOR := $(call uniq, $(filter-out $(UNSELECT_VENDOR), $(ALL_VENDOR)) $(WITH_VENDOR)) +.PHONY: $(ALL_VENDOR) # Specify dependencies: fable: @@ -78,7 +78,7 @@ models: runtime osi: runtime models oak: runtime engine: models oak -${PLUGIN_PKGS}: runtime models +$(PLUGIN_PKGS): runtime models plugins/esmini: osi vendor/esmini: vendor/open-simulation-interface @@ -114,36 +114,36 @@ CONAN_OPTIONS := # Usage: $(call _make_target_rule, TARGET-NAME, MAKE-TARGET, HELP-DESCRIPTION, MAKE-ARGUMENTS) define _make_target_rule -${1}: - $(call print_header, "Proceeding to $(call unquote, ${3})") - ${MAKE} ${SUBMAKEFLAGS} ${4} ${2} +$(1): + $(call print_header, "Proceeding to $(call unquote, $(3))") + $(MAKE) $(SUBMAKEFLAGS) $(4) $(2) endef # Usage: $(call _make_target_rules, TARGET-NAME, HELP-DESCRIPTION, HELP-CATEGORY, PACKAGE-DIRS) define _make_target_rules help:: - $(call print_help_target, ${1}, ${2}, ${3}) -$(call _make_target_rule,${1},${1}-each,${2},-f Makefile.all) -${1}-each: ${4} + $(call print_help_target, $(1), $(2), $(3)) +$(call _make_target_rule,$(1),$(1)-each,$(2),-f Makefile.all) +$(1)-each: $(4) endef REGEX_TARGET := 's/(-vendor|-select)?-each//' -${ALL_PKGS} ${ALL_VENDOR}: - ${MAKE} -C $@ $(shell echo ${MAKECMDGOALS} | sed -re ${REGEX_TARGET}) +$(ALL_PKGS) $(ALL_VENDOR): + $(MAKE) -C $@ $(shell echo $(MAKECMDGOALS) | sed -re $(REGEX_TARGET)) # Usage: $(call make_vendor_target, TARGET-NAME, HELP-DESCRIPTION, HELP-CATEGORY) define make_vendor_target -$(eval $(call _make_target_rules,${1},${2},${3},${SELECT_VENDOR})) +$(eval $(call _make_target_rules,$(1),$(2),$(3),$(SELECT_VENDOR))) endef # Usage: $(call make_every_target, TARGET-NAME, HELP-DESCRIPTION, HELP-CATEGORY) define make_every_target -$(eval $(call _make_target_rules,${1},${2},${3},${ALL_PKGS})) +$(eval $(call _make_target_rules,$(1),$(2),$(3),$(ALL_PKGS))) endef # Usage: $(call make_select_target, TARGET-NAME, HELP-DESCRIPTION, HELP-CATEGORY) define make_select_target -$(eval $(call _make_target_rules,${1},${2},${3},${SELECT_PKGS})) +$(eval $(call _make_target_rules,$(1),$(2),$(3),$(SELECT_PKGS))) endef # --------------------------------------------------------------------------- # @@ -154,7 +154,7 @@ endef help:: $(call print_help_section, "Available multi-package targets") -ifneq "${ALL_VENDOR}" "" +ifneq "$(ALL_VENDOR)" "" help:: $(call make_vendor_target, export-vendor, "export all vendor packages", "[conan-cache]") $(call make_vendor_target, package-vendor, "create all vendor packages", "[conan-cache]") @@ -189,19 +189,19 @@ $(call make_select_target, clean-select, "remove build artifacts", "[in-source]" help:: echo $(call print_help_subsection, "Options") -ifneq "${ALL_VENDOR}" "" - $(call print_help_option, WITH_VENDOR, "", "include optional vendor packages from ${_grn}UNSELECT_VENDOR${_rst}") +ifneq "$(ALL_VENDOR)" "" + $(call print_help_option, WITH_VENDOR, "", "include optional vendor packages from $(_grn)UNSELECT_VENDOR$(_rst)") endif - $(call print_help_option, WITH_PKGS, "", "include optional packages from ${_grn}UNSELECT_PKGS${_rst}") + $(call print_help_option, WITH_PKGS, "", "include optional packages from $(_grn)UNSELECT_PKGS$(_rst)") $(call print_help_option, LOCKFILE_SOURCE, "", "use specified conanfile as lockfile source for build") echo $(call print_help_subsection, "Defines") - $(call print_help_option, BUILD_POLICY, ${BUILD_POLICY}) - $(call print_help_define, CONAN_OPTIONS, ${CONAN_OPTIONS}) -ifneq "${ALL_VENDOR}" "" - $(call print_help_define_lines, UNSELECT_VENDOR, ${UNSELECT_VENDOR}) - $(call print_help_define_lines, SELECT_VENDOR, ${SELECT_VENDOR}) + $(call print_help_option, BUILD_POLICY, $(BUILD_POLICY)) + $(call print_help_define, CONAN_OPTIONS, $(CONAN_OPTIONS)) +ifneq "$(ALL_VENDOR)" "" + $(call print_help_define_lines, UNSELECT_VENDOR, $(UNSELECT_VENDOR)) + $(call print_help_define_lines, SELECT_VENDOR, $(SELECT_VENDOR)) endif - $(call print_help_define_lines, UNSELECT_PKGS, ${UNSELECT_PKGS}) - $(call print_help_define_lines, SELECT_PKGS, ${SELECT_PKGS}) + $(call print_help_define_lines, UNSELECT_PKGS, $(UNSELECT_PKGS)) + $(call print_help_define_lines, SELECT_PKGS, $(SELECT_PKGS)) echo diff --git a/Makefile.docker b/Makefile.docker index 298004c7..5a1b3143 100644 --- a/Makefile.docker +++ b/Makefile.docker @@ -2,61 +2,61 @@ # # This file defines all Docker targets. -PROJECT_ROOT := $(dir $(abspath $(lastword ${MAKEFILE_LIST}))) -PROJECT_VERSION := $(shell make --no-print-directory -C ${PROJECT_ROOT} -f Makefile.package info-version) +PROJECT_ROOT := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +PROJECT_VERSION := $(shell make --no-print-directory -C $(PROJECT_ROOT) -f Makefile.package info-version) UBUNTU_NAME := ubuntu UBUNTU_VERSIONS := 20.04 22.04 DOCKER := DOCKER_BUILDKIT=1 docker DOCKER_IMAGE_NAME := cloe/cloe-engine -DOCKER_IMAGE_VERSION := ${PROJECT_VERSION} -DOCKER_IMAGE := ${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION} -DOCKER_DEVIMAGE := ${DOCKER_IMAGE_NAME}-dev:${DOCKER_IMAGE_VERSION} -DOCKER_CONTEXT := ${PROJECT_ROOT} +DOCKER_IMAGE_VERSION := $(PROJECT_VERSION) +DOCKER_IMAGE := $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_VERSION) +DOCKER_DEVIMAGE := $(DOCKER_IMAGE_NAME)-dev:$(DOCKER_IMAGE_VERSION) +DOCKER_CONTEXT := $(PROJECT_ROOT) DOCKER_USER_ARGS += -DOCKER_BUILD_ARGS += --build-arg PROJECT_VERSION=${PROJECT_VERSION} +DOCKER_BUILD_ARGS += --build-arg PROJECT_VERSION=$(PROJECT_VERSION) DOCKER_RUN_ARGS += --rm -ifndef (${https_proxy},) +ifndef ($(https_proxy),) DOCKER_NETWORK := host DOCKER_BUILD_ARGS += --network=host \ - --build-arg https_proxy="${https_proxy}" \ - --build-arg http_proxy="${http_proxy}" \ - --build-arg no_proxy="${no_proxy}" + --build-arg https_proxy="$(https_proxy)" \ + --build-arg http_proxy="$(http_proxy)" \ + --build-arg no_proxy="$(no_proxy)" DOCKER_RUN_ARGS += --network=host \ - --env https_proxy="${https_proxy}" \ - --env http_proxy="${http_proxy}" \ - --env no_proxy="${no_proxy}" + --env https_proxy="$(https_proxy)" \ + --env http_proxy="$(http_proxy)" \ + --env no_proxy="$(no_proxy)" else DOCKER_NETWORK := internal endif -ifeq ($(shell [ -f ${PROJECT_ROOT}/setup.sh ] && echo "true"),true) -DOCKER_BUILD_ARGS += --secret id=setup,src=${PROJECT_ROOT}/setup.sh -DOCKER_RUN_ARGS += -v "${PROJECT_ROOT}/setup.sh:/root/setup.sh" +ifeq ($(shell [ -f $(PROJECT_ROOT)/setup.sh ] && echo "true"),true) +DOCKER_BUILD_ARGS += --secret id=setup,src=$(PROJECT_ROOT)/setup.sh +DOCKER_RUN_ARGS += -v "$(PROJECT_ROOT)/setup.sh:/root/setup.sh" endif -ifneq (${CONAN_PROFILE},) -DOCKER_BUILD_ARGS += --build-arg CONAN_PROFILE="${CONAN_PROFILE}" +ifneq ($(CONAN_PROFILE),) +DOCKER_BUILD_ARGS += --build-arg CONAN_PROFILE="$(CONAN_PROFILE)" endif -ifneq (${VENDOR_TARGET},) -DOCKER_BUILD_ARGS += --build-arg VENDOR_TARGET="${VENDOR_TARGET}" +ifneq ($(VENDOR_TARGET),) +DOCKER_BUILD_ARGS += --build-arg VENDOR_TARGET="$(VENDOR_TARGET)" endif -ifneq (${PACKAGE_TARGET},) -DOCKER_BUILD_ARGS += --build-arg PACKAGE_TARGET="${PACKAGE_TARGET}" +ifneq ($(PACKAGE_TARGET),) +DOCKER_BUILD_ARGS += --build-arg PACKAGE_TARGET="$(PACKAGE_TARGET)" endif -ifeq (${KEEP_SOURCES},1) +ifeq ($(KEEP_SOURCES),1) DOCKER_BUILD_ARGS += --build-arg KEEP_SOURCES=1 endif # ----------------------------------------------------------------------------- -include ${PROJECT_ROOT}/Makefile.help +include $(PROJECT_ROOT)/Makefile.help .PHONY: help .SILENT: help @@ -73,25 +73,25 @@ help:: $(call print_help_target, run-ubuntu-VERSION, "run the Ubuntu VERSION image") $(call print_help_target, release-all, "release all Ubuntu versions") $(call print_help_target, release-ubuntu-VERSION, "release the Ubuntu VERSION image") - $(call print_help_target, remove-current-images, "remove and prune all ${DOCKER_IMAGE} Docker images") - $(call print_help_target, remove-all-images, "remove and prune all ${DOCKER_IMAGE_NAME} Docker images") + $(call print_help_target, remove-current-images, "remove and prune all $(DOCKER_IMAGE) Docker images") + $(call print_help_target, remove-all-images, "remove and prune all $(DOCKER_IMAGE_NAME) Docker images") echo $(call print_help_section, "User configuration") - $(call print_help_define, CONAN_PROFILE, ${CONAN_PROFILE}) - $(call print_help_define, VENDOR_TARGET, ${VENDOR_TARGET}) - $(call print_help_define, PACKAGE_TARGET, ${PACKAGE_TARGET}) - $(call print_help_define, KEEP_SOURCES, ${KEEP_SOURCES}) - $(call print_help_args_lines, DOCKER_USER_ARGS, ${DOCKER_USER_ARGS}) + $(call print_help_define, CONAN_PROFILE, $(CONAN_PROFILE)) + $(call print_help_define, VENDOR_TARGET, $(VENDOR_TARGET)) + $(call print_help_define, PACKAGE_TARGET, $(PACKAGE_TARGET)) + $(call print_help_define, KEEP_SOURCES, $(KEEP_SOURCES)) + $(call print_help_args_lines, DOCKER_USER_ARGS, $(DOCKER_USER_ARGS)) echo $(call print_help_section, "Docker configuration") - $(call print_help_define, UBUNTU_NAME, "${UBUNTU_NAME}") - $(call print_help_define_lines, UBUNTU_VERSIONS, ${UBUNTU_VERSIONS}) - $(call print_help_define, DOCKER, "${DOCKER}") - $(call print_help_define, DOCKER_CONTEXT, "${DOCKER_CONTEXT}") - $(call print_help_define, DOCKER_NETWORK, "${DOCKER_NETWORK}") - $(call print_help_define, DOCKER_IMAGE, "${DOCKER_IMAGE}") - $(call print_help_args_lines, DOCKER_BUILD_ARGS, ${DOCKER_BUILD_ARGS}) - $(call print_help_args_lines, DOCKER_RUN_ARGS, ${DOCKER_RUN_ARGS}) + $(call print_help_define, UBUNTU_NAME, "$(UBUNTU_NAME)") + $(call print_help_define_lines, UBUNTU_VERSIONS, $(UBUNTU_VERSIONS)) + $(call print_help_define, DOCKER, "$(DOCKER)") + $(call print_help_define, DOCKER_CONTEXT, "$(DOCKER_CONTEXT)") + $(call print_help_define, DOCKER_NETWORK, "$(DOCKER_NETWORK)") + $(call print_help_define, DOCKER_IMAGE, "$(DOCKER_IMAGE)") + $(call print_help_args_lines, DOCKER_BUILD_ARGS, $(DOCKER_BUILD_ARGS)) + $(call print_help_args_lines, DOCKER_RUN_ARGS, $(DOCKER_RUN_ARGS)) echo .SILENT: FORCE @@ -101,61 +101,61 @@ FORCE: # prerequisites of every target with patterns. .PHONY: build-all -build-all: $(addprefix build-ubuntu-,${UBUNTU_VERSIONS}) +build-all: $(addprefix build-ubuntu-,$(UBUNTU_VERSIONS)) .PHONY: test-all -test-all: $(addprefix test-ubuntu-,${UBUNTU_VERSIONS}) +test-all: $(addprefix test-ubuntu-,$(UBUNTU_VERSIONS)) .PHONY: release-all -release-all: $(addprefix release-ubuntu-,${UBUNTU_VERSIONS}) +release-all: $(addprefix release-ubuntu-,$(UBUNTU_VERSIONS)) ubuntu-%: FORCE build-ubuntu-% test-ubuntu-% @echo - @echo "Completed building and testing: ${DOCKER_IMAGE}-$@" + @echo "Completed building and testing: $(DOCKER_IMAGE)-$@" .PHONY: all -all: $(addprefix ubuntu-,${UBUNTU_VERSIONS}) +all: $(addprefix ubuntu-,$(UBUNTU_VERSIONS)) build-devc-%: FORCE Dockerfile - ${DOCKER} build -f Dockerfile ${DOCKER_BUILD_ARGS} ${DOCKER_USER_ARGS} \ + $(DOCKER) build -f Dockerfile $(DOCKER_BUILD_ARGS) $(DOCKER_USER_ARGS) \ --build-arg UBUNTU_VERSION=$* \ --target stage-setup-system \ - -t ${DOCKER_DEVIMAGE}-ubuntu-$* \ - ${DOCKER_CONTEXT} + -t $(DOCKER_DEVIMAGE)-ubuntu-$* \ + $(DOCKER_CONTEXT) build-ubuntu-%: FORCE Dockerfile - ${DOCKER} build -f Dockerfile ${DOCKER_BUILD_ARGS} ${DOCKER_USER_ARGS} \ + $(DOCKER) build -f Dockerfile $(DOCKER_BUILD_ARGS) $(DOCKER_USER_ARGS) \ --build-arg UBUNTU_VERSION=$* \ - -t ${DOCKER_IMAGE}-ubuntu-$* \ - ${DOCKER_CONTEXT} + -t $(DOCKER_IMAGE)-ubuntu-$* \ + $(DOCKER_CONTEXT) test-ubuntu-%: FORCE - docker run ${DOCKER_RUN_ARGS} ${DOCKER_USER_ARGS} ${DOCKER_IMAGE}-ubuntu-$* \ + docker run $(DOCKER_RUN_ARGS) $(DOCKER_USER_ARGS) $(DOCKER_IMAGE)-ubuntu-$* \ bash -ec "[ -f /root/setup.sh ] && source /root/setup.sh; make smoketest" run-devc-%: FORCE - docker run -it ${DOCKER_RUN_ARGS} ${DOCKER_USER_ARGS} --mount type=bind,source=$$(pwd),destination=/cloe ${DOCKER_DEVIMAGE}-ubuntu-$* + docker run -it $(DOCKER_RUN_ARGS) $(DOCKER_USER_ARGS) --mount type=bind,source=$$(pwd),destination=/cloe $(DOCKER_DEVIMAGE)-ubuntu-$* run-ubuntu-%: FORCE - docker run -it ${DOCKER_RUN_ARGS} ${DOCKER_USER_ARGS} ${DOCKER_IMAGE}-ubuntu-$* + docker run -it $(DOCKER_RUN_ARGS) $(DOCKER_USER_ARGS) $(DOCKER_IMAGE)-ubuntu-$* release-ubuntu-%: FORCE @test -f setup.sh || echo 'Error: require setup.sh for user authentication' - ${DOCKER} run ${DOCKER_RUN_ARGS} ${DOCKER_USER_ARGS} ${DOCKER_IMAGE}-ubuntu-$* \ + $(DOCKER) run $(DOCKER_RUN_ARGS) $(DOCKER_USER_ARGS) $(DOCKER_IMAGE)-ubuntu-$* \ bash -ec 'source /root/setup.sh && upload_conan_packages' .PHONY: require-setup-sh require-setup-sh: - @if [ ! -f ${PROJECT_ROOT}/setup.sh ]; then \ - echo "ERROR: require ${PROJECT_ROOT}/setup.sh to proceed"; \ + @if [ ! -f $(PROJECT_ROOT)/setup.sh ]; then \ + echo "ERROR: require $(PROJECT_ROOT)/setup.sh to proceed"; \ exit 1; \ fi .PHONY: remove-current-images remove-current-images: - docker rmi $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep '${DOCKER_IMAGE}') + docker rmi $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep '$(DOCKER_IMAGE)') .PHONY: remove-all-images remove-all-images: - docker rmi $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep '${DOCKER_IMAGE_NAME}:') + docker rmi $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep '$(DOCKER_IMAGE_NAME):') diff --git a/Makefile.help b/Makefile.help index 84fdc9b0..2a0bc50a 100644 --- a/Makefile.help +++ b/Makefile.help @@ -21,10 +21,10 @@ # Usage: $(call assert_numeric_bool, VARIABLE-NAME) define assert_numeric_bool -$(if $(filter-out 0 1,${$1}), $(error Unexpected value for parameter $1, expect either 0 or 1)) +$(if $(filter-out 0 1,$($1)), $(error Unexpected value for parameter $1, expect either 0 or 1)) endef -# Usage: $(call uniq, ${LIST-OF-WORDS}) +# Usage: $(call uniq, $(LIST-OF-WORDS)) define uniq $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) endef @@ -58,39 +58,39 @@ _dim := \e[2m define print_header @printf "________________________________________" @printf "________________________________________\n" - @printf ":: %s\n" ${1} + @printf ":: %s\n" $(1) endef # Usage: $(call print_help_section, SECTION-TITLE) define print_help_section - @printf "%s:\n" ${1} + @printf "%s:\n" $(1) endef # Usage: $(call print_help_subsection, SUBSECTION-TITLE) define print_help_subsection - @printf " %s:\n" ${1} + @printf " %s:\n" $(1) endef # Usage: $(call print_help_target, TARGET-NAME, HELP-DESCRIPTION, HELP-CATEGORY) define print_help_target - @printf " ${_blu}% -21s${_rst} % -45b ${_dim}%s${_rst}\n" ${1} ${2} ${3} + @printf " $(_blu)% -21s$(_rst) % -45b $(_dim)%s$(_rst)\n" $(1) $(2) $(3) endef # Usage: $(call print_help_option, VAR-NAME, VAR-DEFAULT, DESCRIPTION) define print_help_option - @printf " % -36s %b\n" $(shell printf "${_grn}%s${_rst}=${_dim}%s${_rst}" ${1} ${2}) ${3} + @printf " % -36s %b\n" $(shell printf "$(_grn)%s$(_rst)=$(_dim)%s$(_rst)" $(1) $(2)) $(3) endef -# Usage: $(call print_help_define, VAR-NAME, ${VAR-NAME}) +# Usage: $(call print_help_define, VAR-NAME, $(VAR-NAME)) define print_help_define - @printf " ${_grn}%s${_rst}=${_dim}%s${_rst}\n" ${1} ${2} + @printf " $(_grn)%s$(_rst)=$(_dim)%s$(_rst)\n" $(1) $(2) endef define print_help_define_align - @printf " ${_grn}%-16s${_rst}=${_dim} %s${_rst}\n" ${1} ${2} + @printf " $(_grn)%-16s$(_rst)=$(_dim) %s$(_rst)\n" $(1) $(2) endef -# Usage: $(call print_help_define_lines, VAR-NAME, ${VAR-NAME}) +# Usage: $(call print_help_define_lines, VAR-NAME, $(VAR-NAME)) # # For example, given a call with the following: # @@ -103,16 +103,16 @@ endef # 20.04 # 22.04 # -# If the contents of ${VAR-NAME} is empty or only contains whitespace, +# If the contents of $(VAR-NAME) is empty or only contains whitespace, # then no extra newline is printed, and it behaves as print_help_define. define print_help_define_lines - @printf " ${_grn}%s${_rst}=${_dim}" ${1} - @if [ -n "$(strip ${2})" ]; then printf "\\ \n"; fi - @printf "%s" "$$(echo " ${2}" | fmt -5)" - @printf "${_rst}\n" + @printf " $(_grn)%s$(_rst)=$(_dim)" $(1) + @if [ -n "$(strip $(2))" ]; then printf "\\ \n"; fi + @printf "%s" "$$(echo " $(2)" | fmt -5)" + @printf "$(_rst)\n" endef -# Usage: $(call print_help_args_lines, VAR-NAME, ${VAR-NAME}) +# Usage: $(call print_help_args_lines, VAR-NAME, $(VAR-NAME)) # # This function behaves as print_help_define_lines, except that # it doesn't split on words, but on arguments. Each argument (leading with -) @@ -129,12 +129,12 @@ endef # --rm # --network host # -# If the contents of ${VAR-NAME} is empty, same behavior as print_help_define. +# If the contents of $(VAR-NAME) is empty, same behavior as print_help_define. define print_help_args_lines - @printf " ${_grn}%s${_rst}=${_dim}" ${1} - @if [ -n "$(strip ${2})" ]; then printf "\\ \n"; fi - @printf "%s" "$$(echo " ${2}" | sed -r -e 's/\W--?[^-]/\n \0/g' -e 's/^\s*\n//')" - @printf "${_rst}\n" + @printf " $(_grn)%s$(_rst)=$(_dim)" $(1) + @if [ -n "$(strip $(2))" ]; then printf "\\ \n"; fi + @printf "%s" "$$(echo " $(2)" | sed -r -e 's/\W--?[^-]/\n \0/g' -e 's/^\s*\n//')" + @printf "$(_rst)\n" endef # Usage: $(call print_help_usage) @@ -142,5 +142,5 @@ endef # This should be called only once, before all other print_help_* calls, # so that the help message starts with a usage statement. define print_help_usage - @printf "Usage: make ${_blu}target${_rst}\n" + @printf "Usage: make $(_blu)target$(_rst)\n" endef diff --git a/Makefile.package b/Makefile.package index 84a81222..d96a069a 100644 --- a/Makefile.package +++ b/Makefile.package @@ -20,35 +20,35 @@ # You should also adjust the PACKAGE_CHANNEL variable. # -PROJECT_ROOT := $(dir $(abspath $(lastword ${MAKEFILE_LIST}))) -PROJECT_VERSION := $(shell [ -r ${PROJECT_ROOT}/VERSION ] && cat ${PROJECT_ROOT}/VERSION || echo unknown) +PROJECT_ROOT := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +PROJECT_VERSION := $(shell [ -r $(PROJECT_ROOT)/VERSION ] && cat $(PROJECT_ROOT)/VERSION || echo unknown) -include ${PROJECT_ROOT}/Makefile.help +include $(PROJECT_ROOT)/Makefile.help # Command for cloe-launch. # # This definition could be `cloe-launch`, but then you wouldn't get the # version of cloe-launch that is from this repository, but one that is # available globally. -CLOE_LAUNCH := PYTHONPATH="${PROJECT_ROOT}/cli" python3 -m cloe_launch +CLOE_LAUNCH := PYTHONPATH="$(PROJECT_ROOT)/cli" python3 -m cloe_launch SHELL := /bin/bash DATE := $(shell date +"%Y%m%d") TIMESTAMP := $(shell date -u +'%Y-%m-%dT%H:%M:%SZ') # Check if we are in a Git repository and try to describe the current -# state if we are. This is used for setting the ${PACKAGE_VERSION} if -# it is not set in conanfile or by ${PROJECT_VERSION}. -HAS_GIT := $(shell [ -e ${PROJECT_ROOT}/.git ] && echo "true") -ifeq (${PROJECT_VERSION},unknown) -ifeq (${HAS_GIT},true) +# state if we are. This is used for setting the $(PACKAGE_VERSION) if +# it is not set in conanfile or by $(PROJECT_VERSION). +HAS_GIT := $(shell [ -e $(PROJECT_ROOT)/.git ] && echo "true") +ifeq ($(PROJECT_VERSION),unknown) +ifeq ($(HAS_GIT),true) GIT_COMMIT_HASH := $(shell git log -1 --format=%h) GIT_COMMIT_DIRTY := $(shell git diff --quiet || echo "-dirty") GIT_DESCRIBE := $(shell git describe --dirty="-dirty" | sed -r "s/^v(.*)/\1/") else GIT_DESCRIBE := "unknown" endif -PROJECT_VERSION := ${GIT_DESCRIBE} +PROJECT_VERSION := $(GIT_DESCRIBE) endif # Default in-source directory. @@ -60,12 +60,12 @@ SOURCE_DIR := . # Don't change these unless you absolutely have to. SOURCE_CONANFILE := conanfile.py -SOURCE_CMAKELISTS:= ${SOURCE_DIR}/CMakeLists.txt +SOURCE_CMAKELISTS:= $(SOURCE_DIR)/CMakeLists.txt LOCKFILE_SOURCE := LOCKFILE_OPTION := -# When running `make clean`, delete the configured ${SOURCE_DIR}? +# When running `make clean`, delete the configured $(SOURCE_DIR)? # Anything other than `true` is taken to be false. CLEAN_SOURCE_DIR := false @@ -78,8 +78,8 @@ BUILD_IN_SOURCE := true BUILD_DIR := build # Don't change these unless you know what you are doing. -BUILD_CONANINFO := ${BUILD_DIR}/conanbuildinfo.txt -BUILD_LOCKFILE := ${BUILD_DIR}/conan.lock +BUILD_CONANINFO := $(BUILD_DIR)/conanbuildinfo.txt +BUILD_LOCKFILE := $(BUILD_DIR)/conan.lock # Default Conan build policy to use when installing Conan dependencies # as well as creating packages. See Conan documentation for possible values. @@ -94,19 +94,20 @@ BUILD_POLICY := outdated # # You probably want to override PACKAGE_CHANNEL, which is actually a USER/CHANNEL # combination. See your project for guidance on naming. -PACKAGE_NAME := $(shell sed -rn 's/.*name\s*=\s*"([^"]+)"$$/\1/p' ${SOURCE_CONANFILE}) +PACKAGE_NAME := $(shell sed -rn 's/.*name\s*=\s*"([^"]+)"$$/\1/p' $(SOURCE_CONANFILE)) PACKAGE_VERSION := $(or \ - $(shell sed -rn 's/\s+version\s*=\s*"([^"]+)"$$/\1/p' ${SOURCE_CONANFILE}), \ - ${PROJECT_VERSION}, \ + $(shell sed -rn 's/\s+version\s*=\s*"([^"]+)"$$/\1/p' $(SOURCE_CONANFILE)), \ + $(PROJECT_VERSION), \ unknown \ ) PACKAGE_CHANNEL := cloe/develop -PACKAGE_FQN := ${PACKAGE_NAME}/${PACKAGE_VERSION}@${PACKAGE_CHANNEL} +PACKAGE_FQN := $(PACKAGE_NAME)/$(PACKAGE_VERSION)@$(PACKAGE_CHANNEL) # Which files to consider as smoketest profiles when running targets # `smoketest-deps` and `smoketest`. This can be useful to override from the # command line if you just want to test one configuration. TEST_CONANFILES := tests/conanfile_*.py +TEST_DIR := tests # It is an order of magnitude faster to parse ~/.conan/editable_packages.json # ourselves than to get conan to do it for us. This should only take us 20ms, @@ -114,16 +115,16 @@ TEST_CONANFILES := tests/conanfile_*.py # or the path to the current conanfile.py is marked as editable. This helps # inform the user when they make a package editable, but then check out another # state of the tree with a different version. -SOURCE_CONANFILE_REALPATH := $(realpath ${SOURCE_CONANFILE}) +SOURCE_CONANFILE_REALPATH := $(realpath $(SOURCE_CONANFILE)) define JQ_PACKAGE_EDITABLE - if has(\"${PACKAGE_FQN}\") then - if .[\"${PACKAGE_FQN}\"].path == \"${SOURCE_CONANFILE_REALPATH}\" then + if has(\"$(PACKAGE_FQN)\") then + if .[\"$(PACKAGE_FQN)\"].path == \"$(SOURCE_CONANFILE_REALPATH)\" then \"editable\" else \"editable-elsewhere\" end else - if ([.[].path] | any(. == \"${SOURCE_CONANFILE_REALPATH}\")) then + if ([.[].path] | any(. == \"$(SOURCE_CONANFILE_REALPATH)\")) then \"editable-other-name\" else \"not-editable\" @@ -131,14 +132,18 @@ define JQ_PACKAGE_EDITABLE end endef +PACKAGE_EDITABLE := $(shell [ -e ~/.conan/editable_packages.json ] \ + && jq -r "$(JQ_PACKAGE_EDITABLE)" ~/.conan/editable_packages.json \ + || echo "not-editable") + # Normally, you should set this in your profile, but if you just want to build # the package in debug mode once, you can do it this way, although it will # only apply to local builds. # # This can be one of: None, Debug, Release, RelWithDebInfo, MinSizeRel BUILD_TYPE := -ifneq "${BUILD_TYPE}" "" -BUILD_TYPE_OPTION := -s ${PACKAGE_NAME}:build_type=${BUILD_TYPE} +ifneq "$(BUILD_TYPE)" "" +BUILD_TYPE_OPTION := -s $(PACKAGE_NAME):build_type=$(BUILD_TYPE) else BUILD_TYPE_OPTION := endif @@ -146,36 +151,36 @@ endif # These options can be set to influence package and configure. CONAN_OPTIONS := -ifneq "${LOCKFILE_SOURCE}" "" -.PHONY: ${BUILD_LOCKFILE} -ifeq "$(realpath ${LOCKFILE_SOURCE})" "$(realpath ${SOURCE_CONANFILE})" -$(error "LOCKFILE_SOURCE must contain superset of SOURCE_CONANFILE package and dependencies") -endif -LOCKFILE_OPTION := --lockfile="${BUILD_LOCKFILE}" -override CONAN_OPTIONS := -${BUILD_LOCKFILE}: ${LOCKFILE_SOURCE} export - # Create lockfile from LOCKFILE_SOURCE. - # - mkdir -p "${BUILD_DIR}" - conan lock create --lockfile-out "${BUILD_LOCKFILE}" ${BUILD_TYPE_OPTION} ${CONAN_OPTIONS} --build -- "${LOCKFILE_SOURCE}" >/dev/null +ifneq "$(LOCKFILE_SOURCE)" "" +LOCKFILE_OPTION := --lockfile="$(BUILD_LOCKFILE)" + +.PHONY: $(BUILD_LOCKFILE) +# Create lockfile from LOCKFILE_SOURCE. +# +$(BUILD_LOCKFILE): $(LOCKFILE_SOURCE) export + mkdir -p "$(BUILD_DIR)" + conan lock create --lockfile-out "$(BUILD_LOCKFILE)" $(BUILD_TYPE_OPTION) $(CONAN_OPTIONS) --build -- "$(LOCKFILE_SOURCE)" >/dev/null else # Lockfile will be created automatically by conan install command. -${BUILD_LOCKFILE}: +$(BUILD_LOCKFILE): endif # When using a --lockfile option, we cannot use profile, settings, options, env # or conf 'host' Conan options. -ifneq "${LOCKFILE_OPTION}" "" -ALL_OPTIONS := ${LOCKFILE_OPTION} ${CONAN_OPTIONS} +ifneq "$(LOCKFILE_OPTION)" "" +ALL_OPTIONS := $(LOCKFILE_OPTION) $(CONAN_OPTIONS) else -ALL_OPTIONS := ${BUILD_TYPE_OPTION} ${CONAN_OPTIONS} +ALL_OPTIONS := $(BUILD_TYPE_OPTION) $(CONAN_OPTIONS) endif # INFORMATIONAL TARGETS ------------------------------------------------------- .DEFAULT_GOAL := help .SILENT: help .PHONY: help -help:: parse-info parse-editable +help:: parse-info + +ifneq ($(DISABLE_HELP_PREAMBLE), true) +help:: $(call print_help_usage) echo echo "The following targets define common operations with this package in" @@ -183,6 +188,9 @@ help:: parse-info parse-editable echo $(call print_help_section, "Available targets") $(call print_help_target, help, "show this help") +endif + +help:: $(call print_help_target, status, "show status of package") $(call print_help_target, info, "show detailed package info") $(call print_help_target, smoketest-deps, "build smoketest dependencies for package") @@ -194,7 +202,7 @@ help:: parse-info parse-editable $(call print_help_target, list, "list installed package files", "[conan-cache]") $(call print_help_target, purge, "remove package from cache", "[conan-cache]") echo -ifeq (${BUILD_IN_SOURCE}, true) +ifeq ($(BUILD_IN_SOURCE), true) $(call print_help_target, editable, "instruct Conan to use in-source build") $(call print_help_target, uneditable, "instruct Conan to use local cache") echo @@ -202,7 +210,7 @@ ifeq (${BUILD_IN_SOURCE}, true) $(call print_help_target, configure, "install dependencies and configure package", "[in-source]") $(call print_help_target, test, "run CMake tests if they are available", "[in-source]") $(call print_help_target, export-pkg, "export build artifacts to Conan cache", "[in-source]") -ifeq (${CLEAN_SOURCE_DIR}, true) +ifeq ($(CLEAN_SOURCE_DIR), true) $(call print_help_target, clean, "remove source and build directories", "[in-source]") else $(call print_help_target, clean, "remove build directory", "[in-source]") @@ -210,49 +218,44 @@ endif echo endif $(call print_help_subsection, "Configuration") - $(call print_help_define_align, LOCKFILE_SOURCE, ${LOCKFILE_SOURCE}) -ifeq (${BUILD_IN_SOURCE}, true) - $(call print_help_define_align, SOURCE_DIR, ${SOURCE_DIR}) + $(call print_help_define_align, LOCKFILE_SOURCE, "$(LOCKFILE_SOURCE)") +ifeq ($(BUILD_IN_SOURCE), true) + $(call print_help_define_align, SOURCE_DIR, "$(SOURCE_DIR)") endif - $(call print_help_define_align, BUILD_DIR, ${BUILD_DIR}) - $(call print_help_define_align, BUILD_POLICY, ${BUILD_POLICY}) - $(call print_help_define_align, BUILD_TYPE, ${BUILD_TYPE}) - $(call print_help_define_align, CONAN_OPTIONS, ${CONAN_OPTIONS}) + $(call print_help_define_align, BUILD_DIR, "$(BUILD_DIR)") + $(call print_help_define_align, BUILD_POLICY, "$(BUILD_POLICY)") + $(call print_help_define_align, BUILD_TYPE, "$(BUILD_TYPE)") + $(call print_help_define_align, CONAN_OPTIONS, "$(CONAN_OPTIONS)") echo $(call print_help_subsection, "Package information") - $(call print_help_define_align, PACKAGE_NAME, ${PACKAGE_NAME}) - $(call print_help_define_align, PACKAGE_VERSION, ${PACKAGE_VERSION}) - $(call print_help_define_align, PACKAGE_CHANNEL, ${PACKAGE_CHANNEL}) - $(call print_help_define_align, PACKAGE_FQN, ${PACKAGE_FQN}) - $(call print_help_define_align, PACKAGE_EDITABLE,${PACKAGE_EDITABLE}) - $(call print_help_define_align, PACKAGE_ID, ${PACKAGE_ID}) - $(call print_help_define_align, PACKAGE_DIR, ${PACKAGE_DIR}) - $(call print_help_define_align, PACKAGE_DATE, ${PACKAGE_DATE}) - $(call print_help_define_align, GIT_COMMIT_HASH, ${GIT_COMMIT_HASH}) + $(call print_help_define_align, PACKAGE_NAME, "$(PACKAGE_NAME)") + $(call print_help_define_align, PACKAGE_VERSION, "$(PACKAGE_VERSION)") + $(call print_help_define_align, PACKAGE_CHANNEL, "$(PACKAGE_CHANNEL)") + $(call print_help_define_align, PACKAGE_FQN, "$(PACKAGE_FQN)") + $(call print_help_define_align, PACKAGE_EDITABLE,"$(PACKAGE_EDITABLE)") + $(call print_help_define_align, PACKAGE_ID, "$(PACKAGE_ID)") + $(call print_help_define_align, PACKAGE_DIR, "$(PACKAGE_DIR)") + $(call print_help_define_align, PACKAGE_DATE, "$(PACKAGE_DATE)") + $(call print_help_define_align, GIT_COMMIT_HASH, "$(GIT_COMMIT_HASH)") echo .PHONY: parse-info .SILENT: parse-info -parse-info: ${BUILD_LOCKFILE} +parse-info: $(BUILD_LOCKFILE) # Fetch package information from Conan. # # This command takes long, so we won't run it by default. Instead, if any # target needs one of these variables, they should depend on this target # to ensure that these variables are set. # - $(eval PACKAGE_INFO := $(shell CONAN_REQUEST_TIMEOUT=0.1 conan info ${ALL_OPTIONS} "${PACKAGE_FQN}" --package-filter "${PACKAGE_FQN}" --paths 2>/dev/null | sed -r 's/$$/\\n/')) - $(eval PACKAGE_ID := $(shell echo -e "${PACKAGE_INFO}" | sed -rn 's/^ *ID: *(.*)$$/\1/p')) - $(eval PACKAGE_DIR := $(shell echo -e "${PACKAGE_INFO}" | sed -rn 's/^ *package_folder: *(.*)$$/\1/p')) - $(eval PACKAGE_DATE := $(shell echo -e "${PACKAGE_INFO}" | sed -rn 's/^ *Creation date: *(.*)$$/\1/p')) - -.PHONY: parse-editable -.SILENT: parse-editable -parse-editable: - $(eval PACKAGE_EDITABLE := $(shell [ -e ~/.conan/editable_packages.json ] && jq -r "${JQ_PACKAGE_EDITABLE}" ~/.conan/editable_packages.json || echo "not-editable")) + $(eval PACKAGE_INFO := $(shell CONAN_REQUEST_TIMEOUT=0.1 conan info $(ALL_OPTIONS) "$(PACKAGE_FQN)" --package-filter "$(PACKAGE_FQN)" --paths 2>/dev/null | sed -r 's/$$/\\n/')) + $(eval PACKAGE_ID := $(shell echo -e "$(PACKAGE_INFO)" | sed -rn 's/^ *ID: *(.*)$$/\1/p')) + $(eval PACKAGE_DIR := $(shell echo -e "$(PACKAGE_INFO)" | sed -rn 's/^ *package_folder: *(.*)$$/\1/p')) + $(eval PACKAGE_DATE := $(shell echo -e "$(PACKAGE_INFO)" | sed -rn 's/^ *Creation date: *(.*)$$/\1/p')) .PHONY: status .SILENT: status -status: parse-info parse-editable +status: parse-info # Show the *approximate* status of each package in the cloe workspace. # # This lets you know whether a package is in editable mode or not, @@ -260,61 +263,62 @@ status: parse-info parse-editable # directory has been modified more recently than the package in the # Conan cache. # - if [ "${PACKAGE_EDITABLE}" != "not-editable" ] ; then \ - echo "${PACKAGE_EDITABLE} : ${PACKAGE_FQN}"; \ + if [ "$(PACKAGE_EDITABLE)" != "not-editable" ] ; then \ + echo "$(PACKAGE_EDITABLE) : $(PACKAGE_FQN)"; \ else \ - if [ -n "${PACKAGE_DATE}" ] && [ -z "$$(find -type f -newermt "${PACKAGE_DATE}")" ]; then \ - echo "ok : ${PACKAGE_FQN}"; \ + if [ -n "$(PACKAGE_DATE)" ] && [ -z "$$(find -type f -newermt "$(PACKAGE_DATE)")" ]; then \ + echo "ok : $(PACKAGE_FQN)"; \ else \ - echo "outdated : ${PACKAGE_FQN}"; \ + echo "outdated : $(PACKAGE_FQN)"; \ fi \ fi .PHONY: info-name .SILENT: info-name info-name: - echo ${PACKAGE_NAME} + echo $(PACKAGE_NAME) .PHONY: info-version .SILENT: info-version info-version: - echo ${PACKAGE_VERSION} + echo $(PACKAGE_VERSION) .PHONY: info-channel .SILENT: info-channel info-channel: - echo ${PACKAGE_CHANNEL} + echo $(PACKAGE_CHANNEL) .PHONY: info-fqn .SILENT: info-fqn info-fqn: - echo ${PACKAGE_FQN} + echo $(PACKAGE_FQN) .PHONY: info .SILENT: info info: parse-info - if [ -z "${PACKAGE_INFO}" ]; then \ + if [ -z "$(PACKAGE_INFO)" ]; then \ echo "Errors occurred, no output available."; \ else \ - echo ${PACKAGE_INFO}; \ + echo $(PACKAGE_INFO); \ fi .PHONY: smoketest smoketest: # Ensure that you have built all smoketest dependencies! - @for conanfile in ${TEST_CONANFILES}; do \ + @for conanfile in $(TEST_CONANFILES); do \ test -f "$${conanfile}" || continue; \ printf "Running BATS tests with conanfile: $${conanfile}\n\n"; \ - SHELL=/bin/bash ${CLOE_LAUNCH} shell "$${conanfile}" ${CONAN_OPTIONS} -- -c "source ${PROJECT_ROOT}/tests/setup_testname.bash; bats tests"; \ + SHELL=/bin/bash $(CLOE_LAUNCH) shell "$${conanfile}" $(CONAN_OPTIONS) -- \ + -c "source $(PROJECT_ROOT)/tests/setup_testname.bash; bats $(TEST_DIR)"; \ done .PHONY: smoketest-deps smoketest-deps: # Ensure that you have exported all relevant packages! - @for conanfile in ${TEST_CONANFILES}; do \ + @for conanfile in $(TEST_CONANFILES); do \ test -f "$${conanfile}" || continue; \ echo "Building dependencies for conanfile: $${conanfile}"; \ - ${CLOE_LAUNCH} prepare "$${conanfile}" ${CONAN_OPTIONS} || break; \ + $(CLOE_LAUNCH) prepare "$${conanfile}" $(CONAN_OPTIONS) || exit 1; \ done # CONFIGURATION TARGETS ------------------------------------------------------- @@ -329,7 +333,7 @@ editable: # # Run `make uneditable` to leave this mode. # - conan editable add . ${PACKAGE_FQN} + conan editable add $(SOURCE_CONANFILE) $(PACKAGE_FQN) .PHONY: uneditable uneditable: @@ -338,17 +342,24 @@ uneditable: # In uneditable mode, Conan will use the package within the Conan cache # (normally located in ~/.conan/data). This is the default behavior. # - conan editable remove ${PACKAGE_FQN} + conan editable remove $(PACKAGE_FQN) # CONAN TARGETS --------------------------------------------------------------- +.PHONY: lockfile +lockfile: $(BUILD_LOCKFILE) + .PHONY: export -export: parse-editable +export: +ifneq (,$(filter $(PACKAGE_EDITABLE),not-editable editable-other-name)) # Export sources to Conan cache. # # This does not build this package but provides the sources and the # build recipe to Conan for on-demand building. # - if [ "${PACKAGE_EDITABLE}" = "not-editable" ] || [ "${PACKAGE_EDITABLE}" = "editable-other-name" ]; then conan export . ${PACKAGE_FQN}; fi + conan export $(SOURCE_CONANFILE) $(PACKAGE_FQN) +else + # Export sources to Conan cache: skipped (package is $(PACKAGE_EDITABLE)) +endif .PHONY: download download: @@ -362,11 +373,11 @@ download: # # See: https://docs.conan.io/en/latest/mastering/policies.html # - conan create . ${PACKAGE_FQN} --build=never ${ALL_OPTIONS} || \ - conan create . ${PACKAGE_FQN} --build=${BUILD_POLICY} --build=${PACKAGE_NAME} ${ALL_OPTIONS} + conan create $(SOURCE_CONANFILE) $(PACKAGE_FQN) --build=never $(ALL_OPTIONS) || \ + conan create $(SOURCE_CONANFILE) $(PACKAGE_FQN) --build=$(BUILD_POLICY) --build=$(PACKAGE_NAME) $(ALL_OPTIONS) .PHONY: package -package: ${BUILD_LOCKFILE} +package: $(BUILD_LOCKFILE) # Build the package in Conan cache unconditionally. # # Conan will retrieve and build all dependencies based on the build policy. @@ -374,8 +385,8 @@ package: ${BUILD_LOCKFILE} # # See: https://docs.conan.io/en/latest/mastering/policies.html # - conan create . ${PACKAGE_FQN} \ - --build=${BUILD_POLICY} --build=${PACKAGE_NAME} ${ALL_OPTIONS} + conan create $(SOURCE_CONANFILE) $(PACKAGE_FQN) \ + --build=$(BUILD_POLICY) --build=$(PACKAGE_NAME) $(ALL_OPTIONS) .PHONY: purge purge: @@ -385,43 +396,39 @@ purge: # has the same ID. Purging all instances is useful for forcing a rebuild # of all instances of this package henceforth. # - -conan remove -f ${PACKAGE_FQN} + -conan remove -f $(PACKAGE_FQN) .PHONY: list list: parse-info # List all files in the Conan cache package directory. # - @tree ${PACKAGE_DIR} + @tree $(PACKAGE_DIR) # IN-SOURCE TARGETS ----------------------------------------------------------- .PHONY: clean clean: # Clean the build directory and Python cache files. # - rm -rf "${BUILD_DIR}" - rm -rf __pycache__ - rm -f CMakeUserPresets.json - rm -f compile_commands.json - rm -f graph_info.json -ifeq (${CLEAN_SOURCE_DIR}, true) - [ "${SOURCE_DIR}" != "." ] && rm -rf "${SOURCE_DIR}" + rm -rf "$(BUILD_DIR)" __pycache__ CMakeUserPresets.json compile_commands.json graph_info.json +ifeq ($(CLEAN_SOURCE_DIR), true) + [ "$(SOURCE_DIR)" != "." ] && rm -rf "$(SOURCE_DIR)" endif -ifeq (${BUILD_IN_SOURCE}, false) +ifeq ($(BUILD_IN_SOURCE), false) .PHONY: all configure test export-pkg -all configure test export-pkg ${SOURCE_DIR} ${SOURCE_CMAKELISTS} ${BUILD_CONANINFO}: +all configure test export-pkg $(SOURCE_DIR) $(SOURCE_CMAKELISTS) $(BUILD_CONANINFO): @echo "Error: [in-source] targets are not supported for this package." @echo "Note: please use [conan-cache] targets, such as 'package'." exit 1 else .PHONY: all -all: ${BUILD_CONANINFO} | ${SOURCE_DIR} +all: $(BUILD_CONANINFO) | $(SOURCE_DIR) # Build the package in-source. # - conan build . --source-folder="${SOURCE_DIR}" --install-folder="${BUILD_DIR}" + conan build $(SOURCE_CONANFILE) --source-folder="$(SOURCE_DIR)" --install-folder="$(BUILD_DIR)" .PHONY: configure -configure: ${BUILD_CONANINFO} +configure: $(BUILD_CONANINFO) ln -rsf "$$(dirname $$(dirname $$(jq -r '.include[0]' CMakeUserPresets.json)))/compile_commands.json" .PHONY: test @@ -430,8 +437,8 @@ test: # # If no tests are available, this will simply return true. # - @if [ -f "${BUILD_DIR}"/CTestTestfile.cmake ]; then \ - cd "${BUILD_DIR}" && ctest; \ + @if [ -f "$(BUILD_DIR)"/CTestTestfile.cmake ]; then \ + cd "$(BUILD_DIR)" && ctest; \ else \ true; \ fi @@ -446,24 +453,24 @@ export-pkg: # # Note that this does not require the package to be editable. # - conan export-pkg . ${PACKAGE_FQN} --build-folder="${BUILD_DIR}" + conan export-pkg $(SOURCE_CONANFILE) $(PACKAGE_FQN) --build-folder="$(BUILD_DIR)" -${SOURCE_DIR}: +$(SOURCE_DIR): # Copy source to an external source directory. # # This usually isn't necessary, and should not be called when # SOURCE_DIR is identical to the current directory. # - [ "$(shell readlink -f "${SOURCE_DIR}")" != "$(shell readlink -f .)" ] - conan source . --source-folder="${SOURCE_DIR}" + [ "$(shell readlink -f "$(SOURCE_DIR)")" != "$(shell readlink -f .)" ] + conan source $(SOURCE_CONANFILE) --source-folder="$(SOURCE_DIR)" -${SOURCE_CMAKELISTS}: | ${SOURCE_DIR} +$(SOURCE_CMAKELISTS): | $(SOURCE_DIR) -${BUILD_CONANINFO}: ${SOURCE_CONANFILE} ${BUILD_LOCKFILE} ${SOURCE_CMAKELISTS} +$(BUILD_CONANINFO): $(SOURCE_CONANFILE) $(BUILD_LOCKFILE) $(SOURCE_CMAKELISTS) # Install package dependencies and configure in-source build. # - mkdir -p "${BUILD_DIR}" - conan install . ${PACKAGE_FQN} --install-folder="${BUILD_DIR}" --build=${BUILD_POLICY} ${ALL_OPTIONS} - conan build --configure . --source-folder="${SOURCE_DIR}" --install-folder="${BUILD_DIR}" - touch ${BUILD_CONANINFO} + mkdir -p "$(BUILD_DIR)" + conan install $(SOURCE_CONANFILE) $(PACKAGE_FQN) --install-folder="$(BUILD_DIR)" --build=$(BUILD_POLICY) $(ALL_OPTIONS) + conan build --configure $(SOURCE_CONANFILE) --source-folder="$(SOURCE_DIR)" --install-folder="$(BUILD_DIR)" + touch $(BUILD_CONANINFO) endif diff --git a/Makefile.setup b/Makefile.setup index d9ac0cb7..626d308d 100644 --- a/Makefile.setup +++ b/Makefile.setup @@ -13,9 +13,9 @@ SHELL := /bin/bash PROJECT_ROOT := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) CONAN_DIR := $(shell conan config home 2>/dev/null || echo "$HOME/.conan") CONAN_PROFILE := default -CONAN_PROFILE_PATH := ${CONAN_DIR}/profiles/${CONAN_PROFILE} +CONAN_PROFILE_PATH := $(CONAN_DIR)/profiles/$(CONAN_PROFILE) -include ${PROJECT_ROOT}/Makefile.help +include $(PROJECT_ROOT)/Makefile.help APT := $(or \ $(shell command -v apt 2>/dev/null), \ @@ -28,7 +28,7 @@ PIP := $(or \ $(shell command -v pip3 2>/dev/null), \ $(shell command -v pip 2>/dev/null) \ ) -ifeq (${VIRTUAL_ENV}, ) +ifeq ($(VIRTUAL_ENV), ) PIP_INSTALL_ARGS := --user --upgrade else PIP_INSTALL_ARGS := --upgrade @@ -37,8 +37,8 @@ endif PIPX := $(shell command -v pipx 2>/dev/null) PIPX_INSTALL_ARGS := ifndef PIPX -PIPX := ${PIP} -PIPX_INSTALL_ARGS := ${PIP_INSTALL_ARGS} +PIPX := $(PIP) +PIPX_INSTALL_ARGS := $(PIP_INSTALL_ARGS) endif .DEFAULT_GOAL := help @@ -49,9 +49,9 @@ help:: $(call print_help_target, setup-git, "perform Git repository setup") $(call print_help_target, setup-conan, "install Conan profile") $(call print_help_target, install-system-deps, "install build (and development) system requirements") - $(call print_help_target, install-python-deps, "install Python runtime requirements with ${_dim}${PIP}${_rst}") - $(call print_help_target, install-sphinx-deps, "install Sphinx runtime requirements with ${_dim}${PIP}${_rst}") - $(call print_help_target, install-python-tools, "install Python development tools with ${_dim}${PIPX}${_rst}") + $(call print_help_target, install-python-deps, "install Python runtime requirements with $(_dim)$(PIP)$(_rst)") + $(call print_help_target, install-sphinx-deps, "install Sphinx runtime requirements with $(_dim)$(PIP)$(_rst)") + $(call print_help_target, install-python-tools, "install Python development tools with $(_dim)$(PIPX)$(_rst)") echo .PHONY: setup-git @@ -61,17 +61,17 @@ setup-git: .PHONY: setup-conan setup-conan: # Install Conan if it is not available. - if ! command -v conan >/dev/null 2>&1; then ${PIP} install --user --upgrade "conan<2"; fi + if ! command -v conan >/dev/null 2>&1; then $(PIP) install --user --upgrade "conan<2"; fi # Initialize Conan configuration if it doesn't already exist. # - # Since running any conan command, even conan --help creates ${CONAN_DIR} + # Since running any conan command, even conan --help creates $(CONAN_DIR) # and the default configuration, we rely on the existence of the default # profile as an indication that we have a "fresh" setup where we can # make our override. - if [ ! -f ${CONAN_PROFILE_PATH} ]; then \ + if [ ! -f $(CONAN_PROFILE_PATH) ]; then \ conan config init; \ - conan profile update settings.compiler.libcxx=libstdc++11 ${CONAN_PROFILE}; \ - conan profile update settings.build_type=Debug ${CONAN_PROFILE}; \ + conan profile update settings.compiler.libcxx=libstdc++11 $(CONAN_PROFILE); \ + conan profile update settings.build_type=Debug $(CONAN_PROFILE); \ fi if ! conan config get general.default_build_profile >/dev/null 2>&1; then \ conan config set general.default_build_profile=default; \ @@ -80,15 +80,15 @@ setup-conan: conan config set general.revisions_enabled=True; \ fi # Install cloe-{debug,normal,release} profiles. - for profile in "${PROJECT_ROOT}"/dist/conan/*.profile; do \ + for profile in "$(PROJECT_ROOT)"/dist/conan/*.profile; do \ export profile_name=$$(basename -s .profile $${profile}); \ - install -m 644 "$${profile}" "${CONAN_DIR}/profiles/$${profile_name}"; \ - sed -r -i "s/default/${CONAN_PROFILE}/" "${CONAN_DIR}/profiles/$${profile_name}"; \ + install -m 644 "$${profile}" "$(CONAN_DIR)/profiles/$${profile_name}"; \ + sed -r -i "s/default/$(CONAN_PROFILE)/" "$(CONAN_DIR)/profiles/$${profile_name}"; \ done # Ensure we have an up-to-date CMake configured. if [ $$(( cmake --version | head -1 | cut -f3 -d' '; echo "3.14.99" ) | sort -V | tail -1) = "3.14.99" ]; then \ - if ! grep "cmake/" ${CONAN_PROFILE_PATH} >/dev/null; then \ - echo -e "[tool_requires]\ncmake/[>=3.15.0]" >> ${CONAN_PROFILE_PATH}; \ + if ! grep "cmake/" $(CONAN_PROFILE_PATH) >/dev/null; then \ + echo -e "[tool_requires]\ncmake/[>=3.15.0]" >> $(CONAN_PROFILE_PATH); \ fi; \ fi @@ -102,8 +102,8 @@ endif .PHONY: install-ubuntu-deps install-ubuntu-deps:: - command -v ${APT} >/dev/null 2>&1 - ${APT} install ${APT_ARGS} \ + command -v $(APT) >/dev/null 2>&1 + $(APT) install $(APT_ARGS) \ bats \ build-essential \ clang-format \ @@ -129,8 +129,8 @@ install-ubuntu-deps:: ; # Require GCC and G++ version >= 8 - if [ "${UBUNTU_VERSION}" == "18.04" ]; then \ - ${APT} install ${APT_ARGS} gcc-8 g++-8; \ + if [ "$(UBUNTU_VERSION)" == "18.04" ]; then \ + $(APT) install $(APT_ARGS) gcc-8 g++-8; \ if [ $$(readlink /usr/bin/g++) == "g++-7" ]; then \ ln -sf /usr/bin/g++-8 /usr/bin/g++ && \ ln -sf /usr/bin/gcc-8 /usr/bin/gcc; \ @@ -140,8 +140,8 @@ install-ubuntu-deps:: # Python ---------------------------------------------------------------------- .PHONY: install-python-deps install-python-deps:: - command -v ${PIP} >/dev/null 2>&1 - ${PIP} install ${PIP_INSTALL_ARGS} \ + command -v $(PIP) >/dev/null 2>&1 + $(PIP) install $(PIP_INSTALL_ARGS) \ click \ "conan<2.0.0" \ libtmux \ @@ -151,12 +151,12 @@ install-python-deps:: .PHONY: install-sphinx-deps install-sphinx-deps: - command -v ${PIP} >/dev/null 2>&1 - ${PIP} install ${PIP_INSTALL_ARGS} -r docs/requirements.txt + command -v $(PIP) >/dev/null 2>&1 + $(PIP) install $(PIP_INSTALL_ARGS) -r docs/requirements.txt .PHONY: install-python-tools install-python-tools:: - command -v ${PIPX} >/dev/null 2>&1 + command -v $(PIPX) >/dev/null 2>&1 for pkg in \ black \ mypy \ @@ -166,5 +166,5 @@ install-python-tools:: yq \ ; \ do \ - ${PIPX} install ${PIPX_INSTALL_ARGS} $${pkg}; \ + $(PIPX) install $(PIPX_INSTALL_ARGS) $${pkg}; \ done