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 ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: Per-target make rules.

  1. 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

  2. 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

  3. 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

  4. 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

+ Reply to Thread