C++ makefile for CPLEX with environment loading CPLEX is a solver for mathematical problems made by IBM, and it offers callable C libraries.

My usual project configuration is a main.cpp file will all the important code and a simple cpxmacro.h file with some macros. Sometimes there are also .dat files with problem data. When the solver does its job (i.e. the main is run), it outputs .lp and .sol files.

I used to let my IDE come up with proper make files, but this time I was provided with a hand-made make file. What a good opportunity to look into it.

CXX = g++
CXXFLAGS = -g -Wall -O
LDADD =

CPX_INCDIR  = /opt/ibm/ILOG/CPLEX_Studio126/cplex/include
CPX_LDPATH  = /opt/ibm/ILOG/CPLEX_Studio126/cplex/lib/x86-64_linux/static_pic
CPX_LDADD = -lcplex -lm -pthread

OBJ = main.o 

%.o: %.cpp
    $(CXX) $(CXXFLAGS) -I$(CPX_INCDIR) -c $^ -o $@

main: $(OBJ)
    $(CXX) $(CXXFLAGS) $(OBJ) -o main -L$(CPX_LDPATH) $(CPX_LDADD)

clean:
    rm -rf $(OBJ) main

.PHONY: clean


As long as I only change the main file, it works. I just have to manually load a small file first, by typing . cplex_env. This is what the file contains:

#!/bin/sh

export PATH=$PATH:/opt/ibm/ILOG/CPLEX_Studio126/opl/bin/x86-64_linux:/opt/ibm/ILOG/CPLEX_Studio126/cplex/bin/x86-64_linux
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/opt/ibm/ILOG/CPLEX_Studio126/opl/bin/x86-64_linux:/opt/ibm/ILOG/CPLEX_Studio126/cplex/bin/x86-64_linux:/opt/ibm/ILOG/CPLEX_Studio126/cpoptimizer/bin/x86-64_linux/


I never tried to change the .h macro file and see what happens, it doesn't look to me like it's being accounted for anywhere in the makefile.

I'd like to:


include the path exports in the make file
make the makefile a little more generic
Instead of providing your own %.o: %.cpp rule, you can let Make use its built-in one.  You need to pass your extra include directory, and the standard way to do that is to add to CXXFLAGS:
CXXFLAGS += -I$(CPX_INCDIR)

Or perhaps
CPLEX_DIR = /opt/ibm/ILOG/CPLEX_Studio126/cplex
CXXFLAGS += -I$(CPLEX_DIR)/include


Similarly, take advantage of the built-in link command; this is especially easy, as there's a built-in rule that will create main from main.o.  You need to tell Make to use the C++ linker rather than the plain (C) linker:
LINK.o = $(LINK.cc)
LDFLAGS += -L$(CPLEX_DIR)/lib/x86-64_linux/static_pic
LDLIBS += -lcplex -lm -pthread


To declare the dependency on the header file, note that main.o needs to be rebuilt whenever the header changes:
main.o: cpxmacro.h

That's all!
Header file dependencies can be hard to manage by hand in larger projects; for these, search for &quot;automatic dependency generation&quot;, or read Paul D. Smith's excellent article.

Modified makfile
With my changes:
CPLEX_DIR = /opt/ibm/ILOG/CPLEX_Studio126/cplex

CXX = g++
CXXFLAGS = -g -Wall -O
CXXFLAGS += -I$(CPLEX_DIR)/include

LINK.o = $(LINK.cc)
LDFLAGS += -L$(CPLEX_DIR)/lib/x86-64_linux/static_pic
LDLIBS += -lcplex -lm -pthread


all: main

main.o: cpxmacro.h


clean:
    $(RM) *~ *.o main

.PHONY: all clean