GNU make 3.81 - how to do this --output-sync = target

The latest version of make has the --output-sync option, which can do STDOUT of each target atom so that when using make --jobs=N

operations were not performed for several purposes,

Unfortunately, I have to use make v 3.81 , because the one that comes with our SDK.

To determine if I need --output-sync , I added some “warnings” around my goals

 all: $(patsubst %.cpp, %.o, $(wildcard *.cpp)) %.o: %.cpp @echo BEFORE @echo MAKEFLAGS=$(MAKEFLAGS) qcc.exe $(CC_FLAGS) $@ $< @echo AFTER 

The exit was very alternating.

 AFTER BEFOREAFTER AFTER AFTER 

Is there a way to emulate the functionality of --output-sync ?

I understand that the build speed can be affected if, for example, there is a way to "block the preliminary recipe for the STDOUT mutex" and release it after the recipe.

I am fine with changing each of our goals, if necessary.

+6
source share
1 answer

You can write all outputs of the recipe to a temporary file and cat-delete it at the end:

 %.o: %.cpp @d=$$(mktemp) && \ echo BEFORE >> $$d 2>&1 && \ echo MAKEFLAGS=$(MAKEFLAGS) >> $$d 2>&1 && \ qcc.exe $(CC_FLAGS) $@ $< >> $$d 2>&1 && \ echo AFTER >> $$d 2>&1 && \ cat $$d && \ rm $$d 

This will not completely prevent striping, because several cat commands can run in parallel if you have multiple processors, but this should greatly reduce the likelihood. If you really want to completely avoid interleaving, you will have to add a spin lock around the cat commands. On GNU / Linux, you can see flock , for example:

 %.o: %.cpp @d=$$(mktemp) && \ echo BEFORE >> $$d 2>&1 && \ echo MAKEFLAGS=$(MAKEFLAGS) >> $$d 2>&1 && \ qcc.exe $(CC_FLAGS) $@ $< >> $$d 2>&1 && \ echo AFTER >> $$d 2>&1 && \ flock /tmp/my-lock-file cat $$d && \ rm $$d 

Explanations:

  • I converted your recipe into one shell call (each line in the make recipe runs in a different shell), so that the shell variable d is available in all the commands in the list.
  • Commands are bound using the && operator: if one of them fails, the entire list crashes with the same exit status, and make tells you so.
  • Instead of putting all the commands on one line, which quickly becomes unreadable, I added \ in front of all line ends except the last. More readable, but still interpreted as a single line made by make.
  • The first command in the list ( mktemp ) atomically creates a unique temporary file. Use any equivalent available in your environment. Note the double $ in d=$$(mktemp) . You must pass the first expansion by make and become d=$(mktemp) when passed to the shell. The same when it comes to expanding the shell of the shell of the variable d : $$d first decrypts make as $d before passing it to the shell.
  • Redirecting the output of commands ( >> $d 2>&1 after the first extension by make) redirects the standard outputs to a temporary file in add mode ( >> $d ) and makes the standard error descriptor a copy of the standard output descriptor ( 2>&1 ), which also adds standard errors in the same temporary file.
0
source

All Articles