5cbd3f29e3
clang-tidy / clang-tidy (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Copilot Setup Steps / copilot-setup-steps (push) Waiting to run
Lint / Validate SBOM (push) Waiting to run
Lint / Enforce style (push) Waiting to run
CI / Test windows-2022, 3.14, External, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test windows-latest, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test windows-latest, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test windows-latest, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test ubuntu-24.04, 3.14, Internal, debug=1, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=1, onnx_ml=1, autogen=1 (push) Waiting to run
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=0, onnx_ml=0, autogen=0 (push) Waiting to run
CI / Test macos-latest, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test macos-latest, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test macos-latest, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test ubuntu-24.04, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test ubuntu-24.04, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
CI / Test ubuntu-24.04, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Waiting to run
Generate and publish ONNX docs / build (push) Waiting to run
Generate and publish ONNX docs / deploy (push) Blocked by required conditions
Pixi CI / Install and lint (ubuntu-24.04-arm) (push) Waiting to run
Pixi CI / Install and lint (windows-2022) (push) Waiting to run
Pixi CI / Xcode generator build (push) Waiting to run
Pixi CI / Install and test (macos-latest, default) (push) Waiting to run
Pixi CI / Install and test (ubuntu-24.04-arm, default) (push) Waiting to run
Pixi CI / Install and test (ubuntu-latest, default) (push) Waiting to run
Pixi CI / Install and test (windows-2022, default) (push) Waiting to run
Pixi CI / Install and test (macos-latest, oldies) (push) Waiting to run
Pixi CI / Install and test (ubuntu-24.04-arm, oldies) (push) Waiting to run
Pixi CI / Install and test (ubuntu-latest, oldies) (push) Waiting to run
Pixi CI / Install and test (windows-2022, oldies) (push) Waiting to run
Scorecard supply-chain security / Scorecard analysis (push) Waiting to run
Fuzz / Run fuzz harnesses (${{ github.event_name == 'schedule' && 'nightly' || 'smoke' }}) (push) Has been cancelled
Create Releases / call-mac (push) Has been cancelled
Create Releases / call-linux (push) Has been cancelled
Create Releases / call-sdist (push) Has been cancelled
Create Releases / call-win (push) Has been cancelled
Create Releases / call-pyodide (push) Has been cancelled
Windows_No_Exception_CI / build (x64, 3.10) (push) Has been cancelled
Check URLs / build (push) Has been cancelled
Create Releases / Attest CI build artifacts (push) Has been cancelled
Create Releases / Check for Publish release build to pypi (push) Has been cancelled
Create Releases / Check for Publish preview build to test.pypi-weekly (push) Has been cancelled
Create Releases / Publish preview build to test.pypi-weekly (push) Has been cancelled
Create Releases / Check for Publish release build to test.pypi (rc-candidates) (push) Has been cancelled
Create Releases / Publish release build to test.pypi (push) Has been cancelled
Create Releases / Check for Publish preview build to pypi-weekly (push) Has been cancelled
Create Releases / Publish preview build to pypi-weekly (push) Has been cancelled
Create Releases / Publish release build to pypi (push) Has been cancelled
Create Releases / test source distribution (push) Has been cancelled
682 lines
24 KiB
CMake
682 lines
24 KiB
CMake
# Minimum CMake required
|
|
cmake_minimum_required(VERSION 3.26)
|
|
# Project
|
|
project(onnx LANGUAGES CXX)
|
|
|
|
include(cmake/Utils.cmake)
|
|
# Honor visibility properties for all target types.
|
|
cmake_policy(SET CMP0063 NEW)
|
|
# Modules FindPython3 and FindPython use LOCATION for lookup strategy.
|
|
cmake_policy(SET CMP0094 NEW)
|
|
|
|
# Set default build type
|
|
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)
|
|
message(STATUS "Build type not set - defaulting to Release")
|
|
set(
|
|
CMAKE_BUILD_TYPE "Release"
|
|
CACHE
|
|
STRING
|
|
"Choose the type of build from: Debug Release RelWithDebInfo MinSizeRel Coverage."
|
|
FORCE)
|
|
endif()
|
|
|
|
# https://reproducible-builds.org/docs/source-date-epoch/
|
|
# cmake's string(TIMESTAMP ...) command reads SOURCE_DATE_EPOCH automatically,
|
|
# which avoids shelling out to `date` (whose flags differ between GNU and BSD).
|
|
string(TIMESTAMP BUILD_DATE "%Y-%m-%d" UTC)
|
|
|
|
if(NOT BUILD_SHARED_LIBS)
|
|
# by default, cmake builds static libraries
|
|
set(BUILD_SHARED_LIBS OFF)
|
|
endif()
|
|
|
|
|
|
option(ONNX_BUILD_PYTHON "Build Python binaries" OFF)
|
|
option(ONNX_BUILD_CUSTOM_PROTOBUF "Build and use ONNX's own protobuf" OFF)
|
|
option(ONNX_USE_PROTOBUF_SHARED_LIBS "Build ONNX using protobuf shared library." OFF)
|
|
option(ONNX_GEN_PB_TYPE_STUBS "Generate protobuf python type stubs" ON)
|
|
option(ONNX_WERROR "Build with Werror" OFF)
|
|
option(ONNX_COVERAGE "Build with coverage instrumentation" OFF)
|
|
option(ONNX_BUILD_TESTS "Build ONNX C++ APIs Tests" OFF)
|
|
option(ONNX_USE_ASAN "Build ONNX with ASAN" OFF)
|
|
option(ONNX_HARDENING "Build with compiler hardening flags (OpenSSF guidelines)" OFF)
|
|
option(ONNX_USE_LITE_PROTO "Use lite protobuf instead of full." OFF)
|
|
option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF)
|
|
option(ONNX_DISABLE_STATIC_REGISTRATION "Disable static registration for ONNX operator schemas." OFF)
|
|
option(ONNX_USE_UNITY_BUILD "Enable Unity (Jumbo) build for" OFF)
|
|
option(ONNX_PYODIDE_BUILD "Build ONNX for Pyodide/Emscripten (wasm32)." OFF)
|
|
option(ONNX_INSTALL "Install ONNX targets, headers, and CMake config files" ON)
|
|
if(WIN32)
|
|
option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime. Ignored if CMAKE_MSVC_RUNTIME_LIBRARY is defined." OFF)
|
|
endif()
|
|
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
if(NOT DEFINED ONNX_ML)
|
|
if(DEFINED ENV{ONNX_ML})
|
|
set(DEFAULT_ONNX_ML $ENV{ONNX_ML})
|
|
else()
|
|
set(DEFAULT_ONNX_ML ON)
|
|
endif()
|
|
option(ONNX_ML "Enable traditional ML API." ${DEFAULT_ONNX_ML})
|
|
endif()
|
|
|
|
if(NOT DEFINED ONNX_VERIFY_PROTO3)
|
|
if(DEFINED ENV{ONNX_VERIFY_PROTO3})
|
|
set(PROTO3_ENABLED $ENV{ONNX_VERIFY_PROTO3})
|
|
else()
|
|
set(PROTO3_ENABLED OFF)
|
|
endif()
|
|
option(ONNX_VERIFY_PROTO3 "Generate code by proto3" ${PROTO3_ENABLED})
|
|
endif()
|
|
|
|
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
else()
|
|
if(CMAKE_CXX_STANDARD VERSION_LESS 17)
|
|
message(FATAL_ERROR "At least C++17 is required.")
|
|
endif()
|
|
endif()
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
set(ONNX_ROOT ${onnx_SOURCE_DIR})
|
|
|
|
# Read ONNX version
|
|
file(READ "${ONNX_ROOT}/VERSION_NUMBER" ONNX_VERSION)
|
|
string(STRIP "${ONNX_VERSION}" ONNX_VERSION)
|
|
|
|
# Parse version components for version macros (strip any pre-release suffix like "rc1")
|
|
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" _ ${ONNX_VERSION})
|
|
set(ONNX_VERSION_MAJOR ${CMAKE_MATCH_1})
|
|
set(ONNX_VERSION_MINOR ${CMAKE_MATCH_2})
|
|
set(ONNX_VERSION_PATCH ${CMAKE_MATCH_3})
|
|
|
|
if(NOT MSVC)
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
|
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
|
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
|
|
if(ONNX_COVERAGE)
|
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT ONNX_NAMESPACE)
|
|
set(ONNX_NAMESPACE "onnx")
|
|
endif()
|
|
|
|
if(MSVC)
|
|
if(NOT ONNX_DISABLE_EXCEPTIONS)
|
|
string(APPEND CMAKE_CXX_FLAGS " /EHsc /wd26812")
|
|
string(APPEND CMAKE_C_FLAGS " /EHsc /wd26812")
|
|
endif()
|
|
add_compile_options(/MP /utf-8 /nologo)
|
|
add_compile_options(
|
|
/wd5287 # https://developercommunity.visualstudio.com/t/warning-C5287:-operands-are-different-e/10877942?sort=newest
|
|
/Zc:lambda # https://developercommunity.visualstudio.com/t/fatal--error-C1001:-Internal-compiler-er/10906076
|
|
)
|
|
endif()
|
|
|
|
if(ONNX_DISABLE_EXCEPTIONS)
|
|
add_compile_definitions("ONNX_NO_EXCEPTIONS")
|
|
# Disable C++ exceptions.
|
|
if(MSVC)
|
|
string(REGEX REPLACE "/EHsc" "/EHs-c-" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
|
add_definitions(-D_HAS_EXCEPTIONS=0)
|
|
else()
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables")
|
|
endif()
|
|
endif()
|
|
|
|
if(ONNX_BUILD_PYTHON AND ONNX_DISABLE_EXCEPTIONS)
|
|
message(FATAL_ERROR
|
|
"ONNX_DISABLE_EXCEPTIONS=ON is incompatible with ONNX_BUILD_PYTHON=ON. "
|
|
"The Python binding requires exceptions to be enabled.")
|
|
endif()
|
|
|
|
if(ONNX_BUILD_PYTHON)
|
|
set(python_dev_component Development.Module Development.SABIModule)
|
|
endif()
|
|
|
|
if(CMAKE_CROSSCOMPILING)
|
|
# When cross-compiling, the interpreter and the compiling/linking steps
|
|
# must use a different package. See the discussion about this at
|
|
# https://gitlab.kitware.com/cmake/cmake/-/issues/25145
|
|
if(ONNX_BUILD_PYTHON)
|
|
find_package(Python3 REQUIRED COMPONENTS ${python_dev_component})
|
|
endif()
|
|
find_package(Python REQUIRED COMPONENTS Interpreter)
|
|
set(ONNX_PYTHON_INTERPRETER Python::Interpreter)
|
|
if(ONNX_BUILD_PYTHON)
|
|
# nanobind >= 2.13 only auto-runs its own find_package(Python ...) when
|
|
# neither Python::Interpreter nor Python::Module exist yet. Since
|
|
# Python::Interpreter is already provided above (host interpreter, while
|
|
# Python3::Module above is the cross-compilation target's dev libs),
|
|
# nanobind would otherwise skip that step and fail to find Python::Module.
|
|
if(NOT TARGET Python::Module)
|
|
add_library(Python::Module ALIAS Python3::Module)
|
|
endif()
|
|
if(TARGET Python3::SABIModule AND NOT TARGET Python::SABIModule)
|
|
add_library(Python::SABIModule ALIAS Python3::SABIModule)
|
|
endif()
|
|
endif()
|
|
else()
|
|
find_package(Python3 REQUIRED COMPONENTS Interpreter ${python_dev_component})
|
|
# Find Python for nanobind
|
|
set(Python_EXECUTABLE ${Python3_EXECUTABLE})
|
|
find_package(Python REQUIRED COMPONENTS Interpreter ${python_dev_component})
|
|
set(ONNX_PYTHON_INTERPRETER Python3::Interpreter)
|
|
endif()
|
|
|
|
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
|
set(CMAKE_NO_SYSTEM_FROM_IMPORTED 1)
|
|
endif()
|
|
|
|
# Build the libraries with -fPIC including the protobuf lib.
|
|
if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
|
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
endif()
|
|
|
|
list(APPEND CMAKE_MODULE_PATH ${ONNX_ROOT}/cmake/external)
|
|
if(NOT ONNX_BUILD_CUSTOM_PROTOBUF)
|
|
if((ONNX_USE_LITE_PROTO AND TARGET protobuf::libprotobuf-lite) OR ((NOT ONNX_USE_LITE_PROTO) AND TARGET protobuf::libprotobuf))
|
|
# Sometimes we need to use protoc compiled for host architecture while linking
|
|
# libprotobuf against target architecture. See https://github.com/caffe2/caffe
|
|
# 2/blob/96f35ad75480b25c1a23d6e9e97bccae9f7a7f9c/cmake/ProtoBuf.cmake#L92-L99
|
|
if(EXISTS "${ONNX_CUSTOM_PROTOC_EXECUTABLE}")
|
|
message(STATUS "Using custom protoc executable")
|
|
set(ONNX_PROTOC_EXECUTABLE ${ONNX_CUSTOM_PROTOC_EXECUTABLE})
|
|
else()
|
|
if(TARGET protobuf::protoc)
|
|
set(ONNX_PROTOC_EXECUTABLE $<TARGET_FILE:protobuf::protoc>)
|
|
endif()
|
|
endif()
|
|
else()
|
|
# Customized version of find Protobuf. We need to avoid situations mentioned
|
|
# in https://github.com/caffe2/caffe2/blob/b7d983f255ef5496474f1ea188edb5e0ac4
|
|
# 42761/cmake/ProtoBuf.cmake#L82-L92 The following section is stolen from
|
|
# cmake/ProtoBuf.cmake in Caffe2
|
|
find_program(Protobuf_PROTOC_EXECUTABLE
|
|
NAMES protoc
|
|
DOC "The Google Protocol Buffers Compiler")
|
|
|
|
# Only if protoc was found, seed the include directories and libraries. We
|
|
# assume that protoc is installed at PREFIX/bin. We use get_filename_component
|
|
# to resolve PREFIX.
|
|
if(Protobuf_PROTOC_EXECUTABLE)
|
|
set(ONNX_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE})
|
|
get_filename_component(_PROTOBUF_INSTALL_PREFIX
|
|
${Protobuf_PROTOC_EXECUTABLE} DIRECTORY)
|
|
get_filename_component(_PROTOBUF_INSTALL_PREFIX
|
|
${_PROTOBUF_INSTALL_PREFIX}/.. REALPATH)
|
|
find_library(Protobuf_PROTOC_LIBRARY
|
|
NAMES protoc
|
|
PATHS ${_PROTOBUF_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
|
|
NO_DEFAULT_PATH)
|
|
if(ONNX_USE_LITE_PROTO)
|
|
find_library(Protobuf_LITE_LIBRARY
|
|
NAMES protobuf-lite
|
|
PATHS ${_PROTOBUF_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
|
|
NO_DEFAULT_PATH)
|
|
else()
|
|
find_library(Protobuf_LIBRARY
|
|
NAMES protobuf
|
|
PATHS ${_PROTOBUF_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
|
|
NO_DEFAULT_PATH)
|
|
endif(ONNX_USE_LITE_PROTO)
|
|
find_path(Protobuf_INCLUDE_DIR google/protobuf/service.h
|
|
PATHS ${_PROTOBUF_INSTALL_PREFIX}/include
|
|
NO_DEFAULT_PATH)
|
|
if(ONNX_USE_PROTOBUF_SHARED_LIBS)
|
|
set(Protobuf_USE_STATIC_LIBS OFF)
|
|
else()
|
|
set(Protobuf_USE_STATIC_LIBS ON)
|
|
endif()
|
|
find_package(Protobuf)
|
|
if(Protobuf_FOUND)
|
|
set(PROTOBUF_DIR "${_PROTOBUF_INSTALL_PREFIX}")
|
|
set(Build_Protobuf OFF)
|
|
if("${Protobuf_VERSION}" VERSION_GREATER_EQUAL "4.22.0")
|
|
# There are extra dependencies for protobuf.
|
|
find_package(absl REQUIRED)
|
|
find_package(utf8_range)
|
|
message(STATUS "absl_VERSION: ${absl_VERSION}")
|
|
set(protobuf_ABSL_USED_TARGETS
|
|
absl::absl_check
|
|
absl::absl_log
|
|
absl::algorithm
|
|
absl::base
|
|
absl::bind_front
|
|
absl::bits
|
|
absl::btree
|
|
absl::cleanup
|
|
absl::cord
|
|
absl::core_headers
|
|
absl::debugging
|
|
absl::die_if_null
|
|
absl::dynamic_annotations
|
|
absl::flags
|
|
absl::flat_hash_map
|
|
absl::flat_hash_set
|
|
absl::function_ref
|
|
absl::hash
|
|
absl::layout
|
|
absl::log_initialize
|
|
absl::log_severity
|
|
absl::memory
|
|
absl::node_hash_map
|
|
absl::node_hash_set
|
|
absl::optional
|
|
absl::span
|
|
absl::status
|
|
absl::statusor
|
|
absl::strings
|
|
absl::synchronization
|
|
absl::time
|
|
absl::type_traits
|
|
absl::utility
|
|
absl::variant
|
|
utf8_range::utf8_range
|
|
utf8_range::utf8_validity
|
|
)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(ONNX_PYODIDE_BUILD)
|
|
# Prevent absl from using EM_JS-based symbolize_emscripten.inc which is
|
|
# incompatible with Emscripten SIDE_MODULE builds (Pyodide).
|
|
add_compile_definitions(STANDALONE_WASM)
|
|
endif()
|
|
|
|
if(NOT ONNX_PROTOC_EXECUTABLE)
|
|
set(Build_Protobuf ON)
|
|
set(protobuf_MSVC_STATIC_RUNTIME ${ONNX_USE_MSVC_STATIC_RUNTIME})
|
|
|
|
include(FetchContent)
|
|
set(ABSL_PROPAGATE_CXX_STD 1)
|
|
set(ONNX_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
|
|
set(ONNX_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
|
# Use this setting to build third-party libs.
|
|
set(BUILD_SHARED_LIBS ${ONNX_USE_PROTOBUF_SHARED_LIBS})
|
|
# Read dependency URLs/hashes from sbom.cdx.json (single source of truth).
|
|
sbom_get_dep("abseil-cpp" _absl)
|
|
sbom_get_dep("protobuf" _protobuf)
|
|
# Assign ${Protobuf_VERSION} to the version read from sbom.cdx.json like `find_package(Protobuf)` would do.
|
|
set(Protobuf_VERSION ${_protobuf_VERSION})
|
|
if(NOT DEFINED ABSL_ENABLE_INSTALL)
|
|
if(ONNX_BUILD_PYTHON)
|
|
set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "Enable installation of Abseil targets")
|
|
else()
|
|
set(ABSL_ENABLE_INSTALL ON CACHE BOOL "Enable installation of Abseil targets")
|
|
endif()
|
|
endif()
|
|
FetchContent_Declare(
|
|
absl
|
|
URL ${_absl_URL}
|
|
URL_HASH SHA256=${_absl_SHA256}
|
|
)
|
|
FetchContent_MakeAvailable(absl)
|
|
FetchContent_Declare(
|
|
Protobuf
|
|
URL ${_protobuf_URL}
|
|
URL_HASH SHA256=${_protobuf_SHA256}
|
|
)
|
|
if(NOT DEFINED protobuf_BUILD_TESTS)
|
|
set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build protobuf tests")
|
|
endif()
|
|
if(EXISTS "${ONNX_CUSTOM_PROTOC_EXECUTABLE}")
|
|
# We already have a host protoc binary; skip building libprotoc and protoc
|
|
# (saves compiling code generators for Java, C#, Kotlin, ObjC, etc.)
|
|
set(protobuf_BUILD_PROTOC_BINARIES OFF CACHE BOOL "Skip building protoc")
|
|
# libupb is only needed by protoc's code generators; skip it too.
|
|
set(protobuf_BUILD_LIBUPB OFF CACHE BOOL "Skip building libupb")
|
|
endif()
|
|
set(protobuf_WITH_ZLIB OFF CACHE BOOL "Skip zlib support")
|
|
if(ONNX_BUILD_PYTHON)
|
|
set(protobuf_INSTALL OFF CACHE BOOL "Skip protobuf install rules")
|
|
endif()
|
|
message(STATUS "Download and build Protobuf from ${_protobuf_URL}")
|
|
FetchContent_MakeAvailable(Protobuf)
|
|
# utf8_validity.h is included by protobuf headers but its include dir
|
|
# is only added via include_directories() inside protobuf's directory scope.
|
|
# Attach it to the protobuf target so ONNX targets can compile .pb.cc files
|
|
# without introducing a global include path.
|
|
if(EXISTS "${protobuf_SOURCE_DIR}/third_party/utf8_range")
|
|
# protobuf::libprotobuf and protobuf::libprotobuf-lite are ALIAS targets
|
|
# and CMake does not allow target_include_directories on aliases;
|
|
# resolve to the real targets before adding the utf8_range include path.
|
|
foreach(_pb_alias libprotobuf libprotobuf-lite)
|
|
if(TARGET protobuf::${_pb_alias})
|
|
get_target_property(_pb_real protobuf::${_pb_alias} ALIASED_TARGET)
|
|
if(NOT _pb_real)
|
|
set(_pb_real protobuf::${_pb_alias})
|
|
endif()
|
|
target_include_directories(
|
|
${_pb_real}
|
|
INTERFACE
|
|
$<BUILD_INTERFACE:${protobuf_SOURCE_DIR}/third_party/utf8_range>
|
|
)
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
if(EXISTS "${ONNX_CUSTOM_PROTOC_EXECUTABLE}")
|
|
set(ONNX_PROTOC_EXECUTABLE ${ONNX_CUSTOM_PROTOC_EXECUTABLE})
|
|
else()
|
|
set(ONNX_PROTOC_EXECUTABLE $<TARGET_FILE:protobuf::protoc>)
|
|
endif()
|
|
# Change back the BUILD_SHARED_LIBS to control the onnx project.
|
|
set(BUILD_SHARED_LIBS ${ONNX_BUILD_SHARED_LIBS})
|
|
set(PROTOBUF_DIR "${protobuf_BINARY_DIR}")
|
|
set(CMAKE_CXX_FLAGS ${ONNX_CMAKE_CXX_FLAGS})
|
|
endif()
|
|
message(STATUS "ONNX_PROTOC_EXECUTABLE: ${ONNX_PROTOC_EXECUTABLE}")
|
|
|
|
# function(RELATIVE_PROTOBUF_GENERATE_CPP SRCS HDRS ROOT_DIR) from
|
|
# https://github.com/tensorflow/tensorflow/blob/d2c3b873/tensorflow/contrib/cmake/tf_core_framework.cmake
|
|
# to solve the problem that customized dir can't be specified when
|
|
# calling PROTOBUF_GENERATE_CPP.
|
|
function(RELATIVE_PROTOBUF_GENERATE_CPP SRCS)
|
|
if(NOT ARGN)
|
|
message(
|
|
SEND_ERROR
|
|
"Error: RELATIVE_PROTOBUF_GENERATE_CPP() called without any proto files"
|
|
)
|
|
return()
|
|
endif()
|
|
|
|
set(${SRCS})
|
|
set(_py_files)
|
|
|
|
set(GEN_PROTO_PY "${ONNX_ROOT}/onnx/gen_proto.py")
|
|
set(GENERATED_FILES)
|
|
foreach(INFILE ${ARGN})
|
|
set(ABS_FILE "${ONNX_ROOT}/${INFILE}")
|
|
get_filename_component(FILE_DIR ${ABS_FILE} DIRECTORY)
|
|
get_filename_component(FILE_WE ${INFILE} NAME_WE)
|
|
# "onnx-data" check is because we do not want to create/compile an "onnx-data-ml.proto" file
|
|
if(ONNX_ML AND NOT(FILE_WE STREQUAL "onnx-data"))
|
|
if(ONNX_NAMESPACE STREQUAL "onnx")
|
|
set(GENERATED_FILE_WE "${FILE_WE}-ml")
|
|
else()
|
|
set(GENERATED_FILE_WE "${FILE_WE}_${ONNX_NAMESPACE}-ml")
|
|
endif()
|
|
else()
|
|
if(ONNX_NAMESPACE STREQUAL "onnx")
|
|
set(GENERATED_FILE_WE "${FILE_WE}")
|
|
else()
|
|
set(GENERATED_FILE_WE "${FILE_WE}_${ONNX_NAMESPACE}")
|
|
endif()
|
|
endif()
|
|
file(RELATIVE_PATH REL_DIR "${ONNX_ROOT}" "${FILE_DIR}")
|
|
set(OUTPUT_PROTO_DIR "${CMAKE_CURRENT_BINARY_DIR}/${REL_DIR}")
|
|
|
|
set(OUTPUT_PB_SRC "${OUTPUT_PROTO_DIR}/${GENERATED_FILE_WE}.pb.cc")
|
|
set(GENERATED_PROTO "${OUTPUT_PROTO_DIR}/${GENERATED_FILE_WE}.proto")
|
|
list(APPEND ${SRCS} "${OUTPUT_PB_SRC}")
|
|
|
|
if(NOT EXISTS "${OUTPUT_PROTO_DIR}")
|
|
file(MAKE_DIRECTORY "${OUTPUT_PROTO_DIR}")
|
|
endif()
|
|
|
|
set(GEN_PROTO_ARGS
|
|
-p
|
|
"${ONNX_NAMESPACE}"
|
|
-o
|
|
"${OUTPUT_PROTO_DIR}"
|
|
"${FILE_WE}")
|
|
if(ONNX_ML)
|
|
list(APPEND GEN_PROTO_ARGS -m)
|
|
endif()
|
|
if(ONNX_USE_LITE_PROTO)
|
|
list(APPEND GEN_PROTO_ARGS -l)
|
|
endif()
|
|
if(ONNX_VERIFY_PROTO3)
|
|
if(NOT ONNX_PROTOC_EXECUTABLE)
|
|
message(FATAL_ERROR "Protobuf compiler not found")
|
|
endif()
|
|
list(APPEND GEN_PROTO_ARGS --protoc_path)
|
|
list(APPEND GEN_PROTO_ARGS "${ONNX_PROTOC_EXECUTABLE}")
|
|
endif()
|
|
|
|
# Use add_custom_command to avoid re-generate of PROTO files
|
|
set(deps ${INFILE})
|
|
if(TARGET protobuf::protoc)
|
|
list(APPEND deps protobuf::protoc)
|
|
endif()
|
|
set(_gen_proto_outputs "${GENERATED_PROTO}")
|
|
if(ONNX_BUILD_PYTHON)
|
|
# gen_proto.py also produces a _pb.py re-export wrapper
|
|
string(REPLACE "-" "_" _stem_py "${FILE_WE}")
|
|
set(_pb_py "${OUTPUT_PROTO_DIR}/${_stem_py}_pb.py")
|
|
list(APPEND _gen_proto_outputs "${_pb_py}")
|
|
list(APPEND _py_files "${_pb_py}")
|
|
endif()
|
|
|
|
add_custom_command(OUTPUT ${_gen_proto_outputs}
|
|
COMMAND ${ONNX_PYTHON_INTERPRETER} "${GEN_PROTO_PY}" ${GEN_PROTO_ARGS}
|
|
DEPENDS ${deps}
|
|
COMMENT "Running gen_proto.py on ${INFILE}")
|
|
message("Generated: ${GENERATED_PROTO}")
|
|
|
|
set(PROTOC_ARGS
|
|
${GENERATED_PROTO}
|
|
-I
|
|
${CMAKE_CURRENT_BINARY_DIR}
|
|
--cpp_out
|
|
${CMAKE_CURRENT_BINARY_DIR})
|
|
if(ONNX_BUILD_PYTHON)
|
|
list(APPEND PROTOC_ARGS --python_out)
|
|
if(ONNX_GEN_PB_TYPE_STUBS)
|
|
list(APPEND PROTOC_ARGS pyi_out:${CMAKE_CURRENT_BINARY_DIR})
|
|
else()
|
|
list(APPEND PROTOC_ARGS ${CMAKE_CURRENT_BINARY_DIR})
|
|
endif()
|
|
endif()
|
|
list(APPEND GENERATED_FILES "${GENERATED_PROTO}")
|
|
|
|
set(_protoc_outputs "${OUTPUT_PB_SRC}")
|
|
if(ONNX_BUILD_PYTHON)
|
|
string(REPLACE "-" "_" _py_stem "${GENERATED_FILE_WE}")
|
|
set(_pb2_py "${OUTPUT_PROTO_DIR}/${_py_stem}_pb2.py")
|
|
list(APPEND _protoc_outputs "${_pb2_py}")
|
|
list(APPEND _py_files "${_pb2_py}")
|
|
if(ONNX_GEN_PB_TYPE_STUBS)
|
|
set(_pb2_pyi "${OUTPUT_PROTO_DIR}/${_py_stem}_pb2.pyi")
|
|
list(APPEND _protoc_outputs "${_pb2_pyi}")
|
|
list(APPEND _py_files "${_pb2_pyi}")
|
|
endif()
|
|
endif()
|
|
|
|
add_custom_command(OUTPUT ${_protoc_outputs}
|
|
COMMAND "${ONNX_PROTOC_EXECUTABLE}" ${PROTOC_ARGS}
|
|
DEPENDS ${GENERATED_FILES}
|
|
COMMENT "Running C++ protocol buffer compiler on ${GENERATED_PROTO}")
|
|
endforeach()
|
|
|
|
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
|
|
set(ONNX_PROTO_PY_FILES ${_py_files} PARENT_SCOPE)
|
|
set(ONNX_GENERATED_PROTO_FILES ${GENERATED_FILES} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
relative_protobuf_generate_cpp(ONNX_PROTO_SRCS
|
|
onnx/onnx.in.proto
|
|
onnx/onnx-operators.in.proto
|
|
onnx/onnx-data.in.proto)
|
|
|
|
# Serialises the gen_proto.py step so parallel builds don't race writing the
|
|
# generated .proto files; protoc and C++ compilation still overlap afterwards.
|
|
add_custom_target(onnx_proto_gen DEPENDS ${ONNX_GENERATED_PROTO_FILES})
|
|
|
|
set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf)
|
|
if(ONNX_USE_LITE_PROTO)
|
|
if(TARGET protobuf::libprotobuf-lite)
|
|
set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf-lite)
|
|
endif()
|
|
endif()
|
|
|
|
# Compile the generated .pb.cc sources in exactly one target: Xcode's build
|
|
# system rejects a protoc custom command shared across several targets.
|
|
add_library(onnx_proto ${ONNX_PROTO_SRCS})
|
|
add_onnx_global_defines(onnx_proto)
|
|
add_dependencies(onnx_proto onnx_proto_gen)
|
|
|
|
# Core library. Hand-written sources come from target_sources(onnx ...) in the
|
|
# subdirectories; the protobuf objects are pulled in from onnx_proto.
|
|
add_library(onnx $<TARGET_OBJECTS:onnx_proto>)
|
|
add_subdirectory(onnx)
|
|
add_dependencies(onnx onnx_proto)
|
|
set_target_properties(onnx PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
|
add_onnx_global_defines(onnx)
|
|
|
|
if(ONNX_BUILD_PYTHON)
|
|
if(BUILD_SHARED_LIBS)
|
|
# The extension links ONNX internals not on the public ONNX_API surface,
|
|
# which a hidden-visibility shared libonnx does not export. The wheel always
|
|
# builds onnx statically; a shared libonnx is for C++ use only.
|
|
message(FATAL_ERROR
|
|
"ONNX_BUILD_PYTHON=ON requires a static onnx; do not combine it with "
|
|
"BUILD_SHARED_LIBS=ON. Use ONNX_BUILD_PYTHON=OFF to build a shared libonnx.")
|
|
endif()
|
|
# find system nanobind
|
|
if(NOT DEFINED nanobind_DIR OR "${nanobind_DIR}" STREQUAL "")
|
|
execute_process(
|
|
COMMAND ${Python_EXECUTABLE} -m nanobind --cmake_dir
|
|
RESULT_VARIABLE NANOBIND_CMAKE_RESULT
|
|
OUTPUT_VARIABLE NANOBIND_CMAKE_DIR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if(NANOBIND_CMAKE_RESULT EQUAL 0 AND EXISTS "${NANOBIND_CMAKE_DIR}")
|
|
set(nanobind_DIR "${NANOBIND_CMAKE_DIR}")
|
|
endif()
|
|
endif()
|
|
find_package(nanobind CONFIG QUIET)
|
|
if(NOT nanobind_FOUND)
|
|
if(FETCHCONTENT_FULLY_DISCONNECTED)
|
|
message(FATAL_ERROR
|
|
"nanobind not found while FETCHCONTENT_FULLY_DISCONNECTED is ON. "
|
|
"Provide nanobind locally (nanobind_DIR/CMAKE_PREFIX_PATH) or use a "
|
|
"FetchContent dependency provider for first-run offline builds.")
|
|
endif()
|
|
include(FetchContent)
|
|
sbom_get_dep("nanobind" _nanobind)
|
|
FetchContent_Declare(
|
|
nanobind
|
|
GIT_REPOSITORY ${_nanobind_URL}
|
|
GIT_TAG v${_nanobind_VERSION}
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_MakeAvailable(nanobind)
|
|
endif()
|
|
|
|
# Configure nanobind: https://nanobind.readthedocs.io/en/latest/api_cmake.html
|
|
nanobind_add_module(
|
|
onnx_cpp2py_export
|
|
NB_STATIC NB_DOMAIN onnx STABLE_ABI FREE_THREADED LTO
|
|
"${ONNX_ROOT}/onnx/cpp2py_export.cc")
|
|
# Force-load the whole (static) archive so the operator schemas' static
|
|
# initializers are not dropped as apparently-unused. $<LINK_LIBRARY:WHOLE_ARCHIVE,...>
|
|
# is the portable --whole-archive / -force_load / /WHOLEARCHIVE spelling.
|
|
target_link_libraries(onnx_cpp2py_export PRIVATE
|
|
$<LINK_LIBRARY:WHOLE_ARCHIVE,onnx>)
|
|
endif()
|
|
|
|
add_onnx_compile_options(onnx_proto)
|
|
add_onnx_compile_options(onnx)
|
|
if(TARGET onnx_cpp2py_export)
|
|
add_onnx_global_defines(onnx_cpp2py_export)
|
|
add_onnx_compile_options(onnx_cpp2py_export)
|
|
endif()
|
|
if(ONNX_USE_ASAN AND NOT MSVC)
|
|
find_package(Sanitizer REQUIRED)
|
|
if(TARGET Sanitizer::address)
|
|
target_link_libraries(onnx PRIVATE Sanitizer::address)
|
|
message(STATUS "Use ASAN")
|
|
endif()
|
|
if(TARGET Sanitizer::undefined)
|
|
target_link_libraries(onnx PRIVATE Sanitizer::undefined)
|
|
message(STATUS "Use UBSAN")
|
|
endif()
|
|
endif()
|
|
|
|
if(ONNX_INSTALL)
|
|
install(DIRECTORY ${ONNX_ROOT}/onnx
|
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
FILES_MATCHING
|
|
PATTERN "*.h"
|
|
PATTERN "backend/test/case" EXCLUDE
|
|
PATTERN "backend/test/data" EXCLUDE)
|
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/onnx
|
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
FILES_MATCHING
|
|
PATTERN "*.h")
|
|
endif()
|
|
|
|
configure_file(
|
|
${PROJECT_SOURCE_DIR}/cmake/ONNXConfigVersion.cmake.in
|
|
${PROJECT_BINARY_DIR}/ONNXConfigVersion.cmake
|
|
@ONLY)
|
|
configure_file(
|
|
${PROJECT_SOURCE_DIR}/cmake/ONNXConfig.cmake.in
|
|
${PROJECT_BINARY_DIR}/ONNXConfig.cmake
|
|
@ONLY)
|
|
if(ONNX_INSTALL)
|
|
install(FILES
|
|
${PROJECT_BINARY_DIR}/ONNXConfigVersion.cmake
|
|
${PROJECT_BINARY_DIR}/ONNXConfig.cmake
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ONNX
|
|
COMPONENT dev)
|
|
endif()
|
|
|
|
if(ONNX_USE_UNITY_BUILD)
|
|
# If ONNX_USE_UNITY_BUILD is set to ON, set onnx to use Unity builds.
|
|
set_target_properties(onnx
|
|
PROPERTIES
|
|
UNITY_BUILD ON
|
|
)
|
|
|
|
# With unity build object file could get big, need this switch in MSVC.
|
|
if(MSVC)
|
|
target_compile_options(onnx PRIVATE /bigobj)
|
|
endif()
|
|
# should be enabled for onnx_proto when protobuf can support Unity builds
|
|
endif()
|
|
|
|
if(ONNX_BUILD_TESTS)
|
|
find_package(GTest)
|
|
if(NOT GTest_FOUND)
|
|
include(googletest)
|
|
endif()
|
|
endif()
|
|
|
|
if(ONNX_INSTALL)
|
|
install(TARGETS
|
|
onnx onnx_proto
|
|
EXPORT ONNXTargets DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
|
|
install(EXPORT ONNXTargets
|
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ONNX"
|
|
NAMESPACE ONNX::
|
|
)
|
|
endif()
|
|
|
|
if(ONNX_BUILD_PYTHON)
|
|
install(TARGETS onnx_cpp2py_export LIBRARY DESTINATION onnx)
|
|
install(FILES ${ONNX_PROTO_PY_FILES} DESTINATION onnx)
|
|
# PEP 770: embed SBOM in dist-info/sboms/ inside the wheel.
|
|
if(DEFINED SKBUILD_METADATA_DIR)
|
|
install(FILES "${CMAKE_SOURCE_DIR}/sbom.cdx.json" DESTINATION "${SKBUILD_METADATA_DIR}/sboms")
|
|
endif()
|
|
endif()
|
|
|
|
if(ONNX_BUILD_TESTS)
|
|
include(${ONNX_ROOT}/cmake/unittest.cmake)
|
|
endif()
|
|
|
|
include(cmake/summary.cmake)
|
|
onnx_print_configuration_summary()
|