Issue
I need to run cmake twice, so it can find the package (Cplex). If I run cmake the first time, then the output is:
-- CPLEX Library: CPLEX_LIBRARY-NOTFOUND
-- ILOCPLEX Library: CPLEX_ILOCPLEX_LIBRARY-NOTFOUND
-- CONCERT Library: CPLEX_CONCERT_LIBRARY-NOTFOUND
-- CPLEX Bin Dir: CPLEX_BIN_DIR-NOTFOUND
...
-- Could NOT find CPLEX (missing: CPLEX_LIBRARY CPLEX_INCLUDE_DIR CPLEX_ILOCPLEX_LIBRARY CPLEX_CONCERT_LIBRARY CPLEX_CONCERT_INCLUDE_DIR)
But when I run cmake the second time, then the output is:
-- CPLEX Library: /opt/ibm/ILOG/CPLEX_Studio201/cplex/lib/x86-64_linux/static_pic/libcplex.a
-- ILOCPLEX Library: /opt/ibm/ILOG/CPLEX_Studio201/cplex/lib/x86-64_linux/static_pic/libilocplex.a
-- CONCERT Library: /opt/ibm/ILOG/CPLEX_Studio201/concert/lib/x86-64_linux/static_pic/libconcert.a
-- CPLEX Bin Dir: CPLEX_BIN_DIR-NOTFOUND
...
-- Found CPLEX: /opt/ibm/ILOG/CPLEX_Studio201/cplex/lib/x86-64_linux/static_pic/libcplex.a
Can this somehow be fixed, so I only need to run cmake once?
File contents
CMakeLists.txt
content:
cmake_minimum_required(VERSION 3.12)
project(...)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
#region cplex
# hint the location of cplex
# the location may be different on your system
set(CPLEX_ROOT_DIR /opt/ibm/ILOG/CPLEX_Studio201/)
# find needed packages
find_package(Cplex REQUIRED)
# include found package
include_directories(SYSTEM ${CPLEX_INCLUDE_DIRS})
#endregion
find_package(OpenMP REQUIRED)
add_library(${PROJECT_NAME})
target_compile_features(${PROJECT_NAME}
PUBLIC
cxx_std_23
)
target_sources(${PROJECT_NAME}
PUBLIC
...
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
${CPLEX_LIBRARIES}
OpenMP
)
cmake/FindCplex.cmake
content is from GitHub.
Solution
While the referenced FindCplex.cmake script describes CPLEX_ROOT_DIR
as a possible hint about Cplex installation, it assumes the variable to be the CACHEd one:
# User can give CPLEX_ROOT_DIR as a hint stored in the cmake cache.
So you have several options:
Pass the variable via command line to
cmake
executable:cmake -DCPLEX_ROOT_DIR=/opt/ibm/ILOG/CPLEX_Studio201/ <other options>
This is a preferred way, because you don't need to hardcode the variable in your project and allows the project to be built on different machines without modifying the project's code.
Define simple CACHE variable in
CMakeLists.txt
:set(CPLEX_ROOT_DIR /opt/ibm/ILOG/CPLEX_Studio201/ CACHE PATH "Path to Cplex installation")
That way the library can be found on your machine without any external configuration. On other machines it can also be found, but with setting the variable in the command line (like in the first case).
Define CACHE variable with FORCE option or as INTERNAL one:
set(CPLEX_ROOT_DIR /opt/ibm/ILOG/CPLEX_Studio201/ CACHE INTERNAL "Path to Cplex installation")
That way the library can be found on your machine without any external configuration. Finding it on other machines, with other CPlex installation directory, would require modification of the project code.
Use this variant only in projects which you want to build on your machine only.
When change the code using option 2, make sure to perform clean reconfiguration (with empty build directory or at least without CMakeCache.txt
file in it). Otherwise the variable's setting won't have an effect because the variable already exists in the cache.
Answered By - Tsyvarev Answer Checked By - Marie Seifert (WPSolving Admin)