首页 > 解决方案 > 在 CMake 中为 CPLEX 传递链接器标志

问题描述

简而言之:我无法将使用 CPLEX 的程序与 CMake 链接,链接器似乎没有找到 CPLEX 库 ( cplex),但找到了一些其他库 ( ilocplex)。从命令行,它确实有效。

详细的:

对于使用 CPLEX 的程序:

#include <ilcplex/ilocplex.h>

int main(int argc, char *argv[]) {
   IloEnv env;
   IloModel model(env);
   IloCplex cplex(model);
 
   return 0;
}

我有以下内容CMakeLists.txt

cmake_minimum_required(VERSION 3.17)
project(myprog C CXX)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(CPLEX)
if (CPLEX_FOUND)
    add_definitions(-DIL_STD)
else()
    message (FATAL_ERROR "CPLEX not found!")
endif()

add_executable(myprog src/main.cpp )
target_include_directories(myprog PUBLIC ${CPLEX_INCLUDE_DIRS})
target_link_libraries(myprog PUBLIC ${CPLEX_LIBRARIES})
set_target_properties(myprog PROPERTIES LINK_FLAGS "-lconcert -lilocplex -lcplex -lpthread -ldl")

cmake/FindCPLEX.cmake

set (CPLEX_DIR "/opt/ibm/ILOG/CPLEX_Studio_Community201")

if (CPLEX_INCLUDE_DIR)
    set(CPLEX_FOUND TRUE)
    set(CPLEX_INCLUDE_DIRS "${CPLEX_INCLUDE_DIR};${CPLEX_CONCERT_INCLUDE_DIR}" )
    set(CPLEX_LIBRARIES "${CPLEX_ILO_LIBRARY};${CPLEX_CONCERT_LIBRARY};${CPLEX_LIBRARY};${CPLEX_PTHREAD_LIBRARY}" )
else (CPLEX_INCLUDE_DIR)

    find_path(CPLEX_INCLUDE_DIR
            NAMES ilcplex/cplex.h
            PATHS "${CPLEX_DIR}/cplex/include"
            )
    find_path(CPLEX_INCLUDE_ILCPLEX
            NAMES cplex.h
            PATHS "${CPLEX_DIR}/cplex/include/ilcplex"
            )

    find_path(CPLEX_CONCERT_INCLUDE_DIR
            NAMES ilconcert/ilomodel.h
            PATHS "${CPLEX_DIR}/concert/include"
            )

    find_path(CPLEX_INCLUDE_ILCONCERT
            NAMES ilomodel.h
            PATHS "${CPLEX_DIR}/concert/include/ilconcert"
            )

    find_library(CPLEX_LIBRARY
            cplex
            PATHS "${CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic"
            "${CPLEX_DIR}/cplex/lib/x86-64_darwin/static_pic/"
            "${CPLEX_DIR}/cplex/lib/x86-64_linux/static_pic"
            )

    find_library(CPLEX_ILO_LIBRARY
            ilocplex
            PATHS "${CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic"
            "${CPLEX_DIR}/cplex/lib/x86-64_darwin/static_pic/"
            "${CPLEX_DIR}/cplex/lib/x86-64_linux/static_pic"
            )

    find_library(CPLEX_CONCERT_LIBRARY
            concert
            PATHS "${CPLEX_DIR}/concert/lib/x86-64_linux/static_pic/"
                  "${CPLEX_DIR}/concert/lib/x86-64_sles10_4.1/static_pic"
                  "${CPLEX_DIR}/concert/lib/x86-64_darwin/static_pic/"
            )

    find_library( CPLEX_PTHREAD_LIBRARY
            pthread
            PATHS "/usr/lib"
            "/usr/lib64"
            "/lib"
            "/lib64"
            )

    find_library( CPLEX_DL_LIBRARY
            dl
            PATHS "/usr/lib"
            "/usr/lib64"
            "/lib"
            "/lib64"
            )

    set(CPLEX_COMPILER_FLAGS "-DIL_STD" CACHE STRING "Cplex Compiler Flags")

    include(FindPackageHandleStandardArgs)
    find_package_handle_standard_args(CPLEX  DEFAULT_MSG
            CPLEX_LIBRARY CPLEX_INCLUDE_DIR CPLEX_CONCERT_INCLUDE_DIR CPLEX_ILO_LIBRARY CPLEX_CONCERT_LIBRARY)


    if(CPLEX_FOUND)
        set(CPLEX_INCLUDE_DIRS "${CPLEX_INCLUDE_DIR};${CPLEX_CONCERT_INCLUDE_DIR};${CPLEX_INCLUDE_ILCPLEX};${CPLEX_INCLUDE_ILCONCERT}" )
        set(CPLEX_LIBRARIES ${CPLEX_CONCERT_LIBRARY} ${CPLEX_ILOCPLEX_LIBRARY} ${CPLEX_LIBRARY} ${CPLEX_PTHREAD_LIBRARY} ${CPLEX_DL_LIBRARY})
    endif(CPLEX_FOUND)

    mark_as_advanced(CPLEX_INCLUDE_DIR CPLEX_LIBRARY CPLEX_CONCERT_INCLUDE_DIR CPLEX_ILO_LIBRARY CPLEX_CONCERT_LIBRARY CPLEX_PTHREAD_LIBRARY)

endif(CPLEX_INCLUDE_DIR)

message(STATUS "CPLEX_ILO_LIBRARY=${CPLEX_ILO_LIBRARY}")
message(STATUS "CPLEX_LIBRARIES=${CPLEX_LIBRARIES}")
message(STATUS "CPLEX_INCLUDE_DIRS=${CPLEX_INCLUDE_DIRS}")
message(STATUS "concert=${concert}")
message(STATUS "cplex=${cplex}")

CPLEX 相关的 CMake 输出是

-- Found CPLEX: /opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/lib/x86-64_linux/static_pic/libcplex.a  
-- CPLEX_ILO_LIBRARY=/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/lib/x86-64_linux/static_pic/libilocplex.a
-- CPLEX_LIBRARIES=/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/lib/x86-64_linux/static_pic/libconcert.a;/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/lib/x86-64_linux/static_pic/libcplex.a;/usr/lib/x86_64-linux-gnu/libpthread.so;/usr/lib/x86_64-linux-gnu/libdl.so
-- CPLEX_INCLUDE_DIRS=/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/include;/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/include;/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/include/ilcplex;/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/include/ilconcert
-- concert=
-- cplex=

错误是

/usr/bin/ld: cannot find -lconcert
/usr/bin/ld: cannot find -lilocplex
/usr/bin/ld: cannot find -lcplex

没有最后一行CMakeLists.txt,错误是

/usr/bin/ld: CMakeFiles/myprog.dir/src/main.cpp.o: in function `main':
/<my path>/src/main.cpp:7: undefined reference to `IloCplex::IloCplex(IloModel)'

那就是链接器在IloEnvin/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/include/ilconcert/iloenv.hIloModelin/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/include/ilconcert/ilomodel.h但不是IloCplexin 中找到类/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/include/ilcplex/ilocplexi.h

从命令行编译是可行的(为了便于阅读,在此处进行了格式化):

$ for f in src/*.cpp; do 
... g++ -c -I/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/include 
... -I/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/include 
... -Iinclude $f -o build/$(basename $f .cpp).o;
... done

$ unset OBJ_FILES 
$ for i in build/*.o; do OBJ_FILES="$i $OBJ_FILES"; done
$ g++ -I/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/include 
... -I/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/include 
... -Iinclude  
... -L/opt/ibm/ILOG/CPLEX_Studio_Community201/cplex/lib/x86-64_linux/static_pic 
... -L/opt/ibm/ILOG/CPLEX_Studio_Community201/concert/lib/x86-64_linux/static_pic 
... $OBJ_FILES 
... -o progr  
... -lconcert -lilocplex -lcplex -lpthread -ldl

标签: c++linuxcmakecplexlinker-flags

解决方案


正如 Tsyvarev 所指出的:与其使用CPLEX_ILOCPLEX_LIBRARYthat is nowhere set,不如CPLEX_ILO_LIBRARY在定义中使用该变量CPLEX_LIBRARIES


推荐阅读