I was flabbergasted to witness the following make output on a 12.1-STABLE (rev 359586) host:
$ make ttytest
cc -O2 -pipe /home/elrond/ttytest.c -o ttytest
ld: error: cannot open output file ttytest: Permission denied
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1
make: stopped in /home/elrond
$ touch ttytest
$ ls -l ttytest
-rw-r--r-- 1 elrond elrond 0 Apr 22 02:05 ttytest
$ ls -ldo .
drwxr-xr-x 44 elrond elrond uarch 91 Apr 22 02:05 .
uid=1001(elrond) gid=1001(elrond) groups=1001(elrond),0(wheel),5(operator),44(video),4000(automedia),4001(mixing)
When using gmake, all went smoothly:
$ gmake ttytest
cc ttytest.c -o ttytest
$ ls -l ttytest
-rwxr-xr-x 1 elrond elrond 24000 Apr 22 02:07 ttytest
$ file ttytest
ttytest: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 12.1 (1201512), FreeBSD-style, with debug_info, not stripped
When trussed, the file creation indeed fails:
36580: openat(AT_FDCWD,"ttytest.tmpc878b15",O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC,0666) ERR#13 'Permission denied'
Created attachment 213656 [details]
Truss trace on bsd make, generated with $ truss -f -a -o truss-make.log make CFLAGS=-v ttytest
Created attachment 213657 [details]
Truss trace on gnu make, generated with $ truss -f -a -o truss-gmake.log gmake CFLAGS=-v ttytest
User error, caused by non-obvious magic behavior (aka "POLA violation") on the part of bmake.
In short, since /usr/obj/home/elrond exists, bsd make is using that as .OBJDIR by default, and changing directory to it before running commands. So it's the permissions on _that_ directory that cause the issue.
It doesn't fail with gmake because that has no such magic behavior.
(In reply to andrew from comment #3)
Indeed, a major POLA violation is it, but also it is still a bug since this "magic behavior" should only select an /usr/obj subdirectory as an objdir only when that directory exists *and* is writable by the current user.