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

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))

Related

Make: How could i change the path of a files which matches certain pattern

I am new to GNUmake.
I have a requirement to replace the file paths based on certain condition.
TARGET_EXCEPTION := /home/ip/lib_build
TGT_TOOLS := /demo/build/new_project
ifdef SET_BUILD
ifneq (0,$(RELEASE))
FILES += $(addprefix $(TARGET_EXCEPTION)/tools/test/,$(subst $(TGTTOOLS)/tools/test/,,$(RELEASE_FILES)))
endif
endif
RELEASE_FILES variable has multiple file paths assigned. Out of those files i am interested only in folders with $(TGT_TOOLS)/tools/test/ and replace it with $(TARGET_EXCEPTION)/tools/test/.. Is there anything wrong in my above code? Please help!
I have a requirement to replace the file paths based on certain condition.
I daresay the actual requirement is probably more like "the tests should be installed in the directory named by $(TARGET_EXCEPTION) in a release build, but in the directory named by $(TGT_TOOLS) otherwise. The distinction is important, because it is clearer and more portable to just assign the path appropriately in the first place.
That might look something like this:
# Possible test install locations
TARGET_EXCEPTION := /home/ip/lib_build
TGT_TOOLS := /demo/build/new_project
####
#
# Determine which location to use
#
ifdef SET_BUILD
TEST_INSTALL_RELEASE := $(RELEASE)
else
TEST_INSTALL_RELEASE := 0
endif
ifneq (0,$(TEST_INSTALL_RELEASE))
TEST_DIR := $(TARGET_EXCEPTION)
else
TEST_DIR := $(TGT_TOOLS)
endif
#
####
# Define the release files in the desired location from the start
RELEASE_FILES := \
# ...
$(TEST_DIR)/tools/test/test1 \
$(TEST_DIR)/tools/test/test2 \
# ...
# No substitution needed; the targets are already named correctly
FILES += $(RELEASE_FILES)
Is there anything wrong in my above code?
It attempts to implement a poor approach. Also, it very well might not interoperate as you require with your makefile's rules related to the affected files. The above might also have the latter problem, but in that case there is also a clear solution: refer to the affected files everywhere by the name format given in the example.

Makefile processing files with same extension

This seems slightly related to How to write Makefile where target and source files have the same extension?. In that question the extensions are the same, but the input and output files seem to be in the same directory and filenames are being conditionally renamed.
I have a large collection of .txt files in ../src/ that need to be processed, and dumped into ./ (which is a directory called target/) as txt files of the same name. I want to use make, so that only files in ../src/ that have been changed get updated in ./. I would like to get the prototype working before I put the real code in.
My Makefile in ./ is as follows:
DIR = ../src
INPUTS = $(wildcard $(DIR)/*.txt)
OUTPUTS = $(patsubst $(DIR)/%.txt,%.txt,$(INPUTS))
all: $(OUTPUTS)
.PHONY: $(INPUTS)
check:
#echo "DIR = $(DIR)"
#echo "INPUTS = $(INPUTS)"
#echo "OUTPUTS = $(OUTPUTS)"
%.txt: $(DIR)/%.txt
sed -e "s/test/cat/g" "$<" > $#
For now, the contents of ../src/ are test1.txt and test2.txt.
As the Makefile stands now, running make test2.txt generates the file as expected.
target/ $ make test2.txt
sed -e "s/test/cat/g" "../src/test2.txt" > test2.txt
Running make check shows the INPUTS and OUTPUTS correctly.
target/ $ make check
DIR = ../src
INPUTS = ../src/test1.txt ../src/test2.txt
OUTPUTS = test1.txt test2.txt
If I run make all, it generates every file, every time. This is expected with the .PHONY $(INPUTS) line in there.
If I remove the .PHONY $(INPUTS) target, Make gets all bound up in itself trying to find the target to make ../src/test1.txt and keeps prefixing $(DIR) in front of it until it makes too long of a filename and gives up.
make: stat: ../src/../src/../src/ [repeat for a few pages] ../src/../src/test1.txt: File name too long
make: stat: ../src/../src/../src/ [repeat for a few pages] ../src/../src/../src/test1.txt: File name too long
make: *** No rule to make target `../src/../src/../src/[repeat]../src/../src/test1.txt', needed by `../src/[repeat]../src/../src/test1.txt'. Stop.
It never does get to processing test2.txt.
As I was drafting this, I had the idea to remove the ../ from the DIR,
and relocate the Makefile so it was parent to both src/ and target/. That approach seems to work, but isn't ideal. Eventually there would be a chain of these Makefiles, each pulling from one directory to another.
Is there a way to keep the Makefile in 'target/' along with the generated destination files, and base those destination files off of something in a relative path?
Replace
%.txt: $(DIR)/%.txt
with:
${CURDIR}/%.txt: $(DIR)/%.txt
This way %.txt does not match any .txt file in any directory. In other words, you limit this rule's scope to files in ${CURDIR}/ only and this prevents that endless recursion.
See §10.5.4 How Patterns Match for more details.
It is also good practice to avoid relative paths:
DIR = $(abspath ../src)

Makefile adding spaces to variables

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.

Generic make rules using define

I'm trying to create a common template to generate rules build a set of test cases and place them in unique target locations but have hit a bit of snag with the define directive. The following is the relevant section of my Makefile:
ROOT=../..
PLATFORM=akyboard_gcc
# include all the test cases for the current platform
# They add to the TEST_CASES variable
TEST_CASES=A B
A_FILES = a1.c a2.c
B_FILES = b1.c b2.c
check: $(TEST_CASES:%=check_%)
define CHECK_template
# build artifact directories
$(1)_BLDDIR=$(ROOT)/build/$(PLATFORM)/$(1)
$(1)_OBJDIR=$$($(1)_BLDDIR)/obj
$(1)_EXEDIR=$$($(1)_BLDDIR)/exe
# prepend src/ to all the files that are part of the test case
$(1)_FILES := $($(1:%=%_FILES):%=src/%)
# add the test runner as one of the files to be compiled
$(1)_FILES += test_runner/$(PLATFORM)/main.c
# construct list of objects generated by sources
$(1)_OBJ = $($(1)_FILES:%.c=$$($(1)_OBJDIR)/%.o)
# This creates a rule such as check_{test_case}:
check_$(1): $$($(1)_OBJ)
#echo 1 $(1)
#echo 2 $$($(1)_FILES)
#echo 3 $$($(1)_OBJ)
#echo 5 $$($(1)_OBJDIR)
#echo 4 $$($(1)_BLDDIR)
#echo 6 $$($(1)_EXEDIR)
$$($(1)_OBJDIR)/%.o: $(ROOT)/%.c
#echo coconut
endef
$(foreach testcase, $(TEST_CASES), \
$(eval $(call CHECK_template,$(testcase))) \
)
Issuing "make check" gives the following error
*** No rule to make target `../../build/akyboard_gcc/A/obj/a1.o', needed by `check_A'. Stop.
If I manually create the target rules below it builds without errors
../../build/akyboard_gcc/A/obj/a1.o:
../../build/akyboard_gcc/A/obj/a2.o:
../../build/akyboard_gcc/B/obj/b1.o:
../../build/akyboard_gcc/B/obj/b2.o:
But changing rules like below causes the build error:
../../build/akyboard_gcc/A/obj/%.o:
Would be grateful for any help.
You can find what wrong with your template by replacing eval with info call.
$(foreach testcase, $(TEST_CASES), $(info $(call CHECK_template,$(testcase))))
And your template is fine. But you probably have a problem with pattern rules.
From GNU make manual:
A pattern rule can be used to build a given file only if there is a
target pattern that matches the file name, and all prerequisites in
that rule either exist or can be built.
Perhaps you don't have required sources in $(ROOT) directory. And make just can't create a rule for object file from pattern.

How to get absolute paths after vpath matching in make?

I have a makefile that depending on some properties sets vpath and generates a list of source files into one variable. I need to run the makefile without compiling anything (the compilation is actually handled by a different makefile) and just see to which real files the filenames get matched depending on the vpath settings.
Option 1: Let make do its path search:
.PHONY: whichfiles
whichfiles: $(LIST_OF_SOURCE_FILES)
#echo $+
Option 2: Simulate the path search using $(wildcard):
.PHONY: whichfiles
whichfiles:
#echo $(foreach f,$(LIST_OF_SOURCE_FILES),$(firstword $(wildcard $(VPATH:%=%/$f)) not-found:$f))
Either way, "make whichfiles" will print the list of matched files.
If some of the files can't be found, option 1 will fail with "no rule to make" reporting the first file that could not be found. Option 2 will print "not-found:" for each missing file.

Resources