Copying a bunch of files with GNU make

Let's say I have a makefile where I want to copy multiple files from one location to another, for example:

  • include/mylib/mylib.h

    to dist/include/mylib/mylib.h

  • include/mylib/platform/linux/platform.h

    to dist/include/mylib/platform.h

This is part of the installation rule. What comes to my mind is something like:

EXTRA_INSTALL += include/mylib/mylib.h=dist/include/mylib/mylib.h
EXTRA_INSTALL += include/mylib/platform/linux/platform.h=dist/include/mylib/platform.h

# All other dependecies (objects, .so, etc.) go through `$(TARGET)`
install: $(TARGET) $(EXTRA_INSTALL)

$(EXTRA_INSTALL):
    @cp $(firstword $(subst =, ,$@)) $(lastword $(subst =, ,$@))

.PHONY: install $(EXTRA_INSTALL)

      

I think this is kind of a hack, but I couldn't think of a proper way to do it. So is there a better way to achieve the same? Note that there is no visible relationship between the input filename and the output, so the sorting rule is dist/include/%.h:include/%.h

not appropriate.

+3


source to share


2 answers


Something like the following might be more readable (although it adds a bit of duplication), it has the advantage of updating files if they may have changed.

EXTRA_INSTALL := dist/include/mylib/mylib.h dist/include/mylib/platform.h

.PHONY: install
install: $(EXTRA_INSTALL)

dist/include/mylib/mylib.h: include/mylib/mylib.h
dist/include/mylib/platform.h: include/mylib/platform/linux/platform.h

.SECONDEXPANSION:
$(EXTRA_INSTALL): $$^
    cp $^ $@

      



You can also opt out .SECONDEXPANSION

entirely at the cost of an extra line per file

EXTRA_INSTALL := dist/include/mylib/mylib.h dist/include/mylib/platform.h

.PHONY: install
install: $(EXTRA_INSTALL)

dist/include/mylib/mylib.h: include/mylib/mylib.h
    cp $^ $@
dist/include/mylib/platform.h: include/mylib/platform/linux/platform.h
    cp $^ $@

      

+2


source


This is a terrible hack. Doing this kind of thing is exactly what it is for make

, you don't have to invent your own mini-language internally make

.

Define the mapping source=target

as a precondition make

and then define the recipe to create it via cp

:

dist/include/mylib/mylib.h: include/mylib/mylib.h 
        cp $^ $@

      



This suggests that the creation of a file dist/include/mylib/mylib.h

depends on another file (so it will be recreated if the other file changes) and that it must be created by copying it.

The answer from user @ user657267 shows how to reduce duplication by decoupling the dependency definition from the recipe for the actual copy, so you don't have to repeat the recipe cp

for every file. However, since the recipe is incredibly simple, I see no harm in just repeating it. You can always replace the recipe with a function call if it gets more complex:

CP := cp -f
copy_file := $(CP) $(1) $(2)

dist/include/mylib/mylib.h: include/mylib/mylib.h 
        $(call copy_file,$^,$@)

dist/include/mylib/platform.h: include/mylib/platform/linux/platform.h
        $(call copy_file,$^,$@)

      

+2


source







All Articles