Makefiile with many flags

230 views Asked by At

I am trying to learn how a Makefile should look like, when it comes to the flags, especially the linking ones. Here is my Makefile:

OBJS    = n.o
SOURCE  = n.cpp
# HEADER = there are no header files, so I commented that
OUT     =       test
CXX     = ../mpich-install/bin/mpic++
FLAGS   =       -I../intel/mkl/include  ../intel/mkl/lib/intel64/libmkl_scalapack_ilp64.a       -Wl,--start-group       ../intel/mkl/lib/intel64/libmkl_intel_ilp64.a ../intel/mkl/lib/intel64/libmkl_core.a  ../intel/mkl/lib/intel64/libmkl_sequential.a    -Wl,--end-group ../intel/mkl/lib/intel64/libmkl_blacs_intelmpi_ilp64.a -lpthread       -lm     -ldl

all: $(OBJS)
        $(CXX)  $(OBJS) -o $(OUT)       $(FLAGS)

# create/compile the individual files >>separately<<
n.o:    n.cpp
        $(CXX)  -c      n.cpp   $(FLAGS)

.PHONY : all
# clean house
clean:
        rm -f $(OBJS)

and then I am getting:

../mpich-install/bin/mpic++     -c      n.cpp   -I../intel/mkl/include  ../intel/mkl/lib/intel64/libmkl_scalapack_ilp64.a       -Wl,--start-group       ../intel/mkl/lib/intel64/libmkl_intel_ilp64.a   ../intel/mkl/lib/intel64/libmkl_core.a  ../intel/mkl/lib/intel64/libmkl_sequential.a    -Wl,--end-group ../intel/mkl/lib/intel64/libmkl_blacs_intelmpi_ilp64.a  -lpthread       -lm     -ldl
g++: warning: ../intel/mkl/lib/intel64/libmkl_scalapack_ilp64.a: linker input file unused because linking not done
g++: warning: ../intel/mkl/lib/intel64/libmkl_intel_ilp64.a: linker input file unused because linking not done
g++: warning: ../intel/mkl/lib/intel64/libmkl_core.a: linker input file unused because linking not done
g++: warning: ../intel/mkl/lib/intel64/libmkl_sequential.a: linker input file unused because linking not done
g++: warning: ../intel/mkl/lib/intel64/libmkl_blacs_intelmpi_ilp64.a: linker input file unused because linking not done
../mpich-install/bin/mpic++     n.o -o test     -I../intel/mkl/include  ../intel/mkl/lib/intel64/libmkl_scalapack_ilp64.a       -Wl,--start-group       ../intel/mkl/lib/intel64/libmkl_intel_ilp64.a   ../intel/mkl/lib/intel64/libmkl_core.a  ../intel/mkl/lib/intel64/libmkl_sequential.a    -Wl,--end-group ../intel/mkl/lib/intel64/libmkl_blacs_intelmpi_ilp64.a  -lpthread       -lm     -ldl

That means that I should use some flags only in the last part of the process. What is the correct way to handle such a case? Maybe create FLAGS1 and FLAGS2? It should work, but I want to know which the correct way.

1

There are 1 answers

9
πάντα ῥεῖ On BEST ANSWER

"... but I want to know which the correct way."

The correct way is to keep up with make standard variable names, in particular CXXFLAGS and LDFLAGS.

You don't want to specify libraries for the linker flags like you try to do here (specifying subjects actually):

FLAGS   =  ... ../intel/mkl/lib/intel64/libmkl_scalapack_ilp64.a

Instead of using FLAGS and giving a direct subject for linking, you should rather use the standard LDFLAGS makefile variable to setup the path, and let the linker find the appropriate static or shared libraries:

  LDFLAGS += -L../intel/mkl/lib/intel64 -lmkl_scalapack_ilp64
# ^^^^^^^ Note the standard build system uses $(LDFLAGS) at the linker stage rule
# -L specifies the paths for finding libraries
# -l<MyLib> actually searches for certain libraries in the given paths,
#           expanding to search for files like libMyLib.a or libMyLib.so.

all: $(OBJS)
        $(CXX)  $(OBJS) -o $(OUT) $(CXXFLAGS) $(LDFLAGS)
#                                          ^^^^^^^^^^ Use them separately at
#                                                     linking stage  
        make    -f      Makefile        clean
#       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This whole line looks very (!!!) suspicious,
#                                             and would just make it harder to debug your
#                                             build system. It's an indicator, you did
#                                             dependencies management wrong.
#                                             Consider to use the compiler's --MF options 
#                                             family, to create a dependency file for the 
#                                             headers, and include it in your makefile.

Distinguish from compilation phase flags (CXXFLAGS), and linking stage flags (LDFLAGS).


Aside:

To avoid this

make    -f      Makefile        clean

action in your final target rule (that was probably added to avoid missing to catch up with header dependencies), add an -MF option to the CXXFLAGS, and include the results.

Here's more detailed information about the various techniques:

Auto-Dependency Generation