If a preqequisite in my makefile refers e.g. to %/../some.file, the recipe for %/../some.file is not run.
My makefile contains a recipe
dir/file:
recipe
%/file2: %/../file
recipe
where % matches against dir/subdir. If I make dir/subdir/file2, make complains that it knows No rule to make target dir/subdir/file2. Even if I make dir/subdir/../file, it knows No rule to make target dir/subdir/../file. However, if I make dir/file and make dir/subdir/file2, everything works fine.
Apparently, referring to parent directories works in prerequisites, but not in targets. Do you know how to work around this?
It looks as if Make does take the '..' literally as a folder name, not being aware that it refer to a parent folder. Therefore 'file' is not the same as 'subdir/../file'. Technically, this is true, since 'subdir' could be a symlink, but I could not find any reference to this.
Workaround: add a helper dependency for each folder
dir/%/../file: dir/file
It's not perfect, since '%' can match dir/x1/x2/file. But depending on the structure of the source tree, it might be sufficient.
I've noticed that the following will work:
dir/subdir/../file: dir/file
But it will work only if there are very few files that can be enumerated.
Related
I have a Makefile with only project-level definitions: which source files to use, what binary or library to make, etc..
It includes ../../Make.Arch for architecture-specific definitions (such as compiler command).
In turn, Make.Arch is meant to include ../etc/Makefile.Standard for all the boilerplate of actually allowing the make system to work .
But include requires a path relative to where the makefile is actually being run (or maybe where the first Makefile is), not relative to the second... What to do?
Make interprets relative paths from the working directory, the directory in which Make is being run. You haven't specified how you're running Make, so I'll assume your running it in the directory with Makefile.
If you are allowed to modify the makefiles, you can change the paths.
You could change Make.Arch from this:
include ../etc/Makefile.Standard
to this:
include ../../../etc/Makefile.Standard
but that would require that any makefile that uses Make.Arch be two directories down from it. That's clearly not a good idea. But we can use a variable:
include $(ARCH_DIR)/../etc/Makefile.Standard
which is provided by Makefile (or any other makefile that uses Make.Arch):
ARCH_DIR := ../..
include $(ARCH_DIR)/Make.Arch
If you are not allowed to modify the makefiles, then you must cheat. One way is to create a symbolic link to Makefile.Standard.
mkdir ../etc
ln -s ../../../etc/Makefile.Standard ../etc
Now Makefile will work. (It ought to be possible to make a link to etc/, but for some reason I can't get that to work right now.)
Here is the make file that I am running,
.PHONY: build
build: pre_build_script $(OUTPUTDIR)/%.cpp
$(OUTPUTDIR)/%.cpp: $(INTXTDIR)/%.txt
python.exe $(SOMEDIR)/somepythonscript.py $(INTXTDIR) $(OUTPUTDIR)
.PHONY: pre_build_script
pre_build_script:
pythonscript.exe $(PREBUILDDIR)
This is the output that I get:
$ make build
pythonscript.exe $(SAMPLEDIR)
make: *** No rule to make target '../obj/CPP/%.cpp', needed by 'build'. Stop.
Looks like I'm missing on some sytanx as I get this error inspite of declaring the target dependency. Any suggestions?
This means make cannot find a file named $(OUTPUTDIR)/%.cpp, a prerequisite for the first rule.
You cannot use % as a wildcard anywhere in a rules like this:
build: pre_build_script $(OUTPUTDIR)/%.cpp
it needs to be a part of pattern rule or a static pattern rule.
You can use $(wildcard $(OUTPUTDIR)/*.cpp) to get a complete list of files, but it's an anti-pattern (pun intended). You are supposed to either exactly know what files are used in what rules, or (know it even better and) create a generic pattern rule.
The second pattern rule (one using somepythonscript.py) is supposed to work on a single source-target file pair, $(INTXTDIR)/%.txt -> $(OUTPUTDIR)/%.cpp. The command seems to process all the files in the directory, which is not incremental: it will redo all the work even if only one file was updated.
GNU Make 3.8.1
I am working on what is basically a plugin for a software product. The plugin is built in a subdirectory of the main product, so the directory structure looks something like:
product
product/src
product/plugin
product/plugin/myPlugin
where "myPlugin" is the name of the plugin I'm working on. What I would like to do, is be able to build myPlugin as well as another version of myPlugin, call it myPlugin-lite. This plugin would have the same sources as myPlugin, but use different flags and defines in the makefiles. The idea was to create a duplicate of the myPlugin tree structure, containing only myPlugin's makefiles, and have it build using the sources from myPlugin. So the directory structure would look like:
product
product/src
product/plugin
product/plugin/myPlugin
product/plugin/myPlugin-lite
myPlugin would build and create all its targets within its subdirectory, and myPlugin-lite would build and create all its targets within its subdirectory. I found a few solutions here: http://make.mad-scientist.net/papers/multi-architecture-builds/ and out of these options it seems like the symbolic links would be best, but it still doesn't feel like the "right" way to do this.
My question is, is this the best/simplest/most maintainable way to do this? If not what are the alternatives?
If the only thing you need from myPlugin is source files then this is exactly what VPATH and The vpath Directive are for.
4.5.1 VPATH: Search Path for All Prerequisites
The value of the make variable VPATH specifies a list of directories that make should search. Most often, the directories are expected to contain prerequisite files that are not in the current directory; however, make uses VPATH as a search list for both prerequisites and targets of rules.
Thus, if a file that is listed as a target or prerequisite does not exist in the current directory, make searches the directories listed in VPATH for a file with that name. If a file is found in one of them, that file may become the prerequisite (see below). Rules may then specify the names of files in the prerequisite list as if they all existed in the current directory. See Writing Recipes with Directory Search.
In the VPATH variable, directory names are separated by colons or blanks. The order in which directories are listed is the order followed by make in its search. (On MS-DOS and MS-Windows, semi-colons are used as separators of directory names in VPATH, since the colon can be used in the pathname itself, after the drive letter.)
For example,
VPATH = src:../headers
specifies a path containing two directories, src and ../headers, which make searches in that order.
With this value of VPATH, the following rule,
foo.o : foo.c
is interpreted as if it were written like this:
foo.o : src/foo.c
assuming the file foo.c does not exist in the current directory but is found in the directory src.
Also see How Not to Use VPATH from MadScientist for more discussion about what they aren't for. Though that's largely just a build-up for the multi-architecture-builds paper you already read.
One rule in my Makefile zips an entire directory (res/) into a ZIP file. Obviously, this rule needs to execute when any file under the res/ directory changes. Thus, I want the rule to have as a prerequisite all files underneath that directory. How can I implement this rule?
In Bash with the globstar option enabled, you can obtain a list of all the files in that directory using the wildcard pattern res/**/*. However, it doesn't seem to work if you specify it as a prerequisite in the Makefile:
filename.jar: res/**/*
Even after touching a file in res/, Make still reports
make: `filename.jar' is up to date.
so clearly it is not recognizing the pattern.
If I declare the directory itself as a prerequisite:
filename.jar: res
then Make will not re-execute when a file is modified (I think make only looks at the modified date of the directory itself, which only changes when immediate children are added, removed, or renamed).
This:
filename.jar: $(wildcard res/**/*)
seems to work, at least on some platforms.
EDIT:
Or better, just cut the knot:
filename.jar: $(shell find res -type f)
I am trying to create a subdirectory in my project (let's call it $PROJECT/child) that needs to pull in a Makefile (let's call it ../Makefile.inc) from its parent, $PROJECT/Makefile.inc. Later I want to copy $PROJECT/child somewhere else so it can run independently of $PROJECT.
There is a common Makefile that needs to be included in both projects and shipped when the subdirectory is copied, and I want it to be included in both cases. So I thought I would link it in during the child build, if it isn't found. (I don't want to just include ../Makefile.inc, because this will disappear when I copy the project, and I don't want the calling build system to be responsible for putting the Makefile.inc in place.)
With those constraints, here's a horrible hack that I've come up with to do this, within $PROJECT/child/Makefile:
HACK = $(shell test -f Makefile.inc || ln -f ../Makefile.inc .)
include $(HACK)Makefile.inc
Notice the extra special duct tape on that second command. I have to actually include $(HACK) even though it's going to end up empty, so that the $(shell ...) will be evaluated. ;-)
Is there a cleaner way to make this happen?
Give a rule to build Makefile.inc. (make will complain that Makefile.inc doesn't exist when it parses the include line, but it will go on parsing the main makefile, apply any rule to build included files, and go back and re-parse the main makefile with the included files.)
include Makefile.inc
Makefile.inc:
ln ../Makefile.inc $#