Home > Software engineering >  How to copy all prerequisites to a certain folder in a Makefile?
How to copy all prerequisites to a certain folder in a Makefile?

Time:10-26

I want to copy all prerequisites into a folder to then process them there. I have tried a shell for loop, but the syntax seems to be different

for f in $^; do cp $f some/folder/; done

I also tried the foreach loop from GNU make

$(foreach f,$^,cp $f some/folder/)

I have found this explanation, but I don't really understand it

make: execute an action for each prerequisite

Here is my recipe

CURRENT := $(PWD)
IMAGE_TREE_SOURCE := ./device/layer/kernelFitImage.its
FIT_PREREQUISITES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/arch/$(TARGET_KERNEL_ARCH)/boot/Image \
                     $(PRODUCT_OUT)/ramdisk-recovery.img \
                     $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/arch/$(TARGET_KERNEL_ARCH)/boot/dts/freescale/imx8mm-gpv-distec.dtb \
                     $(IMAGE_TREE_SOURCE)
FIT_IMAGE_TARGET := $(PRODUCT_OUT)/boot/fitImage
$(FIT_IMAGE_TARGET): $(FIT_PREREQUISITES)
    echo "Creating FIT image"
    mkdir -p $(dir $@)
    # for f in $^; do $$f $(PRODUCT_OUT)/boot; done
    cd $(PRODUCT_OUT)/boot
    cp $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/arch/$(TARGET_KERNEL_ARCH)/boot/Image .
    cp $(PRODUCT_OUT)/ramdisk-recovery.img .
    cp $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/arch/$(TARGET_KERNEL_ARCH)/boot/dts/freescale/imx8mm-gpv-distec.dtb .
    cp $(IMAGE_TREE_SOURCE) .
    mkimage -f kernelFitImage.its $@
    rm ./Image 
    rm ./ramdisk-recovery.img
    rm ./imx8mm-gpv-distec.dtb
    rm ./kernelFitImage.its
    cd $(CURRENT)

I am trying to substitute all the copy statements to clean this recipe up a bit.

CodePudding user response:

You don't need a loop; why can't you just use cp $^ $(PRODUCT_OUT)/boot ? However, the for loop DOES work. If you go look in the directory after the failure, don't you see the files you copied there? If something is failing you'll have to look for some other problem.

I will point out that unless you're setting oneshell in your makefile, this can't work:

cd $(PRODUCT_OUT)/boot
cp $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/arch/$(TARGET_KERNEL_ARCH)/boot/Image .
 ...

Every individual logical line in a recipe is run in a separate shell. So after each line is complete, the shell exits (so make knows what its exit code is and whether it failed or not). When that happens all context local to the shell which includes environment variables and the working directory, are thrown away.

So, the cd ... line above is a no-op: it will change to the directory in a subshell, then the subshell exits and you're back where you started. The next shell will still be in the original directory.

You have to turn this into a single logical line, by adding semicolons and backslashes:

cd $(PRODUCT_OUT)/boot; \
cp $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/arch/$(TARGET_KERNEL_ARCH)/boot/Image .; \
 ...
  • Related