[CodeClean] fix indent and codestyle
[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 # ncnn
345 ncnn_dep = dependency('', required: false)
346 if not get_option('ncnn-support').disabled()
347   ncnn_dep = dependency('ncnn', required: false)
348   if (not ncnn_dep.found())
349     ncnn_lib = cxx.find_library('ncnn', required: false)
350     if (ncnn_lib.found() and cxx.check_header('ncnn/net.h'))
351       ncnn_dep = declare_dependency(dependencies: [ ncnn_lib ])
352     endif
353   endif
354 endif
355
356 # datarepo requires json-glib-1.0 in the name of json_glib_dep
357 json_glib_dep = dependency('json-glib-1.0', required: false)
358 if get_option('datarepo-support').enabled() and not json_glib_dep.found()
359   error('json-glib-1.0 is required for datarepo-support option.')
360 endif
361 if not get_option('datarepo-support').disabled() and not json_glib_dep.found()
362   message('datarepo-support is off because json-glib-1.0 is not available.')
363 endif
364
365 # ml-agent
366 ml_agent_dep = dependency('', required: false)
367 if not get_option('ml-agent-support').disabled()
368   ml_agent_dep = dependency('ml-agent', required: false)
369   if not ml_agent_dep.found()
370     if cc.check_header('ml-agent/ml-agent-interface.h', dependencies: [glib_dep], required: get_option('ml-agent-support'))
371       ml_agent_dep = cc.find_library('ml-agent', required: true)
372     endif
373   endif
374 endif
375
376 # features registration to be controlled
377 #
378 # register feature as follows
379 #  <string: feature_name> :  {
380 #      target: <string>, extra_deps: <list>,  project_args: <dict>,
381 #      project_args_disabled: <string>, extra_args: <dict: meson variables to be registered>,
382 features = {
383   'video-support': {
384     'project_args_disabled': { 'NO_VIDEO': 1 },
385   },
386   'audio-support': {
387     'project_args_disabled': { 'NO_AUDIO': 1 },
388   },
389   'tf-support': {
390     'target': 'tensorflow',
391     'extra_deps': [ protobuf_dep ],
392     'project_args': { 'ENABLE_TENSORFLOW': 1 },
393   },
394   'tflite-support': {
395     'target': 'tensorflow-lite',
396     'project_args': { 'ENABLE_TENSORFLOW_LITE': 1 }
397   },
398   'tflite2-support': {
399     'target': 'tensorflow2-lite',
400     'project_args': { 'ENABLE_TENSORFLOW2_LITE': 1 }
401   },
402   'pytorch-support': {
403     'target': 'pytorch',
404     'target_alt': 'torch',
405     'project_args': { 'ENABLE_PYTORCH': 1 }
406   },
407   'caffe2-support': {
408     'target': 'caffe2',
409     'project_args': { 'ENABLE_CAFFE2': 1 }
410   },
411   'deepview-rt-support': {
412     'extra_deps': [ deepview_rt_dep ],
413     'project_args': { 'ENABLE_DEEPVIEW_RT': 1 }
414   },
415   'mvncsdk2-support': {
416     'target': 'libmvnc',
417     'project_args': { 'ENABLE_MOVIDIUS_NCSDK2' : 1}
418   },
419   'nnfw-runtime-support': {
420     'extra_deps': [ nnfw_dep ],
421     'project_args': { 'ENABLE_NNFW_RUNTIME': 1 }
422   },
423   'armnn-support': {
424     'extra_deps': [ armnn_dep ],
425     'project_args': { 'ENABLE_ARMNN': 1 }
426   },
427   'orcc-support': {
428     'extra_deps': [ orc_dep, pg_orcc_dep ],
429     'project_args': {'HAVE_ORC': 1},
430     'project_args_disabled': { 'DISABLE_ORC': 1 },
431     'extra_args': {'orcc_args': [pg_orcc, '--include', 'glib.h'] }
432   },
433   'snpe-support': {
434     'extra_deps': [ snpe_dep ],
435     'project_args': { 'ENABLE_SNPE' : 1 },
436   },
437   'flatbuf-support': {
438     'extra_deps': [ flatc_dep, flatbuf_dep, flatbuf_version_check_dep ],
439     'project_args': { 'ENABLE_FLATBUF': 1 }
440   },
441   'protobuf-support': {
442     'extra_deps': [ pb_comp_dep, protobuf_dep ],
443     'project_args': { 'ENABLE_PROTOBUF': 1 }
444   },
445   'tensorrt-support': {
446     'extra_deps': [ nvinfer_dep, nvparsers_dep, cuda_dep, cudart_dep ],
447     'project_args': { 'ENABLE_TENSORRT': 1 }
448   },
449   'grpc-support': {
450     'extra_deps': [ grpc_dep, gpr_dep, grpcpp_dep ],
451     'project_args': { 'ENABLE_GRPC': 1 }
452   },
453   'lua-support': {
454     # TODO: support various Lua versions
455     'target': 'lua',
456     'target_alt': 'lua5.1',
457     'project_args': { 'ENABLE_LUA': 1 }
458   },
459   'mqtt-support': {
460     'extra_deps': [ pahomqttc_dep ],
461     'project_args': { 'ENABLE_MQTT': 1 }
462   },
463   'tvm-support': {
464     'target': 'tvm_runtime',
465     'project_args': { 'ENABLE_TVM' : 1 }
466   },
467   'trix-engine-support': {
468     'target': 'npu-engine',
469     'project_args': { 'ENABLE_TRIX_ENGINE' : 1 }
470   },
471   'nnstreamer-edge-support': {
472     'target': 'nnstreamer-edge',
473     'project_args': { 'ENABLE_NNSTREAMER_EDGE': 1 }
474   },
475   'mxnet-support': {
476     'extra_deps': [ mxnet_dep ],
477     'project_args': { 'ENABLE_MXNET' : 1 }
478   },
479   'ncnn-support': {
480     'extra_deps': [ ncnn_dep ],
481     'project_args': { 'ENABLE_NCNN' : 1 }
482   },
483   'datarepo-support': {
484     'extra_deps': [ json_glib_dep ],
485   },
486   'ml-agent-support': {
487     'extra_deps': [ ml_agent_dep ],
488     'project_args': { 'ENABLE_ML_AGENT' : 1 }
489   },
490   'onnxruntime-support': {
491     'target': 'libonnxruntime',
492     'project_args': { 'ENABLE_ONNXRUNTIME': 1 }
493   }
494 }
495
496 project_args = {}
497 # This section controls the flow of feature registration.
498 foreach feature_name, data : features
499   variable_name = feature_name.underscorify()
500   variable_deps_name = variable_name + '_deps'
501   variable_available_name = variable_name + '_is_available'
502
503   _available = true
504
505   target = data.get('target', '')
506
507   _deps = []
508
509   if target != ''
510     target_dep = dependency(target, required: false)
511     if not target_dep.found()
512       target_alt = data.get('target_alt', '')
513       if target_alt != ''
514         target_dep = dependency(target_alt, required: false)
515       endif
516     endif
517
518     if get_option(feature_name).enabled() and not target_dep.found()
519       error('@0@ is enabled but unable to find the target dependency'.format(feature_name))
520     endif
521
522     _deps += target_dep
523   endif
524   _deps += data.get('extra_deps', [])
525
526
527   foreach dep : _deps
528     if not dep.found()
529       _available = false
530     endif
531   endforeach
532
533   if get_option(feature_name).disabled() or not _available
534     project_args += data.get('project_args_disabled', {})
535     set_variable(variable_deps_name, [])
536     set_variable(variable_available_name, false)
537     message('@0@ is off because it is either not available or disabled'.format(feature_name))
538     continue
539   endif
540
541   # handle when available
542   project_args += data.get('project_args', {})
543
544   set_variable(variable_deps_name, _deps)
545   set_variable(variable_available_name, true)
546
547   foreach name, value : data.get('extra_args', {})
548     set_variable(variable_name + '_' + name, value)
549   endforeach
550
551 endforeach
552
553 #Definitions enabled by meson_options.txt
554 message('Following project_args are going to be included')
555 message(project_args)
556 foreach name, value: project_args
557   add_project_arguments('-D@0@=@1@'.format(name, value), language: ['c', 'cpp'])
558 endforeach
559
560 # Add redundant declaration flag when caffe2 and pytorch both are disabled
561 if not (pytorch_support_is_available or caffe2_support_is_available)
562   redundant_decls_flag = '-Wredundant-decls'
563   if cc.has_argument (redundant_decls_flag)
564     add_project_arguments([redundant_decls_flag], language: 'c')
565   endif
566   if cxx.has_argument (redundant_decls_flag)
567     add_project_arguments([redundant_decls_flag], language: 'cpp')
568   endif
569 endif
570
571 # Python3
572 have_python3 = false
573 if not get_option('python3-support').disabled()
574   # Check python 3.x
575   python3_dep = dependency('python3', required: false)
576   if python3_dep.found() and python3_dep.version().version_compare('>= 3.8')
577     # The name of .pc file provides C/CXX/LD_FLAGS for Python C API has been changed since v3.8
578     python3_dep = dependency('python3-embed', required: false)
579   endif
580
581   if python3_dep.found()
582     pg_pkgconfig = find_program('pkg-config')
583
584     python3_inc_args = []
585     python3_inc_args += run_command(pg_pkgconfig, ['python3', '--cflags'], check : true).stdout().strip().split()
586     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()
587     r = run_command('python3', ['-m', 'site', '--user-site'], check : false)
588     if r.returncode() == 0
589       python3_inc_args += '-I' + r.stdout().strip() + '/numpy/core/include'
590     endif
591     python3_inc_valid_args = []
592
593     foreach python3_inc_arg : python3_inc_args
594       if cxx.has_argument(python3_inc_arg) and \
595           cxx.check_header('numpy/arrayobject.h', args : python3_inc_arg, dependencies : python3_dep)
596         python3_inc_valid_args += python3_inc_arg
597         have_python3 = true
598         break
599       endif
600     endforeach
601
602     if have_python3
603       python3_dep = declare_dependency(dependencies: python3_dep,
604           compile_args : python3_inc_valid_args)
605     else
606       warning('Found python3, but failed to find numpy.')
607       warning('Disable nnstreamer-python3.')
608       python3_dep = disabler()
609     endif
610   endif
611
612   if get_option('python3-support').enabled() and not have_python3
613     error('Cannot find python3 with numpy support')
614   endif
615 endif
616
617 # Set sub-plugin priority
618 tflite_subplugin_list = []
619 if tflite2_support_is_available
620   tflite_subplugin_list += 'tensorflow2-lite'
621 endif
622 if tflite_support_is_available
623   tflite_subplugin_list += 'tensorflow1-lite'
624 endif
625
626 nnstreamer_conf.set('TFLITE_SUBPLUGIN_PRIORITY', ','.join(tflite_subplugin_list))
627
628 # Set configuration to install .ini
629 nnstreamer_install_conf = configuration_data()
630 nnstreamer_install_conf.merge_from(nnstreamer_conf)
631
632 nnstreamer_install_conf.set('ENABLE_ENV_VAR', get_option('enable-env-var'))
633 nnstreamer_install_conf.set('ENABLE_SYMBOLIC_LINK', get_option('enable-symbolic-link'))
634 nnstreamer_install_conf.set('TORCH_USE_GPU', get_option('enable-pytorch-use-gpu'))
635
636 # Element restriction
637 restriction_config = ''
638
639 if get_option('enable-element-restriction')
640   restriction_config = '''[element-restriction]
641 enable_element_restriction=True
642 allowed_elements=''' + get_option('allowed-elements')
643 endif
644
645 nnstreamer_install_conf.set('ELEMENT_RESTRICTION_CONFIG', restriction_config)
646 nnstreamer_install_conf.set('TEST_TEMPLATE_DIR', unittest_base_dir) # TEST_TEMPLATE_DIR will be empty if `install-test` is false
647
648 # Extra configuration
649 extra_config_path = ''
650 if get_option('extra_config_path') != ''
651   extra_config_path = 'extra_config_path=' + get_option('extra_config_path')
652 endif
653 nnstreamer_install_conf.set('EXTRA_CONFIG_PATH', extra_config_path)
654
655 # Install .ini
656 configure_file(input: 'nnstreamer.ini.in', output: 'nnstreamer.ini',
657   install_dir: nnstreamer_inidir,
658   configuration: nnstreamer_install_conf
659 )
660
661 # Install .pc
662 configure_file(input: 'nnstreamer-single.pc.in', output: 'nnstreamer-single.pc',
663   install_dir: join_paths(nnstreamer_libdir, 'pkgconfig'),
664   configuration: nnstreamer_install_conf
665 )
666 configure_file(input: 'nnstreamer.pc.in', output: 'nnstreamer.pc',
667   install_dir: join_paths(nnstreamer_libdir, 'pkgconfig'),
668   configuration: nnstreamer_install_conf
669 )
670 configure_file(input: 'nnstreamer-internal.pc.in', output: 'nnstreamer-internal.pc',
671   install_dir: join_paths(nnstreamer_libdir, 'pkgconfig'),
672   configuration: nnstreamer_install_conf
673 )
674
675 # Check whether mqtt broker is running or not.
676 check_mosquitto = run_command ('bash', './tests/check_broker.sh', check : true).stdout()
677 if check_mosquitto != ''
678   add_project_arguments('-D__MQTT_BROKER_ENABLED__=1', language: ['c', 'cpp'])
679 endif
680
681 # Float16 Support
682 if get_option('enable-float16')
683   arch = target_machine.cpu_family()
684   add_project_arguments('-DFLOAT16_SUPPORT', language: ['c', 'cpp'])
685
686   if arch == 'aarch64'
687     message ('Float16 for aarch64 enabled. Modern gcc-aarch64 generally supports float16 with __fp16. It uses IEEE 754-2008 format.')
688   elif arch == 'arm'
689     add_project_arguments('-mfp16-format=ieee', language: ['c', 'cpp'])
690     message ('Float16 for arm (32b) enabled. Modern gcc-arm generally supports float16 with __fp16 by -mfp16-format=ieee for IEEE 754-2008 format.')
691   elif arch == 'x86_64' or arch == 'x86'
692     # GCC 12+ has fp16 avx512 support.
693     has_avx512fp16 = cc.has_argument('-mavx512fp16')
694
695     if (has_avx512fp16)
696       add_project_arguments(['-mavx512fp16'], language: ['c', 'cpp'])
697       message ('Float16 for x86_64 enabled. Modern gcc-x64 genrally supports float16 with _Float16. -mavx512fp16 added for hardware acceleration')
698     else
699       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.')
700     endif
701   else
702     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).')
703   endif
704
705 endif
706
707 # A few distros do not have execinfo.h
708 if not cc.has_header('execinfo.h')
709   add_project_arguments('-D_NO_EXECINFO_', language: ['c', 'cpp'])
710 endif
711
712 # See if src-iio can be built or not
713 gst18_dep = dependency('gstreamer-' + gst_api_verision, version : '>=1.8', required : false)
714 tensor_src_iio_build = false
715 if gst18_dep.found() and build_platform != 'macos'
716   add_project_arguments('-D_ENABLE_SRC_IIO', language: ['c', 'cpp'])
717   message('tensor_src_iio enabled')
718   tensor_src_iio_build = true
719 else
720   message('tensor_src_iio disabled: it requires GStreamer >= 1.8 and Linux')
721 endif
722
723 # Build nnstreamer (common, plugins)
724 subdir('gst')
725
726 # Build ext subplugins
727 subdir('ext')
728
729 # Build Utility
730 subdir('tools/development')
731
732 # Build unittests
733 if get_option('enable-test')
734   # ini file generator template for the plugins from other repository
735   configure_file(input: 'nnstreamer.ini.in', output: 'nnstreamer-test.ini.in',
736     install: get_option('install-test'),
737     install_dir: unittest_base_dir,
738     copy: true,
739   )
740
741   # temporary ini file for test, enable env variables.
742   nnstreamer_test_conf = configuration_data()
743   nnstreamer_test_conf.merge_from(nnstreamer_conf)
744
745   nnstreamer_test_conf.set('ENABLE_ENV_VAR', true)
746   nnstreamer_test_conf.set('ENABLE_SYMBOLIC_LINK', false)
747   nnstreamer_test_conf.set('TORCH_USE_GPU', false)
748   nnstreamer_test_conf.set('EXTRA_CONFIG_PATH', '')
749   nnstreamer_test_conf.set('ELEMENT_RESTRICTION_CONFIG', '')
750
751   configure_file(input: 'nnstreamer.ini.in', output: 'nnstreamer-test.ini',
752     install: get_option('install-test'),
753     install_dir: unittest_base_dir,
754     configuration: nnstreamer_test_conf
755   )
756
757   path_gst_plugin = join_paths(meson.build_root(), 'gst')
758   path_ext_plugin = join_paths(meson.build_root(), 'ext')
759
760   path_nns_conf = join_paths(meson.build_root(), 'nnstreamer-test.ini')
761   path_nns_plugin_prefix = join_paths(path_ext_plugin, 'nnstreamer')
762   path_nns_plugin_filters = join_paths(path_nns_plugin_prefix, 'tensor_filter')
763   path_nns_plugin_decoders = join_paths(path_nns_plugin_prefix, 'tensor_decoder')
764   path_nns_plugin_converters = join_paths(path_nns_plugin_prefix, 'tensor_converter')
765   path_nns_plugin_trainers = join_paths(path_nns_plugin_prefix, 'tensor_trainer')
766
767   testenv = environment()
768   testenv.set('GST_PLUGIN_PATH', path_gst_plugin + ':' + path_ext_plugin)
769   testenv.set('NNSTREAMER_CONF', path_nns_conf)
770   testenv.set('NNSTREAMER_FILTERS', path_nns_plugin_filters)
771   testenv.set('NNSTREAMER_DECODERS', path_nns_plugin_decoders)
772   testenv.set('NNSTREAMER_CONVERTERS', path_nns_plugin_converters)
773   testenv.set('NNSTREAMER_TRAINERS', path_nns_plugin_trainers)
774   testenv.set('NNSTREAMER_SOURCE_ROOT_PATH', meson.source_root())
775   testenv.set('NNSTREAMER_BUILD_ROOT_PATH', meson.build_root())
776   if have_python3
777     py3_module_path = join_paths(meson.current_build_dir(), 'ext/nnstreamer/extra')
778     run_command('ln', '-sf',
779         py3_module_path + '/nnstreamer_python3.' + so_ext,
780         py3_module_path + '/nnstreamer_python.' + so_ext, check : true)
781     testenv.set('PYTHONPATH', py3_module_path)
782   endif
783
784   subdir('tests')
785 endif