Makefile adding spaces to variables - makefile

I am trying to use a makefile in order to compile my story in LaTex. I am trying to use a variable in order to complete the file name for my story. If I simply run make, it works. However, I need to be able to run a specific command from make.
pdflatex "\\def\\isdraft{1} \\input{FMPGC.tex}"
How would I create a variable from PROJ + OBJS so that I could do something like what I am trying to do below. If I run the below code for make draft, it fails out and APPEARS that it is adding numerous spaces between FMPGC and tex.
How could I combine two variables with a "." symbol between the pair so I can compile my story in the below command. I have also experimented with not escaping the \ symbols and that seems to have no effect.
# This makefile compiles my story using LaTex
# Author:
#
# VARS - Variables to be changed for reuse of my script
PROJ = "FMPGC" # The name of the project
OBJS = "tex" # The extension for the content
AUXS = "aux" # The aux extensions
CHAP = "chapters/" # The chapters
FOO = $(PROJ) += "."
F002 = $(FOO) += $(OBJS)
# Configuration:
CC = pdflatex # The compiler
# Rules
all:
$(CC) $(PROJ).$(OBJS)
draft:
$(CC) "\\def\\isdraft{1} \\input{$(FOO2)}"
The current error comes from it not inputting anything into the variable as of right now -
pdflatex "\\def\\isdraft{1} \\input{}"
Below seems to be the exact issue.
<*> \def\isdraft{1} F
MPGC.tex
---------------- Updated Make File
# This makefile compiles my story using LaTex
# Author:
#
# VARS - Variables to be changed for reuse of my script
# The name of the project
PROJ:=FMPGC
# The extension for the content
OBJS:=tex
# The aux extensions
AUXS:=aux
# The chapters
CHAP:=chapters/
# Configuration:
# The compiler
CC=pdflatex
# Rules
all:
$(CC) $(PROJ).$(OBJS);
draft:
$(CC) "\def\isdraft{1} $(PROJ).$(OBJS)";
Updated Error ----
pdflatex "\def\isdraft{1} FMPGC.tex";
This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
LaTeX2e <2014/05/01>
Babel <3.9k> and hyphenation patterns for 21 languages loaded.
! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
<*> \def\isdraft{1} F
MPGC.tex
?
! Emergency stop.
...
<*> \def\isdraft{1} F
MPGC.tex
! ==> Fatal error occurred, no output PDF file produced!
Transcript written on texput.log.

In the The Two Flavors of Variables section of the GNU make Manual we find:
If you put whitespace at the end of a variable value, it is a good idea to put a comment like that at the end of the line to make your intent clear. Conversely, if you do not want any whitespace characters at the end of your variable value, you must remember not to put a random comment on the end of the line after some whitespace, such as this:
dir := /foo/bar # directory to put the frobs in
Here the value of the variable dir is ‘/foo/bar ’ (with four trailing spaces), which was probably not the intention. (Imagine something like ‘$(dir)/file’ with this definition!)

Thanks to #Etan Reisner I was able to fix it after reviewing the documentation.
My make file now looks like this -
# This makefile compiles my story using LaTex
# Author:
#
# VARS - Variables to be changed for reuse of my script
# The name of the project
PROJ:=FMPGC
# The extension for the content
OBJS:=tex
# The aux extensions
AUXS:=aux
# The chapters
CHAP:=chapters/
# Configuration:
# The compiler
CC=pdflatex
# Rules
all:
$(CC) $(PROJ).$(OBJS);
draft:
$(CC) "\def\isdraft{1} \input{$(PROJ).$(OBJS)}";
I can now compile my document and it adds my variable for use inside of LaTex.

Related

How to call pandoc from makefile on different files?

I am working on a writing project and would like to use make for running pandoc on files. So far I've tried to pass arguments to make like I do with a bash script.
For example:
$ make chapter 2
In the make file chapter is the target and 2 would be the argument.
I don't know if makefiles have the facility to take cli arguments. I haven't been able to find what I'm looking for in the documentation.
So far I have tried to run make with this recipe.
chapter:
#pandoc -s -o "$1.epub" "$1.md"
I get this error back
pandoc: .md: openBinaryFile: does not exist (No such file or directory)
make: *** [Makefile:2: chapter] Error 1
This is for turning sections of a book I'm working on into epubs. I'm open to other ways to do this with make seeing as tokens don't to work.
In the make file chapter is the target and 2 would be the argument
$ make chapter num=2
The assignment to variables on the make command-line overrides any definition inside the makefile
(yep, such variables effectively become read-only).
This suggests a makefile something like:
num = $(error You must set $$num to the chapter number you want (make chapter num=4))
.PHONY: chapter
chapter:
pandoc -s -o "${num}.epub" "${num}.md"
What's going on here?
Well, if you forget to set num,
when make expands the recipe for chapter the
$(error) will cause make to stop.
$ make
Makefile:5: *** You must set $num to the chapter number you want (make chapter num=4). Stop.
And your original example?
$ make chapter num=2
pandoc -s -o "2.epub" "2.md"
Tips
I rarely recommend using the # prefix — Users can use make's -s if they don't want to see the shell commands
Don't lie to make — In particular, your rule does not produce a file called chapter, so please tell make that by marking the target .PHONY
The natural way to say this in Make is to enumerate all the chapters as targets, typically as dependencies for make all.
So basically
src := $(wildcard *.md)
epubs := $(patsubst %.md,%.epub,$(src))
.PHONY: all
all: $(epubs)
%.epub: %.md
pandoc -s -o $# $<
You can say make ch4.epub if you have a chapter whose source is ch4.md. You can't really pass in an argument which isn't a file name or a target name, and these cannot contain spaces.
I suppose you could add a phony like
.PHONY: 2
2: ch2.epub
to be able to say make 2 and have it mean make ch2.epub. If file names are systematically named like this, you could generalize to
short := $(patsubst ch%.md,%,$(src))
.PHONY: $(short)
$(short): %: ch%.epub
Don't use # in front, it just makes things harder. You can use make -s if you don't want to see the output and not wreck your Makefile.

Unable to execute all prerequisites for a target in makefile

I have been trying to execute all prerequisites for a particular target in makefile. But whenever the prerequisite is a target with single/multiple info values, I find that the other prerequisites are not executed(which come after the 'info' based target)
I have tried reducing the number of info in values in prerequisites to just 1. in that case also i could not find other prerequisites to execute.
Thus my problem is to understand how to execute a single/multi-line info based prerequisite and continue executing other prerequisites.
# Define new line and separator
.PHONY:newline
newline:
#echo
.PHONY:separator
separator:
$(info -------------------------------)
# Print the project details
.PHONY:project
project:
$(info Project Details)
$(info Author : xyz)
# Help menu
.PHONY:help
help: newline separator project separator newline
Expected outcome
$ make help
-------------------------------
Project Details
Author : xyz
-------------------------------
Outcome received
$ make help
-------------------------------
Project Details
Author : xyz
In make any target's recipe is executed at most once per build. So just don't do this, it's very very wrong.
Also, $(info ...) is a text substitution, which is executed before any external command in the same recipe, so mixing it with echo generally is a bad idea.
If you're trying to avoid repeating long dash lines, you can always do this with variables:
sep := --------------------
define nl :=
endef
...
help:
$(info $(nl)$(sep))
$(info Project details)
...
$(info $(sep)$(nl))

Make file with multiple potential dependencies

I'm trying to make a make file for a static page generator, and I'm using jinja and pandoc so far, and the idea is to have a file structure as such
.
|-content
|-public
|-templates
|-Makefile
VPATH=public
TARGETS=$(find content -regex ".*(htm|md)" | sed -e "s/md$/htm/g;s/^content/public/g")
all: $(TARGETS)
#echo fullbuild
public/%: content/%
content/%.md:
# Pandoc script
pandoc -i $# -o ${${#:.md=.htm}:content=public}
content/%.htm:
# Jinja Script
The problem I'm having (At least I think that's it) is that according to me the syntax is
# For a final result
target: dependency
commands
# A rule for dependency
dependency:
commands
My dependencies are in the content dir and my targets are in the public dir that may or may not exist yet, and almost all the files I generate will be htm files, and in that case if the target is public/some/route/to/file.htm the dependency will be any of this two content/some/route/to/file.(htm|md).
I can easily generate by walking the content dir, and changing extensions.
How should I write the rules properly, so
- Make knows where to "watch" for changes every time I do a make, because right now it points that every file is up to date
- How do I indicate properly the dependency of a file to it's content file.
This rule:
public/%: content/%
does nothing because pattern rules without recipes delete existing pattern rules, they don't define new pattern rules.
It's very simple, you should write two rules like this:
public/%.htm: content/%.md:
# Pandoc script
pandoc -i $< -o $#
public/%.htm: content/%.htm
# Jinja Script
Here's a hint: whenever you're writing a makefile recipe and you discover that you need to create a target which is different than exactly $#, unmodified, immediately stop what you're doing and back up: you've taken a wrong turn.

Make doesn't like $(addprefix a,b)

Make is giving me the error:
make/sources.make:16: *** missing separator. Stop.
The terminal process terminated with exit code: 2
The code that is generating this error is:
$(addprefix a,b)
I've checked for spaces, but I didn't find anything.
If I comment it out, no errors are given. I've narrowed it down to this one line, and I can't figure it out. 'a' and 'b' can be replaced with anything, and it still won't work. However, if you remove all arguments to it, like this $(addprefix ,) then no errors are given.
What is going on here?
Full code of makefile that contains the error:
# sources.make - source files
# path of source files
SOURCEPATH=src
# build list of source files
# categorize source files
SOURCE_MAIN=main.c
# add categories to SOURCES as needed
SOURCES+=$(SOURCE_MAIN)
# add the SOURCEPATH to each source file
#$(addprefix $(SOURCEPATH),$(SOURCES)) <------ This is the true error code
$(addprefix a,b)
# extra files to remove
TRASHFILES = stdout.txt stderr.txt
# extra directories to remove
TRASHDIRS = junkdir
# build target
TARGET = $(PROG)$(EXT)
# generate object files
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
# generate dependency files
DEPENDS = $(patsubst %.c,%.d,$(SOURCES))
The offending line is interpreted as a rule, not a directive. It should instead read:
SOURCES := $(addprefix $(SOURCEPATH)/,$(SOURCES))

Can I expand macro JUST ONE TIME in specific target?

A = "demo"
%.o:%.cpp
$(CC) -c $^ $(A) -o $#
default:$(all_objs)
game:A = $(shell read -p 'Enter game version: ' gv && echo $$gv)
game:$(all_objs)
Just a snippet makefile above. If I make game, main problem is each compilation of sources will expand $(A) and it will request user to input game version over and over. $(A) has default content "demo" only if user doesn't make game target.
So, is there any way to set $(A) to be expanded && ?
game:A:=$(shell read -p 'Enter game version: ' gv && echo $$gv)
Notice ':='
Update:
Reading user input in real build targets is not a good idea. Make is widely used and whoever invokes it - they wouldn't expect this.
I see two ways to do what you wanted:
make version=some_version. It will override version variable (name may be almost anything). If you have assigned its default value in makefile - it will be changed to some_version (unless variable declared with override flag, which disables this behaviour)
Create make config rule, which would perform required configuration actions and save them into, say, config.mk. In makefile you could have -include config.mk ('-' sign says make that this file may be missing. If it is required (e.g. contains some mandatory configuration options), remove minus sign).

Resources