Per-target make rules. - Unix
This is a discussion on Per-target make rules. - Unix ; I have a project that consists of a bunch of static libraries, each
with their own individual testing programs. Right now I have Makefiles
all over the place and it is very disorganized. I am trying to write a
common ...
-
Per-target make rules.
I have a project that consists of a bunch of static libraries, each
with their own individual testing programs. Right now I have Makefiles
all over the place and it is very disorganized. I am trying to write a
common Makefile that I can include when I need to that defines rules
for building a static library and a tester program.
The library can have multiple source files, and so can the tester
program. This means I want to be able to do something like this in
each of the library Makefiles (using gcc and C++ as an example):
LIB_SOURCE = lib1.cpp lib2.cpp lib3.cpp
LIB_OUTPUT = liblib.a
TEST_SOURCE = test1.cpp test2.cpp
TEST_OUTPUT = testlib
include CommonMakefile
And voila, magic happens. My problem is I need to pass different
compiler options to gcc for the library and tester program. I don't
know how to do that in CommonMakefile. I can define something like
this (just assume undefined vars in example below are defined
somewhere else):
LIB_OBJS = $(sort $(LIB_SOURCE:.cpp=.o))
TEST_OBJS = $(sort $(TEST_SOURCE:.cpp=.o))
all: lib test
lib: $(LIB_OUTPUT)
test: $(TEST_OUTPUT)
$(LIB_OUTPUT): $(LIB_OBJS)
ar rs $(LIB_OUTPUT) $(LIB_OBJS)
$(TEST_OUTPUT): $(LIB_OUTPUT) $(TEST_OBJS)
g++ $(LINKER_CFLAGS) $(LIB_OUTPUT) $(TEST_OBJS) -o $@
..cpp.o:
g++ $(COMMON_CFLAGS) -c $<
But the .cpp.o rule uses the same set of flags without caring what the
final target will be. Is there some way I can do what I'm trying to
do, which is effectively use different values for COMMON_CFLAGS
depending on whether or not I'm building source files for the library
or the tester program? There is no source file that is used by both
the lib and tester program, that is a restriction that I am fine with
if it has to be that way.
Thanks,
Jason
-
Re: Per-target make rules.
jason.cipriani@gmail.com schrieb:
> I have a project that consists of a bunch of static libraries, each
> with their own individual testing programs. Right now I have Makefiles
> all over the place and it is very disorganized. I am trying to write a
> common Makefile that I can include when I need to that defines rules
> for building a static library and a tester program.
>
> The library can have multiple source files, and so can the tester
> program. This means I want to be able to do something like this in
> each of the library Makefiles (using gcc and C++ as an example):
>
> LIB_SOURCE = lib1.cpp lib2.cpp lib3.cpp
> LIB_OUTPUT = liblib.a
> TEST_SOURCE = test1.cpp test2.cpp
> TEST_OUTPUT = testlib
> include CommonMakefile
>
> And voila, magic happens. My problem is I need to pass different
> compiler options to gcc for the library and tester program. I don't
> know how to do that in CommonMakefile. I can define something like
> this (just assume undefined vars in example below are defined
> somewhere else):
>
> LIB_OBJS = $(sort $(LIB_SOURCE:.cpp=.o))
> TEST_OBJS = $(sort $(TEST_SOURCE:.cpp=.o))
>
> all: lib test
>
> lib: $(LIB_OUTPUT)
>
> test: $(TEST_OUTPUT)
>
> $(LIB_OUTPUT): $(LIB_OBJS)
> ar rs $(LIB_OUTPUT) $(LIB_OBJS)
>
> $(TEST_OUTPUT): $(LIB_OUTPUT) $(TEST_OBJS)
> g++ $(LINKER_CFLAGS) $(LIB_OUTPUT) $(TEST_OBJS) -o $@
>
> .cpp.o:
> g++ $(COMMON_CFLAGS) -c $<
>
> But the .cpp.o rule uses the same set of flags without caring what the
> final target will be. Is there some way I can do what I'm trying to
> do, which is effectively use different values for COMMON_CFLAGS
> depending on whether or not I'm building source files for the library
> or the tester program? There is no source file that is used by both
> the lib and tester program, that is a restriction that I am fine with
> if it has to be that way.
>
> Thanks,
> Jason
You could write the object files to different directories, each
directory containing object files with a common set of CFLAGS. Then
rules as below:
$(DDIR)/%.o: %.c
$(CC) $(D_CFLAGS) -c $< -o $@
$(CDIR)/%.o: %.c
$(CC) $(C_CFLAGS) -c $< -o $@
HTH,
Thomas
-
Re: Per-target make rules.
On May 29, 11:02 am, Thomas Maier-Komor wrote:
> You could write the object files to different directories, each
> directory containing object files with a common set of CFLAGS. Then
> rules as below:
>
> $(DDIR)/%.o: %.c
> $(CC) $(D_CFLAGS) -c $< -o $@
>
> $(CDIR)/%.o: %.c
> $(CC) $(C_CFLAGS) -c $< -o $@
Thanks! So I took your suggestion and did it that way, but then I was
having other issues related to having a bunch of subdirectories for
different .o files. I found something called "static rules" in
Makefiles that accomplish something similar, and while they do prevent
me from using the same source file in both lib and test program
(unlike yours, which allows for that no problems), I'm OK with that.
So I am now doing something like this:
$(LIB_OBJS): %.o: %.cpp
$(CC) $(LIB_CFLAGS) -c $<
$(TEST_OBJS): %.o: %.cpp
$(CC) $(TEST_CFLAGS) -c $<
And that almost works perfect, except now I am having a different
problem. I didn't mention this, but some of the libraries have special
cases per source file; for example, in addition to the above generic
rules, an individual library's Makefile needs to be able to specify
extra options per-file, which I did like this when I was using .cpp.o
before:
special.o: special.cpp
$(CC) $(LIB_CFLAGS) -funroll-loops -Wno-long-long $<
And that would appear in the individual Makefiles that included the
common one. Also, I generate dependency information (using g++ -M) so
I have a separate dependency file with lines in it like:
special.o: special.h include.h something.h
That all used to work fine, but now when I'm using the static rules,
Make complains about overriding existing rules (whereas with implicit
rules, rules for the same target were all combined, with static rules,
they aren't combined). Is there some way I can do this?
I could go back to using the solution of placing .o files in separate
directories... in fact, this is all becoming kind of a nightmare and I
think I may take your suggestion one step further and just put the
tester program source in separate directories altogether.
What a pain. I've spent an unacceptable amount of time today working
on Makefiles and organizing directory structures. I can't come up with
a good solution that I'm happy with.
Thanks,
Jason
-
Re: Per-target make rules.
jason.cipriani@gmail.com schrieb:
> On May 29, 11:02 am, Thomas Maier-Komor wrote:
>> You could write the object files to different directories, each
>> directory containing object files with a common set of CFLAGS. Then
>> rules as below:
>>
>> $(DDIR)/%.o: %.c
>> $(CC) $(D_CFLAGS) -c $< -o $@
>>
>> $(CDIR)/%.o: %.c
>> $(CC) $(C_CFLAGS) -c $< -o $@
>
> Thanks! So I took your suggestion and did it that way, but then I was
> having other issues related to having a bunch of subdirectories for
> different .o files. I found something called "static rules" in
> Makefiles that accomplish something similar, and while they do prevent
> me from using the same source file in both lib and test program
> (unlike yours, which allows for that no problems), I'm OK with that.
> So I am now doing something like this:
>
> $(LIB_OBJS): %.o: %.cpp
> $(CC) $(LIB_CFLAGS) -c $<
>
> $(TEST_OBJS): %.o: %.cpp
> $(CC) $(TEST_CFLAGS) -c $<
>
> And that almost works perfect, except now I am having a different
> problem. I didn't mention this, but some of the libraries have special
> cases per source file; for example, in addition to the above generic
> rules, an individual library's Makefile needs to be able to specify
> extra options per-file, which I did like this when I was using .cpp.o
> before:
>
> special.o: special.cpp
> $(CC) $(LIB_CFLAGS) -funroll-loops -Wno-long-long $<
>
> And that would appear in the individual Makefiles that included the
> common one. Also, I generate dependency information (using g++ -M) so
> I have a separate dependency file with lines in it like:
>
> special.o: special.h include.h something.h
>
> That all used to work fine, but now when I'm using the static rules,
> Make complains about overriding existing rules (whereas with implicit
> rules, rules for the same target were all combined, with static rules,
> they aren't combined). Is there some way I can do this?
>
> I could go back to using the solution of placing .o files in separate
> directories... in fact, this is all becoming kind of a nightmare and I
> think I may take your suggestion one step further and just put the
> tester program source in separate directories altogether.
>
> What a pain. I've spent an unacceptable amount of time today working
> on Makefiles and organizing directory structures. I can't come up with
> a good solution that I'm happy with.
>
> Thanks,
> Jason
I was once in your situation and investigate a couple of different
approaches until I settled with the one I've mentioned. My need for
having different compile flag, was in fact a software (sysstat, look
http://www.maier-komor.de/sysstat.html) that consists of a 64bit and a
32bit binary and therefore needs different compile flags. Of course,
when having object files for different architectures, the separation
into different directories really makes sense.
But, one more thing I wanted to mention: Be careful how you write your
Makefiles, because not every UNIX uses GNU Make. It is nowadays
available almost everywhere, but it might not be the default. So
sticking to standard make functionality really makes sense.
I'm entirely unhappy with the whole build process issue, because it
feels like reinventing the wheel every time. And all that nifty tools
(getconf, autoconf, automake, etc) aren't really easy to deal with
(especially when you need things like lex, yacc, and such), and don't
really work all the time (e.g. autoconf expecting /bin/sh being a bash -
urgh!).
So whatever you do - this seemingly very basic stuff always needs a lot
of testing :-(
Cheers,
Thomas