You can do implicit rules which requires a very verbose makefile, which is what automake and other make generation tools do. God help you figure out what went wrong.
If you make people go to a directory approach you've now imposed a new structure on their code. One reason for the multitude of packages is each one matches their target community better.
If both the .o and the .a are created from another file, wouldn't it be safe to just rely on either one of them? (Obviously, you will need to be consistent in choice.)
That is, if every time a .o is created, so is the .a, then where is the difficulty? Just rely on one (the .o). I could conceive of a scenario where the .a updated but the .o didn't, but I don't know of any tools that really work that way right now. I thought the norm was to at least touch all output files.
Further, if that is happening, seems you are safest having two rules, anyway.
Also, having two rules means duplicating a command:
foo: foo.a
baz $(BAZ_OPTIONS) foo
foo: foo.o
baz $(BAZ_OPTIONS) foo
That's bad from a maintenance perspective.The solution to the multiple target problem is using the built in magic .INTERMEDIATE rule which isn't entirely obvious how it works.
I'm curious how .INTERMEDIATE helps in this case. I did find this link[1], which was a rather fun read down how one might go about solving this, along with all of the inherent problems.
[1] http://www.gnu.org/software/automake/manual/html_node/Multip...
ASM = A09/a09
%.o %.l : %.a
$(ASM) -o $(*F).o -l $(*F).l $(*F).a
clean:
/bin/rm -rf *.o *.l
foo : disasm.l
bar : disasm.o
baz : disasm.l disasm.o
The target baz has both a .l and a .o, both of which are produced in one command. The line that begins with "%.o" starts an implicit rule, which loosely states, in English: "to produce a .o file, or a .l file, run the following ...". $(*F) is a GNUism that maps to the filename of the source (directory part, if any, is stripped). This works. I tested all three targets (foo, bar, baz) with a "make clean" between each one.(and for the really curious, a09 is a 6809 assembler; disasm.a is a 6809 diassembler, written in 6809; binary is a 2K relocatable library)
all: copied o a
source:
echo "message" > source
foo.o foo.a: source
(echo -n ".o: "; cat source) > foo.o
(echo -n ".a: "; cat source) > foo.a
o: foo.o
cat foo.o > o
a: foo.a
cat foo.a > a
copied: foo.o foo.a
cat foo.o foo.a > copied
The third rule simulates a compiler producing two outputs. Now if foo.o changes, both "copied" and "o" will be updated, and if foo.a changes, both "copied" and "a" will be updated. (And if either foo.o or foo.a are deleted, the compiler will be rerun, as will everything depending on foo.a or foo.o.)This is gnu make 4.0.