I wrote a simple makefile to generate pdf using latex and I succeeded.
However, There are 2 point that irritates me:
when I run make the output PDF is in the same folder where the makefile is written and I want to change that
I want to copy the pdf file generated to another file with another name but I don't know how to do that
Here is a snippet of my code:
# Generating the file
$(FILE).pdf: $(IMAGES) $(PACKAGES) $(COMMON_TEX_SOURCES) $(FILE_TEX_SOURCES) $(FILE_IMAGES)
latexmk -lualatex $(FILE)
##############################################################################
#rule to generate file
file: $(FILE).pdf
Your help is appreciated
To make the target go into a another folder, change the target path:
some/dir/$(FILE).pdf: $(IMAGES) ...
To copy the file from one place to another:
some/other/dir/$(FILE).pdf: some/dir/$(FILE).pdf
cp $< $#
Related
I have a directory that contains a bunch of folders, all of which contain a .go file that I will want to build, and I'm trying to create a Makefile that can accomplish this. These are the requirements I'm looking to fill:
1.) I want this to be dynamic so that the number of folders can grow and change, and I won't need to update the Makefile every time.
2.) I also want the .go files to be able to have different names than the folder that holds them (for example, if the folder is lambda1 then the .go file shouldn't need to be named lambda1.go).
3.) Lastly, I want each binary to be output in the same folder that its source file is in.
This is what the folder structure looks like with the built binaries included:
lambdas
lambda1
--first.go
--first (binary)
lambda2
--second.go
-- second (binary)
lamba3
--third.go
--third (binary)
...
This is what the actual build commands look like:
GOOS=linux go build -o lambdas/lambda1/first lambdas/lambda1/first.go
GOOS=linux go build -o lambdas/lambda2/second lambdas/lambda2/second.go
and then in a later step I need to zip that binary like this:
zip lambdas/lambda1/function.zip lambdas/lambda1/first
zip lambdas/lambda2/function.zip lambdas/lambda2/second
It seems like what I need is to loop through the lambdas directory, and for each directory, get the name of the .go file, and then using those dir paths and file names, I could create each build command.
I'm brand new to Makefiles and have been trying to figure this out for about a day now and am not having luck. Thank you for any help.
What about something like this:
# Find all the .go files under lambdas
GOFILES := $(shell find lambdas -name \*.go)
GOPROGS := $(GOFILES:%.go=%)
GOZIPS := $(GOPROGS:%=%.zip)
# We want to build all the progs and zips
all: $(GOPROGS) $(GOZIPS)
# How to build each prog from a .go file
$(GOPROGS): % : %.go
GOOS=linux go build -o $# $<
# How to build each zip from a prog file
$(GOZIPS) : %.zip : %
zip $# $<
I'm using static pattern rules here but you could use normal pattern rules as well.
Oh I didn't notice you want the zip files to have the same name. This of course assumes that there will be only one .go file, and hence one program, in every directory? Seems limited.
This is not so simple because the names don't match. Although it could be done via separate rules if you really wanted to, the simplest thing to do is just put both the compile and zip into the same rule:
# Find all the .go files under lambdas
GOFILES := $(shell find lambdas -name \*.go)
GOPROGS := $(GOFILES:%.go=%)
# We want to build all the progs
all: $(GOPROGS)
# How to build each prog from a .go file
$(GOPROGS): % : %.go
GOOS=linux go build -o $# $<
zip $(#D)/function.zip $#
A code generator is executed from GNU make. The generator produces several files (depending on the input), and only touches the files, when their content change. Therefore a sentinel target needs to be used to record the generator execution time:
GEN_READY : $(gen_input_files)
gen.exe $(gen_input_files)
touch GEN_READY
$(gen_output_files): GEN_READY
It works well, except when a generated file is deleted, but the sentinel file is left in place. Since the sentinel is there, and it's up-to-date, the generator is not executed again.
What is the proper solution to force make to re-run the generator in this case?
Here is one way to group them using an archive:
# create archive of output files from input files passed through gen.exe
GEN_READY.tar: $(gen_input_files)
#echo Generate the files
gen.exe $^
#echo Put generated files in archive
tar -c -f $# $(gen_output_files)
#echo Remove intermediate files (recreated by next recipe)
rm $(gen_output_files)
# Extracting individual files for use as prerequisite or restoration
$(gen_output_files): GEN_READY.tar
#echo Extract one member
tar -x -f $< $#
Since tar (and zip for that matter) allows duplicate entries there could be opportunities updating or appending files in archive instead of rewriting if input-output relation allows.
Edit: Simplified solution.
I have a folder with some markdown files I want to process using pandoc and output them into another folder for a Jekyll site. I am attempting to use the following Makefile:
MARKDOWN = $(wildcard *.md)
jekyll-build : _posts/$(MARKDOWN)
bundle exec jekyll build
_posts/%.md : source/%.md
pandoc -s -t markdown-citations -o $# $<
However, instead of looking for the contents of the _posts folder, make is looking for any *.md files in the current working directory (where I have an index.md file), then complains it can't find _posts/index.md. From this question I gather it's the expected behavior of pattern rules, so my question is: how do I get make to look for all existing files in the source folder and run the recipe on each one of them?
MARKDOWN = $(wildcard source/*.md)
POSTS := $(patsubst source/%,_posts/%, $(MARKDOWN))
jekyll-build : $(POSTS)
...
_posts/%.md : source/%.md
...
I have few txt files in a directory. I want to run a shell script only on the files which have been modified. How can I achieve this through Makefile?
Have written the following part but it builds all the txt files in the directory. Would be great to get some pointers on this.
FILENAME:= $(wildcard dir/txts/*/*.txt)
.PHONY: build-txt
build-txt: $(FILENAME)
sh build-txts.sh $^
I'm guessing you want something like this:
files := $(wildcard dir/txts/*/*.txt)
dummies := $(addprefix .mod_,$files)
all:$(dummies)
$(dummies): .mod_% : %
sh build-txts.sh $^
touch $#
For any new text file, it will run the script, and create a .mod counterpart. For any non-new text file, it will check if the timestamp is newer than the .mod files timestamp. If it is, it runs the script, and then touches the .mod (making the .mod newer than the text). For any text file that has not been modified since the last make, the .mod file will be newer and the script will not run. Notice that the .mod files are NOT PHONY targets. They are dummy files who exist solely to mark when the text file was last modified. You can stick them in a dummy directory for easy cleaning as well.
If you need something where you don't want to rebuild the text files by default on a fresh checkout, or your script criteria isn't based on timestamps, you would need something a bit more tricky:
files := $(wildcard dir/txts/*/*.txt)
md5s:= $(addprefix .md5_,$files)
all:$(md5s)
.PHONY:$(md5s)
$(md5s):
( [ -e $# ] && md5sum -c $# ) || \
( sh build-txts.sh $# && md5sum $(#:.md5_=) > $# )
Here, you run the rule for all text files regardless, and you use bash to determine if the file is out of date. If the text file does not exist, or the md5sum is not correct, it runs the script, then updates the md5sum. Because the rules are phony, they always run for all the .md5sum files regardless of whether they already exist.
Using this method, you could submit the .md5 files to your repository, and it would only run the script on those files whose md5 sum changed after checkout.
Pretty new to GNU Make. This is a less complex example of something more general I have been trying to get to work.
I have many input files that have similar name format .txt, and I have a shell script that will take the input file and generate an output of the same name but with a different extension .wc. I have written the following Make file.
# name of dependencies
SRC = $(wildcard *.txt)
# get name of targets (substitute .wc for .txt)
TAR = $(SRC:.txt=.wc)
all: $(TAR)
%.wc: %.txt
sh word_count.sh $<
This runs fine, and will generate all the .wc output files. However, if I modify one of the input(dependency) files, they are all rebuilt. So the question is; what is the best way to get GNU Make to only process the modified .txt files in the directory?