Makefile Include directive when migrating from Unix to Linux

I am tasked with porting old code to C ++, from Unix to Linux. The project consists of several Makefiles for different "modules" of the library. I solved some problems, but now I have problems with the include directive.

Apparently, the way to create Make files is to have separate include directives for different files, and it worked on the Unix server for many years.

For instance:

include ../../../../util/genmake.def processControl.slOBJS = processControl.o outputControlOBJS = outputControl.o inputControlOBJS = inputControl.o cleanList = *.o *.C *.out processControl.sl outputControl inputControl all: processControl.sl outputControl inputControl processControl.sl: $(processControl.slOBJS) include ../../../../util/genmake.slinc outputControl: $(outputControlOBJS) include ../../../../util/genmake.exeinc inputControl: $(inputControlOBJS) include ../../../../util/genmake.exeinc include ../../../../util/genmake.inc 

You can see here that, including the tabs, apply only to the indicated goals! They are part of the recipe for this purpose.

However, this construct does NOT work on Linux, I get this error:

 include ../../../../util/genmake.slinc make: include: Command not found make: *** [processControl.sl] Error 127 

Obviously, I cannot just remove the tab, because include should only be for this purpose ...

So, I tried replacing it with the 'source' command for the source of the incoming file, for example:

  source ../../../../util/genmake.slinc 

This does not work, and I also tried to include the included code directly in the include file (commenting on the include command) - this handles errors related to the Makefile, but this is not a good solution, since it is really difficult to port and maintain it in order to reproduce the same code throughout the project in all modules, and then, of course, every small change that I would have to reflect in all the files.

Can someone make an expert, please, advice on this issue? In addition, as a rule, any recommendations on how best to approach this migration task will be welcome :)

Thanks!

EDIT- Additional Information: Content genmake.slinc:


 ####################################################################### ## This include will inherit the target and dependent files in ## a make file that inlcudes it. ## The inclusion of this file should look like: ## ## {target}: {dependent file list} ## include genmake.slinc ## ####################################################################### @echo "----------------------------------------------------------------" @echo " (G) Creating shared library $@ from $($(MaKeObJs:x=$(@)OBJS))"; @echo "----------------------------------------------------------------" @echo "$(CPP) -b -o $@ $($(MaKeObJs:x=$(@)OBJS))" @$(CPP) -b -o $@ $($(MaKeObJs:x=$(@)OBJS)) @echo " Moving shared library to $(SHLIBINSTALL) as lib$(@)" @$(MV) $@ $(SHLIBINSTALL)/lib$(@) @echo "----------------------------------------------------------------" 

These are the tabs before @.

Now the contents of genmake.exeinc:


 ####################################################################### ## This include will inherit the target and dependent files in ## a make file that inlcudes it. ## The inclusion of this file should look like: ## ## {target}: {dependent file list} ## include /opt/app/fba/util/genmake.exeinc ## ####################################################################### @cp $(SHLIBINSTALL)/* $(TEMP_SHLIB_DIR)/. @echo "----------------------------------------------------------------" @echo " (G) Linking $($(MaKeObJs:x=$(@)OBJS)) to make $@ " @echo " LDOPTS set to: $(LDOPTS)" # @echo " $(PURIFY) $(LD) " @echo " SHLIB Temp Path: $(TEMP_SHLIB_DIR) @echo " FBA libraries: $(FBALIB)" @echo " Application libraries: $(APPLIBS)" $(PURIFY) $(LD) -o $@ $($(MaKeObJs:x=$(@)OBJS)) \ $(CXXOPTS) \ $(LDFLAGS) \ $(FBALIB) \ $(PROLDLIBS) \ `cat /usr/local/opt/oracle/product/t1c3d771/lib/ldflags` \ `cat /usr/local/opt/oracle/product/t1c3d771/lib/sysliblist` \ $(APPLIBS) @echo " Moving executable to $(EXEINSTALL) " @$(MV) $@ $(EXEINSTALL) @echo "----------------------------------------------------------------" 

If I go into the Makefile and delete the leading tabs in the include, I get this error: .. /../../../util/genmake.slinc:10: *** the commands start before the first goal. Stop.

+5
source share
2 answers

Just add the target to include as a variable: For example, genmake.exeinc will become:

 $(targetControl): $(depControlOBJS) @cp $(SHLIBINSTALL)/* $(TEMP_SHLIB_DIR)/. @echo "----------------------------------------------------------------" @echo " (G) Linking $($(MaKeObJs:x=$(@)OBJS)) to make $@ " @echo " LDOPTS set to: $(LDOPTS)" # @echo " $(PURIFY) $(LD) " @echo " SHLIB Temp Path: $(TEMP_SHLIB_DIR) @echo " FBA libraries: $(FBALIB)" @echo " Application libraries: $(APPLIBS)" $(PURIFY) $(LD) -o $@ $($(MaKeObJs:x=$(@)OBJS)) \ $(CXXOPTS) \ $(LDFLAGS) \ $(FBALIB) \ $(PROLDLIBS) \ `cat /usr/local/opt/oracle/product/t1c3d771/lib/ldflags` \ `cat /usr/local/opt/oracle/product/t1c3d771/lib/sysliblist` \ $(APPLIBS) @echo " Moving executable to $(EXEINSTALL) " @$(MV) $@ $(EXEINSTALL) @echo "----------------------------------------------------------------" 

Then modify the relevant parts of your makefile as follows:

 #outputControl: $(outputControlOBJS) targetControl=outputControl depControlOBJS=$(outputControlOBJS) include ../../../../util/genmake.exeinc #inputControl: $(inputControlOBJS) targetControl=inputControl depControlOBJS=$(inputControlOBJS) include ../../../../util/genmake.exeinc 
0
source

My idea of ​​letting gnumake do all the processing turned out to be wrong. The relevant differences between HP-UX 11i Version 1 and the latest version of Linux are as follows:

  • TAB before include silently ignored; it is now interpreted as a recipe prefix, and gnu make tries to find the include executable on your computer.

  • include in gnu make silently adds a blank line to the combined output, resets the recipe on the border of each included file (as MadScientist correctly points out), so the included file cannot consist only of recipes.

If the included files do not use the same trick recursively (and in your example they seem to be just actions without additional include ), you can use awk to prepare the combined Makefile on the fly like this:

 awk '{ if (NF == 2 && $1 == "include") { while ((getline line < $2) > 0) print line ; close($2) } else print }' Makefile | make -f - 

The script above will process the files as they are on your system, no editing is required.

+1
source

Source: https://habr.com/ru/post/1262589/


All Articles