Home > Net >  The order of execution in Makefile - "rm -rf" does not finish on time?
The order of execution in Makefile - "rm -rf" does not finish on time?

Time:02-01

Makefile:

# Defines

BUILD_PATH ?= out
REPO_NAME ?= my_work_dir
REPO_URL ?= [email protected]:your_org/your_repo
REPO_BRANCH  := main

### Functions

define clone_repository
    echo Cloning repository...
    git -C $(1) init --quiet
    git -C $(1) remote add origin $(2)
    git -C $(1) fetch origin --progress --quiet --depth 1 $(3)
    git -C $(1) reset --quiet --hard FETCH_HEAD
endef

define get_sha1
    $(2):=$(shell git -C $(1) rev-parse HEAD)
endef

### Targets

do_the_work:
    # Prepare
    rm -rf $(BUILD_PATH)/$(REPO_NAME)
    mkdir -p $(BUILD_PATH)/$(REPO_NAME)
    # Clone
    $(call clone_repository,$(BUILD_PATH)/$(REPO_NAME),$(REPO_URL),$(REPO_BRANCH))
    # SHA1
    $(eval $(call get_sha1,$(BUILD_PATH)/$(REPO_NAME),REPO_BRANCH_SHA1))
    # Do...
    # do_something --sha1 REPO_BRANCH_SHA1

What I tried to do in the do_the_work is:

  • Step 1: create an empty dir
  • Step 2: clone repository
  • Step 3: get sha1 from repository
  • Step 4: do something with sha1 info

However, when I execute the do_the_work, I get error (please not that $(BUILD_PATH)/$(REPO_NAME) evaluates to out/my_work_dir):

fatal: cannot change to 'out/my_work_dir': No such file or directory
rm -rf out/my_work_dir
mkdir -p out/my_work_dir
echo Cloning repository...
.
.
.
etc

But, when I run the same command again, it executes OK! Is this because the out/my_work_dir is in place already? It also works if the dir is completely empty.

Seems like the Step 3 $(eval $(call get_sha1...) executed before the Step 1 mkdir finished? How do I fix this?

To me it seems that rm -rf gets prolonged if the dir does not exist at all.

CodePudding user response:

The error is in the $(shell ...) invocation in define get_sha1 which runs when you define the function, not when you call it.

This seems like an overcomplication anyway; I would simply get rid of the define and replace the recipe with one where the result is stored in a shell variable.

do_the_work:
    ...
    # SHA1
    sha1=$$(git -C $(BUILD_PATH)/$(REPO_NAME) rev-parse HEAD); \
    # Do...
    # do_something --sha1 "$$sha1"
  • Related