0
votes

I have a problem getting a makefile to work. I have several parsers that compile XML schemas as follows:

$(srcdir)/schema_1_parser.cpp: \
                 $(srcdir)/schema_1_parser.l \
                 $(srcdir)/schema_1_parser.tab.cpp
    $(LEX) -Pschema_1 -o$(srcdir)/schema_1_parser.cpp \
                        $(srcdir)/schema_1_parser.l

$(srcdir)/schema_1_parser.tab.cpp $(srcdir)/schema_1_parser.tab.hpp: \
                $(srcdir)/schema_1_parser.y
    $(YACC) -ldv -p schema_1 -o $(srcdir)/schema_1_parser.tab.cpp \
                                $(srcdir)/schema_1_parser.y

There are multiple such rule pairs, using schema_2, schema_3, etc. The names do follow a pattern that I would like to exploit if I can. (At the moment I have special rules only.)

I added the second target $(srcdir)/schema_1_parser.tab.hpp because of a makefile error "Do not know how to make schema_1_parser.tab.hpp", even though the header gets generated automatically together with the .tab.cpp file.

Now the bison parser is being called twice. I read up on this and am given to believe that this is expected behavior for special rules with multiple targets, and that I should use pattern rules instead. However, I am a bit unsure what about the command line options -Pschema_1 for flex and -p schema_1 for bison. Can I use the pattern to take care of those also? (My experience has been negative, but I may be missing something else.)

1

1 Answers

0
votes

Well, we can't give you a complete answer because you didn't show us any of the other rules, so we don't know what parts of the patterns are common between them. But, yes of course there are multiple ways to handle the situation you describe. If your parsers all match the pattern %_parser.y and %_parser.l, you can write the rules like this:

$(srcdir)/%_parser.cpp: \
             $(srcdir)/%_parser.l \
             $(srcdir)/%_parser.tab.cpp
        $(LEX) -P$* -o$@ $<

$(srcdir)/%_parser.tab.cpp $(srcdir)/%_parser.tab.hpp: \
            $(srcdir)/%_parser.y
        $(YACC) -ldv -p $* -o $(srcdir)/$*_parser.tab.cpp $<

Because $* expands to the stem of the pattern.

If this doesn't work, you can use recursive variables:

NAME_schema_1_parser = schema_1

$(srcdir)/%.cpp: $(srcdir)/%.l $(srcdir)/%.tab.cpp
        $(LEX) -P$(NAME_$*) -o$@ $<

$(srcdir)/%.tab.cpp $(srcdir)/%.tab.hpp: $(srcdir)/%.y
        $(YACC) -ldv -p $(NAME_$*) -o $(srcdir)/$*_parser.tab.cpp $<

You may also be able to use target-specific or pattern-specific variables.