0

I am trying to use CLion to work with IBM ILOG CPLEX 12.7.1 on my Mac OS 10.13.1 (macOS High Sierra). Here is a very simple piece of C++ code.

#include <iostream>
#include <ilcplex/ilocplex.h>
using namespace std;
int main() {
    std::cout << "Hello, World!" << std::endl;
    IloEnv env;
    x: IloCplex cplex(env);
    std::cout << env.getVersion() << endl;

    return 0;
}

The following in my Makefile.

SYSTEM = x86-64_osx
LIBFORMAT = static_pic
CPLEXDIR = /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex
CONCERTDIR = /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/concert
# ---------------------------------------------------------------------
# Compiler selection 
# --------------------------------------------------------------------- 
CCC = clang++ -O0
# ---------------------------------------------------------------------
# Compiler options 
# ---------------------------------------------------------------------
CCOPT = -m64 -O -fPIC -fexceptions -DNDEBUG -DIL_STD -stdlib=libc++
# ---------------------------------------------------------------------
# Link options and libraries
# ---------------------------------------------------------------------

CPLEXBINDIR = $(CPLEXDIR)/bin/$(BINDIST)

CPLEXLIBDIR = $(CPLEXDIR)/lib/$(SYSTEM)/$(LIBFORMAT)
CONCERTLIBDIR = $(CONCERTDIR)/lib/$(SYSTEM)/$(LIBFORMAT)

CCLNDIRS  = -L$(CPLEXLIBDIR) -L$(CONCERTLIBDIR) 
CCLNFLAGS = -lconcert -lilocplex -lcplex -lm -lpthread -ldl #-framework CoreFoundation -framework IOKit -stdlib=libc++
all:
   make main

CONCERTINCDIR = $(CONCERTDIR)/include
CPLEXINCDIR = $(CPLEXDIR)/include

CCFLAGS = $(CCOPT) -I$(CPLEXINCDIR) -I$(CONCERTINCDIR) 
# ------------------------------------------------------------
main: main.o
$(CCC) $(CCFLAGS) $(CCLNDIRS) -o main main.o $(CCLNFLAGS)
main.o: ./main.cpp
$(CCC) -c $(CCFLAGS) ./main.cpp -o main.o

Here is the CMakeLists.txt, which I have tried to create it with parameters exactly as mentioned in the Makefile.

cmake_minimum_required(VERSION 3.14)
project(cplextest)
add_executable(cplextest main.cpp)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -m64 -O -fPIC -fexceptions -DNDEBUG -DIL_STD -stdlib=libc++")
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/include/)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/include/ilcplex)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/concert/include)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/concert/include/ilconcert)
find_library(lib1 NAMES libcplex.a PATHS /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/lib/x86-64_osx/static_pic/)
find_library(lib2 NAMES libilocplex.a PATHS /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/lib/x86-64_osx/static_pic/)
find_library(lib3 NAMES libcplexdistmip.a PATHS /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/lib/x86-64_osx/static_pic/)
set (CMAKE_SHARED_LINKER_FLAGS "-lconcert -lilocplex -lcplex -lm -lpthread -ldl #-framework CoreFoundation -framework IOKit -stdlib=libc++")
target_link_libraries(cplextest PUBLIC ${lib1})
target_link_libraries(cplextest PUBLIC ${lib2})
target_link_libraries(cplextest PUBLIC ${lib3})

However, while Makefile works flawlessly (i.e., I can successfully run my program from a terminal), CLion produces the following error messages.

====================[ Build | cplextest | Debug ]===============================
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake --build /Users/soheilmn/CLionProjects/CplexTest/cmake-build-debug --target cplextest -- -j 2
[ 50%] Linking CXX executable cplextest
Undefined symbols for architecture x86_64:
  "IloCplex::IloCplex(IloEnv)", referenced from:
      _main in main.cpp.o
  "IloCplexI::getVersion() const", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [cplextest] Error 1
make[2]: *** [CMakeFiles/cplextest.dir/all] Error 2
make[1]: *** [CMakeFiles/cplextest.dir/rule] Error 2
make: *** [cplextest] Error 2

Interestingly, if I comment out the line (x) in my C++ code, I can successfully run my code from CLion. This is indeed very confusing to me, because my understanding is both procedures use clang++ and the same libraries/header files. Any help will be highly appreciated. (Sorry for the long post in advance!)

Thanks!

Soheilmn
  • 29
  • 1
  • 4

2 Answers2

0

CMAKE_SHARED_LINKER_FLAGS specifies flags to use when creating new shared libraries. But your project doesn't create shared libraries, it creates an executable. You should just pass all the library names to target_link_libraries like this:

target_link_libraries(cplextest PUBLIC "concert;cplex;ilocplex;cplexdistmip")

Then you may need to add the library search path (/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio1271/cplex/lib/x86-64_osx/static_pic/) and it should all work. Run make VERBOSE=1 after running cmake if you want to see what linker command is actually run.

To enable pthreads, see cmake and libpthread

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Thank you very much for your help. To make sure I fully understand you, I need to ask these questions: 1. So, you are saying I do not need to use `CMAKE_SHARED_LINKER_FLAGS` but then what is the correct way of passing these flags to the linker? 2) I have already passed the library search path that you have mentioned by using `find_library`. Isn't that the right way of doing it and I should go with another command? 3. How/Where do I run `make VERBOSE=1' in CLion? Do I need to put that command somewhere in the `Makefile' or `CMakeLists.txt'? Many thanks for the help, again! – Soheilmn Oct 05 '19 at 16:21
  • Use `target_link_options` to add linker options if you need any (maybe you don't). Use `target_link_libraries` to add libraries to link. You can pass full paths to `target_link_libraries` so there is absolutely no need to use `find_library` when you know the full absolute path already. I don't use CLion so can't help you with the VERBOSE=1 part, but that isn't essential, just a debugging tool you can try to figure out at some point. – John Zwinck Oct 06 '19 at 01:53
  • Thanks! Works perfectly now. – Soheilmn Oct 08 '19 at 15:23
0

Special thanks go to "John Zwinck" for his help. I thought it makes sense to share the final CMake file that perfectly works with IBM ILOG CPLEX 12.9 under macOS 10.13.1 / CLion 2109.2.3. Here it is:

cmake_minimum_required(VERSION 3.14)
project(cplextest)
add_executable(cplextest main.cpp)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -m64 -O -fPIC -fexceptions -DNDEBUG -DIL_STD -stdlib=libc++")
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/cplex/include/)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/cplex/include/ilcplex)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/concert/include)
include_directories(/Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/concert/include/ilconcert)
target_link_libraries(cplextest PUBLIC /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/cplex/lib/x86-64_osx/static_pic/libcplex.a)
target_link_libraries(cplextest PUBLIC /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/cplex/lib/x86-64_osx/static_pic/libilocplex.a)
target_link_libraries(cplextest PUBLIC /Users/soheilmn/Applications/IBM/ILOG/CPLEX_Studio129/concert/lib/x86-64_osx/static_pic/libconcert.a)
set (target_link_options "-lconcert -lilocplex -lcplex -lm -lpthread -ldl -framework CoreFoundation -framework IOKit -stdlib=libc++")
Soheilmn
  • 29
  • 1
  • 4