Reputation: 12616
Say I have a makefile in which I want to copy a few files from one place to another, e.g.:
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 "install" rule. What comes to my mind is something of the sort:
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 it's a sort 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 thing? Note that there's no apparent connection between the input filename and the output one, so a rule of the sort dist/include/%.h:include/%.h
would not be suitable.
Upvotes: 3
Views: 306
Reputation: 171263
It's a horrible hack. Doing this kind of thing is exactly what make
is for, you don't need to invent your own mini-language inside make
.
Define the source=target
mapping as a make
prerequisite instead, then define the recipe for creating it via cp
:
dist/include/mylib/mylib.h: include/mylib/mylib.h
cp $^ $@
This says creating the file dist/include/mylib/mylib.h
depends on the other file (so it will be recreated if the other file changes) and that it should be created by copying it.
The answer from @user657267 shows how to reduce duplication by separating the definition of the dependencies from the recipe for doing the actual copying, so you don't need to repeat the cp
recipe on every file. However, as the recipe is incredibly simple, I see no harm in just repeating it. You could always replace the recipe with a function call if it got more complicated:
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,$^,$@)
Upvotes: 2
Reputation: 20990
Something like the following might be more readable (although it adds a little duplication), it has the benefit of updating the files if they happen to 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 could also forgo .SECONDEXPANSION
entirely at the expense 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 $^ $@
Upvotes: 2