0

I have a very simple Makefile that just shells out to another Makefile:

all:
    cd src && make all

My directory structure (the Makefile is in the top-level directory):

[I] mqudsi@php ~/bbcp> tree -d
.
├── bin
│   └── FreeBSD
├── obj
│   └── FreeBSD
├── src
└── utils

This works just fine under Linux, but under FreeBSD, it gives an error about src not being found.

To debug, I updated the Makefile command to pwd; cd src && make all and I discovered that somehow when I run make in the top-level directory, it is being executed under ./obj instead, meaning it's looking for ./obj/src/ to cd into.

Aside from the fact that I have no clue why it's doing that, I presumed for sure that calling gmake instead of make under FreeBSD would take care of it, but that wasn't the case (and I'm relieved, because I can't believe there is that huge of a difference between BSD make and GNU make in terms of core operation).

The odd thing is, deleting obj makes everything work perfectly. So in the presence of an obj directory, make cds into ./obj first; otherwise it executes as you'd expect it to.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125

1 Answers1

1

Answering my own question here.

From the FreeBSD make man page:

.OBJDIR      A path to the directory where the targets are built.  Its
             value is determined by trying to chdir(2) to the follow-
             ing directories in order and using the first match:

             1.   ${MAKEOBJDIRPREFIX}${.CURDIR}

              (Only if `MAKEOBJDIRPREFIX' is set in the environ-
              ment or on the command line.)

             2.   ${MAKEOBJDIR}

              (Only if `MAKEOBJDIR' is set in the environment or
              on the command line.)

             3.   ${.CURDIR}/obj.${MACHINE}

             4.   ${.CURDIR}/obj

             5.   /usr/obj/${.CURDIR}

             6.   ${.CURDIR}

             Variable expansion is performed on the value before it's
             used, so expressions such as
               ${.CURDIR:S,^/usr/src,/var/obj,}
             may be used.  This is especially useful with
             `MAKEOBJDIR'.

             `.OBJDIR' may be modified in the makefile via the special
             target `.OBJDIR'.  In all cases, make will chdir(2) to
             the specified directory if it exists, and set `.OBJDIR'
             and `PWD' to that directory before executing any targets.

The key part being

In all cases, make will chdir(2) to specified directory if it exists, and set .OBJDIR'PWD' to that directory before executing any targets.

By contrast, the GNU make manual page makes no such reference to any sort of automatic determination of OBJDIR, only that it will be used if it is set.

The solution was to override the OBJDIR variable via the pseudotarget .OBJDIR:

.OBJDIR: ./

all:
    cd src && make
clean:
    cd src && make clean

An alternative solution is to prefix the cd targets with ${CURDIR}, which isn't modified after the chdir into OBJDIR.

I don't get why gmake behaved the same way, however. That feels almost like a bug to me.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125