2

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?

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220

1 Answers1

1

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 command make obj will create the OBJDIRs. See the file bsd.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 command make obj or the command make 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 be bmake obj && bmake all, since the second bmake(1) process has now the chance to change to the OBJDIR created by the previous run.

Michaël Le Barbier
  • 6,103
  • 5
  • 28
  • 57
  • Thanks for the elaborate answer. I meant the make shipped with the system. And all that `env MAKEOBJDIR=/xxx/obj make obj` does for me is creating the `/xxx/obj` directory, which is absolutely pointless and redundant. The hard part that I want it to automate is the creation of all the subdirectories as needed... As it looks bmake doesn't really support this. – Yakov Galka Dec 30 '16 at 10:41
  • @ybungalobill You should investigate the difference between MAKEOBJDIR and MAKEOBJDIRPREFIX. Again, bmake (the program) will not create any directory on its own, this is should be implemented by he macros you use. If you opt for using the makefiles shipped with the system, have a look at cat's [Makefile](https://github.com/freebsd/freebsd/blob/master/bin/cat/Makefile), esp. the `.include ` directive. To handle file hierarchies see the parent directory's [Makefile](https://github.com/freebsd/freebsd/blob/master/bin/Makefile) esp. the `.include ` directive. – Michaël Le Barbier Jan 02 '17 at 06:23
  • 1
    The makefiles you link use the bsd's mk-files infrastructure to automatically build everything from those `SRC`, and `SUBDIR` vars. I assume that that infrastructure is also responsible for creating the subdirectories, rather than bmake itself. I *don't have any of those variables and don't want to use them*. I already have the rules written by me and only wish make could auto-create the subdirectories of the targets. I've already asked it in other places and nobody seems to know how to do it. I guess it is simply not supported out-of-the-box. – Yakov Galka Jan 02 '17 at 08:08
  • In particular, notice that I have only one makefile, not makefile per directory. – Yakov Galka Jan 02 '17 at 08:09
  • @ybungalobill Then you are in the third of the cases I listed: “If you use custom bmake(1) directives, …” and you definitely need to implement the creation of object directories manually. When a project grows,having roughly a directory per artefact to produce (e.g. a program or a library) makes it easier to move things around and rebuild parts independently (think “loose coupling”). – Michaël Le Barbier Jan 02 '17 at 08:33