0

I'm having trouble establishing automatic dependency in my Makefile. The goal is to create a C++ library from a number of Protocol Buffer files, some of which might be in read-only directories. To get around the write permission, I want to generate the C++ files in the Makefile directory. The actual Makefile is created from Makefile.am. The following simplified script is supposed to do the trick for building automatic dependencies, but it doesn't:

mypbfiles = /usr/share/project/my_file.proto
MY_PB_FILES = $(notdir ${mypbfiles})
MY_SOURCE_FILES = ${MY_PB_FILES:.proto=.pb.cc}

lib_LTLIBRARIES = lib@PACKAGE_NAME@_protobuf.la
lib@PACKAGE_NAME@_protobuf_la_SOURCES = ${MY_SOURCE_FILES}
lib@PACKAGE_NAME@_protobuf_la_LDFLAGS = -version-info @MAJOR_VERSION@:@MINOR_VERSION@:0

$(MY_SOURCE_FILES): $(mypbfiles)
    @for proto_file in $(mypbfiles); do \
        gen_file=`echo ${proto_file} | perl -pe 's/\.proto/\.pb\.cc/; s|.*/||'`;\
        echo "*** Building ${gen_file} from $${proto_file} ***"; \
        protoc -I${mypbdir} --cpp_out=./ $${proto_file};\
done

LTLIBRARIES = $(lib_LTLIBRARIES)
all: Makefile $(LTLIBRARIES)

I then decided to add the following two lines to the script:

foo:
    echo ${MY_SOURCE_FILES}

Running 'make foo' shows the following output:

echo my_file.pb.cc
my_file.pb.cc

So MY_SOURCE_FILES does contain the right value, but the dependency is not established. However, making the following change in the script fixes the problem:

lib@PACKAGE_NAME@_protobuf_la_SOURCES = my_file.pb.cc

You might ask why not make that change and be happy with it? The problem is that Makefile.am is fed to a program which handles 'lib@PACKAGE_NAME@_protobuf_xxx'. So I have to find a way to make things work! My suspicion is that using the 'notdir' function somehow doesn't expand the variable 'MY_PB_FILES' the way I intend it.

I am not all that versed in GNU Makefile, so any suggestion or help is greatly appreciated.

nads
  • 378
  • 3
  • 13
  • In your example you use `lib@PACKAGE_NAME@_protobuf_la_SOURCES` and in your "fixed" example you use `lib@PACKAGE_NAME@_protobuf_la_SOURCE` (no `S`). Is that a typo in the question? Also, you didn't specify exactly what you mean by "the dependency is not established"... what do you want to happen that does not happen? – MadScientist Jun 30 '13 at 19:34
  • That was a typo. I'll edit the posting. Thanks for noticing. What I do want to happen is seeing the following statement: *** Building my_file.pb.cc from /usr/share/project/my_file.proto *** – nads Jun 30 '13 at 19:39
  • To me this looks like an automake file. I think you'll need to discuss it with the automake folks. My suspicion is that automake is handling something for you that works properly with a static string like `my_file.pb.cc`, but won't expand a variable like `${MY_SOURCE_FILES}` so it doesn't work that way. – MadScientist Jul 01 '13 at 13:31
  • I thought about that too, but am not sure if this is an automake issue. If you modify the generated makefile by hand and statically assign my_file.pb.cc to ${MY_SOURCE_FILES}, then make works as intended. – nads Jul 01 '13 at 14:53
  • Yes, that's what I said above about "automake is handling something for you". That is, automake may be looking at the makefile and doing something special with source files. But since automake is not make, it requires the values in the variable to be explicit, not in a variable. I don't know enough about automake to tell you, that's why I suggested you ask the automake folks. – MadScientist Jul 01 '13 at 15:07

1 Answers1

0

The goal is to create a C++ library from a number of Protocol Buffer files, some of which might be in read-only directories.

Can't you just copy them to $(top_builddir) to get around this problem?

To get around the write permission, I want to generate the C++ files in the Makefile directory.

So these will be in $(top_builddir) too.

You should probably check out the answer given here which sets up the protocol buffers compiler and more importantly sets up the rule in Makefile.am. You might have to modify it a little for your case.

So basically something like:

my_file.proto : /usr/share/project/my_file.proto
    cp $< $@

%.pb.cc %.pb.h: %.proto
    $(PROTOC) --proto_path=$(dir $^) --cpp_out=$(dir $^) $^

lib_LTLIBRARIES = lib@PACKAGE_NAME@_protobuf.la
lib@PACKAGE_NAME@_protobuf_la_SOURCES = my_file.pb.cc
lib@PACKAGE_NAME@_protobuf_la_LDFLAGS = -version-info @MAJOR_VERSION@:@MINOR_VERSION@:0

The only tricky thing here I see is: what goes into the tarball when make dist is invoked? Do you really want to distribute my_file.pb.cc?

Community
  • 1
  • 1
ldav1s
  • 15,885
  • 2
  • 53
  • 56
  • The goal is to avoid the need to manually include both my_file.proto and my_file.pb.cc. It is possible that Makefile.am contains many .proto files, or the file goes through multiple modification in its lifetime. It is unreasonable to expect the developer(s) to remember this condition all the time. The problem, as @MadScientist correctly pointed out, has to do with automake's inability to expand MY_SOURCE_FILES to establish dependency. I have asked a similar question to the automake folks, but haven't heard from anyone yet. – nads Jul 10 '13 at 08:57