Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile Include directive while migrating from Unix to Linux

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.

like image 915
Carmageddon Avatar asked Nov 09 '22 03:11

Carmageddon


1 Answers

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.

like image 144
Alex Cohn Avatar answered Nov 14 '22 23:11

Alex Cohn