2 # Copyright © 2020 Arm Ltd. All rights reserved.
4 # SPDX-License-Identifier: MIT
6 option(BUILD_CAFFE_PARSER "Build Caffe parser" OFF)
7 option(BUILD_TF_PARSER "Build Tensorflow parser" OFF)
8 option(BUILD_ONNX_PARSER "Build Onnx parser" OFF)
9 option(BUILD_UNIT_TESTS "Build unit tests" ON)
10 option(BUILD_TESTS "Build test applications" OFF)
11 option(BUILD_FOR_COVERAGE "Use no optimization and output .gcno and .gcda files" OFF)
12 option(ARMCOMPUTENEON "Build with ARM Compute NEON support" OFF)
13 option(ARMCOMPUTECL "Build with ARM Compute OpenCL support" OFF)
14 option(ARMNNREF "Build with ArmNN reference support" ON)
15 option(PROFILING_BACKEND_STREAMLINE "Forward the armNN profiling events to DS-5/Streamline as annotations" OFF)
16 # options used for heap profiling and leak checking
17 option(HEAP_PROFILING "Build with heap profiling enabled" OFF)
18 option(LEAK_CHECKING "Build with leak checking enabled" OFF)
19 option(GPERFTOOLS_ROOT "Location where the gperftools 'include' and 'lib' folders to be found" Off)
20 # options used for tensorflow lite support
21 option(BUILD_TF_LITE_PARSER "Build Tensorflow Lite parser" OFF)
22 option(BUILD_ARMNN_SERIALIZER "Build Armnn Serializer" OFF)
23 option(BUILD_ARMNN_QUANTIZER "Build ArmNN quantizer" OFF)
24 option(BUILD_ACCURACY_TOOL "Build Accuracy Tool" OFF)
25 option(FLATC_DIR "Path to Flatbuffers compiler" OFF)
26 option(TF_LITE_GENERATED_PATH "Tensorflow lite generated C++ schema location" OFF)
27 option(FLATBUFFERS_ROOT "Location where the flatbuffers 'include' and 'lib' folders to be found" Off)
28 option(DYNAMIC_BACKEND_PATHS "Colon seperated list of paths where to load the dynamic backends from" "")
29 option(BUILD_GATORD_MOCK "Build the Gatord simulator for external profiling testing." ON)
30 option(BUILD_TIMELINE_DECODER "Build the Timeline Decoder for external profiling." ON)
31 option(SHARED_BOOST "Use dynamic linking for boost libraries" OFF)
32 option(BUILD_BASE_PIPE_SERVER "Build the server to handle external profiling pipe traffic" ON)
33 option(BUILD_PYTHON_WHL "Build Python wheel package" OFF)
34 option(BUILD_PYTHON_SRC "Build Python source package" OFF)
36 include(SelectLibraryConfigurations)
38 set(COMPILER_IS_GNU_LIKE 0)
39 if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU OR ${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
40 set(COMPILER_IS_GNU_LIKE 1)
43 # Enable CCache if available and not disabled
44 option(USE_CCACHE "USE_CCACHE" ON)
45 find_program(CCACHE_FOUND ccache)
46 if(CCACHE_FOUND AND USE_CCACHE)
47 get_property(rule_launch_compile DIRECTORY PROPERTY RULE_LAUNCH_COMPILE)
48 set_property(DIRECTORY PROPERTY RULE_LAUNCH_COMPILE "CCACHE_CPP2=yes ${rule_launch_compile} ccache")
51 # Enable distcc if available and not disabled
52 option(USE_DISTCC "USE_DISTCC" OFF)
53 find_program(DISTCC_FOUND distcc)
54 if(DISTCC_FOUND AND USE_DISTCC)
55 get_property(rule_launch_compile DIRECTORY PROPERTY RULE_LAUNCH_COMPILE)
56 set_property(DIRECTORY PROPERTY RULE_LAUNCH_COMPILE "${rule_launch_compile} distcc")
59 # Set to release configuration by default
60 if(NOT CMAKE_BUILD_TYPE)
61 set(CMAKE_BUILD_TYPE "Release")
64 # Compiler flags that are always set
65 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
66 if(COMPILER_IS_GNU_LIKE)
67 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Werror -Wold-style-cast -Wno-missing-braces -Wconversion -Wsign-conversion")
68 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
69 # Disable C4996 (use of deprecated identifier) due to https://developercommunity.visualstudio.com/content/problem/252574/deprecated-compilation-warning-for-virtual-overrid.html
70 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /MP /wd4996")
71 add_definitions(-DNOMINMAX=1 -DNO_STRICT=1)
73 if("${CMAKE_SYSTEM_NAME}" STREQUAL Android)
74 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -llog")
75 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -llog")
78 # Compiler flags for Release builds
79 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
80 if(COMPILER_IS_GNU_LIKE)
81 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
82 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
83 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /O2")
86 # Compiler flags for Debug builds
87 if(COMPILER_IS_GNU_LIKE)
88 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
89 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
90 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /ZI /Od")
91 # Disable SAFESEH which is necessary for Edit and Continue to work
92 set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
93 set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
96 # Modify RelWithDebInfo so that NDEBUG isn't defined.
97 # This enables asserts.
98 if (COMPILER_IS_GNU_LIKE)
99 string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
100 elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
101 string(REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
104 # Compiler flags for code coverage measurements
105 if(BUILD_FOR_COVERAGE)
106 if(NOT CMAKE_BUILD_TYPE EQUAL "Debug")
107 message(WARNING "BUILD_FOR_COVERAGE set so forcing to Debug build")
108 set(CMAKE_BUILD_TYPE "Debug")
111 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
112 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
115 if(BUILD_FOR_COVERAGE AND NOT BUILD_UNIT_TESTS)
116 message(WARNING "BUILD_FOR_COVERAGE set but not BUILD_UNIT_TESTS, so code coverage will not be able to run")
119 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
123 add_definitions(-DBOOST_ALL_DYN_LINK)
124 set(Boost_USE_STATIC_LIBS OFF)
126 set(Boost_USE_STATIC_LIBS ON)
128 add_definitions("-DBOOST_ALL_NO_LIB") # Turn off auto-linking as we specify the libs manually
129 find_package(Boost 1.59 REQUIRED COMPONENTS unit_test_framework system filesystem program_options)
130 include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
131 link_directories(${Boost_LIBRARY_DIRS})
134 find_package (Threads)
136 # Favour the protobuf passed on command line
137 if(BUILD_TF_PARSER OR BUILD_CAFFE_PARSER OR BUILD_ONNX_PARSER)
138 find_library(PROTOBUF_LIBRARY_DEBUG NAMES "protobufd"
139 PATHS ${PROTOBUF_ROOT}/lib
140 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
141 find_library(PROTOBUF_LIBRARY_DEBUG NAMES "protobufd")
143 find_library(PROTOBUF_LIBRARY_RELEASE NAMES "protobuf"
144 PATHS ${PROTOBUF_ROOT}/lib
145 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
146 find_library(PROTOBUF_LIBRARY_RELEASE NAMES "protobuf")
148 select_library_configurations(PROTOBUF)
150 find_path(PROTOBUF_INCLUDE_DIRS "google/protobuf/message.h"
151 PATHS ${PROTOBUF_ROOT}/include
152 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
153 find_path(PROTOBUF_INCLUDE_DIRS "google/protobuf/message.h")
155 include_directories(SYSTEM "${PROTOBUF_INCLUDE_DIRS}")
156 add_definitions(-DPROTOBUF_USE_DLLS)
159 # Caffe and its dependencies
160 if(BUILD_CAFFE_PARSER)
161 add_definitions(-DARMNN_CAFFE_PARSER)
163 find_path(CAFFE_GENERATED_SOURCES "caffe/proto/caffe.pb.h"
164 HINTS ${CAFFE_BUILD_ROOT}/include)
165 include_directories(SYSTEM "${CAFFE_GENERATED_SOURCES}")
169 add_definitions(-DARMNN_TF_PARSER)
171 find_path(TF_GENERATED_SOURCES "tensorflow/core/protobuf/saved_model.pb.cc")
173 # C++ sources generated for tf protobufs
174 file(GLOB_RECURSE TF_PROTOBUFS "${TF_GENERATED_SOURCES}/*.pb.cc")
176 # C++ headers generated for tf protobufs
177 include_directories(SYSTEM "${TF_GENERATED_SOURCES}")
180 if(BUILD_ONNX_PARSER)
181 add_definitions(-DARMNN_ONNX_PARSER)
183 find_path(ONNX_GENERATED_SOURCES "onnx/onnx.pb.cc")
185 # C++ headers generated for onnx protobufs
186 include_directories(SYSTEM "${ONNX_GENERATED_SOURCES}")
189 # Flatbuffers support for TF Lite and Armnn Serializer
190 if(BUILD_TF_LITE_PARSER OR BUILD_ARMNN_SERIALIZER)
191 # verify we have a valid flatbuffers include path
192 find_path(FLATBUFFERS_INCLUDE_PATH flatbuffers/flatbuffers.h
193 HINTS ${FLATBUFFERS_ROOT}/include /usr/local/include /usr/include)
195 message(STATUS "Flatbuffers headers are located at: ${FLATBUFFERS_INCLUDE_PATH}")
197 find_library(FLATBUFFERS_LIBRARY
198 NAMES libflatbuffers.a flatbuffers
199 HINTS ${FLATBUFFERS_ROOT}/lib /usr/local/lib /usr/lib)
201 message(STATUS "Flatbuffers library located at: ${FLATBUFFERS_LIBRARY}")
204 # Flatbuffers schema support for TF Lite
205 if(BUILD_TF_LITE_PARSER)
206 find_path(TF_LITE_SCHEMA_INCLUDE_PATH
208 HINTS ${TF_LITE_GENERATED_PATH})
210 message(STATUS "Tf Lite generated header found at: ${TF_LITE_SCHEMA_INCLUDE_PATH}")
212 add_definitions(-DARMNN_TF_LITE_PARSER)
215 if(BUILD_ARMNN_SERIALIZER)
216 add_definitions(-DARMNN_SERIALIZER)
217 add_definitions(-DARMNN_SERIALIZER_SCHEMA_PATH="${CMAKE_CURRENT_SOURCE_DIR}/src/armnnSerializer/ArmnnSchema.fbs")
220 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
221 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/profiling)
224 # Note that ARM Compute has a different folder layout depending on the branch but also on
225 # whether it comes from a prepackaged archive (this is why we add several hints below)
226 if(ARMCOMPUTENEON OR ARMCOMPUTECL)
227 find_path(ARMCOMPUTE_INCLUDE arm_compute/core/CL/ICLKernel.h
228 PATHS ${ARMCOMPUTE_ROOT}/include
229 PATHS ${ARMCOMPUTE_ROOT}/applications/arm_compute
230 PATHS ${ARMCOMPUTE_ROOT}
231 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
232 find_path(ARMCOMPUTE_INCLUDE arm_compute/core/CL/ICLKernel.h)
233 include_directories(SYSTEM "${ARMCOMPUTE_INCLUDE}")
235 # Find the Arm Compute libraries if not already specified (the user may have already defined this in advance,
236 # e.g. if building clframework as a dependent cmake project)
237 if (NOT DEFINED ARMCOMPUTE_LIBRARIES)
238 # We link to the static variant so that customers don't need to find and build a compatible version of clframework.
239 # First try the folders specified ARMCOMPUTE_BUILD_DIR (with PATH_SUFFIXES for
241 if ((NOT DEFINED ARMCOMPUTE_BUILD_DIR) AND (DEFINED ARMCOMPUTE_ROOT))
242 # Default build directory for ComputeLibrary is under the root
243 set(ARMCOMPUTE_BUILD_DIR ${ARMCOMPUTE_ROOT}/build)
246 find_library(ARMCOMPUTE_LIBRARY_DEBUG NAMES arm_compute-static
247 PATHS ${ARMCOMPUTE_BUILD_DIR}
248 PATH_SUFFIXES "Debug"
249 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
250 find_library(ARMCOMPUTE_LIBRARY_RELEASE NAMES arm_compute-static
251 PATHS ${ARMCOMPUTE_BUILD_DIR}
252 PATH_SUFFIXES "Release"
253 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
254 find_library(ARMCOMPUTE_CORE_LIBRARY_DEBUG NAMES arm_compute_core-static
255 PATHS ${ARMCOMPUTE_BUILD_DIR}
256 PATH_SUFFIXES "Debug"
257 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
258 find_library(ARMCOMPUTE_CORE_LIBRARY_RELEASE NAMES arm_compute_core-static
259 PATHS ${ARMCOMPUTE_BUILD_DIR}
260 PATH_SUFFIXES "Release"
261 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
263 # In case it wasn't there, try a default search (will work in cases where
264 # the library has been installed into a standard location)
265 find_library(ARMCOMPUTE_LIBRARY_DEBUG NAMES arm_compute-static)
266 find_library(ARMCOMPUTE_LIBRARY_RELEASE NAMES arm_compute-static)
267 find_library(ARMCOMPUTE_CORE_LIBRARY_DEBUG NAMES arm_compute_core-static)
268 find_library(ARMCOMPUTE_CORE_LIBRARY_RELEASE NAMES arm_compute_core-static)
270 # In case it wasn't there, try the dynamic libraries
271 # This case will get used in a linux setup where the Compute Library
272 # has been installed in a standard system library path as a dynamic library
273 find_library(ARMCOMPUTE_LIBRARY_DEBUG NAMES arm_compute)
274 find_library(ARMCOMPUTE_LIBRARY_RELEASE NAMES arm_compute)
275 find_library(ARMCOMPUTE_CORE_LIBRARY_DEBUG NAMES arm_compute_core)
276 find_library(ARMCOMPUTE_CORE_LIBRARY_RELEASE NAMES arm_compute_core)
278 set(ARMCOMPUTE_LIBRARIES
279 debug ${ARMCOMPUTE_LIBRARY_DEBUG} ${ARMCOMPUTE_CORE_LIBRARY_DEBUG}
280 optimized ${ARMCOMPUTE_LIBRARY_RELEASE} ${ARMCOMPUTE_CORE_LIBRARY_RELEASE} )
284 # ARM Compute NEON backend
286 # Add preprocessor definition for ARM Compute NEON
287 add_definitions(-DARMCOMPUTENEON_ENABLED)
288 # The ARM Compute headers contain some NEON intrinsics, so we need to build armnn with NEON support on armv7
289 if(${CMAKE_SYSTEM_PROCESSOR} MATCHES armv7 AND COMPILER_IS_GNU_LIKE)
290 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon")
294 # ARM Compute OpenCL backend
296 # Always use Arm compute library OpenCL headers
297 find_path(OPENCL_INCLUDE CL/cl2.hpp
298 PATHS ${ARMCOMPUTE_ROOT}/include
299 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
301 # Link against libOpenCL in opencl-1.2-stubs, but don't search there at runtime
302 link_libraries(-L${ARMCOMPUTE_BUILD_DIR}/opencl-1.2-stubs)
303 set(OPENCL_LIBRARIES OpenCL)
305 include_directories(SYSTEM ${OPENCL_INCLUDE})
307 # Add preprocessor definition for ARM Compute OpenCL
308 add_definitions(-DARMCOMPUTECL_ENABLED)
310 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DARM_COMPUTE_DEBUG_ENABLED")
313 # Used by both Arm Compute backends, but should be added
314 # to the search path after the system directories if necessary
315 if(ARMCOMPUTENEON OR ARMCOMPUTECL)
316 find_path(HALF_INCLUDE half/half.hpp)
317 find_path(HALF_INCLUDE half/half.hpp
318 PATHS ${ARMCOMPUTE_ROOT}/include
319 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
320 include_directories(SYSTEM ${HALF_INCLUDE})
323 # ArmNN reference backend
325 add_definitions(-DARMNNREF_ENABLED)
328 # ArmNN dynamic backend
329 if(DYNAMIC_BACKEND_PATHS)
330 add_definitions(-DARMNN_DYNAMIC_BACKEND_ENABLED)
333 if(SAMPLE_DYNAMIC_BACKEND)
334 add_definitions(-DSAMPLE_DYNAMIC_BACKEND_ENABLED)
337 # Streamline annotate
338 if(PROFILING_BACKEND_STREAMLINE)
339 include_directories("${GATOR_ROOT}/annotate")
340 add_definitions(-DARMNN_STREAMLINE_ENABLED)
343 if(HEAP_PROFILING OR LEAK_CHECKING)
344 # enable heap profiling for everything except for referencetests
345 if(NOT ${PROJECT_NAME} STREQUAL "referencetests")
346 find_path(HEAP_PROFILER_INCLUDE gperftools/heap-profiler.h
347 PATHS ${GPERFTOOLS_ROOT}/include
348 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
349 include_directories(SYSTEM "${HEAP_PROFILER_INCLUDE}")
350 find_library(GPERF_TOOLS_LIBRARY
352 HINTS ${GPERFTOOLS_ROOT}/lib)
353 link_directories(${GPERFTOOLS_ROOT}/lib)
355 link_libraries(${GPERF_TOOLS_LIBRARY})
357 add_definitions("-DARMNN_HEAP_PROFILING_ENABLED=1")
360 add_definitions("-DARMNN_LEAK_CHECKING_ENABLED=1")
363 message(STATUS "Heap profiling and leak checking are disabled for referencetests")
366 # Valgrind only works with gperftools version number <= 2.4
367 CHECK_INCLUDE_FILE(valgrind/memcheck.h VALGRIND_FOUND)
371 if(NOT BUILD_CAFFE_PARSER)
372 message(STATUS "Caffe parser support is disabled")
375 if(NOT BUILD_TF_PARSER)
376 message(STATUS "Tensorflow parser support is disabled")
379 if(NOT BUILD_TF_LITE_PARSER)
380 message(STATUS "Tensorflow Lite parser support is disabled")
383 if(NOT BUILD_ARMNN_SERIALIZER)
384 message(STATUS "Armnn Serializer support is disabled")
387 if(NOT BUILD_ARMNN_QUANTIZER)
388 message(STATUS "ArmNN Quantizer support is disabled")
391 if(NOT BUILD_PYTHON_WHL)
392 message(STATUS "PyArmNN wheel package is disabled")
395 if(NOT BUILD_PYTHON_SRC)
396 message(STATUS "PyArmNN source package is disabled")
399 if(BUILD_PYTHON_WHL OR BUILD_PYTHON_SRC)
400 find_package(PythonInterp 3 REQUIRED)
401 if(NOT ${PYTHONINTERP_FOUND})
402 message(FATAL_ERROR "Python 3.x required to build PyArmNN, but not found")
405 find_package(PythonLibs 3 REQUIRED)
406 if(NOT ${PYTHONLIBS_FOUND})
407 message(FATAL_ERROR "Python 3.x development package required to build PyArmNN, but not found")
410 find_package(SWIG 4 REQUIRED)
411 if(NOT ${SWIG_FOUND})
412 message(FATAL_ERROR "SWIG 4.x requried to build PyArmNN, but not found")
416 # ArmNN source files required for all build options
417 include_directories(SYSTEM third-party)