make does not realize that a relative path name dependency is the same as an absolute pathname target - gnu-make

The following is a simplified makefile for a problem I'm having:
all: /tmp/makey/../filey
#echo All done
/tmp/filey:
#echo Filey
When I run make it says:
make-3.79.1-p7: * No rule to make target /tmp/makey/../filey', needed byall'. Stop.
Clearly it does not realize that /tmp/makey/../filey is the same as /tmp/filey. Any ideas how I can make this work?
Thanks
Ciao
-- Murali

Newer versions of GNU make have $(abspath ...) and $(realpath ...) functions you can apply to your prerequisites and targets to resolve the paths to the same string. If you've constructed these names yourself (for example, $(PREFIX)/../filey) then you can use $(dir $(PREFIX))filey instead.
Other than that, there's no way to solve this problem. Make uses string matching on targets and if the strings are not identical, they don't match (there's a special case to ignore the simple prefix ./) Even if make understood this distinction (by applying abspath itself to each target name, maybe) it would still not help in the face of symbolic links for example.
The only "real" answer would be for make to understand something about the underlying file system (device IDs and inodes for example) that let you talk about files without referring to their pathname. However, in a portable program like make doing this is problematic.

Related

Return one folder above current directory in Julia

In Julia, I can get the current directory from
#__DIR__
For example, when I run the above in the "Current" folder, it gives me
"/Users/jtheath/Dropbox/Research/Projects/Coding/Current"
However, I want it to return one folder above the present folder; i.e.,
"/Users/jtheath/Dropbox/Research/Projects/Coding"
Is there an easy way to do this in a Julia script?
First, please note that #__DIR__ generally expands to the directory of the current source file (it does however return the current working directory if there are no source files involved, e.g when run from the REPL). In order to reliably get the current working directory, you should rather use pwd().
Now to your real question: I think the easiest way to get the path to the parent directory would be to simply use dirname:
julia> dirname("/Users/jtheath/Dropbox/Research/Projects/Coding/Current")
"/Users/jtheath/Dropbox/Research/Projects/Coding"
Note that AFAIU this only uses string manipulations, and does not care whether the paths involved actually exist in the filesystem (which is why the example above works on my system although I do not have the same filesystem structure as you). dirname is also relatively sensitive to the presence/absence of a trailing slash (which shouldn't be a problem if you feed it something that comes directly from pwd() or #__DIR__).
I sometimes also use something like this, in the hope that it might be more robust when I want to work with paths that actually exist in the filesystem:
julia> curdir = pwd()
"/home/francois"
julia> abspath(joinpath(curdir, ".."))
"/home/"

Why does gnu make delete this file?

Consider this Makefile:
.PHONY: all
all: main.txt
main.txt: build/main.txt
cp build/main.txt .
%/main.txt: %/data.txt
cp $*/data.txt $*/main.txt
%/data.txt:
touch $*/data.txt
After running make, build/data.txt is removed automatically. Why is this the case?
I tried adding .PRECIOUS: build/% to the file, but it it not help, the file was still removed. How can I prevent this?
According to the GNU Make documentation
You can also list the target pattern of an implicit rule (such as ‘%.o’) as a prerequisite file of the special target .PRECIOUS to preserve intermediate files created by rules whose target patterns match that file’s name.
the prerequisite for.PRECIOUS needs to be the (exact) target pattern of an existing implicit rule.
In your case this would be %/data.txt instead.
The documentation hints at this, but is not particularly clear about it.
As a side note: As far as I can tell build/main.txt is not automatically deleted since it is explicitly named as a prerequisite for the main.txt target and build/data.txt is automatically deleted since it is never explicitly named.

GNU make: include file only if target is not "clean"

Using GNU make, I want to include a file, except if the current target is "clean".
That is, I want to do the equivalent of the following:
ifneq($(TARGET),clean)
-include somefile.txt
endif
But for that, I need a variable whose value is the target given on the command line (here named $(TARGET)). Such a variable does not seem to exist, and I can understand why, because you could have multiple targets on the command line, some of which you might want to include the file for, and others not. Actually, it would be fine if the file is included when there are other targets besides "clean". The only real problem I currently have is that when the file to be included does not exist, Make will try to build it, which is unnecessary when you're about to delete it again when executing the "clean" target.
So, is there another way to accomplish what I want?
You can use MAKECMDGOALS. Use it like this to handle multiple arguments on the command line:
ifeq (clean,$(filter clean,$(MAKECMDGOALS)))
-include somefile.txt
endif
However, this is often fraught because if you run make clean all or whatever, the include file won't be included even though it might be needed for all.
If you really need this to be reliable another way is to use recursion for your "top-level" arguments, running them one at a time in a sub-make.
You could usefully check that if clean is a target then it is the only target. Otherwise strange things can go wrong silently causing much wailing and gnashing of teeth. My most recent Makefile includes the following. (NB tested but not as yet used extensively).
ifeq (clean,$(filter clean,$(MAKECMDGOALS)))
ifneq($(strip $(filter-out clean,$(MAKECMDGOALS)))
$(error ERROR: can not make other targets with clean
endif
endif

what is the meaning of ${PWD:A}?

I am reading some zsh scripts and found this syntax ${PWD:A}. I know what $PWD is and the bash variable substitution syntax (largely thanks to this excellent tutorial). Despite of that, I haven't found any docs that explain about the ${variable:flag} syntax for zsh.
${PWD:A} returns the symlink-free absolute path of $PWD. It does so by:
prepending the current directory
resolving any .. and .
resolving symbolic links, if the system has the realpath system call - which modern systems do.
As $PWD already is the absolute path of the current directory and does not contain .. or . elements (at least it really should not), ${PWD:A} only has to resolve any symbolic links.
The ${name:flag} syntax allows the use of History Expansion Modifiers on parameters.
It actually is explained in the section Parameter Expansion of the ZSH Manual (see also man zshexpn). Unfortunately it is just a single sentence in the text and not listed with the other ${nameXXXXX} expansions:
In addition to the following operations, the colon modifiers described in Modifiers in History Expansion can be applied: for example, ${i:s/foo/bar/} performs string substitution on the expansion of parameter $i.
A list of the available modifiers can be found in the subsection Modifiers under History Expansion. In the case of A:
a
Turn a file name into an absolute path: prepends the current directory, if necessary, and resolves any use of .. and . in the path. Note that the transformation takes place even if the file or any intervening directories do not exist.
A
As a, but also resolve use of symbolic links where possible. Note that resolution of .. occurs before resolution of symbolic links. This call is equivalent to a unless your system has the realpath system call (modern systems do).

How do /** and /* differ in terms of directory navigation in Grunt?

This is quite an easy one for you guys, but I can't find a definitive/formal answer to this question.
Suppose we are in directory A. Then,
"A/* " probably means: Every file and folder directly inside A.
"A/** " then may mean: Every file and folder inside A, and every file and folder directly inside every child that is directly inside A. (Basically, an extension of /* operator that traverses one level deeper of the root folder? aka "/** " = "/* /* " )
My "directly inside" terminology might be wrong. May be its better to say "direct child" or something, but you get the idea.
Then, what does "A/**/* " mean? Is it equal to "A/* /* /* " ?
Although this seems basic, its quite confusing when I don't have a formal definition of the operators.
I'm currently using Javascript and trying to modify a Gruntfile. But I guess these operators may come up in any context.
This behavior is not intrinsic to JavaScript and is not related to any operators: as far as JavaScript is concerned, it is just a string.
The handling of such glob expansion is determined by the specific library/consumer. For gruntjs it is covered in Grunt Globbing Patterns:
It is often impractical to specify all source filepaths individually, so Grunt supports filename expansion (also know as globbing) via the built-in node-glob and minimatch libraries ..
* matches any number of characters, but not /
** matches any number of characters, including /, as long as it's the only thing in a path part
All most people need to know is that foo/*.js will match all files ending with .js in the foo/ subdirectory, but foo/**/*.js will match all files ending with .js in the foo/ subdirectory and all of its subdirectories.
As such (but refer to the specific documentation!), /**/ generally means "match any depth of directories" and /*/ or /* means "match a single directory or file part".
The gruntjs documentation is a bit vague on the specific mechanics of ** in the standard "/**/*.x" pattern, but referring to node-glob says:
If a "globstar" (**) is alone in a path portion, then it matches zero or more directories and subdirectories searching for matches. It does not crawl symlinked directories.
[.. The double-star character] is supported in the manner of bsdglob and bash 4.3, where ** only has special significance if it is the only thing in a path part. That is, a/**/b will match a/x/y/b, but a/**b will not.
Using this knowledge we get the equivalency (when used as a path component), of A/**/f with A/f, A/*/f, A/*/*/f, etc for every number of intermediate directories.
If you see A/**/* that means to recursively search all the way down the tree of every folder under folder A. For more information look up basic linux style file commands.

Resources