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
1 Answer 1
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 "automatic dependency generation", 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
CC
(C compiler) ->CXX
(C++ compiler);CPPFLAGS
(C preprocessor flags) ->CXXFLAGS
(C++ compiler flags);CPX_LIBDIR
->CPX_LDPATH
;CPX_LDFLAGS
->CPX_LDADD
;LDFLAGS
->LDADD
. \$\endgroup\$CXX=g++
. BUT also replace all locations where you useCC
withCXX
. If you are writing C++ code use the correct variables ore represent it. \$\endgroup\$