I am tasked with migrating an ancient C++ based code, from Unix environment to Linux. The project is made up of multiple Makefiles, for different "modules" of the library. I have resolved some problems, however now having trouble with the include directive.
Apparently, the way the Makefiles are constructed, is to have a separate include directives, for different files, and it worked for years in the Unix server.
For example:
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, tabbed includes, only refer to the specified targets! They are part of the recipe for that target.
However, this construct is NOT working in Linux, I get this error:
include ../../../../util/genmake.slinc
make: include: Command not found
make: *** [processControl.sl] Error 127
Obviously I can't just remove the tab, because the include should be only for that target...
So, I have tried to replace it with a shell 'source' command to source the included file like:
source ../../../../util/genmake.slinc
This doesnt work apparently, and I also tried to bring in the included code directly into the include file (commenting out the include command) - this handles the errors related to Makefile, but this is not a good solution, as it would be really hard to migrate and maintain it, having to replicate the same code all over the project into all modules, and then of course every tiny change I would have to reflect on all files.
Can any Make expert please advice on this issue? Also, generally any advice on how best to approach this migration task, would be welcome :)
Thanks!
EDIT- Extra information: Content of 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 "----------------------------------------------------------------"
Those are tabs before @.
Now content 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 to the Makefile, and remove leading tabs on the includes, I get this error: ../../../../util/genmake.slinc:10: *** commands commence before first target. Stop.
My idea of letting gnumake do all processing proved to be wrong. The relevant differences between HP-UX 11i Version 1 and the latest Linux build are as follows:
TAB before include
was silently ignored; now it is interpreted as recipe prefix, and gnu make tries to find include executable on your machine.
include
in gnu make silently adds an empty line to the merged output resets the recipe on the boundary of each included file (as MadScientist correctly pointed out), thus included file cannot consist of recipe statements only.
If the included files don't use the same trick recursively (and in your example they seem to be plain actions, with no additional include statements), you can use awk to prepare the merged 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 handle files as they are on your system, no editing is necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With