bugmake - Bugs: bug #57914, abspath does resolve symlink


bug #57914: abspath does resolve symlink

Submitted by:  None
Submitted on:  Fri 28 Feb 2020 09:07:50 AM UTC  
Severity:  3 - Normal Item Group:  Bug
Status:  Not A Bug Privacy:  Public
Assigned to:  None Open/Closed:  Closed
Component Version:  4.1 Operating System:  POSIX-Based
Fixed Release:  None Triage Status:  None

Add a New Comment (Rich Markup)

You are not logged in

Please log in, so followups can be emailed to you.


( Jump to the original submission)

Wed 01 Apr 2020 07:15:46 PM UTC, comment #8: 

Right... GNU make doesn't have any option to act like "pwd -L" does when it manages paths.

The user could do that themselves in their makefile since they have access to "$(PWD)".  Maybe not pretty, but something like this could work:

labspath = $(patsubst $(CURDIR)/%,$(PWD)/%,$(abspath $1))

$(info labspath = $(call labspath,$(dir)))

which puts back the "$(PWD)" prefix.

Paul D. Smith <psmith>
Project Administrator
Wed 01 Apr 2020 06:43:51 PM UTC, comment #7: 

Thank you all for your explanations. I think I now understand it correctly :)

comment #6:

> Just as another proof that it's a feature of the shell: if you don't use the shell's built-in pwd command but instead use /bin/pwd, you'll see that just like make (also not a built-in command in the shell :-)) it shows the physical path:

This one I know (already met in practice).

According to the documentation, it is just a matter of defaults: "pwd" w/o args defaults to "pwd -L", but "/bin/pwd" to "/bin/pwd -P", but that are just defaults:

sdettmer@RefVm3:/tmp $ cd /tmp/
sdettmer@RefVm3:/tmp $ mkdir /tmp/x1
sdettmer@RefVm3:/tmp $ ln -s /tmp/x1 foo
sdettmer@RefVm3:/tmp $ (cd foo && pwd -L && pwd && pwd -P)
sdettmer@RefVm3:/tmp $ (cd foo && /bin/pwd -L && /bin/pwd && /bin/pwd -P)
sdettmer@RefVm3:/tmp $

At least my /bin/pwd (GNU coreutils 8.26) is using $PWD from environment:

sdettmer@RefVm3:/tmp $ man pwd|grep -1 -- -L

       -L, --logical
              use PWD from environment, even if it contains symlinks

sdettmer@RefVm3:/tmp $ (cd foo && /bin/pwd -L && PWD="" /bin/pwd -L )

I guess the different defaults are needed for complex compatibility issues.

Steffen Dettmer <sdettmer>
Tue 31 Mar 2020 10:27:06 PM UTC, comment #6: 

Just as another proof that it's a feature of the shell: if you don't use the shell's built-in pwd command but instead use /bin/pwd, you'll see that just like make (also not a built-in command in the shell :-)) it shows the physical path:

$ mkdir /tmp/x1

$ ln -s /tmp/x1 foo

$ (cd foo && pwd)

$ (cd foo && /bin/pwd)

I don't know about cmake, but I can only assume that it's using the PWD environment variable it inherited from the shell to determine the current working directory, rather than asking the operating system like /bin/pwd (and make) do.

Paul D. Smith <psmith>
Project Administrator
Tue 31 Mar 2020 06:48:58 PM UTC, comment #5: 

I haven't seen half the mails relating to this bug, which might explain how it lay unloved for so long.  I don't think I'm really adding anything to Boyski's posts, which I hadn't seen (and they aren't in my "spam folder"), but here's a demonstration that Make doesn't know what Bash thinks is the logical directory:

martind@paris:/tmp/rtc-400921-FILE-macro/logical$ strace -f make 2>&1 | grep cwd
getcwd("/tmp/rtc-400921-FILE-macro/physical", 4096) = 36
getcwd("/tmp/rtc-400921-FILE-macro/physical", 4096) = 36
martind@paris:/tmp/rtc-400921-FILE-macro/logical$ strace /bin/pwd 2>&1 | grep cwd
getcwd("/tmp/rtc-400921-FILE-macro/physical", 4096) = 36

Well, it could look at:

martind@paris:/tmp/rtc-400921-FILE-macro/logical$ env | grep logical

... if it were willing to sacrifice potential portability or complexity.

Is bash doing the best thing it can?  Yes:

martind@paris:/tmp/rtc-400921-FILE-macro$ strace -f bash -c 'cd logical' 2>&1 | grep chdir
chdir("/tmp/rtc-400921-FILE-macro/logical") = 0

I didn't see the behavior mentioned in the Linux man page for chdir, though there are mentions of ELOOP there, with extra detail at https://pubs.opengroup.org/onlinepubs/009695399/functions/chdir.html, which convinced me that it was chdir rather than getcwd that's following the link.

Martin Dorey <mdorey>
Tue 31 Mar 2020 06:22:15 PM UTC, comment #4: 

I cannot answer anything WRT cmake because I don't know it well but I can say that yes, the OS only knows/cares about "physical". Bash maintains a variable called PWD which tracks the "logical" or "virtual" path and normally when you use the pwd builtin it simply echoes the value of $PWD. But that's not a Linux feature per se, it's a bash behavior.

You can easily try this: using bash, cd through a symlink. You will find that "pwd" reports the logical path whereas the utility /bin/pwd, which is outside of bash and knows nothing about it, reports the physical path as does bash's "pwd -P".

The whole subject of which path should be reported as the "real" cwd is a bit controversial and has been the subject of arguments over the years. There are people who disapprove of the fact that bash reports logical by default. Bottom line, what bash and make say will disagree for this reason.

David Boyce <boyski>
Tue 31 Mar 2020 06:07:59 PM UTC, comment #3: 


thanks so much for your quick reply and detailed explanation!

For my understanding I added:
  /tmp/57914/subdir -> .
and found correctly:
  make -f subdir/Makefile
  $(abspath subdir/Makefile) == /tmp/57914/subdir/Makefile
as well as my (non-)issue:
  make -C subdir
  make: Entering directory '/tmp/57914'
  $(abspath Makefile) == /tmp/57914/Makefile
  make: Leaving directory '/tmp/57914'

Did I understand correctly:
With saying after chdir its "physical" this means this is how the OS/kernel/POSIX(?) sees it and thus make sees it, too?
So my shell has special features to "emulate" that it looks as if it would be "logical"?

This confused me, because in cmake its exactly the other way around: it is not possible (without recompilation of cmake) to use physical paths; they are (almost) always logical. I now understand that cmake tries to mimic the shells behavior (with more or less success). Probably this is required since cmake does not support relative paths (like autoconf/automake do) but has everything absolute, and to avoid breaking $HOME symlinking to "randomized" mountpoints. What a pitty.

Could you please tell me if I understood correctly of, if possible, point me to a place where I can read more, please?

Steffen Dettmer <sdettmer>
Tue 31 Mar 2020 03:34:01 PM UTC, comment #2: 

Here's a test case showing that it behaves as documented:

$ pwd

$ ls -lrt
total 4
-rw-rw-r-- 1 xxxxxxx users 95 Mar 31 08:20 tst57914.mk
lrwxrwxrwx 1 xxxxxxx users 11 Mar 31 08:21 Makefile -> tst57914.mk

$ cat Makefile
path := $(lastword $(MAKEFILE_LIST))
$(info $$(abspath $(path)) == $(abspath $(path)))

$ make
$(abspath Makefile) == /tmp/57914/Makefile
[NOT tst57914.mk]

Your case differs in that you've cd-ed through the symlink. Once that's done the path is "physical" in both cases.

A shell like bash tracks both variants and can be queried for them:

$ pwd

$ pwd -P

But make does not.

David Boyce <boyski>
Fri 28 Feb 2020 09:17:05 AM UTC, comment #1: 

I tested on "Debian GNU/Linux 8" with:

  GNU Make 4.0
  Built for x86_64-pc-linux-gnu

and on "Devuan GNU/Linux ascii" with:

  GNU Make 4.1
  Built for x86_64-pc-linux-gnu

Steffen Dettmer <sdettmer>
Fri 28 Feb 2020 09:07:50 AM UTC, original submission:  

The function "abspath" does resolve symlinks and thus changes from "logical path" to "physical path". In the manual the opposite is stated:

  $(abspath names…)
  Note that, in contrast to realpath function, abspath does not resolve symlinks

In a CWD were one of its components is a symbolic link, I expect that abspath and realpath return different strings: the first the "logical" one with the symlink name, the second the "physical" one with the resolved "real" directory name. Is my expectation correct?

To illustrate the problem:

  mkdir /tmp/rtc-400921-FILE-macro
  cd /tmp/rtc-400921-FILE-macro
  mkdir physical
  ln -s physical logical
  cd logical
  echo -e 'default: Makefile\n\t@echo abspath of dependee : $(abspath $<)\n\t@echo realpath of dependee: $(realpath $<)\n' > Makefile

So the Makefile contains:

  default: Makefile
        @echo abspath of dependee : $(abspath $<)
        @echo realpath of dependee: $(realpath $<)

both functions show the same physical path:

  abspath of dependee : /tmp/rtc-400921-FILE-macro/physical/Makefile
  realpath of dependee: /tmp/rtc-400921-FILE-macro/physical/Makefile

I expect the abspath to be "/tmp/rtc-400921-FILE-macro/logical/Makefile".

Is my expectation correct? What do I do wrongly? Or did I really found a bug in GNUMake?




(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by psmith (Posted a comment)
  • -email is unavailable- added by mdorey (Posted a comment)
  • -email is unavailable- added by boyski (Posted a comment)
  • -email is unavailable- added by sdettmer (Posted a comment)

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.




    Follow 2 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-03-31 psmith StatusNone => Not A Bug
        Open/ClosedOpen => Closed

    Back to the top

    Powered by Savane 3.6