OS: FreeBSD 11.0-RELEASE
I have the following directory structure:
/xxx/obj/
/xxx/src/deep.cpp
/xxx/flat.cpp
/xxx/makefile
The content of makefile is as follows:
flat.out: flat.o
deep.out: src/deep.o
I have no problem building flat:
/xxx $ make flat.out
c++ -O2 -pipe -c /xxx/flat.cpp -o flat.o
cc -O2 -pipe flat.o -o flat.out
/xxx $ ls obj
flat.o flat.out
But when I try to build deep it fails:
/xxx $ make deep.out
c++ -O2 -pipe -c /xxx/src/deep.cpp -o src/deep.o
error: unable to open output file 'src/deep.o': 'No such file or directory'
1 error generated.
*** Error code 1
Stop.
make: stopped in /xxx
If I then create /xxx/obj/src
manually it succeeds:
/xxx $ mkdir obj/src
/xxx $ make deep.out
c++ -O2 -pipe -c /xxx/src/deep.cpp -o src/deep.o
cc -O2 -pipe src/deep.o -o deep.out
/xxx $ ls obj
deep.out flat.o flat.out src
/xxx $ ls obj/src
deep.o
According to this source bmake (aka bsdmake?) supports automatic creation of out-of-source OBJDIRs, but I cannot figure out how exactly.
How do I configure bmake to create the relevant directories automatically, in the general case?
Automatic creation of out-of-source OBJDIRs is supported but not in the sense you seem to expect it. Creation of out-of-source OBJDIRs can be implemented with bmake(1) directives but is not supported by the bmake(1) program itself. That said,
If you use bmake(1) directives shipped with FreeBSD to build your project, then the creation of OBJDIRs is supported and implemented by the
obj
target, so that the commandmake obj
will create the OBJDIRs. See the filebsd.obj.mk
for further documentation and implementation details. FreeBSD sources contain a lot of examples of programs using these directives to build.If you use bmake(1) directives shipped as the (portable) bsdowl package, then the creation of OBJDIRs is supported and implemented by the target
obj
so that the commandmake obj
or the commandmake preparatives
using a more general target will create the OBJDIRs. The example directory contains several C-based examples showing how to prepare your Makefiles to build your project with the bsdowl package.If you use custom bmake(1) directives, then you will have to implement a target taking care of this creation yourself. The file
bsd.obj.mk
is definitely a good source to get started with this.An important point to note, is that bmake(1) determines its actual working directory before processing any targets, which means that it is almost always the right thing to do to execute the target requesting the creation of OBJDIRs on its own. Because of this, the command
bmake obj all
from your example would fail with the same error message you reported above. The correct invocation would instead bebmake obj && bmake all
, since the secondbmake(1)
process has now the chance to change to the OBJDIR created by the previous run.