Source for
git clone git://
Log | Files | Refs | README | LICENSE

commit 2d7a57c4fd350dd707aef47f8474c83fdeefdb6d (patch)
parent 196eed4cde955aee098091b003e65ddf17e4d004
Author: Alex Karle <>
Date:   Tue, 28 Sep 2021 01:07:39 -0400

blog: Add new entry on `make obj`; what, how, why

This is kind of an immediate followup to text-only(7),
which largely skimmed over the HOW and focused more on
just announcing

I'm not 100% in love with the flow/wording of this draft,
but I've read it a few times and I think it's ready to
share. I suppose I can always edit it later.

Mblog.7 | 23++++++++++++++---------
Amake-obj.7 | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+), 9 deletions(-)

diff --git a/blog.7 b/blog.7 @@ -18,34 +18,39 @@ Otherwise, posts below are from newest to oldest: .Pp .Bl -bullet -compact .It +.Xr make-obj 7 +\(em out-of-tree builds with BSD +.Xr make 1 +(09/28/2021) +.It .Xr text-only 7 -- announcing (09/20/2021) +\(em announcing (09/20/2021) .It .Xr creative-coding 7 -- learning through creative limitation (07/18/2021) +\(em learning through creative limitation (07/18/2021) .It .Xr use-feeds 7 -- RSS/Atom feeds; what, why, and how (02/09/2021) +\(em RSS/Atom feeds; what, why, and how (02/09/2021) .It .Xr my-old-man 7 -- Adventures in using +\(em Adventures in using .Xr mdoc 7 for this site's source (12/30/2020) .It .Xr on-writing 7 -- On Writing Without an Audience (10/22/2020) +\(em On Writing Without an Audience (10/22/2020) .It .Xr self-hosted 7 -- Migrating to a Self-Hosted Site (07/19/2020) +\(em Migrating to a Self-Hosted Site (07/19/2020) .It .Xr BLM 7 -- Black Lives Matter (07/13/2020) +\(em Black Lives Matter (07/13/2020) .It .Xr domain-names 7 -- What's in a (domain) name? (03/24/2020) +\(em What's in a (domain) name? (03/24/2020) .It .Xr a-new-hope 7 -- A New Hope (12/19/2019) +\(em A New Hope (12/19/2019) .El .Sh SEE ALSO .Bl -bullet -compact diff --git a/make-obj.7 b/make-obj.7 @@ -0,0 +1,156 @@ +.Dd September 28, 2021 +.Dt MAKE-OBJ 7 +.Os +.Sh NAME +.Nm make-obj +.Nd out-of-tree builds with BSD +.Xr make 1 +.Sh DESCRIPTION +If you've ever built parts of OpenBSD from source, +you may know that the sequence of commands recommended by +.Xr release 8 +is: +.Pp +.Bd -literal -offset indent +$ make obj +$ make +# make install +.Ed +.Pp +If, like me, you've forgotten the +.Ql make obj +step, +you'll find yourself with many derived files in the +current directory of whatever program you're building. +By running +.Ql make obj +first, +a directory called +.Pa obj +appears and the derived files +(usually +.Pa *.o +files) are placed there instead. +Cleverly, the +.Pa obj +directory is actually a symlink to +another filesystem under +.Pa /usr/obj , +making it truly an out-of-tree build. +.Pp +Up until recently, +I understood what the +.Ql obj +target did and why it was useful. +However, it wasn't until I tried to replicate it with the +build for +that I discovered how it worked. +I figured I'd document it here in case it helps anyone else. +.Sh HOW IT WORKS +My discovery of the inner workings of this target was a classic +lesson in RTFM. +After 10-15 minutes of trying to parse the makefiles in +.Pa /usr/share/mk , +I finally searched for +.Pa obj +in the +.Xr make 1 +man page, +and sure enough the answer was the first hit! +I've copied it for convenience below +(licensed under the BSD-3 clause): +.Pp +.Bl -tag -offset indent +.It Va .OBJDIR +Path to the directory where targets are built. +At startup, +.Ic make +searches for an alternate directory to place target files. +.Ic make +tries to +.Xr chdir 2 into +.Ev MAKEOBJDIR +(or +.Pa obj +if +.Ev MAKEOBJDIR +is not defined), +and sets +.Va .OBJDIR +accordingly. +Should that fail, +.Va .OBJDIR +is set to +.Va .CURDIR . +.El +.Pp +With this new knowledge, +getting an out-of-tree build was almost as simple as running +.Ql mkdir obj +before +.Ql make ! +.Pp +The one catch was that, +having chdir'd in, +I had to canonicalize the paths to any scripts used in the build recipes. +For instance, +I have a script in the +.Pa bin/ +directory of this repo. +To call it from the +.Pa obj +directory, +I needed to use its absolute path via the +.Va .CURDIR +variable: +.Pp +.Dl $(.CURDIR)/bin/ < $< > $@ +.Sh PORTABILITY +While I mostly build my site on OpenBSD, +it's important to me that it builds with GNU make too. +.Pp +Unfortunately, +the +.Va .OBJDIR +chdir'ing appears to be an extension in OpenBSD's +make (and possibly NetBSD too). +The good news is that, +with one more trick, +GNU make support is easy to add +(albeit without out-of-tree builds). +.Pp +The one final hack to support GNU make was to define +a portable version of +.Va .CURDIR . +Since +.Va .CURDIR +isn't defined in GNU make (which uses +.Va CURDIR +instead), +I had to define the +.Va DIR +variable that's the concatenation of the two: +.Pp +.Dl DIR = $(.CURDIR)$(CURDIR) +.Pp +.Sh CONCLUSION +I hope this sheds some light on why +.Ql make obj +is common practice on OpenBSD as well as +how to add similar support to your own projects! +.Pp +While not as flexible as GNU make's pattern matching +inference rules (that allow builds in subdirectories), +I find the chdir-ing into +.Pa obj +a cleverly simple way +to obtain a similar end result. +.Sh SEE ALSO +.Bl -bullet -compact +.It +.Xr blog 7 +.It +.Xr text-only 7 +.It +.Xr my-old-man 7 +.El