What are ellipses (...) used for in a Makefile.am? - makefile

I made a library using libtool a while back.
In my example code, the Makefile.am contains ellipses (...). I don't remember what purpose they serve, and googling around I haven't found an answer. What are they for?
ignitech_example_SOURCES = ignitech.cpp …
ignitech_example_dyn_SOURCES = ignitech.cpp …
ignitech_example_LDADD = ../libignitech.la
ignitech_example_dyn_LDADD = -lignitech
example:
$(MAKE) $(AM_MAKEFLAGS) -C .. all
$(MAKE) $(AM_MAKEFLAGS) ignitech_example
$(MAKE) $(AM_MAKEFLAGS) ignitech_example_dyn

Elipses do not have any special significance to Automake. If you put an elipsis in a list of file names, as in the example, then it will be interpreted as a file name. Automake especially attributes no special significance to the Unicode single-character elipsis, such as appears in your example.
Overall, I'm inclined to guess that the Makefile.am fragment presented in the question in fact is not drawn from a working Automake input file at all, but instead copied verbatim from an example in a book or tutorial, where the elipses are not meant to be taken as literal file content.

Related

How to make install using path with space and dot

I want to make install(sudo make install) using path with space and dot. (e.g. /Applications/Sample App.app/Contents/Resources)
However, following error invoked.
ginstall: target 'App.app/Contents/Resources/lib/libserialport.a' is not a directory
If I use the path with only space, sudo make install really works well with \ escape character.
Makefiles and pathnames which contain spaces do not mix well. Make uses whitespace to split strings into lists. For example, of you write this:
SOURCES = foo.c bar.c baz.c
OBJECTS = $(patsubst %.c,%.o, $(SOURCES))
program: $(OBJECTS)
Then make will treat the variables SOURCES and OBJECTS as lists of strings, split on whitespace characters, and program will depend on the three items foo.o, bar.o, baz.o.
Make does not know at all that some strings should not be split this way (because they refer to pathnames). Like many early scripting languages, it is completely based on string interpolation. This is true for the shell script fragments used to write the build steps as well.
There are some workarounds possible, but they all depend on how variables are used within the makefile. Recursive makefiles can pose additional problems if the contents of these variables are passed down explicitly to the invoked make command using the shell.
In some cases, the fix is rather simple, so if there is an install rule like this:
install: program
$(INSTALL) -m 755 program $(DESTDIR)$(bindir)/program
It may be sufficient to add quotes, like this:
install: program
$(INSTALL) -m 755 program "$(DESTDIR)$(bindir)/program"
But this really depends on the makefile in question.
If the project uses automake (like libserialport), the simplest solution is to use the DESTDIR support in the generated makefile to install the whole thing to a path which does not contain spaces, and then move it to the final destination afterwards. This assumes that the project does not internally embed the final installation path, though.

Makefile where target names unknown

I'm trying to write a Makefile where multiple source files (in my case they are markdown) create multiple target files (pdfs). However, the target files generated have extra characters in the file name that can't be predicted (it happens to be a version number encoded in the source), but ideally the Makefile would not have to read the source itself.
So, for example:
file1.md => file1-v1.pdf
file2.md => file2-v2.pdf
...
I can calculate source name given a target name (by excluding anything after the hyphen and adding .md), but cannot calculate target name given the source.
Is it possible to write a Makefile that builds only the targets where the source have been updated?
This will be ugly, but it will work.
As it often is with Make, our problem divides into these two problems:
1. construct a list of targets
2. build them
Suppose we have five md files which map to pdf files (whose names we don't know beforehand):
file1.md => file1-v1.pdf
file2.md => file2-v1.pdf
file3.md => file3-v1.pdf
file4.md => file4-v1.pdf
file5.md => file5-v1.pdf
We can't use the real output file names as targets, because we don't know them beforehand, but we see five input files and know that we must build one output file for each. For now, a fake target name will do:
file1-dummy.pdf: file1.md
zap file1.md
When Make executes this rule, it produces the file file1-v1.pdf. The fact that it doesn't produce a file named file1-dummy.pdf is disquieting, but not a serious problem. We can turn this into a pattern rule:
%-dummy.pdf: %.md
zap $<
Then all we have to do is turn the list of existing input files (file1.md, file2.md, ...) into a list of dummy targets (file1-dummy.pdf, file2-dummy.pdf, ...), and build them. So far, so good.
But suppose some of the output files already exist. If file2-v2.pdf already exists -- and is newer than file2.md -- then we would prefer that Make not rebuild it (by attempting to build file2-dummy.pdf). In that case we would prefer that file2-v2.pdf be in the target list, with a rule that worked like this:
file2-v2.pdf: file2.md
zap $<
This is not easy to turn into a pattern rule, because Make does not handle wildcards very well, and cannot cope with multiple wildcards in a single phrase, not without a lot of clumsiness. But there is a way to write one rule that will cover both cases. First note that we can obtain the part of a variable before the hyphen with this kludge:
$(basename $(subst -,.,$(VAR)))
Armed with this, and with secondary expansion, we can write a pattern rule that will work with both cases, and construct a target list that will exploit it:
# There are other ways to construct these two lists, but this will do.
MD := $(wildcard *.md)
PDF := $(wildcard *.pdf)
PDFROOTS := $(basename $(subst -,.,$(basename $(PDF))))
MDROOTS := $(filter-out $(PDFROOTS), $(basename $(MD)))
TARGETS:= $(addsuffix -foo.pdf, $(MDROOTS)) $(PDF)
.SECONDEXPANSION:
%.pdf: $$(basename $$(subst -,., $$*)).md
# perform actions on $<
Make's algorithm always starts with the final output product and works its way backwards to the source files, to see what needs to be updated.
Therefore, you HAVE to be able to enumerate the final output product as a target name and correlate that back to the inputs that generate that output, for make to work.
This is also why make is not a great tool for building Java, for example, since the output filenames don't map easily to the input file names.
So, you must have at least one target/prerequisite pair which is derivable (for implicit rules), or state-able (for explicit rules)--that is, known at the time you write the makefile. If you don't then a marker file is your only alternative. Note you CAN add extra generated, non-derivative prerequisites (for example, in compilers you can add header files as prerequisites that are not related to the source file name), in addition to the known prerequisite.
#Beta's answer is informative and helpful, but I needed a solution (using GNU Make 4.1) that worked when the destination filename bears no resemblance to the input filename, for example, if it is generated from its content. I came up with the following, which takes every file matching *.in, and creates a file by reading the contents of the source file, appending a .txt, and using it as a filename to create. (For example, if test.in exists and contains foo, the makefile will create a foo.txt file.)
SRCS := $(wildcard *.in)
.PHONY: all
all: all_s
define TXT_template =
$(2).txt: $(1)
touch $$#
ALL += $(2).txt
endef
$(foreach src,$(SRCS),$(eval $(call TXT_template, $(src), $(shell cat $(src)))))
.SECONDARY_EXPANSION:
all_s: $(ALL)
The explanation:
The define block defines the recipe needed to make the text file from the .in file. It's a function that takes two parameters; $(1) is the .in. file and $(2) is the contents of it, or the base of the output filename. Replace touch with whatever makes the output. We have to use $$# because eval will expand everything once, but we want $# to left after this expansion. Since we have to collect all the generated targets so we known what all the make, the ALL line accumulates the targets into one variable. The foreach line goes through each source file, calls the function with the source filename and the contents of the file (i.e. what we want to be the name of the target, here you'd normally use whatever script generates the desired filename), and then evaluates the resulting block, dynamically adding the recipe to make. Thanks to Beta for explaining .SECONDARY_EXPANSION; I needed it for reasons not entirely clear to me, but it works (putting all: $(ALL) at the top doesn't work). The all: at the top depends on the secondary expansion of all_s: at the bottom and somehow this magic makes it work. Comments welcome.
maybe try this ? or something along those lines
# makefile
SRCS=$(wildcard *.md)
PDFS=$(shell printf *.pdf)
$(PDFS): $(SRCS)
command ...
the printf *.pdf is meant to either expand to the first of the pdf files if they exist, else fail if they don't and that will signal to make that it should build. if this doesn't work i suggest maybe experimenting with find, ls or other listing tools (e.g. compgen, complete), maybe even in combination with xargs to get everything on one line.

Detect if make command target is a path or a phony

Background
I am writing several books in Markdown. My files are structured as follows:
Description
writing/
Makefile 1. main Makefile (shown below)
book.template 2. pandoc template that uses TITLE
books/
current.txt 3. contains the current book name
book1/
meta.mk 4. sub-Makefile that defines TITLE
chapters/
01.md 5. actual text of book 1, chapter 1
02.md
...
book2/
meta.mk
chapters/
01.md
02.md
...
...
Here is the Makefile:
CURR_BOOK_NAME:=$(shell cat books/current.txt)
CURR_BOOK_DIR:=books/$(CURR_BOOK_NAME)/
CURR_CHAPTERS_DIR:=$(CURR_BOOK_DIR)chapters/
CURR_CHAPTERS:=$(wildcard $(CURR_CHAPTERS_DIR)*.pdf)
# suppose that each meta.mk defines the TITLE variable
include $(CURR_BOOK_DIR)/meta.mk
all: pdfs
...
pdfs: $(CURR_CHAPTERS)
%.pdf: %.md book.template
pandoc -o $# $< ... \
--template=book.template \
--variable=title:$(TITLE)
I usually work on only one book at a time. Thus, it was convenient to create a file current.txt with the name of the current book. Now I just type make to compile the current book to PDF by having the Makefile read in current.txt. Note that the PDF depends on a variable defined in the book-specific meta.mk.
Question
Occasionally, I want to make a small change to another book. How should I modify the Makefile so that I don’t have to update current.txt and then change it back each time? To be more precise, I would like to detect whether the arguments passed to make on the command line are phony targets or paths. For example, I would like the process to look like:
$ cat books/current.txt
book1
$ ls books/*/chapters/*
books/book1/chapters/01.md books/book1/chapters/02.md
books/book2/chapters/01.md books/book2/chapters/02.md
$ make
pandoc -o books/book1/chapters/01.pdf ... --variable=title:One
pandoc -o books/book1/chapters/02.pdf ... --variable=title:One
$ ls books/*/chapters/*
books/book1/chapters/01.md books/book1/chapters/02.md
books/book1/chapters/01.pdf books/book1/chapters/02.pdf
books/book2/chapters/01.md books/book2/chapters/02.md
$ make books/book2/chapters/01.pdf
pandoc -o books/book2/chapters/01.pdf ... --variable=title:Two
$ ls books/*/chapters/*
books/book1/chapters/01.md books/book1/chapters/02.md
books/book1/chapters/01.pdf books/book1/chapters/02.pdf
books/book2/chapters/01.md books/book2/chapters/02.md
books/book2/chapters/01.pdf
Possible solutions
It was suggested to override the variable on the command line:
make CURR_BOOK_NAME=book2 books/book2/chapters/01.pdf
However, I think this is too verbose and redundant, since it requires repeating the name of the book twice, and typing the name of the internal variable CURR_BOOK_NAME once.
Note
This is a simplified example. Please ask if you want to see the actual Makefile. Also, feel free to clarify the question title.
The following valuable answer was posted earlier, but after a short discussion of pros/cons in the comments, the answerer deleted it and left a downvote without opting to comment. I reproduce it here in case it helps other users. I am still looking for a “more complicated” solution that avoids the redundancy and allows building individual chapters.
A simple solution would be copy your Makefile to a new file, say book.mak and delete the first line CURR_BOOK_NAME:=$(shell cat books/current.txt). Then create new Makefile like this:
CURR_BOOK_NAME:=$(shell cat books/current.txt)
current:
$(MAKE) -f book.mak CURR_BOOK_NAME="$(CURR_BOOK_NAME)"
book1:
$(MAKE) -f book.mak CURR_BOOK_NAME="book1"
book2:
$(MAKE) -f book.mak CURR_BOOK_NAME="book2"
Then when you change something in book1 while book2 is current just type make book1. The makefile will figure out what's changed and update it.
If you really want to be able to type make books/book2/chapters/01.pdf then it's a fair bit more complicated.
I would restructure this so that your top-level Makefile is referenced from the top-level directory of each individual project. Think of it as a support library for each book project and manage it accordingly.
The individual Makefile can then be as simple as
include /usr/local/share/lib/bookmaker/main.mk
... assuming you call the library bookmaker and install it at this path. (It could live in a tree somewhere below your home directory just as well.)
I would think of this as a normalization of your de facto project structure, more than a new arrangement. Your individual books already depend on the bookmaker Makefile, but forcing them to live in physical subdirectories makes it harder to work on an experimental clone (assuming you manage each individual book as a separate Git project -- if not, switching to this model probably makes even more sense!). You can also get rid of the minor but pesky inconvenience of the "current" state file you will now obviously no longer need.

GNU Make -- Append to a variable all targets matching a pattern

Before I start, I'll mention that I'm not using GNU Make in this case for building a C/C++ project.
Makefile:
DEST_DIR = build/
SRC_DIR = src/
$(SRC_DIR)a/ : $(SOMETHING_ELSE)
$(DO_SOMETHING_TO_GENERATE_A_DIR)
$(DEST_DIR)% : $(SRC_DIR)%
cp -r $^ $#
ALL_DEPS += <SOMETHING>
... more code which appends to ALL_DEPS ...
.PHONY: all
all : $(ALL_DEPS)
I've got some files not generated via Make rules in $(SRC_DIR). (For the sake of this example, let's say there's a directory $(SRC_DIR)b/ and a file $(SRC_DIR)c .)
I want to append to ALL_DEPS all targets which represent files or directories in $(DEST_DIR) so that "make all" will run all of the available $(DEST_DIR)% rules.
I thought to do something like this:
ALL_DEPS += $(addprefix $(DEST_DIR),$(notdir $(wildcard $(SRC_DIR)*)))
But of course, that doesn't catch anything that hasn't yet been made. (i.e. it doesn't append $(DEST_DIR)a/ to the list because $(SRC_DIR)a/ doesn't yet exist when the $(wildcard ...) invocation is evaluated and the shell doesn't include it in the results returned by the $(wildcard ...) invocation.)
So, rather than a function which finds all (currently-existing) files matching a pattern, I need one which finds all targets matching a pattern. Then, I could do something like this:
ALL_DEPS += $(addprefix $(DEST_DIR),$(notdir $(targetwildcard $(SRC_DIR)*)))
If it matters any, I've got much of the GNU Make code split across multiple files and included by a "master" Makefile. The ALL_DEPS variable is appended to in any of these files which has something to add to it. This is in an attempt to keep the build process modular as opposed to dropping it all in one monster Makefile.
I'm definitely still learning GNU Make, so it's not unlikely that I'm missing something fairly obvious. If I'm just going about this all wrong, please let me know.
Thanks!
It is simply not possible to do what you're trying to do; you're trying to get make to recognise something that doesn't exist.
This is part of the reason why, in general, wildcards are bad (the other being that you can end up including stuff you didn't mean to). The right thing to do here is to explicitly create a list of source files (ls -1 | sed -e 's/\(.*\)/sources+=\1/' > dir.mk) and perform the patsubst transformation on that list.
If you have additional files that are generate as part of the build, then you can append them to that list and their rules will be found as you'd expect.

I Want my makefile to be more order independent!

This is related to my previous question: Why does .PHONY not work in this situation?.
I have a makefile system that I wrote to make it easy for developers who are not familiar with make, to do their tasks. In short, there is a generic portion which would be the same for all projects, and a set of makefiles that are specific for a given project. The project specific ones include the generic ones. It worked great on make 3.80 for some reason, but when I tried it out on make 3.81 I ran into a few problems. That forced me to make changes that are mentioned in the above post. Now I have some new problems, so I decided to make another post. Like in that post, I made a much smaller and simpler set of makefiles that show the problem. Unfortunatly, the "simple" case consists of 6 files. Sorry about that. First I'll start with the "project specific" ones (these are meant to be simple):
makefile:
TARGETS:=\
Lib1.mk \
Lib2.mk \
my_prog.mk \
include generic/top.mk
Lib1.mk:
BINARY:=Lib1
TYPE:=LIB
LOCATION:=a/location
include generic/rules.mk
Lib2.mk:
BINARY:=Lib2
TYPE:=LIB
LOCATION:=another/location
LIBS:=Lib1
include generic/rules.mk
my_prog.mk:
BINARY:=my_prog
TYPE:=EXE
LOCATION:=some/location
LIBS:=Lib1 Lib2
include generic/rules.mk
A quick description: Makefile simply lists the names of all the targets. A target is either a executable or a library. BINARY is the name of the library or executable (extensions are added by the generic part). TYPE is either EXE or LIB. LOCATION is where the binary should go. LIBS is whatever libraries this binary depends on. The real ones handles creating all the -L, rpath, etc. stuff for the user (as well as their equivalents for visual studio). Now for the generic ones (these do the REAL work):
generic/top.mk:
ALL_BINS:=
.PHONY: all
all:
include $(TARGETS)
all: $(ALL_BINS)
%.so %.exe:
mkdir -p $(dir $#)
touch $#
clean:
rm -rf out
and finally..
generic/rules.mk:
ifeq (EXE,$(TYPE))
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/$(BINARY).exe
else
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/lib$(BINARY).so
endif
$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$($(a).FULL_FILE_NAME))
ALL_BINS+=$(BINARY)
$(BINARY): $($(BINARY).FULL_FILE_NAME)
$($(BINARY).FULL_FILE_NAME): $($(BINARY).DEP_LIBS)
BINARY:=
LOCATION:=
LIBS:=
Ok, in this state, things work fine. Make handles all the dependencies correctly, and if I touch any of the files, it will correctly "build" only the ones that it has to, and nothing more. The problem happens when you take the m_prog.mk line from makefile and move it to the top of the list, like so:
TARGETS:=\
my_prog.mk \
Lib1.mk \
Lib2.mk \
The problem seems to be that while its is going through rules.mk for my_prog.mk it does not yet know what the full library path for Lib1 and Lib2 (they are empty strings). So in the end, it considers my_prog to be dependent on nothing and it tries to build it out of order. In this example, you just see it "touch" my_prog first and then the other 2. Of course, when I have real compiler and linker commands in there, it throws an error.
Back when I simply had the .PHONY targets depend on each other (so my_prog depended on Lib1 and Lib2) life was easy and harmonious. Now that I can't do that, life became more difficult.
You may say, "heck just put it in the right order!". Well up to now, this has been handled automatically through make for the end users. In fact, most customers have been putting things in alphabetical order. They don't know or care what order they depend on each other. It would stink to have to tell them to re-order all of that now. Sorry for the length of this post. I'd appreciate any answers!
If you set variables using the := assignment operator, the assignment is evaluated immediately.
If you set variables using just = as the assignment operator, they're evaluated lazily, as late as possible (at the time of actual use).
See http://www.gnu.org/software/automake/manual/make/Flavors.html.
There are several ways to do what you want. The cleanest is probably by using vpath. Just modify rules.mk:
$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$(a).so)
ALL_BINS+=$(BINARY)
vpath %.so out/$(LOCATION)

Resources