For example, given a list of files in current directory, how to copy the files into another directory.
dest_dir := /usr/bin/test
.PHONY: install
install: $(dest_dir)
#there files are in current directory
xpi_built := install.rdf \
chrome.manifest \
$(wildcard content/*.js) \
$(wildcard content/*.xul) \
$(wildcard content/*.xml) \
$(wildcard content/*.css) \
$(wildcard skin/*.css) \
$(wildcard skin/*.png) \
$(wildcard locale/*/*.dtd) \
$(wildcard locale/*/*.properties)
#how to copy there files to another directory
$(dest_dir)/% : $(xpi_built)
#mkdir -p $(dest_dir)
#cp $< $#
How could I copy the list of files into the destination directory?
.PHONY: copy_files
copy_files: $(xpi_built)
#mkdir -p $(dest_dir)
#cp $^ $(dest_dir)
Related
Here is my Makefile:
NAME := libftprintf.a
LIB := ar rcs
CC := gcc
CFLAGS := -Wall -Wextra -Werror
SRCS_DIR := ./sources/
HDRS_DIR := ./headers/
OBJS_DIR := ./objectives/
SRCS_FILES := ft_conv.c \
ft_eval_hex.c \
ft_eval_number.c \
ft_eval_string.c \
ft_parsers.c \
ft_strs_join.c \
ft_eval_char.c \
ft_eval_int.c \
ft_eval_percent.c \
ft_handler.c \
ft_printf.c
HDRS_FILES := ft_conv.h \
ft_eval_hex.h \
ft_eval_number.h \
ft_eval_string.h \
ft_parsers.h \
ft_strs_join.h \
ft_eval_char.h \
ft_eval_int.h \
ft_eval_percent.h \
ft_handler.h \
ft_printf.h
OBJS_FILES := $(SRCS_FILES:.c=.o)
SRCS := $(addprefix $(SRCS_DIR),$(SRCS_FILES))
HDRS := $(addprefix $(HDRS_DIR),$(HDRS_FILES))
OBJS := $(addprefix $(OBJS_DIR),$(OBJS_FILES))
LIBFT_DIR := ./libft/
LIBFT_NAME := libft.a
LIBFT := $(addprefix $(LIBFT_DIR),$(LIBFT_NAME))
RM := rm -rf
all: $(NAME)
bonus: all
bonus_one: all
bonus_two: all
$(NAME): $(OBJS)
$(LIB) $(NAME) $(OBJS) $(LIBFT)
$(OBJS_DIR)%.o: $(SRCS_DIR)%.c $(HDRS) Makefile | $(OBJS_DIR) subsystem
$(CC) $(CFLAGS) -c $< -o $# -I $(HDRS_DIR) -I $(LIBFT_DIR)
subsystem:
#$(MAKE) -C $(LIBFT_DIR)
$(OBJS_DIR):
mkdir $(OBJS_DIR)
clean:
#$(MAKE) -C $(LIBFT_DIR) clean
$(RM) $(OBJS_DIR)
fclean: clean
#$(MAKE) -C $(LIBFT_DIR) fclean
$(RM) $(NAME)
re: fclean all
.PHONY: all subsystem bonus bonus_one bonus_two clean fclean re
The problem is so: if I do make all, then touch libftprintf.a I would expect that make all will rebuild libftprintf.a since it was changed and target all depends on that file. However, make does nothing and I can't understand this behavior.
Also, there is one more minor issue: during make all I create a directory objectives where I store all .o files. Calling make fclean and make all entirely rebuilds the target, however calling make re results in an error:
rm -rf ./objectives/
rm -rf *libft objectives here*
rm -rf libft.a
rm -rf libftprintf.a
make: *** No rule to make target `objectives', needed by `objectives/ft_conv.o'. Stop.
If I call make re right after this error, the target builds as always. Also, if I change re target to this, I do not receive any errors:
re:
#$(MAKE) fclean
#$(MAKE) all
Could not find solutions to my problems anywhere on the Internet.
Touching libprintf.a won't cause anything to rebuild. Make rebuilds targets that are out of date. Out of date means that either the target doesn't exist, or some prerequisite of the target is newer than the target.
After you run make then libprintf.a is up to date, which means it's newer than all its prerequisites. Running touch libprintf.a just makes it even newer than its prerequisites than it was before, so make still considers it up to date.
If you want to rebuild libprintf.a you need to touch (or delete) one of its prerequisites, not the target itself.
The reason for your second issue seems to be related to the makefile in the libft subdirectory. It seems like you're using the --no-print-directories option here: you should avoid using that, at least as long as you're debugging, so that you can see where make is going and which makefile it's running.
I want to create *.o for each cpp file inside variable "CPPS" (in Ubuntu)
CPPS := file1.cpp \
file2.cpp \
file3.cpp \
folder1/file4.cpp \
folder2/file5.cpp \
folder2/folder21/file6.cpp
OBJS := file1.o \
file2.o \
file3.o \
file4.o \
file5.o \
file6.o
test:$(OBJS)
$(CXX) $(FLAG) -o m $(OBJS)
I want to create *.o for each cpp automatically. And I want to create *.o inside the same folder of Makefile.
If all the cpps are in the same folder as Makefile, we can use
%.o:%.cpp
$(CXX) $(FLAG) -c -o $# $< $(INC)
But the problem is they are in different folders, currently I have to write a script to create a lnk for each file. Is there a way to iterator over each file inside a variable? or it there an another way to do that?
Using source files in different directories is what the vpath directive is for:
CPPS := file1.cpp ...
OBJS := file1.o ...
vpath %.cpp folder1 folder2 folder2/folder21
all: $(OBJS)
And you can generate the vpath and OBJS from CPPS, rather than typing them all in by hand:
CPPS := file1.cpp ...
OBJS := $(notdir $(CPPS:.cpp=.o))
SRCDIRS := $(dir $(CPPS))
vpath %.cpp $(SRCDIRS)
all: $(OBJS)
Scratching my head for a while now, but I would like to copy an arbitrary list of files with paths to under specified path in system.
File layout:
data/a/file1.ext1
data/b/randomfile.ext2
data/c/file3.ext3
data/c/subdir/randomfile.2
Running make -f Makefile deploy DESTDIR=/path/to/somewhere copies those files to:
$(DESTDIR)/a/file1.ext1
$(DESTDIR)/b/randomfile.ext2
$(DESTDIR)/c/file3.ext3
$(DESTDIR)/c/subdir/randomfile.2
Makefile:
$FILES = \
a/file1.ext1 \
b/randomfile.ext2 \
c/file3.ext3 \
c/subdir/randomfile.2
ifneq ($(filter env_check,$(MAKECMDGOALS)),$())
ifndef DESTDIR
$(error DESTDIR not defined)
endif
endif
# lots of currently broken rules :(
# check whether target directory has certain structure
# check whether all the files listed in $(FILES) are in repository
Are you looking for something like this?
FILES := ...
DST_FILES := $(addprefix $(DESTDIR)/,$(FILES))
ifneq ($(filter env_check,$(MAKECMDGOALS)),$())
ifndef DESTDIR
$(error DESTDIR not defined)
endif
endif
all: $(DST_FILES)
$(DST_FILES) : ${DESTDIR}/% : %
#echo "$< ==> $#"
#[[ -e $< ]] || (echo "some error for $<" && false)
#mkdir -p $(dir $#)
#cp $< $#
[Edit]:
Although the version somewhat worked, I still needed to do following adjustments:
Files in source repository are stored under data directory - fixed by using $addprefix call
When file in $(DESTDIR) already existed, it was never copied - used the .FORCE target. (Another option would be --always-make commandline option).
Eventually, the working Makefile looks like that:
# File are stored under data/
FILES= \
foo/file1.ext \
bar/file2.txe \
bar/dir/file3.txt
ifneq ($(filter env_check,$(MAKECMDGOALS)),$())
ifndef DESTDIR
$(error DESTDIR not defined)
endif
endif
.PHONY: deploy help
help:
#echo "Deploy stuff"
# Check whether certain directories in the output are present
env_check:
#test -d $(DESTDIR)/WEB-INF -a -d $(DESTDIR)/META-INF || \
( echo "DESTDIR: \"$(DESTDIR)\" is not proper deployment path" && exit 1 )
DST_FILES := $(addprefix $(DESTDIR)/, $(FILES))
# We need to add our path prefix to local files and FORCE to always do the copying
$(DST_FILES) : $(addprefix $(DESTDIR), %) : $(addprefix data,%) .FORCE
#cp -pv $< $#
.FORCE:
deploy: env_check $(DST_FILES)
#echo "Deployment done..."
I am trying to use a Makefile for compiling a PDF when any of a number of Markdown files change:
# Compile report
source := draft
output := dist
sources := $(wildcard $(source)/*.md)
objects := $(patsubst %.md,%.pdf,$(subst$(source),$(output),$(sources)))
all: $(objects)
report-print.md: $(source)/%.md
cat draft/*.md | pandoc \
--variable geometry:a4paper \
--number-sections \
--toc \
--f markdown \
-s \
-o dist/report-print.pdf \
.PHONY : clean
clean:
rm -f $(output)/*.pdf
I get an error:
make: *** No rule to make target `dist/01-title.pdf', needed by `all'. Stop.
The file draft/01-title.md is one of of the source files.
You don't have a rule for creating one .pdf file from one .md file. Which is fine, because that's not what you want to do. You want to create a single pdf file from all the .md files (as I understand it). So, ditch all the objects stuff; you don't need to create all those individual pdf files.
There are a number of other minor problems: you aren't creating the same filename as your target (report-print.md vs. $(output)/report-print.pdf), you should use automatic variables, etc.)
Your makefile will simply be:
source := draft
output := dist
sources := $(wildcard $(source)/*.md)
all: $(output)/report-print.pdf
$(output)/report-print.pdf: $(sources)
cat $^ | pandoc \
--variable geometry:a4paper \
--number-sections \
--toc \
--f markdown \
-s \
-o $#
.PHONY : clean
clean:
rm -f $(output)/*.pdf
I would like make to copy files from the source directory into a target directory. And i would like to avoid copying unchanged files. Therefore, I am trying to utilize make function of checking for newer files with a %.:%. rule.
Now, in this instance, the source and target EXTENSION are the same. There are object files elsewhere but not for the graphical assets.
I use make to copy images.
TARGET := target
SOURCE := source
GRAPHICS := $(foreach dir,$(SOURCE), $(wildcard $(dir)/*.jpg ) $(wildcard $(dir)/**/*.jpg ) $(wildcard $(dir)/*.png ) $(wildcard $(dir)/**/*.png ) $(wildcard $(dir)/*.gif ) $(wildcard $(dir)/**/*.gif ) )
JPG = $(GRAPHICS:.jpg=.tmp)
PNG = $(GRAPHICS:.png=.tmp)
GIF = $(GRAPHICS:.gif=.tmp)
And then use the following rule to copy files into target directory:
%.tmp:%.jpg
find $< | cpio -p -d -v $(TARGET)
Questions
Is it possible to string replace the TARGET directory here
and thereby use the make newer capability?
I tried
JPG = $(GRAPHICS:$(TARGET).jpg=.tmp)
But that fails with No rule to make target. Is it only possible to compare source and object in the same directory?
Can one make a rule such that the source and object are the same extension?
%.jpg:%.jpg
The closest I can come up with is:
$(TARGET)%.jpg:%.jpg
but that never runs. Even after a clean.
Here is the solution.
This 'setup' remains the same.
TARGET := target
SOURCE := source GRAPHICS := $(foreach dir,$(SOURCE), $(wildcard $(dir)/*.jpg )
$(wildcard $(dir)/**/*.jpg ) $(wildcard $(dir)/*.png ) $(wildcard $(dir)/**/*.png )
$(wildcard $(dir)/*.gif ) $(wildcard $(dir)/**/*.gif ) )
Now add a prefix to ALL (space separated) values in the $GRAPHICS string
TARGET_GRAPHICS := $(addprefix $(TARGET)/, $(GRAPHICS) )
Note that patsubst aka -- TARGET_GRAPHICS := $(patsubst %, $(TARGET)/%, $(GRAPHICS) ) -- only worked for the first entry. Perhaps I was doing it incorrectly.
Provide a pattern match for each file type. Here do whatever you wish. In my case, copy the input into the target directory. cpio will make the needed directories. cp -p might also work as needed.
$(TARGET)/%.jpg : %.jpg
#echo "--- .jpg copying " $< " to " $# " into dir " $(<D)
#find $< | cpio -p -d -v $(TARGET)
$(TARGET)/%.png : %.png
#echo "--- .png copying " $< " to " $#
#find $< | cpio -p -d -v $(TARGET)
$(TARGET)/%.gif : %.gif
#echo "--- .gif Copying " $< " to " $#
#find $< | cpio -p -d -v $(TARGET)
So you want the copy of d1/d2/f.png into out/d1/d2/f.png to make use of make's dependency checking?
out/d1/d2/f.png: d1/d2/f.png
out/d1/d2/f.png:
cp $< $#
Adding a jpg file d3/g.jpg say,
out/d3/g.jpg: d3/g.jpg
out/d1/d2/f.png: d1/d2/f.png
out/d1/d2/f.png out/d3/g.jpg:
cp $< $#
We can express this more cleanly with a static pattern rule.
out/d3/g.jpg out/d1/d2/f.png: out/% %
cp $< $#
Nice. So adding your ${GRAPHICS} and fleshing things out a bit
outdir := out/
targets := $(addprefix ${outdir},${GRAPHICS})
.PHONY: all
all: ${targets} ; : $# Success
${targets}: ${outdir}%: %
echo $< | cpio -d -p ${outdir}
Parallel safe too, so make -j9 will exercise your 8 CPUs nicely.