Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can you guys provide a clear CMakeLists.txt example on how to include onnxruntime for a C++ project? #3124

Closed
siquike opened this issue Mar 2, 2020 · 14 comments
Labels
documentation improvements or additions to documentation; typically submitted using template

Comments

@siquike
Copy link

siquike commented Mar 2, 2020

Is your feature request related to a problem? Please describe.
I want to be able to do find(onnxruntime) in my CMakeLists.txt and move on with my day. Can you guys provide a clear CMakeLists.txt example on how to include onnxruntime for a C++ project?

System information

  • ONNX Runtime version (you are using): Not relevant

Describe the solution you'd like
Can you guys provide a clear CMakeLists.txt example on how to include onnxruntime for a C++ project?

Describe alternatives you've considered
Looked everywhere online for a solution.

@snnn
Copy link
Member

snnn commented Mar 2, 2020

onnxruntime doesn't support CMake find_package yet.

@snnn snnn added documentation improvements or additions to documentation; typically submitted using template question labels Mar 2, 2020
@jgbradley1
Copy link
Contributor

I second this request.

@stale
Copy link

stale bot commented Jul 18, 2020

This issue has been automatically marked as stale due to inactivity and will be closed in 7 days if no further activity occurs. If further support is needed, please provide an update and/or more details.

@stale stale bot added the wontfix label Jul 18, 2020
@stale
Copy link

stale bot commented Jul 25, 2020

This issue has been automatically closed due to inactivity. Please reactivate if further support is needed.

@stale stale bot closed this as completed Jul 25, 2020
@jcarius
Copy link

jcarius commented Aug 19, 2020

Hi all,
for those facing the same issue, I can provide two exemplary solutions that work for Ubuntu (18.04). The second one might be applicable cross-plattform, but I have not tested this.

A) The hacky way via linux environment variables
Download the latest linux release and extract the archive. Copy over the include and lib directory contents into a folder structure of your choice, for example under /home/<USERNAME>/.local/include and /home/<USERNAME>/.local/lib, respectively . If this folder is not automatically checked by the linker, then export the environment variables
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/<USERNAME>/.local/lib
export LIBRARY_PATH=$LIBRARY_PATH:/home/<USERNAME>/.local/lib
such that the shared library is found during link and runtime. If the headers are not discovered automatically, add a corresonding include_directories directive in your CMakeLists.txt. Finally, your target should target_link_libraries against onnxruntime.

B) Create libraryConfig.cmake to enable find_package(onnxruntime)
This solution is much cleaner and does not require messing up the shared library paths nor a global installation. Again, extract the release into something like /home/<USERNAME>/.local/include and /home/<USERNAME>/.local/lib. Then, add onnxruntimeConfig.cmake under /home/<USERNAME>/.local/share/cmake/onnxruntime. Once /home/<USERNAME>/.local/share/cmake is on your CMAKE_PREFIX_PATH one can simply find_package(onnxruntime) and link the corresponding targets against ${onnxruntime_LIBRARIES}.

If the maintainers are interested, I can create a PR with the Cmake configuration. For the time being, I'm pasting onnxruntimeConfig.cmake below:

# This will define the following variables:
#   onnxruntime_FOUND        -- True if the system has the onnxruntime library
#   onnxruntime_INCLUDE_DIRS -- The include directories for onnxruntime
#   onnxruntime_LIBRARIES    -- Libraries to link against
#   onnxruntime_CXX_FLAGS    -- Additional (required) compiler flags

include(FindPackageHandleStandardArgs)

# Assume we are in <install-prefix>/share/cmake/onnxruntime/onnxruntimeConfig.cmake
get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(onnxruntime_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)

set(onnxruntime_INCLUDE_DIRS ${onnxruntime_INSTALL_PREFIX}/include)
set(onnxruntime_LIBRARIES onnxruntime)
set(onnxruntime_CXX_FLAGS "") # no flags needed


find_library(onnxruntime_LIBRARY onnxruntime
    PATHS "${onnxruntime_INSTALL_PREFIX}/lib"
)

add_library(onnxruntime SHARED IMPORTED)
set_property(TARGET onnxruntime PROPERTY IMPORTED_LOCATION "${onnxruntime_LIBRARY}")
set_property(TARGET onnxruntime PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${onnxruntime_INCLUDE_DIRS}")
set_property(TARGET onnxruntime PROPERTY INTERFACE_COMPILE_OPTIONS "${onnxruntime_CXX_FLAGS}")

find_package_handle_standard_args(onnxruntime DEFAULT_MSG onnxruntime_LIBRARY onnxruntime_INCLUDE_DIRS)

@WilliamTambellini
Copy link
Contributor

@snnn A script like onnxruntimeConfig.cmake is today the StateOftheArt practive for any library to cleanly integrate with any other project using cmake. I would be ok to prepare a PR to integrate it in the onnxrt master unless @jcarius would prefer to.
Would you mind reopening at least that ticket ?

@jcarius
Copy link

jcarius commented Dec 9, 2020

@WilliamTambellini thank you for picking this up and please go ahead, I don't have the time at the moment to make a clean PR.

Apart from the onnxruntimeConfig.cmake pasted above, it probably makes sense to also install a onnxruntimeVersion.cmake in the same directory, something like this:

set(PACKAGE_VERSION "1.4.0")

# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
  set(PACKAGE_VERSION_COMPATIBLE TRUE)
  if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
    set(PACKAGE_VERSION_EXACT TRUE)
  endif()
endif()

gdolle added a commit to gdolle/opentrack that referenced this issue Aug 1, 2021
- Address review comment opentrack#1306 (comment)
- Update ONNXRuntime module to use a specific `onnxruntime` target.
- Use OpenCV components instead.

NOTE:

ONNXRuntinme may provide their own ONNXRuntimeConfig.cmake and
ONNXRuntimeVersion.cmake in the future.
See microsoft/onnxruntime#3124 for reference
@prateek9623
Copy link
Contributor

Hi all,
I have created "Findonnxruntime.cmake" to help with this issue,

# Find onnxruntime library
#
# usage:
#   find_package(onnxruntime REQUIRED)
# if wants to check for particular execution provider:
#   find_package(onnxruntime REQUIRED COMPONENTS onnxruntime_providers_<PROVIDER_NAME>)
#   find_package(onnxruntime REQUIRED COMPONENTS onnxruntime_providers_cuda onnxruntime_providers_tensorrt)
# tested with cuda and tensorrt
#
#
# Note: This file only search libs of execution providers, not their dependencies 
#

include(FindPackageHandleStandardArgs)
# checking if onnxruntime_ROOT contain cmake find_package compatible config
file(GLOB __cmake_config_file "${onnxruntime_ROOT}/lib/cmake/onnxruntime/onnxruntimeConfig.cmake")
LIST(LENGTH __cmake_config_file __cmake_config_file_count)
if(__cmake_config_file_count GREATER 0)
  set(ARGS "")
  if(${onnxruntime_FIND_VERSION})
    list(APPEND ARGS ${onnxruntime_FIND_VERSION})
  endif()
  if(${onnxruntime_FIND_VERSION_EXACT})
    list(APPEND ARGS "EXACT")
  endif()
  if (${onnxruntime_FIND_QUIET})
    list(APPEND ARGS "QUIET")
  elseif (${onnxruntime_FIND_REQUIRED})
    list(APPEND ARGS "REQUIRED")
  endif()
  if(onnxruntime_FIND_COMPONENTS)
    list(APPEND ARGS "COMPONENTS" ${onnxruntime_FIND_COMPONENTS})
  endif()
  # recalling find_package with args but with specified path
  find_package(onnxruntime ${ARGS} CONFIG PATHS ${onnxruntime_ROOT})
else()
  # checking if onnxruntime_ROOT contain nuget package
  file(GLOB __nupkg_file "${onnxruntime_ROOT}/Microsoft.ML.OnnxRuntime.*.nupkg")
  LIST(LENGTH __nupkg_file __nuget_file_count)
  if(__nuget_file_count GREATER 0)
    list (GET __nupkg_file 0 __nupkg_file)
    STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" onnxruntime_VERSION "${__nupkg_file}")
    message(STATUS "Loading using nuget")

    set(ORT_INCLUDE_DIR "${onnxruntime_ROOT}/build/native/include/")
    if(WIN32)
      set(ORT_LIBRARY_DIR "${onnxruntime_ROOT}/runtimes/win-x64/native/")
    elseif(UNIX)
      set(ORT_LIBRARY_DIR "${onnxruntime_ROOT}/runtimes/linux-x64/native/")
    else()
      message(FATAL_ERROR "Nuget package only support Win and linux")
    endif()
    set(onnxruntime_FOUND FALSE)
    if(EXISTS ${ORT_INCLUDE_DIR} AND EXISTS ${ORT_LIBRARY_DIR})
      set(onnxruntime_FOUND TRUE)
    endif()
    if(onnxruntime_FOUND)
      add_library(onnxruntime::onnxruntime SHARED IMPORTED)
      set_target_properties(onnxruntime::onnxruntime PROPERTIES 
        IMPORTED_CONFIGURATIONS RELEASE
        INTERFACE_INCLUDE_DIRECTORIES "${ORT_INCLUDE_DIR}"
        )
      if(WIN32)
        set_target_properties(onnxruntime::onnxruntime PROPERTIES
          IMPORTED_IMPLIB "${ORT_LIBRARY_DIR}onnxruntime.lib"
          IMPORTED_LOCATION "${ORT_LIBRARY_DIR}onnxruntime.dll"
        )
      elseif(UNIX AND NOT APPLE)
        set_target_properties(onnxruntime::onnxruntime PROPERTIES IMPORTED_LOCATION "${ORT_LIBRARY_DIR}libonnxruntime.so")
      endif()
    endif()
  elseif(EXISTS "${onnxruntime_ROOT}/bin" AND EXISTS "${onnxruntime_ROOT}/include" AND EXISTS "${onnxruntime_ROOT}/lib")
    set(ORT_INCLUDE_DIR "${onnxruntime_ROOT}/include/")
    set(ORT_RUNTIME_DIR "${onnxruntime_ROOT}/bin/")
    set(ORT_LIBRARY_DIR "${onnxruntime_ROOT}/lib/")
    set(onnxruntime_FOUND TRUE)
    add_library(onnxruntime::onnxruntime SHARED IMPORTED)
    set_target_properties(onnxruntime::onnxruntime PROPERTIES 
      IMPORTED_CONFIGURATIONS RELEASE
      INTERFACE_INCLUDE_DIRECTORIES "${ORT_INCLUDE_DIR}"
      )
    if(WIN32)
      set_target_properties(onnxruntime::onnxruntime PROPERTIES
        IMPORTED_IMPLIB "${ORT_LIBRARY_DIR}onnxruntime.lib"
        IMPORTED_LOCATION "${ORT_RUNTIME_DIR}onnxruntime.dll"
      )
    elseif(UNIX AND NOT APPLE)
      set_target_properties(onnxruntime::onnxruntime PROPERTIES IMPORTED_LOCATION "${ORT_LIBRARY_DIR}libonnxruntime.so")
    endif()
  endif()
  if(onnxruntime_FOUND)
    function(import_providers provider_name)
      if(WIN32)
        set(lib_path "${ORT_LIBRARY_DIR}onnxruntime_providers_${provider_name}.dll")
      elseif(UNIX AND NOT APPLE)
        set(lib_path "${ORT_LIBRARY_DIR}libonnxruntime_providers_${provider_name}.so")
      endif()
      if(EXISTS ${lib_path})
          add_library(onnxruntime::onnxruntime_providers_${provider_name} MODULE IMPORTED)
          set_target_properties(onnxruntime::onnxruntime_providers_${provider_name} PROPERTIES 
            IMPORTED_CONFIGURATIONS RELEASE
            INTERFACE_INCLUDE_DIRECTORIES ${ORT_INCLUDE_DIR}
            IMPORTED_LOCATION ${lib_path}
          )
        set(onnxruntime_onnxruntime_providers_${provider_name}_FOUND TRUE PARENT_SCOPE)
      endif()
    endfunction(import_providers)
    set(ORT_PROVIDERS cuda;tensorrt)
    foreach(__component ${ORT_PROVIDERS})
      import_providers(${__component})
    endforeach()
    find_package_handle_standard_args(
      onnxruntime
      REQUIRED_VARS onnxruntime_ROOT 
      FOUND_VAR onnxruntime_FOUND
      VERSION_VAR onnxruntime_VERSION
      HANDLE_COMPONENTS
    )
  endif()
endif()

It can be used as a cmake module to find onnxruntime, and I have tested it with onnxruntime current cmake install package, NuGet package, and cmake package config file.
I have also created a PR to support cmake package config file creation automatically #8919

@lucasjinreal
Copy link

any moredern way to use this?

@developer239
Copy link

@lucasjinreal
I have minimalistic (no extra cmake file) working example here:

snnn pushed a commit that referenced this issue Jun 20, 2023
**Description**: 
Adds support for cmake find_package.

**Motivation and Context**
As mentioned in issue #7150 onnxruntime doesn't have support for CMake
find_package, this PR adds that and also adds the CMake package version
file. Now anyone can link onnxruntime like this:
```cmake
find_package(onnxruntime)
add_executable(test Source.cpp)
target_link_libraries(test PRIVATE onnxruntime::onnxruntime)
```
this also simplifies #3124
@roachsinai
Copy link

@snnn could you update example at https://github.com/microsoft/onnxruntime-inference-examples/blob/main/c_cxx/CMakeLists.txt for cmake? as #8919 has been merged.

@shizidushu
Copy link

Hi all, I have created "Findonnxruntime.cmake" to help with this issue,

# Find onnxruntime library
#
# usage:
#   find_package(onnxruntime REQUIRED)
# if wants to check for particular execution provider:
#   find_package(onnxruntime REQUIRED COMPONENTS onnxruntime_providers_<PROVIDER_NAME>)
#   find_package(onnxruntime REQUIRED COMPONENTS onnxruntime_providers_cuda onnxruntime_providers_tensorrt)
# tested with cuda and tensorrt
#
#
# Note: This file only search libs of execution providers, not their dependencies 
#

include(FindPackageHandleStandardArgs)
# checking if onnxruntime_ROOT contain cmake find_package compatible config
file(GLOB __cmake_config_file "${onnxruntime_ROOT}/lib/cmake/onnxruntime/onnxruntimeConfig.cmake")
LIST(LENGTH __cmake_config_file __cmake_config_file_count)
if(__cmake_config_file_count GREATER 0)
  set(ARGS "")
  if(${onnxruntime_FIND_VERSION})
    list(APPEND ARGS ${onnxruntime_FIND_VERSION})
  endif()
  if(${onnxruntime_FIND_VERSION_EXACT})
    list(APPEND ARGS "EXACT")
  endif()
  if (${onnxruntime_FIND_QUIET})
    list(APPEND ARGS "QUIET")
  elseif (${onnxruntime_FIND_REQUIRED})
    list(APPEND ARGS "REQUIRED")
  endif()
  if(onnxruntime_FIND_COMPONENTS)
    list(APPEND ARGS "COMPONENTS" ${onnxruntime_FIND_COMPONENTS})
  endif()
  # recalling find_package with args but with specified path
  find_package(onnxruntime ${ARGS} CONFIG PATHS ${onnxruntime_ROOT})
else()
  # checking if onnxruntime_ROOT contain nuget package
  file(GLOB __nupkg_file "${onnxruntime_ROOT}/Microsoft.ML.OnnxRuntime.*.nupkg")
  LIST(LENGTH __nupkg_file __nuget_file_count)
  if(__nuget_file_count GREATER 0)
    list (GET __nupkg_file 0 __nupkg_file)
    STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" onnxruntime_VERSION "${__nupkg_file}")
    message(STATUS "Loading using nuget")

    set(ORT_INCLUDE_DIR "${onnxruntime_ROOT}/build/native/include/")
    if(WIN32)
      set(ORT_LIBRARY_DIR "${onnxruntime_ROOT}/runtimes/win-x64/native/")
    elseif(UNIX)
      set(ORT_LIBRARY_DIR "${onnxruntime_ROOT}/runtimes/linux-x64/native/")
    else()
      message(FATAL_ERROR "Nuget package only support Win and linux")
    endif()
    set(onnxruntime_FOUND FALSE)
    if(EXISTS ${ORT_INCLUDE_DIR} AND EXISTS ${ORT_LIBRARY_DIR})
      set(onnxruntime_FOUND TRUE)
    endif()
    if(onnxruntime_FOUND)
      add_library(onnxruntime::onnxruntime SHARED IMPORTED)
      set_target_properties(onnxruntime::onnxruntime PROPERTIES 
        IMPORTED_CONFIGURATIONS RELEASE
        INTERFACE_INCLUDE_DIRECTORIES "${ORT_INCLUDE_DIR}"
        )
      if(WIN32)
        set_target_properties(onnxruntime::onnxruntime PROPERTIES
          IMPORTED_IMPLIB "${ORT_LIBRARY_DIR}onnxruntime.lib"
          IMPORTED_LOCATION "${ORT_LIBRARY_DIR}onnxruntime.dll"
        )
      elseif(UNIX AND NOT APPLE)
        set_target_properties(onnxruntime::onnxruntime PROPERTIES IMPORTED_LOCATION "${ORT_LIBRARY_DIR}libonnxruntime.so")
      endif()
    endif()
  elseif(EXISTS "${onnxruntime_ROOT}/bin" AND EXISTS "${onnxruntime_ROOT}/include" AND EXISTS "${onnxruntime_ROOT}/lib")
    set(ORT_INCLUDE_DIR "${onnxruntime_ROOT}/include/")
    set(ORT_RUNTIME_DIR "${onnxruntime_ROOT}/bin/")
    set(ORT_LIBRARY_DIR "${onnxruntime_ROOT}/lib/")
    set(onnxruntime_FOUND TRUE)
    add_library(onnxruntime::onnxruntime SHARED IMPORTED)
    set_target_properties(onnxruntime::onnxruntime PROPERTIES 
      IMPORTED_CONFIGURATIONS RELEASE
      INTERFACE_INCLUDE_DIRECTORIES "${ORT_INCLUDE_DIR}"
      )
    if(WIN32)
      set_target_properties(onnxruntime::onnxruntime PROPERTIES
        IMPORTED_IMPLIB "${ORT_LIBRARY_DIR}onnxruntime.lib"
        IMPORTED_LOCATION "${ORT_RUNTIME_DIR}onnxruntime.dll"
      )
    elseif(UNIX AND NOT APPLE)
      set_target_properties(onnxruntime::onnxruntime PROPERTIES IMPORTED_LOCATION "${ORT_LIBRARY_DIR}libonnxruntime.so")
    endif()
  endif()
  if(onnxruntime_FOUND)
    function(import_providers provider_name)
      if(WIN32)
        set(lib_path "${ORT_LIBRARY_DIR}onnxruntime_providers_${provider_name}.dll")
      elseif(UNIX AND NOT APPLE)
        set(lib_path "${ORT_LIBRARY_DIR}libonnxruntime_providers_${provider_name}.so")
      endif()
      if(EXISTS ${lib_path})
          add_library(onnxruntime::onnxruntime_providers_${provider_name} MODULE IMPORTED)
          set_target_properties(onnxruntime::onnxruntime_providers_${provider_name} PROPERTIES 
            IMPORTED_CONFIGURATIONS RELEASE
            INTERFACE_INCLUDE_DIRECTORIES ${ORT_INCLUDE_DIR}
            IMPORTED_LOCATION ${lib_path}
          )
        set(onnxruntime_onnxruntime_providers_${provider_name}_FOUND TRUE PARENT_SCOPE)
      endif()
    endfunction(import_providers)
    set(ORT_PROVIDERS cuda;tensorrt)
    foreach(__component ${ORT_PROVIDERS})
      import_providers(${__component})
    endforeach()
    find_package_handle_standard_args(
      onnxruntime
      REQUIRED_VARS onnxruntime_ROOT 
      FOUND_VAR onnxruntime_FOUND
      VERSION_VAR onnxruntime_VERSION
      HANDLE_COMPONENTS
    )
  endif()
endif()

It can be used as a cmake module to find onnxruntime, and I have tested it with onnxruntime current cmake install package, NuGet package, and cmake package config file. I have also created a PR to support cmake package config file creation automatically #8919

@prateek9623 Can you provide a CMakeLists.txt file to illustrate how to use it with cuda provider?

@prateek9623
Copy link
Contributor

@shizidushu Let's say you have this Findonnxruntime.cmake present in the subfolder named cmake. Then your CMakeLists.txt will look something like this:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(CUDAToolkit 11 REQUIRED COMPONENTS cublas)
find_package(CUDNN 8 REQUIRED)
find_package(onnxruntime 1.13 REQUIRED COMPONENTS onnxruntime_providers_cuda OPTIONAL_COMPONENTS onnxruntime_providers_tensorrt)
add_executable(Test Source.cpp)
target_link_libraries(Test PRIVATE onnxruntime::onnxruntime)

And your source file:

#include "onnxruntime_cxx_api.h"

@vipcxj
Copy link

vipcxj commented Apr 8, 2024

@prateek9623 I found some problem when using you cmake in linux.

  1. ${onnxruntime_ROOT}/build/native/include/ should be ${onnxruntime_ROOT}/buildTransitive/native/include/
  2. After my program Demo linked with ibonnxruntime.so, and I found the really dependent so file is libonnxruntime.so.${version}, however, only libonnxruntime.so exists in the nuget package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation improvements or additions to documentation; typically submitted using template
Projects
None yet
Development

No branches or pull requests