3
\$\begingroup\$

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
\$\endgroup\$
  • 2
    \$\begingroup\$ Minor suggestions: 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\$ – Gluttton Oct 24 '14 at 12:08
  • \$\begingroup\$ @Agostino: You should use CXX=g++. BUT also replace all locations where you use CC with CXX. If you are writing C++ code use the correct variables ore represent it. \$\endgroup\$ – Martin York Oct 25 '14 at 7:43
  • \$\begingroup\$ @Gluttton renamings done and makefile working again. Is there anything else I can do? E.g. why is LDADD empty, and why should I call it like that instead of LDFLAGS? \$\endgroup\$ – Agostino Oct 29 '14 at 7:48
1
\$\begingroup\$

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
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.