68222

Make starts in wrong directory under FreeBSD

Question:

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 <em>somehow</em> 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.

Answer1:

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

<blockquote>

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

</blockquote>

By contrast, the <a href="https://www.gnu.org/software/make/manual/make.html" rel="nofollow">GNU make manual page</a> 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.

Recommend

  • Bug in external link tracking when opening the link in a new window in Google Analytics?
  • Can printf “%x\\n” \\'a be performed in awk?
  • Append to line that is preceded AND followed by empty line
  • Handling cron jobs in docker?
  • what -j4 value is used to invoke make?
  • Why does this code crash on the distributed app but work in the debugger?
  • Prevent Emacs from modifying the OS X clipboard?
  • Easier way to do non-recursive list on gcs bucket outside appengine
  • Read stdin in chunks in Bash pipe
  • vi mode to emacs mode while on R
  • Extracting individual digits from a float
  • How to use the resource module to measure the running time of a function?
  • Possible to get the line number of the currently executing sproc in SQL Server?
  • How to set an entity field that does not exist on the table but does exists in the raw SQL as an ali
  • Meteor.. accounts- password— Create account on client without login
  • Thread synchronization with syncwarp
  • SSL client cert authentication for only some URLs?
  • is there a way to update filter with async data
  • rewrite uppercase url to lowercase url htaccess
  • How can I run DataNucleus Bytecode Enhancer from SBT?
  • Access user's phone number on iOS 7
  • Jquery Knockout: ko.computed() vs classic function?
  • Java color detection
  • How to assign byte[] as a pointer in C#
  • zope_i18n_compile_mo_files doesn't work on a Zeo configuration
  • OOP Javascript - Is “get property” method necessary?
  • WPF - CanExecute dosn't fire when raising Commands from a UserControl
  • Scrapy recursive link crawler
  • Sails.js/waterline: Executing waterline queries in toJSON function of a model?
  • What is the “return” in scheme?
  • What is Eclipse's Declaration View used for?
  • Redux, normalised entities and lodash merge
  • ActionScript 2 vs ActionScript 3 performance
  • How to make Safari send if-modified-since header?
  • Apache 2.4 - remove | delete | uninstall
  • How to pass list parameters for each object using Spring MVC?
  • What are the advantages and disadvantages of reading an entire file into a single String as opposed
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • JaxB to read class hierarchy
  • How to get NHibernate ISession to cache entity not retrieved by primary key