views:

77

answers:

2

Not sure if the title makes sense... so I'll elaborate a bit.

I'm toying with this makefile that uses gcc's auto-dependency list generator.

At the same time, I wanted to keep a nice sorted directory structure that separates source, headers, and resources.

The layout's nice and simple like so

  • MAIN
    • src
    • include
    • objects
    • dependencies

Now, the makefile dependency list generator atm is this:

$(DEP_PATH)%.d : $(SRC_PATH)%.c
    @${CC} $(CFLAGS) -MM -c $(INCLUDE) $< > $(DEP_PATH)$*.d
include $@

The idea here being that we generate the dependency rule, then include it to the make build.

and the result for say, foo1.o is:

foo1.o: src/foo1.c include/foo1.h include/foo2.h include/foo3.h

This would work fine if I labled all my objects to be found in the main directory... however since they in /main/objects instead... the make says it can't find the rule for /main/objects/foo1.o

Now, I tried this:

@echo "$(OBJ_PATH)" > $(DEP_PATH)$*.d
@${CC} $(CFLAGS) -MM -c $(INCLUDE) $< >> $(DEP_PATH)$*.d

Which the > feeds the object path to the new/overwritten file, then concatenates the GCC auto-dependency rule generation to it... but it adds the newline between the two sets.

I tried cat'ing two separate files with said info as well... but they also get the newlines.

Is there a nice way to prepend the dependency file w/out adding the newline?

Also, if you've got any real nice tutorials on makefiles, cat, and echo, I'd really appreciate it.

Thanks for any and all responses.

+3  A: 

The answer to the question you asked is sed:

@${CC} blah blah blah | sed 's|^|$(OBJ_PATH)|' > $(DEP_PATH)$*.d

But you're going to have a different problem with this part:

include $@

The include directive is for Make itself, it is not a shell command (like $(CC)...). And $@ is an automatic variable, defined within the rule, not available to directives outside the rule. Instead, try something like this:

include $(DEP_PATH)/*.d

and take a look at Advanced Auto-Dependency Generation.

Beta
Nice. Does exactly what I wanted in a single line. Thank you very much.I am unfortunately not sure how sed is working however. Looking at the man page, it shows s/regex/replace but this s/^/$(OBJ_PATH) actually prepends it?
CodeXCDM
The `^` means the beginning of the line, so `s/^/foo/` prepends. Also, I used `|` instead of `/` as the delimiter for readability because I was hardcoding `/main/objects/`. When I switched to `$(OBJ_PATH)` I should have changed `|` to `/`.
Beta
Thanks again! BTW, I think you meant $* instead of just *, no?
CodeXCDM
@Code, no, Beta meant `*`, but I think he should have meant `include $(object_files:%=$(OBJ_PATH)/%.d)`.
Pavel Shved
@Pavel Shved, well no, that's not quite what I meant to mean. I agree that `$(object_files:%=%(DEP_PATH)/%.d)` works better if `%.d` is a separate target, but if the command that builds `foo.d` is in the `%.o` rule instead, you can use `$(DEP_PATH)*.d` and avoid some unnecessary Making.
Beta
A: 
CodeXCDM