passing parameter in make file - makefile

I am using visual code on mac for python and very new to make file environment.
I have a make file command as below,
mkdir mydir
zip mydir/test test1111/mypython.py
How should I parameterize test1111? Thanks.

ZIP = zip
test_CONTENT = \
test1111/mypython.py
mydir/test.zip: ${test_CONTENT}
#mkdir -p ${#D}
${ZIP} $# $^

Related

extra links from foreach in Makefile

I'm on a mac using GNU Make to manage my dotfiles. There's a directory with my emacs config files and a corresponding target in the Makefile:
all: _emacs
.PHONY: all list $(MAKECMDGOALS)
....
EMACS_SOURCE_DIR := $(abspath ./emacs)
EMACS_TARGET_DIR := $(abspath $(HOME)/.emacs.d)
EMACS_CONFIG_FILES := $(wildcard $(EMACS_SOURCE_DIR)/*.el)
_emacs: | $(EMACS_TARGET_DIR)
#echo $(call message,"Setting up config files for emacs")
$(foreach file, \
$(EMACS_CONFIG_FILES), \
ln -sf $(file) $(addsuffix /, $(EMACS_TARGET_DIR)))
$(EMACS_TARGET_DIR):
#echo "Creating directory $(EMACS_TARGET_DIR)"
#mkdir -p $#
When I run make _emacs it creates some extra links:
.emacs.d -> /Users/xxx/.emacs.d/
-sf -> -sf
early-init.el -> /Users/xxx/Projects/bootstrap/emacs/early-init.el
init-org.el -> /Users/xxx/Projects/bootstrap/emacs/init-org.el
init-pkgs.el -> /Users/xxx/Projects/bootstrap/emacs/init-pkgs.el
init.el -> /Users/xxx/Projects/bootstrap/emacs/init.el
ln -> ln
I'm struggling to understand what exactly is happening and how to avoid having the first two and the last soft links created.
In general it's a bad idea to try to construct a complex shell command using make functions inside a recipe. You should simply use shell constructs: for example use the shell for loop, not the make foreach loop.
Let's see what your recipe does:
_emacs: | $(EMACS_TARGET_DIR)
$(foreach file, \
$(EMACS_CONFIG_FILES), \
ln -sf $(file) $(addsuffix /, $(EMACS_TARGET_DIR)))
Make functions manipulate text. They don't know anything about commands, shell syntax, etc. Before make invokes the shell it first expands the script. What will this result in? This:
ln -sf .../emacs/early-init.el /Users/xxx/.emacs.d/ ln -sf .../emacs/init-org.el /Users/xxx/.emacs.d/ ln -sf ...
Maybe now you can see the problem.
If you wanted to do this using make's foreach you have to add a shell delimiter so the shell knows where one command ends and the next begins; something like:
$(foreach file, \
$(EMACS_CONFIG_FILES), \
ln -sf $(file) $(addsuffix /, $(EMACS_TARGET_DIR)) ; )
(note the ; at the end). Now when make expands it will look like this:
ln -sf .../emacs/early-init.el /Users/xxx/.emacs.d/ ; ln -sf .../emacs/init-org.el /Users/xxx/.emacs.d/ ; ln -sf ...
If I were you, I'd instead use a shell loop. It's just much simpler to understand:
for file in $(EMACS_CONFIG_FILES); do \
ln -sf $$file $(addsuffix /, $(EMACS_TARGET_DIR)) ; \
done
But, for what you want to do you don't need a loop at all; you can link multiple files into the same directory with one command:
ln -sf $(EMACS_CONFIG_FILES) $(EMACS_TARGET_DIR)
(I'm not sure what the addsuffix was needed for, or why you couldn't just write it as $(EMACS_TARGET_DIR)/ without the addsuffix)

Make: Can we have directories as a target in GNUmakefile

I am working on GNUmake to create symlink to specific file by parsing whole directory which has a folder which needs to be linked.
Here is my makefile snippet.
TGT_LINK = /lan/test/workspace/build/tools
all_target: release_buid complete_test $(TGT_LINK)
$(TGT_LINK):
if [ ! -d $# ]; then mkdir -p $#; fi
cd $#; \
tar_ln=`\ls -d synopsystcl* | sed 's/synopsys//'`; \
sour_dir=`\ls -d synopsystcl*`; \
if ! [ -e $tar_ln ]; then \
ln -s $sour_dir $tar_ln; \
fi
Directory : /lan/test/workspace/build/tools Contains following content in it
polaris.so link.a dynamic.so kbuild.so README.txt license.txt synopsystcl5.5 build.json
Here i am trying to create symlink with name tcl5.5 pointing to synopsystcl5.5 with my above target $(TGT_LINK) code.
tcl5.5 -> synopsystcl5.5
After successful completion of two targets : release_buid complete_test , build is not proceeding to go for next target $(TGT_LINK) to create symlink. Could you please help whats wrong in code?
I would let make itself to check and recreate symlink as needed, i.e.:
TGT_LINK = /lan/test/workspace/build/tools
all_target: release_buid complete_test symlink
.PHONY: symlink
symlink: $(patsubst $(TGT_LINK)/tcl%, $(TGT_LINK)/synopsystcl%, $(wildcard $(TGT_LINK)/tcl*))
$(TGT_LINK)/synopsystcl%: $(TGT_LINK)/tcl%
set -e; \
cd $(#D); \
rm -f $(#F); \
ln -s $(<F) $(#F)
I would also consider reordering targets if there are dependencies indeed. One should never assume that dependency list is processed left to right; it will also lead to errors when parallel build (-j) is involved. If you have dependencies that something should happen before something else, it should be explicitly stated, e.g.:
all_target: symlink
symlink: complete_test
complete_test: release_buid

How to get Makefile to only produce a file name without extension?

I'm trying to make a Makefile that exports a markdown file to a pdf file that uses the same filename as the original markdown file. I used "basename" command but it produces "inputfile.md.pdf" instead of "inputfile.pdf".
Please see my code below (I adapted a code I found on the Internet. Thank you!):
.PHONY: pdf docx apa format
FILES := $(wildcard ./*.md)
pdf:
for file in $(FILES); do \
pandoc $$file \
--bibliography mypath \
--csl mypath \
--filter pandoc-citeproc \
--template eisvogel \
-o $(basename $$file).pdf; \
open $(basename $$file).pdf; \
done
Anyone who can help me? I'm a novice in Makefile (and programming in general) so any detailed help would be very much appreciated.
I also tried these codes below, but they generated an error message:
-o $(basename -s ".md" $$file).pdf; \
-o $(basename -s .md $$file).pdf; \
The way you write $(basename …) you get the basename make function. This would normally the right thing, but you try to reference a shell variable file in its argument, which is unavailable at the make layer.
In this case, it is probably easiest to call the basename shell utility, at the shell level. Therefore, you need to escape the $ to get shell substitution, like this:
-o "$$(basename -s .md $$file)".pdf; \
open "$$(basename -s .md $$file)".pdf; \
Alternatively, you could try to move the loop to the make layer, perhaps using foreach.

automake: process a configuration file

I'm wondering how to process a data template so as to install properly configurations files
accordingly to "make distcheck".
For instance I try severals ways like this but either the template (here rsyslog.conf) is finally installed by "make install" or it leaks for "make distcheck".
The one bellow is based on this thread :
Install data directory tree with massive number of files using automake
rsyslogdir = $(sysconfdir)/rsyslog.d
dist_rsyslog_DATA = $(name).conf
install-data-hook: rsyslog.conf
cp rsyslog.conf $(name)$.conf
sed $(rsyslogdir)$(name).conf -i -e \
"s!TEMPLATE!$(name)!"
Do I have to process my template file like a source file even if it concern a configuration file ?
Thanks for your advices.
So, I continue on my first tries and it finaly works.
Thanks William.
EXTRA_DIST = rsyslog.conf
rsyslogdir = $(sysconfdir)/rsyslog.d
dist_rsyslog_DATA = $(name).conf
$(name).conf: rsyslog.conf
sed rsyslog.conf \
-e "s!TEMPLATE!$(name)!" \
> $#
clean-local:
rm -f $(name).conf

Makefile rule to build with same name, but different directory

I would like a rule something like:
build/%.ext: src/%.ext
action
I have one directory of files in a folder that I want to optimize and then output to a different folder. However, the files have the same name in the input and output folders. I have tried various iterations of the rule above, but make will either always or never rebuild depending how I tweak the above. Suggestions?
EDIT:
I ended up with the following solution, which works great!
JS = \
src/js/script2.js \
src/js/script1.js
JS_OPT = $(patsubst src/js/%.js,web/js/%.js, $(JS))
all: $(JS_OPT)
$(JS_OPT): web/js/%.js: src/js/%.js
cat $# | ./bin/jsmin > $<
Try somethink like this:
INPUT_FILES = \
src/a.txt \
src/b.txt \
OPTIMIZED_FILES=$(patsubst src/%.ext,build/%.ext,$(INPUT_FILES))
$(OPTIMIZED_FILES): build/%.ext: src/%.txt
optimize_command $# $<

Resources