1
votes

Background

I am just getting started with C++ programming on LINUX. In my last question, I asked about best practices of using makefiles for a big application. "SO" users suggested to read Miller's paper on recursive makefiles and avoid makefile recursion (I was using recursive makefiles).

I have followed miller and created a makefile like the below. Following is the project structure

root
...makefile
...main.cpp
...foo
......foo.cpp
......foo.h
......module.mk

My makefile looks like the below

#Main makefile which does the build

CFLAGS =
CC = g++
PROG = fooexe

#each module will append the source files to here
SRC :=

#including the description
include foo/module.mk

OBJ := $(patsubst %.cpp, %.o, $(filter %.cpp,$(SRC))) main.o

#linking the program
fooexe: $(OBJ)
    $(CC) -o $(PROG) $(OBJ)

%.o:
    $(CC) -c $(SRC)

main.o:
    $(CC) -c main.cpp

depend:
    makedepend -- $(CFLAGS) -- $(SRC)

.PHONY:clean
clean:
    rm -f *.o

Here is the module.mk in foo directory.

SRC += foo/foo.cpp

When I run make -n, I get the following output.

g++ -c  foo/foo.cpp
g++ -c main.cpp
g++ -o fooexe  foo/foo.o main.o

Questions

  • Where should I create the object(.o) files? All object files in a single directory or each object files in it's own modules directory? I mean which is the best place to generate foo.o? Is it in foo directory or the root (My example generates in the root)?
  • In the provided example, g++ -c foo/foo.cpp command generates the .o file in the root directory. But when linking(g++ -o fooexe foo/foo.o main.o) it is looking for the foo/foo.o. How can I correct this?

Any help would be great

4
Our build system at my company is setup so each module has a "obj" directory where objects & binaries are put. Binaries are then posted up to the toplevel bin if the build succeeds. It works really well.Brian Gianforcaro

4 Answers

1
votes
  • Where should I create the object(.o) files? All object files in a single directory or each object files in it's own modules directory? I mean which is the best place to generate foo.o? Is it in foo directory or the root (My example generates in the root)?

I find it easier for investigating failed builds to localize object files in a separate directory under the module level directory.

foo
    |_ build
    |_ src 

Depending on the size of the project, these object files are grouped to form a component at a higher level and so on. All components go to a main build directory which is where the main application can be run from (has all dependent libraries etc).

  • In the provided example, g++ -c foo/foo.cpp command generates the .o file in the root directory. But when linking(g++ -o fooexe foo/foo.o main.o) it is looking for the foo/foo.o. How can I correct this?

Use:

 g++ -o fooexe  foo.o main.o
0
votes

+1 for SCons.
I am using SCons, too. It scans the dependencies for you and it only rebuilds when source has changed as it uses cryptographic hash sums instead of timestamps.

In my SCons build the objects live in parallel directories to the source (to enable multiple builds like combinations of 32bit and 64bit, release and debug):

src
.build
  linux
    i686
      debug
      release
    x86_64
      debug
      release
0
votes

With regards to object and other generated interim files, I put these in a directory completely separate from the sources (I.e. under a directory that is excluded from backup and revision control). It may be slightly more bother to setup in projects or makefiles, but it saves time packaging up sources, and it is easier to have clean backups and revision control.

I create a subdirectory structure for the object files that matches the subdirectory structure for sources. Typically I have a separate subdirectory for each of my libraries and programs.

Additionally I also use multiple compilers (and versions) and multiple operating systems, so I will reproduce the object file directory structure under a directory for each of these compilers (which have newer versions of the standard and vendor libraries) to prevent object files with mismatched included header file versions.

-1
votes

The best thing you can do for yourself is to use something better than Make. SCons is my tool of choice on POSIX systems. Boost also has a build tool that is very flexible, but I had a hard time wrapping my head around it.

Oh, and if you want to use make, go ahead and build recursive makefiles. It really isn't that big a deal. I worked on a gigantic project using tons of recursive makefiles over the last three years, and it worked just fine.