From 0ac03b6150d0f95ffbb8894c16d1222a6001a6a0 Mon Sep 17 00:00:00 2001 From: nosamad <48175289+nosamad@users.noreply.github.com> Date: Thu, 28 Mar 2019 07:43:21 +0100 Subject: [PATCH] feat(webfuse): eclipse cdt project (#17) adds convenience run and discovery targets (for first build target) allows usage of host container (volume mount/ dind) fixes portable workspace configuration adds makefile targets to CDT configuration fixes localization * adds eclipse-cdt project and necessary discovery for toolchain settings * extends targets and fixes discovery * renames CDT Eclipse project * enables portable workspace docker-build on build server --- .cproject | 117 ++++++++++++++++ .project | 27 ++++ .settings/language.settings.xml | 15 ++ .settings/org.eclipse.cdt.core.prefs | 12 ++ .travis.yml | 1 + Makefile | 173 ++++++++++++++++-------- build/amd64-ubuntu-builder.dockerfile | 10 +- build/arm32v7-ubuntu-builder.dockerfile | 10 +- build/discover_cc_settings.sh | 56 ++++++++ build/get_container_id.sh | 39 ++++++ build/get_source_date_epoch.sh | 18 +-- 11 files changed, 408 insertions(+), 70 deletions(-) create mode 100644 .cproject create mode 100644 .project create mode 100644 .settings/language.settings.xml create mode 100644 .settings/org.eclipse.cdt.core.prefs create mode 100755 build/discover_cc_settings.sh create mode 100755 build/get_container_id.sh diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..ca3f25c --- /dev/null +++ b/.cproject @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + + check + true + true + true + + + make + + memcheck + true + true + true + + + make + + distclean + true + true + true + + + make + + discover-cc + true + true + true + + + make + + all + true + true + true + + + make + + lint + true + true + true + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..ccf5306 --- /dev/null +++ b/.project @@ -0,0 +1,27 @@ + + + webfuse + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml new file mode 100644 index 0000000..dc364b8 --- /dev/null +++ b/.settings/language.settings.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..7ab0c7a --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/BUILDTARGET/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/BUILDTARGET/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/BUILDTARGET/value=amd64-ubuntu-builder +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/BUILDVERBOSE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/BUILDVERBOSE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/BUILDVERBOSE/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/VERBOSE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/VERBOSE/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/VERBOSE/value= +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/append=true +environment/project/cdt.managedbuild.toolchain.gnu.base.2091678410/appendContributed=true diff --git a/.travis.yml b/.travis.yml index 52dbbc9..d0cb055 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ before_install: env: global: - PARALLELMFLAGS="-j2" + - PORTABLE_WORSPACE=1 matrix: - MARCH=amd64 CHECK_TARGET=memcheck - MARCH=arm32v7 CHECK_TARGET=check diff --git a/Makefile b/Makefile index c1a6f2c..235d7f9 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +PARALLELMFLAGS ?= -j$(shell nproc) +MAKEFLAGS += $(PARALLELMFLAGS) --no-builtin-rules + .PHONY: default default: all @@ -5,24 +8,33 @@ default: all export SOURCE_DATE_EPOCH ?= $(shell $(PROJECT_ROOT)/build/get_source_date_epoch.sh) export BUILDTIME ?= $(shell date -u -d '@$(SOURCE_DATE_EPOCH)' --rfc-3339 ns 2>/dev/null | sed -e 's/ /T/') +export DOCKER ?= docker + +DOCKER_BUILDKIT ?= -VERBOSE ?= -MARCH ?= +VERBOSE ?= +BUILDVERBOSE ?= +BUILDTARGET ?= +MARCH ?= $(call march,$(BUILDTARGET)) PROJECT_NAME ?= webfuse PROJECT_ROOT ?= . VERSION ?= $(shell cat $(PROJECT_ROOT)/VERSION) OUT ?= $(PROJECT_ROOT)/.build -PARALLELMFLAGS ?= -j$(shell nproc) UID ?= $(shell id -u) -DOCKER ?= docker -DOCKER_BUILDKIT ?= - CONTAINER_USER ?= $(UID) CONTAINER_GROUP ?= $(shell id -g) -CONTAINER_WORKSPACE ?= /workspace + +HOST_CONTAINER ?= $(shell $(PROJECT_ROOT)/build/get_container_id.sh) +HOST_CONTAINER := $(HOST_CONTAINER) + +$(HOST_CONTAINER)PORTABLE_WORSPACE ?= +CONTAINER_PROJECT_ROOT ?= /workspace/src +CONTAINER_OUT ?= /workspace/out +$(PORTABLE_WORSPACE)CONTAINER_PROJECT_ROOT = $(abspath $(PROJECT_ROOT)) +$(PORTABLE_WORSPACE)CONTAINER_OUT = $(abspath $(OUT)) UBUNTU_CODENAME ?= bionic @@ -54,6 +66,11 @@ $(OUT)/docker/qemu-arm-static-$(QEMU_VERSION): URL := https://github.com/multiar # Architecture-specific rule target configuration +march = $(shell echo '$1' | sed -n -e 's@\([^-]*\)-.*@\1@p') + +TARGETS += $(BUILDTARGET) +MARCH := $(MARCH) + MARCH_AMD64 := $(filter-out amd64,$(MARCH)) $(MARCH_AMD64)MARCHS += amd64 $(MARCH_AMD64)TARGETS += amd64-ubuntu-builder @@ -74,9 +91,10 @@ $(addprefix $(OUT)/docker/,$(UBUNTU_TARGETS)): CODENAME := $(UBUNTU_CODENAME) # Common rule target configuration -MAKEFLAGS += $(PARALLELMFLAGS) --no-builtin-rules +CMAKEFLAGS += '-GNinja' -CMAKEFLAGS += -GNinja +BUILDSILENT := $(if $(BUILDVERBOSE),,1) +$(BUILDSILENT)NINJAFLAGS += -v DOCKER_RUNFLAGS += --interactive DOCKER_RUNFLAGS += --rm @@ -85,11 +103,14 @@ DOCKER_RUNFLAGS += --user $(CONTAINER_USER):$(CONTAINER_GROUP) DOCKER_RUNFLAGS += --device /dev/fuse --cap-add SYS_ADMIN --security-opt apparmor:unconfined DOCKER_RUNFLAGS += --env SOURCE_DATE_EPOCH DOCKER_RUNFLAGS += --env BUILDTIME +DOCKER_RUNFLAGS += --env NINJA_STATUS +DOCKER_RUNFLAGS += $(addprefix --volumes-from ,$(HOST_CONTAINER)) DOCKER_BUILDARGS += CODENAME=$(CODENAME) DOCKER_BUILDARGS += PARALLELMFLAGS=$(PARALLELMFLAGS) DOCKER_BUILDARGS += USERID=$(UID) -DOCKER_BUILDARGS += WORKSPACE=$(CONTAINER_WORKSPACE) +DOCKER_BUILDARGS += PROJECT_ROOT=$(CONTAINER_PROJECT_ROOT) +DOCKER_BUILDARGS += OUT=$(CONTAINER_OUT) DOCKER_BUILDFLAGS += --rm DOCKER_BUILDFLAGS += $(addprefix --build-arg ,$(DOCKER_BUILDARGS)) @@ -101,16 +122,13 @@ OUT_DIRS += $(addprefix $(OUT)/,$(TARGETS)) BUILD_TARGETS += $(addprefix build-,$(TARGETS)) CHECK_TARGETS += $(addprefix check-,$(TARGETS)) +CLEAN_TARGETS += $(addprefix clean-,$(TARGETS)) +RUN_TARGETS += $(addprefix run-,$(firstword $(TARGETS))) EXTRACT_TARGETS += $(patsubst $(OUT)/%.tar.gz,$(OUT)/src/%,$(FETCH_TARGETS)) +DISCOVER_CC_TARGETS += $(addprefix discover-cc-,$(firstword $(TARGETS))) RULE_TARGETS = $(addprefix $(OUT)/,$(addsuffix /rules.mk,$(TARGETS))) -BUILD_TARGETS := $(BUILD_TARGETS) -CHECK_TARGETS := $(CHECK_TARGETS) -MEMCHECK_TARGETS := $(MEMCHECK_TARGETS) -CONTAINER_GROUP := $(CONTAINER_GROUP) -VERSION := $(VERSION) -PROJECT_ROOT := $(PROJECT_ROOT) -OUT := $(OUT) +TARGETS := $(sort $(TARGETS)) # Macros @@ -118,36 +136,67 @@ echo_if_silent = VERBOSE=1 $(VERBOSE)echo_if_silent = echo $1 $(VERBOSE)SILENT := @ -image_rule = $$(OUT)/docker/$1: $$(OUT)/docker/$1.dockerfile $$(EXTRACT_TARGETS) $$(PROJECT_ROOT)/Makefile; $$(call image,$1) +$(HOST_CONTAINER)container_run_volumes += '$(realpath $(PROJECT_ROOT)):$(CONTAINER_PROJECT_ROOT):cached' +$(HOST_CONTAINER)container_run_volumes += '$(realpath $(OUT)/$1):$(CONTAINER_OUT)/$1:delegated' + +container_run = $(DOCKER) run $(DOCKER_RUNFLAGS) $3 \ + $(addprefix --volume ,$(call container_run_volumes,$1)) \ + --workdir '$(CONTAINER_OUT)/$1' \ + $(PROJECT_NAME)-$1:$(VERSION) \ + $2 + +image_rule = \ + $$(OUT)/docker/$1: $$(OUT)/docker/$1.dockerfile $$(EXTRACT_TARGETS) $$(PROJECT_ROOT)/Makefile; \ + $$(call image,$1) image = $(SILENT) \ $(call echo_if_silent,docker build $(PROJECT_NAME)-$1:$(VERSION) $(OUT)) \ && $(DOCKER) build $(DOCKER_BUILDFLAGS) --iidfile $@ --file $< --tag $(PROJECT_NAME)-$1:$(VERSION) $(OUT) -run_rule = run-$1: $$(OUT)/docker/$1; $$(call run,$1,/bin/bash,--tty) -run = $(SILENT) \ - $(call echo_if_silent,TARGET=$1 $2) \ - && $(DOCKER) run $(DOCKER_RUNFLAGS) $3 \ - --volume '$(realpath $(PROJECT_ROOT)):$(CONTAINER_WORKSPACE)' \ - --volume '$(realpath $(OUT)/$1):$(CONTAINER_WORKSPACE)/$(notdir $(OUT))' \ - --workdir '$(CONTAINER_WORKSPACE)/$(notdir $(OUT))' \ - $(PROJECT_NAME)-$1:$(VERSION) \ - $2 - -configure_rule = $$(OUT)/$1/CMakeCache.txt: $$(PROJECT_ROOT)/CMakeLists.txt $$(OUT)/docker/$1; $$(call configure,$1) -configure = $(call run,$1,cmake $(CMAKEFLAGS) ..) && touch $@ - -build_rule = build-$1: $$(OUT)/$1/CMakeCache.txt; $$(call build,$1) -build = $(call run,$1,ninja $(PARALLELMFLAGS) $(GLOAS)) - -check_rule = check-$1: build-$1; $$(call check,$1) -check = $(call run,$1,ctest $(CTESTFLAGS)) - -memcheck_rule = memcheck-$1: build-$1; $$(call memcheck,$1) -memcheck = $(call run,$1,ctest -T memcheck $(CTESTFLAGS)) +run_rule = \ + run-$1: $$(OUT)/docker/$1; \ + $$(call run_recipe,$1,/bin/bash,--tty) +run = $(call echo_if_silent,TARGET=$1 $2) && $(call container_run,$1,$2,$3) +run_recipe = $(SILENT)-$(call run,$1,$2,$3) + +configure_rule = \ + $$(OUT)/$1/CMakeCache.txt: $$(PROJECT_ROOT)/CMakeLists.txt $$(OUT)/docker/$1; \ + $$(call configure,$1) +configure = $(SILENT) \ + $(call run,$1,sh -c 'cmake $(CMAKEFLAGS) $(CONTAINER_PROJECT_ROOT) && $(CONTAINER_PROJECT_ROOT)/build/discover_cc_settings.sh $(notdir $@) $(realpath $(dir $@))') \ + && touch $@ + +build_rule = \ + build-$1: $$(OUT)/$1/CMakeCache.txt; \ + $$(call build,$1) +build = $(SILENT)$(call run,$1,ninja $(PARALLELMFLAGS) $(NINJAFLAGS) $(GOALS)) + +check_rule = \ + check-$1: build-$1; + +memcheck_rule = \ + memcheck-$1: build-$1; \ + $$(call memcheck,$1) +memcheck = $(SILENT)$(call run,$1,ctest -T memcheck $(CTESTFLAGS)) + +discover_cc_settings_rule = \ + $$(OUT)/$1/include_dirs.txt: $$(OUT)/$1/CMakeCache.txt; \ + $$(call discover_cc_settings,$1) +discover_cc_settings = $(SILENT) \ + $(call run,$1,$(CONTAINER_PROJECT_ROOT)/build/discover_cc_settings.sh $(notdir $<) $(realpath $(dir $<))) + +discover_cc_rule = \ + discover-cc-$1: $$(OUT)/$1/include_dirs.txt; \ + $$(call discover_cc,$1) +discover_cc = $(SILENT)cat $< + +clean_rule = \ + clean-$1: ; \ + $$(call clean,$1) +clean = $(SILENT)-rm -rf $(OUT)/$1 # Rules -ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),distclean) -include $(RULE_TARGETS) endif @@ -166,28 +215,47 @@ $(RULE_TARGETS): $(PROJECT_ROOT)/Makefile | $(OUT_DIRS) echo '$(call memcheck_rule,$(TARGET))'; \ echo; \ echo '$(call run_rule,$(TARGET))'; \ + echo; \ + echo '$(call discover_cc_settings_rule,$(TARGET))'; \ + echo; \ + echo '$(call discover_cc_rule,$(TARGET))'; \ + echo; \ + echo '$(call clean_rule,$(TARGET))'; \ } > $@ -.PHONY: all -all: $(BUILD_TARGETS) +.PHONY: all build-% +all: $(BUILD_TARGETS); -.PHONY: check -check: $(CHECK_TARGETS) +.PHONY: check check-% +check: $(CHECK_TARGETS); -.PHONY: memcheck -memcheck: $(MEMCHECK_TARGETS) +.PHONY: memcheck memcheck-% +memcheck: $(MEMCHECK_TARGETS); -.PHONY: clean -clean: $(CLEAN_TARGETS) - $(SILENT)-rm -rf $(OUT_DIRS) +.PHONY: lint lint-% +lint: $(LINT_TARGETS); + +.PHONY: run run-% +run: $(RUN_TARGETS); + +.PHONY: clean clean-% +clean: $(CLEAN_TARGETS); + +.PHONY: get-deps get-deps-% +get-deps: $(EXTRACT_TARGETS); -.PHONY: get-deps -get-deps: $(EXTRACT_TARGETS) +.PHONY: discover-cc discover-cc-% +discover-cc: $(DISCOVER_CC_TARGETS); + +.PHONY: distclean +distclean: + $(SILENT)-rm -rf $(OUT_DIRS) .PHONY: debug-print-% debug-print-%: @printf '%s\n' '$*:' $($*) +$(CHECK_TARGETS): GOALS := test $(CHECK_TARGETS) $(MEMCHECK_TARGETS): CONTAINER_USER := user $(OUT)/docker/qemu-arm-static-$(QEMU_VERSION): @@ -211,6 +279,3 @@ $(OUT)/src/%: $(OUT)/%.tar.gz | $(OUT_DIRS) $(OUT_DIRS): $(SILENT)mkdir -p $@ -.PRECIOUS: $(OUT)/docker/% $(OUT)/%/CMakeCache.txt -.DELETE_ON_ERROR: $(OUT)/%/CMakeCache.txt - diff --git a/build/amd64-ubuntu-builder.dockerfile b/build/amd64-ubuntu-builder.dockerfile index 6e98aed..543b826 100644 --- a/build/amd64-ubuntu-builder.dockerfile +++ b/build/amd64-ubuntu-builder.dockerfile @@ -10,6 +10,7 @@ RUN set -x \ cmake \ ninja-build \ pkg-config \ + rsync \ valgrind \ && rm -rf /var/lib/apt/lists/* @@ -70,12 +71,13 @@ ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" ARG USERID=1000 -ARG WORKSPACE=/workspace +ARG PROJECT_ROOT=/workspace/src +ARG OUT=/workspace/out RUN set -x \ && useradd -u "$USERID" -ms /bin/bash user \ - && mkdir -p "$WORKSPACE" \ - && chown user:user "$WORKSPACE" + && mkdir -p "$PROJECT_ROOT" "$OUT" \ + && chown user:user "$PROJECT_ROOT" "$OUT" -WORKDIR "$WORKSPACE" +WORKDIR "$OUT" diff --git a/build/arm32v7-ubuntu-builder.dockerfile b/build/arm32v7-ubuntu-builder.dockerfile index d706488..f605e0c 100644 --- a/build/arm32v7-ubuntu-builder.dockerfile +++ b/build/arm32v7-ubuntu-builder.dockerfile @@ -12,6 +12,7 @@ RUN set -x \ cmake \ ninja-build \ pkg-config \ + rsync \ && rm -rf /var/lib/apt/lists/* COPY src /usr/local/src @@ -71,12 +72,13 @@ ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" ARG USERID=1000 -ARG WORKSPACE=/workspace +ARG PROJECT_ROOT=/workspace/src +ARG OUT=/workspace/out RUN set -x \ && useradd -u "$USERID" -ms /bin/bash user \ - && mkdir -p "$WORKSPACE" \ - && chown user:user "$WORKSPACE" + && mkdir -p "$PROJECT_ROOT" "$OUT" \ + && chown user:user "$PROJECT_ROOT" "$OUT" -WORKDIR "$WORKSPACE" +WORKDIR "$OUT" diff --git a/build/discover_cc_settings.sh b/build/discover_cc_settings.sh new file mode 100755 index 0000000..61a08fd --- /dev/null +++ b/build/discover_cc_settings.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +set -e + +export LANG=C +export LC_ALL=C + +cleanup() { + rm -rf "$INCLUDE_DIRS_TMPFILE" +} + +trap cleanup TERM INT EXIT + +DEST="${DEST:-$PWD}" + +CMAKE_CACHE_FILE="${1:-CMakeCache.txt}" +CMAKE_CXX_COMPILER="$(sed -n -e 's/CMAKE_CXX_COMPILER:FILEPATH=\(.*\)$/\1/p' "$CMAKE_CACHE_FILE")" +CMAKE_C_COMPILER="$(sed -n -e 's/CMAKE_C_COMPILER:FILEPATH=\(.*\)$/\1/p' "$CMAKE_CACHE_FILE")" + +INCLUDE_DIRS_PREFIX="${2:-$DEST}" +INCLUDE_DIRS_TMPFILE="$(mktemp -p "$DEST" include_dirs_XXXXXXXXXX.txt)" +INCLUDE_DIRS_FILE="${INCLUDE_DIRS_FILE:-$DEST/include_dirs.txt}" + +C_BUILTIN_FILE="${C_BUILTIN_FILE:-$DEST/builtins.h}" +CXX_BUILTIN_FILE="${CXX_BUILTIN_FILE:-$DEST/builtins.hpp}" + +if [ -z "${RSYNC+x}" ]; then + RSYNC=rsync +fi + +{ + { + echo | "$CMAKE_CXX_COMPILER" -xc++ -E -Wp,-v - 2>&1; + echo | "$CMAKE_C_COMPILER" -xc -E -Wp,-v - 2>&1; + } \ + | sed -n -e 's/\s\+\(\/.*$\).*/\1/p'; + + sed -n -e 's/.*_INCLUDE_DIRS:INTERNAL=\(.*\)$/\1/p' "$CMAKE_CACHE_FILE"; +} \ +| sed 's/;/\n/g' | sed '/^$/d' | sort -u 2>/dev/null 1> "$INCLUDE_DIRS_TMPFILE" + +{ + echo '#include <...> search starts here:' + sed -n -e "s@\(.*\)@$INCLUDE_DIRS_PREFIX\1@p" "$INCLUDE_DIRS_TMPFILE" + echo 'End of search list.' +} > "$INCLUDE_DIRS_FILE" + +if [ -n "$RSYNC" ]; then + "$RSYNC" -arR --files-from="$INCLUDE_DIRS_TMPFILE" / "$DEST" + echo "Include folders copied to $DEST" >&2 +fi + +"$CMAKE_C_COMPILER" -xc -dM -E - < /dev/null > "$C_BUILTIN_FILE" +echo "C Compiler built-ins written to $C_BUILTIN_FILE" >&2 +"$CMAKE_CXX_COMPILER" -xc++ -dM -E - < /dev/null > "$CXX_BUILTIN_FILE" +echo "C++ Compiler built-ins written to $CXX_BUILTIN_FILE" >&2 diff --git a/build/get_container_id.sh b/build/get_container_id.sh new file mode 100755 index 0000000..d262287 --- /dev/null +++ b/build/get_container_id.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +set -e + +container_id() { + if [ "$#" -le 0 ]; then + # shellcheck disable=SC2119 + container_id_by_cgroup + else + "$DOCKER" inspect --format='{{.Id}}' "$@" + fi +} + +# shellcheck disable=SC2120 +container_id_by_cgroup() { + impl_container_id_by_cgroup "$@" || return "$?" +} + +impl_container_id_by_cgroup() { + file="${1:-/proc/self/cgroup}" + + while IFS= read -r cmd; do + id="$(echo "$cmd" | sed -n -e 's/[^:]*:[^:]*:.*\/\([0-9a-fA-F]\+\)$/\1/p')" + if container_id "$id" >/dev/null 2>&1; then + echo "$id" + return 0 + fi + done < "$file" + + return 1 +} + +DOCKER="${DOCKER:-docker}" + +if [ -z "${CONTAINER+x}" ] && [ -n "$DOCKER" ]; then + CONTAINER="$(container_id "$@")" || true +fi + +echo "$CONTAINER" diff --git a/build/get_source_date_epoch.sh b/build/get_source_date_epoch.sh index a8bb69a..1e3dada 100755 --- a/build/get_source_date_epoch.sh +++ b/build/get_source_date_epoch.sh @@ -1,25 +1,27 @@ #!/bin/sh +set -e + export LANG=C export LC_ALL=C [ -n "$TOPDIR" ] && cd "$TOPDIR" try_git() { - [ -e .git ] || return 1 - SOURCE_DATE_EPOCH="$(git log -1 --format=format:%ct)" - [ -n "$SOURCE_DATE_EPOCH" ] + [ -e .git ] || return 1 + SOURCE_DATE_EPOCH="$(git log -1 --format=format:%ct)" + [ -n "$SOURCE_DATE_EPOCH" ] } try_hg() { - [ -d .hg ] || return 1 - SOURCE_DATE_EPOCH="$(hg log --template '{date}' -l 1 | cut -d. -f1)" - [ -n "$SOURCE_DATE_EPOCH" ] + [ -d .hg ] || return 1 + SOURCE_DATE_EPOCH="$(hg log --template '{date}' -l 1 | cut -d. -f1)" + [ -n "$SOURCE_DATE_EPOCH" ] } try_mtime() { - perl -e 'print((stat $ARGV[0])[9])' "$0" - [ -n "$SOURCE_DATE_EPOCH" ] + perl -e 'print((stat $ARGV[0])[9])' "$0" + [ -n "$SOURCE_DATE_EPOCH" ] } try_git || try_hg || try_mtime || SOURCE_DATE_EPOCH=""