3
$\begingroup$

I'm trying to incorporate or-tools into my cmake project.

I've tried some of the suggestions given by the project maintainers, who give a few different ways to integrate or-tools in the readme and in a template project. I've tried both, yielding the same result.

The first method is building locally and using cmake's find_package:

################
##  OR_TOOLS  ##
################
message(STATUS "Installing OR-Tools...")
# Download and install or-tools at configure time
configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ortools.CMakeLists.txt
${CMAKE_BINARY_DIR}/ortools-download/CMakeLists.txt)
# CMake configure
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
  RESULT_VARIABLE result
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/ortools-download)
if(result)
  message(FATAL_ERROR "CMake step for ortools failed: ${result}")
endif()
# CMake Build/Install
execute_process(COMMAND ${CMAKE_COMMAND} --build .
  RESULT_VARIABLE result
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/ortools-download)
if(result)
  message(FATAL_ERROR "Build step for ortools failed: ${result}")
endif()
message(STATUS "Installing OR-Tools...DONE")

list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/deps)
find_package(ortools REQUIRED)

where in the cmake directory I have a file ortools.CmakeLists.txt:

cmake_minimum_required(VERSION 3.8)

project(ortools-download NONE)

include(ExternalProject)
ExternalProject_Add(ortools_project
  GIT_REPOSITORY https://github.com/google/or-tools.git
  GIT_TAG "stable"
  GIT_SHALLOW TRUE
  GIT_PROGRESS TRUE
  CMAKE_ARGS
    "-G@CMAKE_GENERATOR@"
    "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-DBUILD_DEPS=ON"
"-DBUILD_SAMPLES=OFF"
"-DBUILD_EXAMPLES=OFF"
"-DBUILD_TESTING=OFF"
"-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/deps"
)

and the second is to use cmake's FetchContent.

    include(FetchContent)
    FetchContent_Declare(
            ortools
            GIT_REPOSITORY https://github.com/google/or-tools.git
            GIT_TAG        stable
    )

    set(BUILD_DEPS ON)
    set(BUILD_SAMPLES OFF)
    set(BUILD_EXAMPLES OFF)
    FetchContent_MakeAvailable(ortools)
    set(requiredlibs ${requiredlibs} ortools::ortools)

Both give the same error, at runtime:

ERROR: Something is wrong with flag 'flagfile' in file 'Users/username/project-root/cmake-build-debug/ortools-download/ortools_project-prefix/src/ortools_project-build/_deps/absl-src/absl/flags/parse.cc'. One possibility: file 'Users/username/project-root/cmake-build-debug/ortools-download/ortools_project-prefix/src/ortools_project-build/_deps/absl-src/absl/flags/parse.cc' is being linked both statically and dynamically into this executable. e.g. some files listed as srcs to a test and also listed as srcs of some shared lib deps of the same test.

For reference, I'm on an Apple Silicon Mac, using cmake 3.22.3, compiling with the flag: -DCMAKE_APPLE_SILICON_PROCESSOR=arm64. I've tried both -DCMAKE_BUILD_TYPE=Release and -DCMAKE_BUILD_TYPE=Debug.

EDIT:

I partially figured it out, however I still have a question: I want to compile a dynamic library from many shared libraries in my project. The static libraries need to be linked to ortools because they reference that library. However, I then want to build a shared library that merges all the separate static libraries together, this doesn't work. Why is that the case, and is there a way to fix it?

Below is my current solution so if anyone else has this issue they can reference. I ended up using the FetchContent method, with a few modifications.

The error gives a hint as to what was happening: "is being linked both statically and dynamically into this executable".

In c++ there are two types of libraries: static and dynamic. My code builds many static libraries and links them to a dynamic library, which is then linked to the executable file.

project structure:

.
├── CMakeLists.txt
├── src
│   ├── CMakeLists.txt # creates the dynamic library
│   ├── [various .cc/.h files]
│   ├── staticlib1
│   │   ├── CMakeLists.txt # creates a static library
│   │   └── [various .cc/.h files]
│   └── staticlib2
│       ├── CMakeLists.txt # creates another static library
│       └── [various .cc/.h files]
└── main.cc

The key is that ortools::ortools can only be linked to either multiple static libraries, or multiple dynamic libraries. It cannot be linked to both static and dynamic libraries.

In src/CMakelists.txt I create a dynamic library and was linking to ortools:

project(project)

SET(SOURCE_FILES_SRC
        example.cc
)

add_subdirectory(staticlib1)
set(requiredlibs ${requiredlibs} staticlib1)

add_subdirectory(staticlib2)
set(requiredlibs ${requiredlibs} staticlib2)

add_library(${DISPATCHER_LIB} SHARED ${SOURCE_FILES_SRC})
target_link_libraries(${DISPATCHER_LIB} ${requiredlibs} ortools::ortools) # linking to dynamic(shared) ortools lib

However, I was also linking to ortools::ortools in the static libraries in src/staticlib1/CMakeLists.txt which caused the issue:

project(project)

set(staticlib1_SOURCE_FILES
        example2.cc)

add_library(staticlib1 STATIC ${staticlib1_SOURCE_FILES})
set_property(TARGET staticlib1 PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(staticlib1 ${requiredlibs} ortools::ortools) # linking to static ortools 

To fix this, changed the dynamic library to a static library

project(project)

SET(SOURCE_FILES_SRC
        example.cc
)

add_subdirectory(staticlib1)
set(requiredlibs ${requiredlibs} staticlib1)

add_subdirectory(staticlib2)
set(requiredlibs ${requiredlibs} staticlib2)

add_library(${DISPATCHER_LIB} ${SOURCE_FILES_SRC}) # now a static library
target_link_libraries(${DISPATCHER_LIB} ${requiredlibs})

I also had to change the FetchContent block in CMakeLists.txt to disable building the ortools dynamic libraries.

set(FETCHCONTENT_QUIET OFF)
include(FetchContent)
FetchContent_Declare(
        ortools
        GIT_REPOSITORY https://github.com/google/or-tools.git
        GIT_TAG        stable
)
set(BUILD_SHARED_LIBS OFF) # disables dynamic(shared) library building
set(BUILD_DEPS ON)
set(BUILD_SAMPLES OFF)
set(BUILD_EXAMPLES OFF)
FetchContent_MakeAvailable(ortools)

As I stated above, at the beginning of the edit, I would like this line

add_library(${DISPATCHER_LIB} ${SOURCE_FILES_SRC}) # now a static library

in src/CMakeLists.txt to be a dynamic library:

add_library(${DISPATCHER_LIB} SHARED ${SOURCE_FILES_SRC}) # now a static library

is there a way to make that work given that I need ortools to link to the static libraries that it is composed of?

$\endgroup$
2
  • $\begingroup$ Try changing project(ortools-download NONE) to specify the language: project(ortools-download LANGUAGES C CXX). $\endgroup$ Commented Apr 26, 2022 at 7:02
  • $\begingroup$ With that change, the FetchContent version worked fine for me on an M1. Otherwise was getting some compiler error when compiling CBC (it's a dep). Also, add set(FETCHCONTENT_QUIET OFF) to see what's going on. $\endgroup$ Commented Apr 26, 2022 at 13:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.