0

[BMAKE (very similar to GNUMake)]

I have a project that depends on files generated by another project and I need make variables in this project that contains the names and locations of those files. So, from this project's Makefile, I'm initiating builds of the other projects.

I have setup my Makefile to have dependencies for each stage as follows:

prepareOther:
  cd otherProject && make

prepareNames: prepareOther

build: prepareNames
  make ${CPP_FLAGS} ${CPP_SRCS}

When the prepareNames target is processed, I need to populate the Make variables CPP_FLAGS (with -I statements) and CPP_SRCS with filenames. However, I want to avoid having to do this using shell scripting within the target's recipe.

I'm using the following code to find and organise the names and locations of the necessary files into the Make variables:

# This example limits filetypes to CPP but using an if statement, C & H files can also be handled.
# In addition, this example only captures the file's name, not location.

PROJECTS=proj1 proj2
RAWNAMES=fileA.cpp fileB.cpp

.for proj in ${PROJECTS}
.   for file in ${RAWNAMES}
THISFILENAME!= find ../${proj}/build/${proj} -maxdepth 1 -name '${proj}_${file}' -exec sh -c  'name="{}"; base=$$(basename $$name); echo "${proj}/$$base"' \;
${CPP_NAME_${proj}::+=${THISFILENAME}}=     ##  The assignment is performed by the '::+='
.   endfor
.endfor

...

.for proj in ${PROJECTS}
CPP_SRCS+=${CPP_NAME_${proj}
.endfor

The problem is that this code gets run before the other projects are built, and therefore the files don't exist yet.

I've tried using a bmake construct .if target(prepareNames) as a guard around the above code, but unless I invoke that target from the CLI, the code is never executed, even though the target is processed internally when I invoke bmake build.

I also tried using the syntax:

prepareNames: Make statement1
prepareNames: Make statement2

But this produces duplicate script for target warnings which causes those lines to be ignored.

Is there a way of doing this using Make code without resorting to convoluted, escaped shell code?

gone
  • 1,079
  • 5
  • 13
  • 31
  • I can't comment on this because I don't know bmake but just to say, the initial statement that bmake is "very similar" to GNU make is really not true at all. Other than both of them implementing the POSIX standard for make and makefiles, they are almost entirely different. And, the kind of thing you want to do here is far outside the POSIX standard and so firmly into the "bmake only" area. – MadScientist Jul 10 '21 at 17:35
  • @MadScientist, if there's a GNU (or other) make way of doing this, I'm willing to try it in bmake. As for the degree of similarity, here's a question that asks for comparisons: https://stackoverflow.com/questions/2131219/merits-of-bmake – gone Jul 11 '21 at 01:16
  • It's a little hard to understand what exactly you want to do since you don't give an actual example and I'm not familiar with advanced bmake constructs. However based on the description I would say that in GNU make you could do it two ways: either use `$(eval ...)` within the recipe of the `prepareNames` target to set make variables after completing the `prepareOther` target, or else have those targets generate included makefiles containing the variable assignments and use GNU make's auto-creation of included makefiles. – MadScientist Jul 11 '21 at 13:26
  • Regarding the comparison, as far as I can tell it doesn't disagree with me. Note that automake (part of autotools) generates POSIX-conforming makefiles so the fact that both GNU make and bmake can use them aligns with what I said above: they both implement the POSIX standard. Beyond that they seem to have a fairly different model of behavior. GNU make is more "Lisp like", and keeps more of make's declarative programming model even in its extensions. bmake extensions appear to me to be more script-like and use a more procedural programming model. – MadScientist Jul 11 '21 at 13:40

0 Answers0