2

I have a quick question about a makefile I have. I have done some searching, but everyone's makefiles are so different that it's hard to follow along unless you really know the make system well, which I really don't.

So, it is enforced upon me that my makefile be called like:

make -f /path/to/src/Makefile "SRCPATH=/path/to/src"

This is so (ideally) all the objects from different makefiles end up in the same place, as this is run from a directory like /some/path/Objects_C

My directory structure looks like this:

src/
  Makefile
  src1.cpp
  src2.cpp
  src3.cpp

src/src_subdir
  subsrc1.cpp
  subsrc2.cpp
  subsrc3.cpp

I cannot have two makefiles due to the dependencies, and in context, it makes much more sense not to.

Anyway, my makefile is rather simple, it looks like:

SRCPATH ?= .

INCLUDES = -I$.......(all my include paths)

vpath % $(SRCPATH)

CPPFLAGS = -g $(INCLUDES)

    OBJS = src1.o \
       src2.o \
       src3.o \
       $(SRCPATH)/src_subdir/subsrc1.o \
       $(SRCPATH)/src_subdir/subsrc2.o \
       $(SRCPATH)/src_subdir/subsrc3.o

.PHONY : clean all

# ====================================================

libname.a : $(OBJS)
ld -r $(OBJS) -o $@

# ====================================================

Now, I get half of what I want...top level src1.o, src2.o, and src3.o appear where I want (where make was run from, the Objects_C directory), but the subsrc.o files are located in /path/to/src/src_subdir. Am I missing something simple, or am I totally spun around?

I really appreciate any help! Every time I feel like I can do the basics with make, it makes me feel like a beginner again.

prelic
  • 4,450
  • 4
  • 36
  • 46
  • 1
    "This is so (ideally) all the objects from different makefiles end up in the same place" Do you mean all .o files in the same directory, or the same *tree*? Because putting them in the same directory is asking for trouble, as two objects might have the same name unless you are micromanaging the names. – user657267 Apr 23 '16 at 01:53
  • @user657267 I totally understand where you are coming from, but this is one of those cases where this build system and standard practice has been defined, and is part of a bigger build system, even though as you mention it may result in problems. I will keep that in mind and bring it up, but without making widespread changes, it will remain this way for now. – prelic Apr 23 '16 at 01:56
  • 1
    "but the `subsrc.o` files are located in `/path/to/src/sub_src`" did you mean `/path/to/src/src_subdir`? – user657267 Apr 23 '16 at 02:03
  • @user657267 - yes, my apologies, in my removal of context and generalizing the summary, I made a mistake. I will edit, but I meant for sub_src and src_subdir to be the same. – prelic Apr 23 '16 at 02:07

1 Answers1

1

If you want to rely on the built-in rules you'll need to modify your vpath.

The subdir objects are defined as /path/to/src/src_subdir/subsrc1.o etc., so it's no surprise that this will be where they end up. If you want these objects to appear in the same place as the others you'll need to say so

 OBJS = src1.o \
       src2.o \
       src3.o \
       subsrc1.o \
       subsrc2.o \
       subsrc3.o

Now all that's left is to inform make where it can find subsrc*.o

vpath %.cpp $(SRCPATH) $(SRCPATH)/src_subdir

As I commented you'll need to make sure you manage your filenames accordingly or you're going to have a bad time. I also changed the vpath pattern as it looks like you only need cpp for now.

Pedantry alert: -g is a compiler flag, not a pre-processor flag, and should be in CXXFLAGS.

Without vpath the other option is to provide explicit rules and recipes, something like

SUBOBJS := subsrc1.o subsrc2.o subsrc3.o
$(SUBOBJS): %.o: $(SRCPATH)/src_subdir/%.cpp
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $(OUTPUT_OPTION) $<

Both methods will result in exactly the same outcome, however the downside to using vpath like this to lump all your object files is the potential to confuse make if the folders hold the same source file name. Since you seem to be managing the names yourself this shouldn't be an issue.

The second method is safer with the minor inconvenience of having to write your own rules and recipes.

When possible you should aim to replicate the source tree in your build dir as it greatly simplifies the makefile.

user657267
  • 20,568
  • 5
  • 58
  • 77
  • Damn, I really thought I tried that! But of course it worked like a charm. I will accept when it becomes available. If you don't mind, could you briefly describe how the second works and/or the difference between the first and second approach you gave (and maybe the implications)? Either way, thanks a lot, I appreciate the help. – prelic Apr 23 '16 at 02:23
  • I will do some experimenting. Again, thanks for the explanation and help! – prelic Apr 23 '16 at 02:33
  • Thanks for the edit, I've learned some more...TIL CPPFLAGS != C++ flags – prelic Apr 23 '16 at 02:44
  • 1
    @prelic Any reason you're using `ld` to make your archives rather than `ar`? There are a couple of neat tricks with `ar` files and make. – user657267 Apr 23 '16 at 02:48
  • I just was googling about that today because half of our make files use ld, and half use ar. What I read indicated that the pros of using ld are that unused symbols/objects will be left out of the library, while ar will always build a full archive. That said, Id *love* to hear your opinion on the matter. – prelic Apr 23 '16 at 02:51
  • @prelic Try writing `libname.a: libname.a($(OBJS))`, delete the recipe you currently have below, and delete the existing `.o` files before running make again, you should be amused. "unused symbols/objects will be left out of the library" That doesn't sound right, how is `ld` supposed to know which symbols won't be used...before they're used? – user657267 Apr 23 '16 at 02:59
  • Oh cool, so it appears that during the compilation of each source file/object generation, it adds the resulting object to the `libname.a` archive? That's pretty neat! Does it have any advantage besides being concise? The reason I made the comment was due to this thread: http://stackoverflow.com/questions/270984/g-partial-linking-instead-of-archives – prelic Apr 23 '16 at 03:14
  • @prelic Ah I get it now, the unresolved symbols are left unresolved, still it looks like the downside to using `ld` is you'll end up with unused stuff in the executable, unless you're the consumer of the archive itself in which case you'll probably be using everything anyway. The other cool thing about using make's built-in rule for archives is that the object files will be considered as intermediate files and deleted after the archive is made (as long as they aren't directly referenced in the makefile). – user657267 Apr 23 '16 at 03:22