alexkarle.com

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

make-obj.7 (3276B) [raw]


      1 .Dd September 28, 2021
      2 .Dt MAKE-OBJ 7
      3 .Os
      4 .Sh NAME
      5 .Nm make-obj
      6 .Nd out-of-tree builds with BSD
      7 .Xr make 1
      8 .Sh DESCRIPTION
      9 If you've ever built parts of OpenBSD from source,
     10 you may know that the sequence of commands recommended by
     11 .Xr release 8
     12 is:
     13 .Pp
     14 .Bd -literal -offset indent
     15 $ make obj
     16 $ make
     17 # make install
     18 .Ed
     19 .Pp
     20 If, like me, you've forgotten the
     21 .Ql make obj
     22 step,
     23 you'll find yourself with many derived files in the
     24 current directory of whatever program you're building.
     25 By running
     26 .Ql make obj
     27 first,
     28 a directory called
     29 .Pa obj
     30 appears and the derived files
     31 (usually
     32 .Pa *.o
     33 files) are placed there instead.
     34 Cleverly, the
     35 .Pa obj
     36 directory is actually a symlink to
     37 another filesystem under
     38 .Pa /usr/obj ,
     39 making it truly an out-of-tree build.
     40 .Pp
     41 Up until recently,
     42 I understood what the
     43 .Ql obj
     44 target did and why it was useful.
     45 However, it wasn't until I tried to replicate it with the
     46 build for text.alexkarle.com
     47 that I discovered how it worked.
     48 I figured I'd document it here in case it helps anyone else.
     49 .Sh HOW IT WORKS
     50 My discovery of the inner workings of this target was a classic
     51 lesson in RTFM.
     52 After 10-15 minutes of trying to parse the makefiles in
     53 .Pa /usr/share/mk ,
     54 I finally searched for
     55 .Pa obj
     56 in the
     57 .Xr make 1
     58 man page,
     59 and sure enough the answer was the first hit!
     60 I've copied it for convenience below
     61 (licensed under the BSD-3 clause):
     62 .Pp
     63 .Bl -tag -offset indent
     64 .It Va .OBJDIR
     65 Path to the directory where targets are built.
     66 At startup,
     67 .Ic make
     68 searches for an alternate directory to place target files.
     69 .Ic make
     70 tries to
     71 .Xr chdir 2 into
     72 .Ev MAKEOBJDIR
     73 (or
     74 .Pa obj
     75 if
     76 .Ev MAKEOBJDIR
     77 is not defined),
     78 and sets
     79 .Va .OBJDIR
     80 accordingly.
     81 Should that fail,
     82 .Va .OBJDIR
     83 is set to
     84 .Va .CURDIR .
     85 .El
     86 .Pp
     87 With this new knowledge,
     88 getting an out-of-tree build was almost as simple as running
     89 .Ql mkdir obj
     90 before
     91 .Ql make !
     92 .Pp
     93 The one catch was that,
     94 having chdir'd in,
     95 I had to canonicalize the paths to any scripts used in the build recipes.
     96 For instance,
     97 I have a genpost.sh script in the
     98 .Pa bin/
     99 directory of this repo.
    100 To call it from the
    101 .Pa obj
    102 directory,
    103 I needed to use its absolute path via the
    104 .Va .CURDIR
    105 variable:
    106 .Pp
    107 .Dl $(.CURDIR)/bin/genpost.sh < $< > $@
    108 .Sh PORTABILITY
    109 While I mostly build my site on OpenBSD,
    110 it's important to me that it builds with GNU make too.
    111 .Pp
    112 Unfortunately,
    113 the
    114 .Va .OBJDIR
    115 chdir'ing appears to be an extension in OpenBSD's
    116 make (and possibly NetBSD too).
    117 The good news is that,
    118 with one more trick,
    119 GNU make support is easy to add
    120 (albeit without out-of-tree builds).
    121 .Pp
    122 The one final hack to support GNU make was to define
    123 a portable version of
    124 .Va .CURDIR .
    125 Since
    126 .Va .CURDIR
    127 isn't defined in GNU make (which uses
    128 .Va CURDIR
    129 instead),
    130 I had to define the
    131 .Va DIR
    132 variable that's the concatenation of the two:
    133 .Pp
    134 .Dl DIR = $(.CURDIR)$(CURDIR)
    135 .Pp
    136 .Sh CONCLUSION
    137 I hope this sheds some light on why
    138 .Ql make obj
    139 is common practice on OpenBSD as well as
    140 how to add similar support to your own projects!
    141 .Pp
    142 While not as flexible as GNU make's pattern matching
    143 inference rules (that allow builds in subdirectories),
    144 I find the chdir-ing into
    145 .Pa obj
    146 a cleverly simple way
    147 to obtain a similar end result.
    148 .Sh SEE ALSO
    149 .Bl -bullet -compact
    150 .It
    151 .Xr blog 7
    152 .It
    153 .Xr text-only 7
    154 .It
    155 .Xr my-old-man 7
    156 .El