filter::python3: do not break converter/decoder
[platform/upstream/nnstreamer.git] / meson.build
1 # If you are using Ubuntu/Xenial, Do "force-version" on meson to get the required version.
2 # If you are using Tizen 5.0+ or Ubuntu/Bionix+, you don't need to mind meson version.
3
4 project('nnstreamer', 'c', 'cpp',
5   version: '2.4.1',
6   license: ['LGPL-2.1'],
7   meson_version: '>=0.50.0',
8   default_options: [
9     'werror=true',
10     'warning_level=2',
11     'c_std=gnu89',
12     'cpp_std=c++17'
13   ]
14 )
15
16 add_project_arguments('-DVERSION="' + meson.project_version() + '"', language: ['c', 'cpp'])
17 version_split = meson.project_version().split('.')
18 add_project_arguments('-DVERSION_MAJOR="' + version_split[0] + '"', language: ['c', 'cpp'])
19 add_project_arguments('-DVERSION_MINOR="' + version_split[1] + '"', language: ['c', 'cpp'])
20 add_project_arguments('-DVERSION_MICRO="' + version_split[2] + '"', language: ['c', 'cpp'])
21
22 cc = meson.get_compiler('c')
23 cxx = meson.get_compiler('cpp')
24 build_platform = ''
25 so_ext = 'so'
26
27 if get_option('enable-tizen')
28   # Pass __TIZEN__ to the compiler
29   add_project_arguments('-D__TIZEN__=1', language: ['c', 'cpp'])
30   build_platform = 'tizen'
31
32   tizenVmajor = get_option('tizen-version-major')
33   add_project_arguments('-DTIZENVERSION='+tizenVmajor.to_string(), language: ['c', 'cpp'])
34   dlog_dep = dependency('dlog')
35 elif not meson.is_cross_build()
36   if cc.get_id() == 'clang' and cxx.get_id() == 'clang'
37     if build_machine.system() == 'darwin'
38       # Pass __MACOS__ to the compiler
39       add_project_arguments('-D__MACOS__=1', language: ['c', 'cpp'])
40       build_platform = 'macos'
41       so_ext = 'dylib'
42     endif
43   endif
44 endif
45
46 # Define warning flags for c and cpp
47 warning_flags = [
48   '-Wmissing-braces',
49   '-Wmaybe-uninitialized',
50   '-Wwrite-strings',
51   '-Wformat',
52   '-Wformat-nonliteral',
53   '-Wformat-security',
54   '-Winit-self',
55   '-Waddress',
56   '-Wno-multichar',
57   '-Wvla',
58   '-Wpointer-arith'
59 ]
60 if cxx.get_id() == 'clang'
61   # For the usage of GstTensorFilterFramework in tensor_filter_support_cc.cc
62   warning_flags += '-Wno-c99-designator'
63 endif
64
65 warning_c_flags = [
66   '-Wmissing-declarations',
67   '-Wmissing-include-dirs',
68   '-Wmissing-prototypes',
69   '-Wnested-externs',
70   '-Waggregate-return',
71   '-Wold-style-definition',
72   '-Wdeclaration-after-statement'
73 ]
74
75 # Setup warning flags for c and cpp
76 foreach extra_arg : warning_flags
77   if cc.has_argument (extra_arg)
78     add_project_arguments([extra_arg], language: 'c')
79   endif
80   if cxx.has_argument (extra_arg)
81     add_project_arguments([extra_arg], language: 'cpp')
82   endif
83 endforeach
84
85 foreach extra_arg : warning_c_flags
86   if cc.has_argument (extra_arg)
87     add_project_arguments([extra_arg], language: 'c')
88   endif
89 endforeach
90
91 gst_api_verision = '1.0'
92
93 # Set install path
94 nnstreamer_prefix = get_option('prefix')
95 nnstreamer_libdir = join_paths(nnstreamer_prefix, get_option('libdir'))
96 nnstreamer_bindir = join_paths(nnstreamer_prefix, get_option('bindir'))
97 nnstreamer_includedir = join_paths(nnstreamer_prefix, get_option('includedir'))
98 nnstreamer_inidir = join_paths(nnstreamer_prefix, get_option('sysconfdir'))
99 # join_paths drops first arg if second arg is absolute path.
100
101 # nnstreamer plugins path
102 plugins_install_dir = join_paths(nnstreamer_libdir, 'gstreamer-' + gst_api_verision)
103
104 # nnstreamer sub-plugins path
105 if get_option('subplugindir') == ''
106   subplugin_install_prefix = join_paths(nnstreamer_prefix, get_option('libdir'), 'nnstreamer')
107 else
108   subplugin_install_prefix = get_option('subplugindir')
109 endif
110 filter_subplugin_install_dir = join_paths(subplugin_install_prefix, 'filters')
111 decoder_subplugin_install_dir = join_paths(subplugin_install_prefix, 'decoders')
112 customfilter_install_dir = join_paths(subplugin_install_prefix, 'customfilters')
113 converter_subplugin_install_dir = join_paths(subplugin_install_prefix, 'converters')
114 unittest_base_dir = join_paths(nnstreamer_bindir, 'unittest-nnstreamer')
115
116 # Set default configuration
117 nnstreamer_conf = configuration_data()
118 nnstreamer_conf.set('VERSION', meson.project_version())
119 nnstreamer_conf.set('PREFIX', nnstreamer_prefix)
120 nnstreamer_conf.set('EXEC_PREFIX', nnstreamer_bindir)
121 nnstreamer_conf.set('LIB_INSTALL_DIR', nnstreamer_libdir)
122 nnstreamer_conf.set('GST_INSTALL_DIR', plugins_install_dir)
123 nnstreamer_conf.set('INCLUDE_INSTALL_DIR', nnstreamer_includedir)
124 nnstreamer_conf.set('SUBPLUGIN_INSTALL_PREFIX', subplugin_install_prefix)
125
126 # Set framework priority about model file extension when automatically selecting framework for tensor filter.
127 nnstreamer_conf.set('FRAMEWORK_PRIORITY_TFLITE', get_option('framework-priority-tflite'))
128 nnstreamer_conf.set('FRAMEWORK_PRIORITY_NB', get_option('framework-priority-nb'))
129 nnstreamer_conf.set('FRAMEWORK_PRIORITY_BIN', get_option('framework-priority-bin'))
130
131 # Set the alias for backward compatibility
132 nnstreamer_conf.set('TRIX_ENGINE_ALIAS', get_option('trix-engine-alias'))
133
134 # Define default conf file
135 add_project_arguments('-DNNSTREAMER_CONF_FILE="' + join_paths(nnstreamer_inidir, 'nnstreamer.ini') + '"', language: 'c')
136
137 # Dependencies
138 glib_dep = dependency('glib-2.0')
139 if glib_dep.version().version_compare('>= 2.68.0')
140   add_project_arguments('-DGLIB_USE_G_MEMDUP2', language: ['c', 'cpp'])
141 endif
142 gobject_dep = dependency('gobject-2.0')
143 gmodule_dep = dependency('gmodule-2.0')
144 gio_dep = dependency('gio-2.0')
145 gst_dep = dependency('gstreamer-' + gst_api_verision)
146 gst_base_dep = dependency('gstreamer-base-' + gst_api_verision)
147 gst_controller_dep = dependency('gstreamer-controller-' + gst_api_verision)
148 gst_video_dep = dependency('gstreamer-video-' + gst_api_verision)
149 gst_audio_dep = dependency('gstreamer-audio-' + gst_api_verision)
150 gst_app_dep = dependency('gstreamer-app-' + gst_api_verision)
151 gst_check_dep = dependency('gstreamer-check-' + gst_api_verision)
152
153 libm_dep = cc.find_library('m') # cmath library
154 libdl_dep = cc.find_library('dl') # DL library
155 thread_dep = dependency('threads') # pthread for tensorflow-lite
156
157 # Protobuf
158 protobuf_dep = dependency('protobuf', version: '>= 3.6.1', required: false)
159
160 # Flatbuffers compiler and libraries
161 flatc = find_program('flatc', required : get_option('flatbuf-support'))
162 flatbuf_dep = disabler()
163 flatbuf_version_check_dep = disabler()
164 flatc_dep = disabler()
165 if flatc.found()
166   # TODO: After bumping up meson version to 0.62.0, we can use flatc.version()
167   # Please refer https://mesonbuild.com/Reference-manual_returned_external_program.html#external_programversion
168   flatc_ver = run_command(flatc, '--version', check : true).stdout().split()[2]
169   flatbuf_dep = dependency('flatbuffers', version: flatc_ver,
170       required : get_option('flatbuf-support'),
171       not_found_message : 'flatbuffers version '+flatc_ver+' is required because flatc (flatbuf-compiler) '+flatc_ver+' is installed'
172       )
173   flatbuf_version_check_dep = dependency('flatbuffers', version: '>=2.0.0',
174       required : get_option('flatbuf-support'))
175   flatc_dep = declare_dependency()
176 endif
177
178 # Protobuf compiler
179 pb_comp = find_program('protoc', required: get_option('protobuf-support'))
180 pb_comp_dep = disabler()
181 if (pb_comp.found())
182   pb_comp_dep = declare_dependency()
183 endif
184
185 #orc
186 pg_orcc = find_program('orcc', required: get_option('orcc-support'))
187 pg_orcc_dep = disabler()
188 if (pg_orcc.found())
189   pg_orcc_dep = declare_dependency()
190 endif
191 orc_dep = dependency('orc-0.4', version: '>= 0.4.17', required: get_option('orcc-support'))
192
193 ## nnfw
194 nnfw_dep = dependency('', required: false)
195 if not get_option('nnfw-runtime-support').disabled()
196   nnfw_dep = dependency('nnfw', required: false)
197   if not nnfw_dep.found()
198     nnfw_dep = cc.find_library('nnfw-dev', required: get_option('nnfw-runtime-support'))
199   endif
200 endif
201
202 # snpe
203 snpe_dep = dependency('', required: false)
204 if not get_option('snpe-support').disabled()
205   # Check whether the platform supports snpe
206   snpe_dep = dependency('snpe', required: false)
207   if (not snpe_dep.found())
208     # TODO: support various arch.
209     if host_machine.system() != 'linux' or host_machine.cpu_family() != 'x86_64'
210       message('Not Supported System & Architecture. Linux x86_64 is required for snpe sub-plugin')
211     else
212       # Check whether $SNPE_ROOT (where SNPE SDK is located) is set.
213       cmd = run_command('sh', '-c', 'echo $SNPE_ROOT', check : true)
214       SNPE_ROOT = cmd.stdout().strip()
215       if SNPE_ROOT != ''
216         message('Got $SNPE_ROOT: @0@'.format(SNPE_ROOT))
217         # TODO: This is not a portable way to check if a directory exists
218         # After bumping up to 0.53.0, the following line can be replaced with one that uses FS module
219         snpe_dir_not_exist = run_command('[', '-d', SNPE_ROOT, ']', check : false).returncode()
220         if snpe_dir_not_exist != 0
221           error('@0@ does not exists'.format(SNPE_ROOT))
222         endif
223
224         snpe_lib = cxx.find_library('SNPE',
225           dirs: join_paths(SNPE_ROOT, 'lib', 'x86_64-linux-clang'),
226           required: true
227         )
228
229         snpe_incdir = include_directories(join_paths(SNPE_ROOT, 'include', 'zdl'))
230
231         snpe_dep = declare_dependency(
232           dependencies: snpe_lib,
233           include_directories: snpe_incdir
234         )
235       endif
236     endif
237   endif
238 endif
239
240 # tensorrt
241 nvinfer_dep = dependency('', required: false)
242 nvparsers_dep = dependency('', required: false)
243 cuda_dep = dependency('', required: false)
244 cudart_dep = dependency('', required: false)
245 if not get_option('tensorrt-support').disabled()
246   # check available cuda versions (11.0 and 10.2 are recommended)
247   cuda_vers = [
248     '11.0',
249     '10.2',
250     '10.1',
251     '10.0',
252     '9.2',
253     '9.1',
254     '9.0'
255   ]
256
257   foreach ver : cuda_vers
258     cuda_dep = dependency('cuda-' + ver, required: false)
259     cudart_dep = dependency('cudart-' + ver, required: false)
260     if cuda_dep.found() and cudart_dep.found()
261       if ver != '11.0' and ver != '10.2'
262         message('Warning: the recommended cuda version is at least 10.2')
263       endif
264       break
265     endif
266   endforeach
267
268   nvinfer_lib = cxx.find_library('nvinfer', required: false)
269   if nvinfer_lib.found() and cxx.check_header('NvInfer.h')
270     nvinfer_dep = declare_dependency(dependencies: nvinfer_lib)
271   endif
272
273   nvparsers_lib = cxx.find_library('nvparsers', required: false)
274   if nvparsers_lib.found() and cxx.check_header('NvUffParser.h')
275     nvparsers_dep = declare_dependency(dependencies: nvparsers_lib)
276   endif
277 endif
278
279 # gRPC
280 grpc_dep = dependency('', required: false)
281 gpr_dep = dependency('', required: false)
282 grpcpp_dep = dependency('', required: false)
283 if not get_option('grpc-support').disabled()
284   grpc_dep = dependency('grpc', required: false)
285   gpr_dep = dependency('gpr', required: false)
286   grpcpp_dep = dependency('grpc++', required: false)
287 endif
288
289 # mqtt (paho.mqtt.c)
290 pahomqttc_dep = dependency('', required: false)
291 if not get_option('mqtt-support').disabled()
292   pahomqttc_dep = dependency('paho-mqtt-c', required: false)
293   if (not pahomqttc_dep.found() and get_option('mqtt-support').enabled())
294     message('mqtt-support is enabled while its pkgconfig is not found. Hardcoded build configuration is used.')
295     pahomqttc_lib1 = cxx.find_library('paho-mqtt3a', required: true)
296     pahomqttc_lib2 = cxx.find_library('paho-mqtt3c', required: true)
297     pahomqttc_lib3 = cxx.find_library('paho-mqtt3as', required: true)
298     pahomqttc_lib4 = cxx.find_library('paho-mqtt3cs', required: true)
299     pahomqttc_dep = declare_dependency(dependencies: [pahomqttc_lib1, pahomqttc_lib2, pahomqttc_lib3, pahomqttc_lib4])
300   endif
301 endif
302
303 # deepview-rt
304 deepview_rt_dep = dependency('', required: false)
305 if not get_option('deepview-rt-support').disabled()
306   deepview_rt_dep = dependency('deepview-rt', required: false)
307   if (not deepview_rt_dep.found())
308     deepview_rt_lib = cxx.find_library('deepview-rt', required: false)
309     if (deepview_rt_lib.found() and cxx.check_header('deepview_rt.h'))
310       deepview_rt_dep = declare_dependency(dependencies: [ deepview_rt_lib ])
311     endif
312   endif
313 endif
314 if get_option('deepview-rt-support').enabled() and not deepview_rt_dep.found()
315   error('deepview-rt enabled but dependencies are not found.')
316 endif
317
318 # armnn
319 armnn_dep = dependency('', required: false)
320 if not get_option('armnn-support').disabled()
321   armnn_dep = dependency('armnn', required: false)
322   if (not armnn_dep.found())
323     armnn_dep = dependency('Armnn', required: false)
324   endif
325   if (not armnn_dep.found())
326     armnn_lib = cxx.find_library('armnn', required: false)
327     if (armnn_lib.found() and cxx.check_header('armnn/ArmNN.hpp'))
328       armnn_dep = declare_dependency(dependencies: [ armnn_lib, thread_dep ])
329     endif
330   endif
331 endif
332
333 # mxnet
334 mxnet_dep = dependency('', required: false)
335 if not get_option('mxnet-support').disabled()
336   mxnet_dep = cxx.find_library('mxnet', required: false)
337   if not mxnet_dep.found()
338     if cxx.check_header('mxnet-cpp/MxNetCpp.h', required: get_option('mxnet-support'))
339       mxnet_dep = declare_dependency(link_args: ['-lmxnet'])
340     endif
341   endif
342 endif
343
344 # nnstreamer-edge
345 nnstreamer_edge_dep = dependency('nnstreamer-edge', method : 'pkg-config', required: false)
346 if get_option('nnstreamer-edge-support').enabled()
347   if not nnstreamer_edge_dep.found()
348     error('nnstreamer-edge not found whilt it is enabled.')
349   endif
350 endif
351 ## Without the explicit method designation, it fails to find cflags in older Meson
352
353 # datarepo requires json-glib-1.0 in the name of json_glib_dep
354 json_glib_dep = dependency('json-glib-1.0', required: false)
355 if get_option('datarepo-support').enabled() and not json_glib_dep.found()
356   error('json-glib-1.0 is required for datarepo-support option.')
357 endif
358 if not get_option('datarepo-support').disabled() and not json_glib_dep.found()
359   message('datarepo-support is off because json-glib-1.0 is not available.')
360 endif
361 # ml-agent
362 ml_agent_dep = dependency('', required: false)
363 if not get_option('ml-agent-support').disabled()
364   ml_agent_dep = dependency('ml-agent', required: false)
365   if not ml_agent_dep.found()
366     if cc.check_header('ml-agent/ml-agent-interface.h', dependencies: [glib_dep], required: get_option('ml-agent-support'))
367       ml_agent_dep = cc.find_library('ml-agent', required: true)
368     endif
369   endif
370 endif
371
372 # features registration to be controlled
373 #
374 # register feature as follows
375 #  <string: feature_name> :  {
376 #      target: <string>, extra_deps: <list>,  project_args: <dict>,
377 #      project_args_disabled: <string>, extra_args: <dict: meson variables to be registered>,
378 features = {
379   'video-support': {
380     'project_args_disabled': { 'NO_VIDEO': 1 },
381   },
382   'audio-support': {
383     'project_args_disabled': { 'NO_AUDIO': 1 },
384   },
385   'tf-support': {
386     'target': 'tensorflow',
387     'extra_deps': [ protobuf_dep ],
388     'project_args': { 'ENABLE_TENSORFLOW': 1 },
389   },
390   'tflite-support': {
391     'target': 'tensorflow-lite',
392     'project_args': { 'ENABLE_TENSORFLOW_LITE': 1 }
393   },
394   'tflite2-support': {
395     'target': 'tensorflow2-lite',
396     'project_args': { 'ENABLE_TENSORFLOW2_LITE': 1 }
397   },
398   'pytorch-support': {
399     'target': 'pytorch',
400     'target_alt': 'Torch',
401     'project_args': { 'ENABLE_PYTORCH': 1 }
402   },
403   'caffe2-support': {
404     'target': 'caffe2',
405     'project_args': { 'ENABLE_CAFFE2': 1 }
406   },
407   'deepview-rt-support': {
408     'extra_deps': [ deepview_rt_dep ],
409     'project_args': { 'ENABLE_DEEPVIEW_RT': 1 }
410   },
411   'mvncsdk2-support': {
412     'target': 'libmvnc',
413     'project_args': { 'ENABLE_MOVIDIUS_NCSDK2' : 1}
414   },
415   'nnfw-runtime-support': {
416     'extra_deps': [ nnfw_dep ],
417     'project_args': { 'ENABLE_NNFW_RUNTIME': 1 }
418   },
419   'armnn-support': {
420     'extra_deps': [ armnn_dep ],
421     'project_args': { 'ENABLE_ARMNN': 1 }
422   },
423   'orcc-support': {
424     'extra_deps': [ orc_dep, pg_orcc_dep ],
425     'project_args': {'HAVE_ORC': 1},
426     'project_args_disabled': { 'DISABLE_ORC': 1 },
427     'extra_args': {'orcc_args': [pg_orcc, '--include', 'glib.h'] }
428   },
429   'snpe-support': {
430     'extra_deps': [ snpe_dep ],
431     'project_args': { 'ENABLE_SNPE' : 1 },
432   },
433   'flatbuf-support': {
434     'extra_deps': [ flatc_dep, flatbuf_dep, flatbuf_version_check_dep ],
435     'project_args': { 'ENABLE_FLATBUF': 1 }
436   },
437   'protobuf-support': {
438     'extra_deps': [ pb_comp_dep, protobuf_dep ],
439     'project_args': { 'ENABLE_PROTOBUF': 1 }
440   },
441   'tensorrt-support': {
442     'extra_deps': [ nvinfer_dep, nvparsers_dep, cuda_dep, cudart_dep ],
443     'project_args': { 'ENABLE_TENSORRT': 1 }
444   },
445   'grpc-support': {
446     'extra_deps': [ grpc_dep, gpr_dep, grpcpp_dep ],
447     'project_args': { 'ENABLE_GRPC': 1 }
448   },
449   'lua-support': {
450     # TODO: support various Lua versions
451     'target': 'lua',
452     'target_alt': 'lua5.1',
453     'project_args': { 'ENABLE_LUA': 1 }
454   },
455   'mqtt-support': {
456     'extra_deps': [ pahomqttc_dep ],
457     'project_args': { 'ENABLE_MQTT': 1 }
458   },
459   'tvm-support': {
460     'target': 'tvm_runtime',
461     'project_args': { 'ENABLE_TVM' : 1 }
462   },
463   'trix-engine-support': {
464     'target': 'npu-engine',
465     'project_args': { 'ENABLE_TRIX_ENGINE' : 1 }
466   },
467   'nnstreamer-edge-support': {
468     'extra_deps': [ nnstreamer_edge_dep ],
469     'project_args': { 'ENABLE_NNSTREAMER_EDGE': 1 }
470   },
471   'mxnet-support': {
472     'extra_deps': [ mxnet_dep ],
473     'project_args': { 'ENABLE_MXNET' : 1 }
474   },
475   'datarepo-support': {
476     'extra_deps': [ json_glib_dep ],
477   },
478   'ml-agent-support': {
479     'extra_deps': [ ml_agent_dep ],
480     'project_args': { 'ENABLE_ML_AGENT' : 1 }
481   },
482   'onnxruntime-support': {
483     'target': 'libonnxruntime',
484     'project_args': { 'ENABLE_ONNXRUNTIME': 1 }
485   }
486 }
487
488 project_args = {}
489 # This section controls the flow of feature registration.
490 foreach feature_name, data : features
491   variable_name = feature_name.underscorify()
492   variable_deps_name = variable_name + '_deps'
493   variable_available_name = variable_name + '_is_available'
494
495   _available = true
496
497   target = data.get('target', '')
498
499   _deps = []
500
501   if target != ''
502     target_dep = dependency(target, required: false)
503     if not target_dep.found()
504       target_alt = data.get('target_alt', '')
505       if target_alt != ''
506         target_dep = dependency(target_alt, required: false)
507       endif
508     endif
509
510     if get_option(feature_name).enabled() and not target_dep.found()
511       error('@0@ is enabled but unable to find the target dependency'.format(feature_name))
512     endif
513
514     _deps += target_dep
515   endif
516   _deps += data.get('extra_deps', [])
517
518
519   foreach dep : _deps
520     if not dep.found()
521       _available = false
522     endif
523   endforeach
524
525   if get_option(feature_name).disabled() or not _available
526     project_args += data.get('project_args_disabled', {})
527     set_variable(variable_deps_name, [])
528     set_variable(variable_available_name, false)
529     message('@0@ is off because it is either not available or disabled'.format(feature_name))
530     continue
531   endif
532
533   # handle when available
534   project_args += data.get('project_args', {})
535
536   set_variable(variable_deps_name, _deps)
537   set_variable(variable_available_name, true)
538
539   foreach name, value : data.get('extra_args', {})
540     set_variable(variable_name + '_' + name, value)
541   endforeach
542
543 endforeach
544
545 #Definitions enabled by meson_options.txt
546 message('Following project_args are going to be included')
547 message(project_args)
548 foreach name, value: project_args
549   add_project_arguments('-D@0@=@1@'.format(name, value), language: ['c', 'cpp'])
550 endforeach
551
552 # Add redundant declaration flag when caffe2 and pytorch both are disabled
553 if not (pytorch_support_is_available or caffe2_support_is_available)
554   redundant_decls_flag = '-Wredundant-decls'
555   if cc.has_argument (redundant_decls_flag)
556     add_project_arguments([redundant_decls_flag], language: 'c')
557   endif
558   if cxx.has_argument (redundant_decls_flag)
559     add_project_arguments([redundant_decls_flag], language: 'cpp')
560   endif
561 endif
562
563 # Python3
564 have_python3 = false
565 if not get_option('python3-support').disabled()
566   # Check python 3.x
567   python3_dep = dependency('python3', required: false)
568   if python3_dep.found() and python3_dep.version().version_compare('>= 3.8')
569     # The name of .pc file provides C/CXX/LD_FLAGS for Python C API has been changed since v3.8
570     python3_dep = dependency('python3-embed', required: false)
571   endif
572
573   if python3_dep.found()
574     pg_pkgconfig = find_program('pkg-config')
575
576     python3_inc_args = []
577     python3_inc_args += run_command(pg_pkgconfig, ['python3', '--cflags'], check : true).stdout().strip().split()
578     python3_inc_args += run_command('python3', ['-c', 'import site\nfor i in site.getsitepackages(): print("-I" + i + "/numpy/core/include")'], check : true).stdout().strip().split()
579     r = run_command('python3', ['-m', 'site', '--user-site'], check : false)
580     if r.returncode() == 0
581       python3_inc_args += '-I' + r.stdout().strip() + '/numpy/core/include'
582     endif
583     python3_inc_valid_args = []
584
585     foreach python3_inc_arg : python3_inc_args
586       if cxx.has_argument(python3_inc_arg) and \
587           cxx.check_header('numpy/arrayobject.h', args : python3_inc_arg, dependencies : python3_dep)
588         python3_inc_valid_args += python3_inc_arg
589         have_python3 = true
590         break
591       endif
592     endforeach
593
594     if have_python3
595       python3_dep = declare_dependency(dependencies: python3_dep,
596           compile_args : python3_inc_valid_args)
597     else
598       warning('Found python3, but failed to find numpy.')
599       warning('Disable nnstreamer-python3.')
600       python3_dep = disabler()
601     endif
602   endif
603
604   if get_option('python3-support').enabled() and not have_python3
605     error('Cannot find python3 with numpy support')
606   endif
607 endif
608
609 # Set sub-plugin priority
610 tflite_subplugin_list = []
611 if tflite2_support_is_available
612   tflite_subplugin_list += 'tensorflow2-lite'
613 endif
614 if tflite_support_is_available
615   tflite_subplugin_list += 'tensorflow1-lite'
616 endif
617
618 nnstreamer_conf.set('TFLITE_SUBPLUGIN_PRIORITY', ','.join(tflite_subplugin_list))
619
620 # Set configuration to install .ini
621 nnstreamer_install_conf = configuration_data()
622 nnstreamer_install_conf.merge_from(nnstreamer_conf)
623
624 nnstreamer_install_conf.set('ENABLE_ENV_VAR', get_option('enable-env-var'))
625 nnstreamer_install_conf.set('ENABLE_SYMBOLIC_LINK', get_option('enable-symbolic-link'))
626 nnstreamer_install_conf.set('TORCH_USE_GPU', get_option('enable-pytorch-use-gpu'))
627
628 # Element restriction
629 restriction_config = ''
630
631 if get_option('enable-element-restriction')
632   restriction_config = '''[element-restriction]
633 enable_element_restriction=True
634 allowed_elements=''' + get_option('allowed-elements')
635 endif
636
637 nnstreamer_install_conf.set('ELEMENT_RESTRICTION_CONFIG', restriction_config)
638 nnstreamer_install_conf.set('TEST_TEMPLATE_DIR', unittest_base_dir) # TEST_TEMPLATE_DIR will be empty if `install-test` is false
639
640 # Extra configuration
641 extra_config_path = ''
642 if get_option('extra_config_path') != ''
643   extra_config_path = 'extra_config_path=' + get_option('extra_config_path')
644 endif
645 nnstreamer_install_conf.set('EXTRA_CONFIG_PATH', extra_config_path)
646
647 # Install .ini
648 configure_file(input: 'nnstreamer.ini.in', output: 'nnstreamer.ini',
649   install_dir: nnstreamer_inidir,
650   configuration: nnstreamer_install_conf
651 )
652
653 # Install .pc
654 configure_file(input: 'nnstreamer-single.pc.in', output: 'nnstreamer-single.pc',
655   install_dir: join_paths(nnstreamer_libdir, 'pkgconfig'),
656   configuration: nnstreamer_install_conf
657 )
658 configure_file(input: 'nnstreamer.pc.in', output: 'nnstreamer.pc',
659   install_dir: join_paths(nnstreamer_libdir, 'pkgconfig'),
660   configuration: nnstreamer_install_conf
661 )
662 configure_file(input: 'nnstreamer-internal.pc.in', output: 'nnstreamer-internal.pc',
663   install_dir: join_paths(nnstreamer_libdir, 'pkgconfig'),
664   configuration: nnstreamer_install_conf
665 )
666
667 # Check whether mqtt broker is running or not.
668 check_mosquitto = run_command ('bash', './tests/check_broker.sh', check : true).stdout()
669 if check_mosquitto != ''
670   add_project_arguments('-D__MQTT_BROKER_ENABLED__=1', language: ['c', 'cpp'])
671 endif
672
673 # Float16 Support
674 if get_option('enable-float16')
675   arch = target_machine.cpu_family()
676   add_project_arguments('-DFLOAT16_SUPPORT', language: ['c', 'cpp'])
677
678   if arch == 'aarch64'
679     message ('Float16 for aarch64 enabled. Modern gcc-aarch64 generally supports float16 with __fp16. It uses IEEE 754-2008 format.')
680   elif arch == 'arm'
681     add_project_arguments('-mfp16-format=ieee', language: ['c', 'cpp'])
682     message ('Float16 for arm (32b) enabled. Modern gcc-arm generally supports float16 with __fp16 by -mfp16-format=ieee for IEEE 754-2008 format.')
683   elif arch == 'x86_64' or arch == 'x86'
684     # GCC 12+ has fp16 avx512 support.
685     has_avx512fp16 = cc.has_argument('-mavx512fp16')
686
687     if (has_avx512fp16)
688       add_project_arguments(['-mavx512fp16'], language: ['c', 'cpp'])
689       message ('Float16 for x86_64 enabled. Modern gcc-x64 genrally supports float16 with _Float16. -mavx512fp16 added for hardware acceleration')
690     else
691       warning ('Float16 for x86_64 enabled. However, software emulation is applied for fp16, making it slower and inconsistent. Use GCC 12+ for AVX512 FP16 support. This build will probably fail unless you bring a compiler that supports fp16 for x64.')
692     endif
693   else
694     error ('Float16 is supported only in aarch64, arm, and x86_64. If you believe the compiler for this architecture supports float16, you will need to update the build script (meson.build).')
695   endif
696
697 endif
698
699 # A few distros do not have execinfo.h
700 if not cc.has_header('execinfo.h')
701   add_project_arguments('-D_NO_EXECINFO_', language: ['c', 'cpp'])
702 endif
703
704 # See if src-iio can be built or not
705 gst18_dep = dependency('gstreamer-' + gst_api_verision, version : '>=1.8', required : false)
706 tensor_src_iio_build = false
707 if gst18_dep.found() and build_platform != 'macos'
708   add_project_arguments('-D_ENABLE_SRC_IIO', language: ['c', 'cpp'])
709   message('tensor_src_iio enabled')
710   tensor_src_iio_build = true
711 else
712   message('tensor_src_iio disabled: it requires GStreamer >= 1.8 and Linux')
713 endif
714
715 # Build nnstreamer (common, plugins)
716 subdir('gst')
717
718 # Build ext subplugins
719 subdir('ext')
720
721 # Build Utility
722 subdir('tools/development')
723
724 # Build unittests
725 if get_option('enable-test')
726   # ini file generator template for the plugins from other repository
727   configure_file(input: 'nnstreamer.ini.in', output: 'nnstreamer-test.ini.in',
728     install: get_option('install-test'),
729     install_dir: unittest_base_dir,
730     copy: true,
731   )
732
733   # temporary ini file for test, enable env variables.
734   nnstreamer_test_conf = configuration_data()
735   nnstreamer_test_conf.merge_from(nnstreamer_conf)
736
737   nnstreamer_test_conf.set('ENABLE_ENV_VAR', true)
738   nnstreamer_test_conf.set('ENABLE_SYMBOLIC_LINK', false)
739   nnstreamer_test_conf.set('TORCH_USE_GPU', false)
740   nnstreamer_test_conf.set('EXTRA_CONFIG_PATH', '')
741   nnstreamer_test_conf.set('ELEMENT_RESTRICTION_CONFIG', '')
742
743   configure_file(input: 'nnstreamer.ini.in', output: 'nnstreamer-test.ini',
744     install: get_option('install-test'),
745     install_dir: unittest_base_dir,
746     configuration: nnstreamer_test_conf
747   )
748
749   path_gst_plugin = join_paths(meson.build_root(), 'gst')
750   path_ext_plugin = join_paths(meson.build_root(), 'ext')
751
752   path_nns_conf = join_paths(meson.build_root(), 'nnstreamer-test.ini')
753   path_nns_plugin_prefix = join_paths(path_ext_plugin, 'nnstreamer')
754   path_nns_plugin_filters = join_paths(path_nns_plugin_prefix, 'tensor_filter')
755   path_nns_plugin_decoders = join_paths(path_nns_plugin_prefix, 'tensor_decoder')
756   path_nns_plugin_converters = join_paths(path_nns_plugin_prefix, 'tensor_converter')
757   path_nns_plugin_trainers = join_paths(path_nns_plugin_prefix, 'tensor_trainer')
758
759   testenv = environment()
760   testenv.set('GST_PLUGIN_PATH', path_gst_plugin + ':' + path_ext_plugin)
761   testenv.set('NNSTREAMER_CONF', path_nns_conf)
762   testenv.set('NNSTREAMER_FILTERS', path_nns_plugin_filters)
763   testenv.set('NNSTREAMER_DECODERS', path_nns_plugin_decoders)
764   testenv.set('NNSTREAMER_CONVERTERS', path_nns_plugin_converters)
765   testenv.set('NNSTREAMER_TRAINERS', path_nns_plugin_trainers)
766   testenv.set('NNSTREAMER_SOURCE_ROOT_PATH', meson.source_root())
767   testenv.set('NNSTREAMER_BUILD_ROOT_PATH', meson.build_root())
768   if have_python3
769     py3_module_path = join_paths(meson.current_build_dir(), 'ext/nnstreamer/extra')
770     run_command('ln', '-sf',
771         py3_module_path + '/nnstreamer_python3.' + so_ext,
772         py3_module_path + '/nnstreamer_python.' + so_ext, check : true)
773     testenv.set('PYTHONPATH', py3_module_path)
774   endif
775
776   subdir('tests')
777 endif