2 # Copyright © 2020 Arm Ltd and Contributors. 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(SAMPLE_DYNAMIC_BACKEND "Include the sample dynamic backend and its tests in the build" OFF)
30 option(BUILD_GATORD_MOCK "Build the Gatord simulator for external profiling testing." ON)
31 option(BUILD_TIMELINE_DECODER "Build the Timeline Decoder for external profiling." ON)
32 option(SHARED_BOOST "Use dynamic linking for boost libraries" OFF)
33 option(BUILD_BASE_PIPE_SERVER "Build the server to handle external profiling pipe traffic" ON)
34 option(BUILD_PYTHON_WHL "Build Python wheel package" OFF)
35 option(BUILD_PYTHON_SRC "Build Python source package" OFF)
36 option(BUILD_STATIC_PIPE_LIBS "Build Static PIPE libraries" OFF)
37 option(BUILD_PIPE_ONLY "Build the PIPE libraries only" OFF)
39 include(SelectLibraryConfigurations)
41 set(COMPILER_IS_GNU_LIKE 0)
42 if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU OR
43 ${CMAKE_CXX_COMPILER_ID} STREQUAL Clang OR
44 ${CMAKE_CXX_COMPILER_ID} STREQUAL AppleClang)
45 set(COMPILER_IS_GNU_LIKE 1)
48 # Enable CCache if available and not disabled
49 option(USE_CCACHE "USE_CCACHE" ON)
50 find_program(CCACHE_FOUND ccache)
51 if(CCACHE_FOUND AND USE_CCACHE)
52 get_property(rule_launch_compile DIRECTORY PROPERTY RULE_LAUNCH_COMPILE)
53 set_property(DIRECTORY PROPERTY RULE_LAUNCH_COMPILE "CCACHE_CPP2=yes ${rule_launch_compile} ccache")
56 # Enable distcc if available and not disabled
57 option(USE_DISTCC "USE_DISTCC" OFF)
58 find_program(DISTCC_FOUND distcc)
59 if(DISTCC_FOUND AND USE_DISTCC)
60 get_property(rule_launch_compile DIRECTORY PROPERTY RULE_LAUNCH_COMPILE)
61 set_property(DIRECTORY PROPERTY RULE_LAUNCH_COMPILE "${rule_launch_compile} distcc")
64 # Set to release configuration by default
65 if(NOT CMAKE_BUILD_TYPE)
66 set(CMAKE_BUILD_TYPE "Release")
69 # Compiler flags that are always set
70 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
71 if(COMPILER_IS_GNU_LIKE)
72 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Werror -Wold-style-cast -Wno-missing-braces -Wconversion -Wsign-conversion")
73 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
74 # Disable C4996 (use of deprecated identifier) due to https://developercommunity.visualstudio.com/content/problem/252574/deprecated-compilation-warning-for-virtual-overrid.html
75 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /MP /wd4996")
76 add_definitions(-DNO_STRICT=1)
78 if("${CMAKE_SYSTEM_NAME}" STREQUAL Android)
79 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -llog")
80 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -llog")
83 # Compiler flags for Release builds
84 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
85 if(COMPILER_IS_GNU_LIKE)
86 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
87 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
88 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /O2")
91 # Compiler flags for Debug builds
92 if(COMPILER_IS_GNU_LIKE)
93 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
94 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
95 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /ZI /Od")
96 # Disable SAFESEH which is necessary for Edit and Continue to work
97 set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
98 set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
101 # Modify RelWithDebInfo so that NDEBUG isn't defined.
102 # This enables asserts.
103 if (COMPILER_IS_GNU_LIKE)
104 string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
105 elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
106 string(REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
109 # Compiler flags for code coverage measurements
110 if(BUILD_FOR_COVERAGE)
111 if(NOT CMAKE_BUILD_TYPE EQUAL "Debug")
112 message(WARNING "BUILD_FOR_COVERAGE set so forcing to Debug build")
113 set(CMAKE_BUILD_TYPE "Debug")
116 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
117 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
120 if(BUILD_FOR_COVERAGE AND NOT BUILD_UNIT_TESTS)
121 message(WARNING "BUILD_FOR_COVERAGE set but not BUILD_UNIT_TESTS, so code coverage will not be able to run")
124 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
126 include(CMakeFindDependencyMacro)
128 if (NOT BUILD_PIPE_ONLY)
130 message(STATUS "Finding Boost")
132 add_definitions(-DBOOST_ALL_DYN_LINK)
133 set(Boost_USE_STATIC_LIBS OFF)
135 set(Boost_USE_STATIC_LIBS ON)
137 add_definitions("-DBOOST_ALL_NO_LIB") # Turn off auto-linking as we specify the libs manually
138 find_package(Boost 1.59 REQUIRED COMPONENTS unit_test_framework)
139 include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
140 link_directories(${Boost_LIBRARY_DIRS})
143 if (NOT BUILD_PIPE_ONLY)
144 # cxxopts (Alternative to boost::program_options)
145 find_path(CXXOPTS_INCLUDE cxxopts/cxxopts.hpp PATHS third-party NO_CMAKE_FIND_ROOT_PATH)
146 include_directories(SYSTEM "${CXXOPTS_INCLUDE}")
149 if (NOT BUILD_PIPE_ONLY)
150 # ghc (Alternative to boost::filesystem)
151 find_path(GHC_INCLUDE ghc/filesystem.hpp PATHS third-party NO_CMAKE_FIND_ROOT_PATH)
152 include_directories(SYSTEM "${GHC_INCLUDE}")
156 find_dependency(Threads)
158 # Favour the protobuf passed on command line
159 if(BUILD_TF_PARSER OR BUILD_CAFFE_PARSER OR BUILD_ONNX_PARSER)
160 find_library(PROTOBUF_LIBRARY_DEBUG NAMES "protobufd"
161 PATHS ${PROTOBUF_ROOT}/lib
162 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
163 find_library(PROTOBUF_LIBRARY_DEBUG NAMES "protobufd")
165 find_library(PROTOBUF_LIBRARY_RELEASE NAMES "protobuf"
166 PATHS ${PROTOBUF_ROOT}/lib
167 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
168 find_library(PROTOBUF_LIBRARY_RELEASE NAMES "protobuf")
170 select_library_configurations(PROTOBUF)
172 find_path(PROTOBUF_INCLUDE_DIRS "google/protobuf/message.h"
173 PATHS ${PROTOBUF_ROOT}/include
174 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
175 find_path(PROTOBUF_INCLUDE_DIRS "google/protobuf/message.h")
177 include_directories(SYSTEM "${PROTOBUF_INCLUDE_DIRS}")
178 add_definitions(-DPROTOBUF_USE_DLLS)
181 # Caffe and its dependencies
182 if(BUILD_CAFFE_PARSER)
183 add_definitions(-DARMNN_CAFFE_PARSER)
185 find_path(CAFFE_GENERATED_SOURCES "caffe/proto/caffe.pb.h"
186 HINTS ${CAFFE_BUILD_ROOT}/include)
187 include_directories(SYSTEM "${CAFFE_GENERATED_SOURCES}")
191 add_definitions(-DARMNN_TF_PARSER)
193 find_path(TF_GENERATED_SOURCES "tensorflow/core/protobuf/saved_model.pb.cc")
195 # C++ sources generated for tf protobufs
196 file(GLOB_RECURSE TF_PROTOBUFS "${TF_GENERATED_SOURCES}/*.pb.cc")
198 # C++ headers generated for tf protobufs
199 include_directories(SYSTEM "${TF_GENERATED_SOURCES}")
202 if(BUILD_ONNX_PARSER)
203 add_definitions(-DARMNN_ONNX_PARSER)
205 find_path(ONNX_GENERATED_SOURCES "onnx/onnx.pb.cc")
207 # C++ headers generated for onnx protobufs
208 include_directories(SYSTEM "${ONNX_GENERATED_SOURCES}")
211 # Flatbuffers support for TF Lite and Armnn Serializer
212 if(BUILD_TF_LITE_PARSER OR BUILD_ARMNN_SERIALIZER)
213 # verify we have a valid flatbuffers include path
214 find_path(FLATBUFFERS_INCLUDE_PATH flatbuffers/flatbuffers.h
215 HINTS ${FLATBUFFERS_ROOT}/include /usr/local/include /usr/include)
217 message(STATUS "Flatbuffers headers are located at: ${FLATBUFFERS_INCLUDE_PATH}")
219 find_library(FLATBUFFERS_LIBRARY
220 NAMES libflatbuffers.a flatbuffers
221 HINTS ${FLATBUFFERS_ROOT}/lib /usr/local/lib /usr/lib)
223 message(STATUS "Flatbuffers library located at: ${FLATBUFFERS_LIBRARY}")
226 # Flatbuffers schema support for TF Lite
227 if(BUILD_TF_LITE_PARSER)
228 find_path(TF_LITE_SCHEMA_INCLUDE_PATH
230 HINTS ${TF_LITE_GENERATED_PATH})
232 message(STATUS "Tf Lite generated header found at: ${TF_LITE_SCHEMA_INCLUDE_PATH}")
234 add_definitions(-DARMNN_TF_LITE_PARSER)
237 if(BUILD_ARMNN_SERIALIZER)
238 add_definitions(-DARMNN_SERIALIZER)
239 add_definitions(-DARMNN_SERIALIZER_SCHEMA_PATH="${CMAKE_CURRENT_SOURCE_DIR}/src/armnnSerializer/ArmnnSchema.fbs")
242 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
243 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/profiling)
246 # Note that ARM Compute has a different folder layout depending on the branch but also on
247 # whether it comes from a prepackaged archive (this is why we add several hints below)
248 if(ARMCOMPUTENEON OR ARMCOMPUTECL)
249 find_path(ARMCOMPUTE_INCLUDE arm_compute/core/CL/OpenCL.h
250 PATHS ${ARMCOMPUTE_ROOT}/include
251 PATHS ${ARMCOMPUTE_ROOT}/applications/arm_compute
252 PATHS ${ARMCOMPUTE_ROOT}
253 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
254 find_path(ARMCOMPUTE_INCLUDE arm_compute/core/CL/OpenCL.h)
255 include_directories(SYSTEM "${ARMCOMPUTE_INCLUDE}")
257 # Find the Arm Compute libraries if not already specified (the user may have already defined this in advance,
258 # e.g. if building clframework as a dependent cmake project)
259 if (NOT DEFINED ARMCOMPUTE_LIBRARIES)
260 # We link to the static variant so that customers don't need to find and build a compatible version of clframework.
261 # First try the folders specified ARMCOMPUTE_BUILD_DIR (with PATH_SUFFIXES for
263 if ((NOT DEFINED ARMCOMPUTE_BUILD_DIR) AND (DEFINED ARMCOMPUTE_ROOT))
264 # Default build directory for ComputeLibrary is under the root
265 set(ARMCOMPUTE_BUILD_DIR ${ARMCOMPUTE_ROOT}/build)
268 find_library(ARMCOMPUTE_LIBRARY_DEBUG NAMES arm_compute-static
269 PATHS ${ARMCOMPUTE_BUILD_DIR}
270 PATH_SUFFIXES "Debug"
271 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
272 find_library(ARMCOMPUTE_LIBRARY_RELEASE NAMES arm_compute-static
273 PATHS ${ARMCOMPUTE_BUILD_DIR}
274 PATH_SUFFIXES "Release"
275 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
276 find_library(ARMCOMPUTE_CORE_LIBRARY_DEBUG NAMES arm_compute_core-static
277 PATHS ${ARMCOMPUTE_BUILD_DIR}
278 PATH_SUFFIXES "Debug"
279 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
280 find_library(ARMCOMPUTE_CORE_LIBRARY_RELEASE NAMES arm_compute_core-static
281 PATHS ${ARMCOMPUTE_BUILD_DIR}
282 PATH_SUFFIXES "Release"
283 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
285 # In case it wasn't there, try a default search (will work in cases where
286 # the library has been installed into a standard location)
287 find_library(ARMCOMPUTE_LIBRARY_DEBUG NAMES arm_compute-static)
288 find_library(ARMCOMPUTE_LIBRARY_RELEASE NAMES arm_compute-static)
289 find_library(ARMCOMPUTE_CORE_LIBRARY_DEBUG NAMES arm_compute_core-static)
290 find_library(ARMCOMPUTE_CORE_LIBRARY_RELEASE NAMES arm_compute_core-static)
292 # In case it wasn't there, try the dynamic libraries
293 # This case will get used in a linux setup where the Compute Library
294 # has been installed in a standard system library path as a dynamic library
295 find_library(ARMCOMPUTE_LIBRARY_DEBUG NAMES arm_compute)
296 find_library(ARMCOMPUTE_LIBRARY_RELEASE NAMES arm_compute)
297 find_library(ARMCOMPUTE_CORE_LIBRARY_DEBUG NAMES arm_compute_core)
298 find_library(ARMCOMPUTE_CORE_LIBRARY_RELEASE NAMES arm_compute_core)
300 set(ARMCOMPUTE_LIBRARIES
301 debug ${ARMCOMPUTE_LIBRARY_DEBUG} ${ARMCOMPUTE_CORE_LIBRARY_DEBUG}
302 optimized ${ARMCOMPUTE_LIBRARY_RELEASE} ${ARMCOMPUTE_CORE_LIBRARY_RELEASE} )
306 # ARM Compute NEON backend
308 # Add preprocessor definition for ARM Compute NEON
309 add_definitions(-DARMCOMPUTENEON_ENABLED)
310 # The ARM Compute headers contain some NEON intrinsics, so we need to build armnn with NEON support on armv7
311 if(${CMAKE_SYSTEM_PROCESSOR} MATCHES armv7 AND COMPILER_IS_GNU_LIKE)
312 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon")
316 # ARM Compute OpenCL backend
318 # Always use Arm compute library OpenCL headers
319 find_path(OPENCL_INCLUDE CL/cl2.hpp
320 PATHS ${ARMCOMPUTE_ROOT}/include
321 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
323 # Link against libOpenCL in opencl-1.2-stubs, but don't search there at runtime
324 link_libraries(-L${ARMCOMPUTE_BUILD_DIR}/opencl-1.2-stubs)
325 set(OPENCL_LIBRARIES OpenCL)
327 include_directories(SYSTEM ${OPENCL_INCLUDE})
329 # Add preprocessor definition for ARM Compute OpenCL
330 add_definitions(-DARMCOMPUTECL_ENABLED)
332 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DARM_COMPUTE_DEBUG_ENABLED")
335 # Used by both Arm Compute backends, but should be added
336 # to the search path after the system directories if necessary
337 if(ARMCOMPUTENEON OR ARMCOMPUTECL)
338 find_path(HALF_INCLUDE half/half.hpp)
339 find_path(HALF_INCLUDE half/half.hpp
340 PATHS ${ARMCOMPUTE_ROOT}/include
341 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
342 include_directories(SYSTEM ${HALF_INCLUDE})
345 # ArmNN reference backend
347 add_definitions(-DARMNNREF_ENABLED)
350 # This is the root for the dynamic backend tests to search for dynamic
351 # backends. By default it will be the project build directory.
352 add_definitions(-DDYNAMIC_BACKEND_BUILD_DIR="${PROJECT_BINARY_DIR}")
354 # ArmNN dynamic backend
355 if(DYNAMIC_BACKEND_PATHS)
356 add_definitions(-DARMNN_DYNAMIC_BACKEND_ENABLED)
359 if(SAMPLE_DYNAMIC_BACKEND)
360 add_definitions(-DSAMPLE_DYNAMIC_BACKEND_ENABLED)
363 # Streamline annotate
364 if(PROFILING_BACKEND_STREAMLINE)
365 include_directories("${GATOR_ROOT}/annotate")
366 add_definitions(-DARMNN_STREAMLINE_ENABLED)
369 if(HEAP_PROFILING OR LEAK_CHECKING)
370 # enable heap profiling for everything except for referencetests
371 if(NOT ${PROJECT_NAME} STREQUAL "referencetests")
372 find_path(HEAP_PROFILER_INCLUDE gperftools/heap-profiler.h
373 PATHS ${GPERFTOOLS_ROOT}/include
374 NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
375 include_directories(SYSTEM "${HEAP_PROFILER_INCLUDE}")
376 find_library(GPERF_TOOLS_LIBRARY
378 HINTS ${GPERFTOOLS_ROOT}/lib)
379 link_directories(${GPERFTOOLS_ROOT}/lib)
381 link_libraries(${GPERF_TOOLS_LIBRARY})
383 add_definitions("-DARMNN_HEAP_PROFILING_ENABLED=1")
386 add_definitions("-DARMNN_LEAK_CHECKING_ENABLED=1")
389 message(STATUS "Heap profiling and leak checking are disabled for referencetests")
392 # Valgrind only works with gperftools version number <= 2.4
393 CHECK_INCLUDE_FILE(valgrind/memcheck.h VALGRIND_FOUND)
397 if(NOT BUILD_CAFFE_PARSER)
398 message(STATUS "Caffe parser support is disabled")
401 if(NOT BUILD_TF_PARSER)
402 message(STATUS "Tensorflow parser support is disabled")
405 if(NOT BUILD_TF_LITE_PARSER)
406 message(STATUS "Tensorflow Lite parser support is disabled")
409 if(NOT BUILD_ARMNN_SERIALIZER)
410 message(STATUS "Armnn Serializer support is disabled")
413 if(NOT BUILD_ARMNN_QUANTIZER)
414 message(STATUS "ArmNN Quantizer support is disabled")
417 if(NOT BUILD_PYTHON_WHL)
418 message(STATUS "PyArmNN wheel package is disabled")
421 if(NOT BUILD_PYTHON_SRC)
422 message(STATUS "PyArmNN source package is disabled")
425 if(BUILD_PYTHON_WHL OR BUILD_PYTHON_SRC)
426 find_package(PythonInterp 3 REQUIRED)
427 if(NOT ${PYTHONINTERP_FOUND})
428 message(FATAL_ERROR "Python 3.x required to build PyArmNN, but not found")
431 find_package(PythonLibs 3 REQUIRED)
432 if(NOT ${PYTHONLIBS_FOUND})
433 message(FATAL_ERROR "Python 3.x development package required to build PyArmNN, but not found")
436 find_package(SWIG 4 REQUIRED)
437 if(NOT ${SWIG_FOUND})
438 message(FATAL_ERROR "SWIG 4.x requried to build PyArmNN, but not found")
442 # ArmNN source files required for all build options
443 include_directories(SYSTEM third-party)