|
1 | | -boost_dep = dependency('boost', modules : ['program_options'], required : true) |
| 1 | +# SPDX-License-Identifier: GPL-2.0-only |
| 2 | +# |
| 3 | +# Copyright (C) 2022-2025, Verdant Consultants, LLC. |
| 4 | +# |
| 5 | + |
| 6 | + |
| 7 | +project('pitrac_lm', 'c', 'cpp', |
| 8 | + meson_version : '>= 0.61', |
| 9 | + version : '0.0.1', |
| 10 | + default_options : [ |
| 11 | + 'werror=true', |
| 12 | + 'warning_level=2', |
| 13 | + 'cpp_std=c++20', |
| 14 | + ], |
| 15 | + license : 'LGPL 2.1+') |
| 16 | + |
| 17 | +add_global_arguments('-Wno-deprecated-enum-enum-conversion', language : 'cpp') |
| 18 | +add_global_arguments('-Wno-deprecated-declarations', language : 'cpp') |
| 19 | +add_global_arguments('-Wno-comment', language : 'cpp') |
| 20 | +add_global_arguments('-Wno-unused', language : 'cpp') |
| 21 | +add_global_arguments('-Wno-error', language : 'cpp') |
| 22 | +add_global_arguments('-D_FILE_OFFSET_BITS=64', language : 'cpp') |
| 23 | +add_global_arguments('-DLIBCXX_ENABLE_INCOMPLETE_FEATURES=ON', language : 'cpp') |
| 24 | +add_global_arguments('-DBOOST_LOG_DYN_LINK', language : 'cpp') |
| 25 | +add_global_arguments('-DBOOST_BIND_GLOBAL_PLACEHOLDERS', language : 'cpp') |
| 26 | +# Enable XNNPACK execution provider for ONNX Runtime |
| 27 | +add_global_arguments('-DUSE_XNNPACK', language : 'cpp') |
| 28 | + |
| 29 | + |
| 30 | +fs = import('fs') |
| 31 | + |
| 32 | +# TBD FIX - The following may be redundant of the above options |
| 33 | +cpp_arguments = ['-pedantic', '-Wno-unused-parameter', '-faligned-new', '-DBOOST_LOG_DYN_LINK', '-Wno-error', '-Wno-deprecated-enum-enum-conversion', '-Wno-decprecated-declarations'] |
| 34 | + |
| 35 | +# Needed for file sizes > 32-bits. |
| 36 | +cpp_arguments += '-D_FILE_OFFSET_BITS=64' |
| 37 | + |
| 38 | +# We need a relatively recent version of gcc that will support c++20 |
| 39 | + |
| 40 | +cxx = meson.get_compiler('cpp') |
| 41 | +cpu = host_machine.cpu() |
| 42 | + |
| 43 | +if cxx.get_id() == 'gcc' |
| 44 | + cpp_arguments += '-Wno-psabi' |
| 45 | +endif |
| 46 | + |
| 47 | +if cpu == 'aarch64' or neon == 'arm64' |
| 48 | + cpp_arguments += [ |
| 49 | + '-mcpu=cortex-a76', |
| 50 | + '-ftree-vectorize', |
| 51 | + '-falign-functions=16', |
| 52 | + '-falign-loops=16', |
| 53 | + '-fomit-frame-pointer', |
| 54 | + '-ffast-math', # Includes funsafe-math-optimizations, fno-signed-zeros, fno-trapping-math |
| 55 | + # XNNPACK-specific optimizations |
| 56 | + '-funroll-loops', # Better for XNNPACK's compute kernels |
| 57 | + '-fprefetch-loop-arrays', # Improve cache utilization |
| 58 | + '-falign-jumps=16', # Better branch prediction |
| 59 | + '-moutline-atomics' # Better for Pi4/5 atomic operations |
| 60 | + ] |
| 61 | +elif neon == 'armv8-neon' |
| 62 | + cpp_arguments += ['-mfpu=neon-fp-armv8', '-ftree-vectorize'] |
| 63 | +endif |
| 64 | + |
| 65 | +ssl_dep = dependency('openssl', required : true) |
| 66 | +activemq_dep = dependency('activemq-cpp', required : true) |
| 67 | +apr_dep = cxx.find_library('apr-1', required : true) |
| 68 | + |
| 69 | +libcamera_dep = dependency('libcamera', required : true) |
2 | 70 | thread_dep = dependency('threads', required : true) |
| 71 | +opencv_dep = dependency('opencv4', required : true, version : '>=4.9.0', include_type: 'system',) |
| 72 | + |
| 73 | +lgpio_dep = dependency('lgpio', required : true) |
| 74 | +fmt_dep = dependency('fmt', required : true) |
| 75 | + |
| 76 | +boost_dep = dependency('boost', method: 'pkg-config', version : '>=1.74.0', modules : ['timer', 'log', 'thread', 'filesystem', 'regex']) |
| 77 | + |
| 78 | +msgpack_dep = dependency('msgpack-cxx', required : true) |
| 79 | +yamlcpp_dep = dependency('yaml-cpp', required : true) |
| 80 | +onnxruntime_dep = dependency('onnxruntime', required : true) |
| 81 | + |
| 82 | +rpicam_app_src = [] |
| 83 | +rpicam_app_dep = [libcamera_dep, lgpio_dep] |
| 84 | + |
| 85 | + |
| 86 | +pitrac_lm_module_deps = [ |
| 87 | + libcamera_dep, thread_dep, opencv_dep, lgpio_dep, rpicam_app_dep, |
| 88 | + fmt_dep, boost_dep, activemq_dep, ssl_dep, apr_dep, msgpack_dep, yamlcpp_dep, onnxruntime_dep,] |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | +subdir('core') |
| 93 | +subdir('encoder') |
| 94 | +subdir('image') |
| 95 | +subdir('output') |
| 96 | +subdir('preview') |
| 97 | +subdir('post_processing_stages') |
3 | 98 |
|
4 | | -rpicam_app_dep += [boost_dep, thread_dep] |
5 | 99 |
|
6 | | -rpicam_app_src += files([ |
7 | | - 'buffer_sync.cpp', |
8 | | - 'dma_heaps.cpp', |
9 | | - 'rpicam_app.cpp', |
10 | | - 'options.cpp', |
11 | | - 'post_processor.cpp', |
| 100 | +# Generate a version string. |
| 101 | +version_cmd = [meson.project_source_root() / 'utils' / 'version.py', meson.project_version()] |
| 102 | + |
| 103 | +# Check if a version.gen file is present. |
| 104 | +# This would have been generated from the meson dist command. |
| 105 | +dist_version_file = meson.project_source_root() / 'version.gen' |
| 106 | +if fs.is_file(dist_version_file) |
| 107 | + version_cmd += fs.read(dist_version_file) |
| 108 | +endif |
| 109 | + |
| 110 | +version_cpp = vcs_tag(command : version_cmd, |
| 111 | + replace_string: '@VER@', |
| 112 | + input : meson.project_source_root() / 'core' / 'version.cpp.in', |
| 113 | + output : 'version.cpp', |
| 114 | + fallback : meson.project_version()) |
| 115 | + |
| 116 | +rpicam_app_src += version_cpp |
| 117 | + |
| 118 | + |
| 119 | +enable_recompile_closed_source = get_option('enable_recompile_closed_source') |
| 120 | +enable_compile_on_pi4 = get_option('enable_compile_on_pi4') |
| 121 | + |
| 122 | +# TBD - This is mostly deprecated. Delete soon! |
| 123 | +if enable_compile_on_pi4 |
| 124 | + message('Compiling on a Pi 4') |
| 125 | + add_global_arguments('-DPITRAC_COMPILING_ON_PI_4', language : 'cpp') |
| 126 | +else |
| 127 | + message('Compiling on a Pi 5') |
| 128 | +endif |
| 129 | + |
| 130 | +closed_source_object_files = [] |
| 131 | +pitrac_lm_sources = [] |
| 132 | + |
| 133 | +if enable_recompile_closed_source |
| 134 | + message('Recompiling closed source code') |
| 135 | + run_command('cp', '/home/USERNAME/Dev/ClosedSourceCode/gs_e6_response.cpp.FULL', 'gs_e6_response.cpp', check:true) |
| 136 | + pitrac_lm_sources += ([ 'gs_e6_response.cpp' ]) |
| 137 | +endif |
| 138 | + |
| 139 | +if enable_recompile_closed_source |
| 140 | + message('Recompiling closed source code') |
| 141 | + run_command('cp', '/home/USERNAME/Dev/ClosedSourceCode/obfuscate.h', 'obfuscate.h', check:true) |
| 142 | + pitrac_lm_sources += ([ 'gs_e6_response.cpp' ]) |
| 143 | +endif |
| 144 | + |
| 145 | +# Move the pre-compiled, closed-source object file(s) into place |
| 146 | +# This is a workaround to the fact that meson will not allow paths in the |
| 147 | +# output and input parameters of a custom_target |
| 148 | +create_closed_source_objects = find_program('create_closed_source_objects.sh') |
| 149 | +closed_source_target = custom_target('copy_closed_source_object', |
| 150 | + input : 'gs_e6_results.cpp', |
| 151 | + output : 'gs_e6_response.cpp.o', |
| 152 | + command : [ create_closed_source_objects, '@INPUT@', '@OUTPUT@'], |
| 153 | +) |
| 154 | + |
| 155 | +if not enable_recompile_closed_source |
| 156 | + message('Using pre-compiled closed object_code') |
| 157 | + pitrac_lm_sources += ([ closed_source_target, ]) |
| 158 | + closed_source_object_files += (['gs_e6_response.cpp.o']) |
| 159 | +endif |
| 160 | + |
| 161 | +if not enable_recompile_closed_source |
| 162 | + r = run_command ( 'cp', '-f', './ClosedSourceObjectFiles/gs_e6_response.cpp.o', '.', check:true) |
| 163 | +endif |
| 164 | + |
| 165 | +libav_dep_names = ['libavcodec', 'libavdevice', 'libavformat', 'libavutil', 'libswresample'] |
| 166 | +libav_deps = [] |
| 167 | + |
| 168 | +pitrac_lm_sources += ([ |
| 169 | + 'ED.cpp', |
| 170 | + 'EDColor.cpp', |
| 171 | + 'EDPF.cpp', |
| 172 | + 'lm_main.cpp', |
| 173 | + 'gs_globals.cpp', |
| 174 | + 'gs_fsm.cpp', |
| 175 | + 'libcamera_interface.cpp', |
| 176 | + 'libcamera_jpeg.cpp', |
| 177 | + 'ball_watcher.cpp', |
| 178 | + 'ball_watcher_image_buffer.cpp', |
| 179 | + 'libcamera_jpeg.cpp', |
| 180 | + 'ball_image_proc.cpp', |
| 181 | + 'onnx_runtime_detector.cpp', |
| 182 | + 'pulse_strobe.cpp', |
| 183 | + 'colorsys.cpp', |
| 184 | + 'cv_utils.cpp', |
| 185 | + 'EllipseDetectorCommon.cpp', |
| 186 | + 'EllipseDetectorYaed.cpp', |
| 187 | + 'golf_ball.cpp', |
| 188 | + 'gs_automated_testing.cpp', |
| 189 | + 'gs_calibration.cpp', |
| 190 | + 'gs_camera.cpp', |
| 191 | + 'gs_web_api.cpp', |
| 192 | + 'gs_clubs.cpp', |
| 193 | + 'gs_club_data.cpp', |
| 194 | + 'gs_options.cpp', |
| 195 | + 'gs_config.cpp', |
| 196 | + 'configuration_manager.cpp', |
| 197 | + 'gs_sim_interface.cpp', |
| 198 | + 'gs_gspro_interface.cpp', |
| 199 | + 'gs_gspro_response.cpp', |
| 200 | + 'gs_gspro_test_server.cpp', |
| 201 | + 'gs_sim_socket_interface.cpp', |
| 202 | + 'gs_e6_interface.cpp', |
| 203 | + 'gs_e6_results.cpp', |
| 204 | + 'logging_tools.cpp', |
| 205 | + 'gs_events.cpp', |
| 206 | + 'worker_thread.cpp', |
| 207 | + 'camera_hardware.cpp', |
| 208 | + 'gs_ipc_message.cpp', |
| 209 | + 'gs_ipc_control_msg.cpp', |
| 210 | + 'gs_results.cpp', |
| 211 | + 'gs_gspro_results.cpp', |
| 212 | + 'gs_ui_system.cpp', |
| 213 | + 'gs_ipc_mat.cpp', |
| 214 | + 'gs_ipc_result.cpp', |
| 215 | + 'gs_ipc_test.cpp', |
| 216 | + 'gs_ipc_system.cpp', |
| 217 | + 'gs_message_consumer.cpp', |
| 218 | + 'gs_message_producer.cpp', |
| 219 | +]) |
| 220 | + |
| 221 | +pitrac_lm_sources += ([ |
| 222 | + rpicam_app_src, |
12 | 223 | ]) |
13 | 224 |
|
14 | | -core_headers = files([ |
15 | | - 'buffer_sync.hpp', |
16 | | - 'completed_request.hpp', |
17 | | - 'dma_heaps.hpp', |
18 | | - 'frame_info.hpp', |
19 | | - 'rpicam_app.hpp', |
20 | | - 'rpicam_encoder.hpp', |
21 | | - 'logging.hpp', |
22 | | - 'metadata.hpp', |
23 | | - 'options.hpp', |
24 | | - 'post_processor.hpp', |
25 | | - 'still_options.hpp', |
26 | | - 'stream_info.hpp', |
27 | | - 'version.hpp', |
28 | | - 'video_options.hpp', |
| 225 | + |
| 226 | +pitrac_lm_include_dirs = ([ |
| 227 | + '.', |
| 228 | + '/usr/include/apr-1.0', |
| 229 | +]) |
| 230 | + |
| 231 | + |
| 232 | + |
| 233 | +pitrac_lm_module_deps += ([ |
| 234 | + rpicam_app_dep, |
29 | 235 | ]) |
30 | 236 |
|
31 | | -install_headers(core_headers, subdir: meson.project_name() / 'core') |
| 237 | +exec = executable('pitrac_lm', |
| 238 | + pitrac_lm_sources, |
| 239 | + include_directories : pitrac_lm_include_dirs, |
| 240 | + install : true, |
| 241 | + objects : closed_source_object_files, |
| 242 | + dependencies : pitrac_lm_module_deps |
| 243 | + ) |
32 | 244 |
|
33 | | -# Install symlinks to the old header directories and names for legacy purposes. |
34 | | -install_symlink('libcamera-apps', |
35 | | - install_dir: get_option('includedir'), |
36 | | - pointing_to: 'rpicam-apps') |
| 245 | +# Hacky two targets, because can't figure out how to execute more than one command |
| 246 | +# per target. TBD |
| 247 | +custom_target('post_build1', |
| 248 | + depends: exec, # Ensure the executable is built first |
| 249 | + input: exec, |
| 250 | + output: 'dummy_file1', # NOTE - command will execute in the build directory |
| 251 | + command: [ 'cp', '-f', './pitrac_lm.p/gs_e6_response.cpp.o', '../ClosedSourceObjectFiles'], |
| 252 | + build_by_default : true |
| 253 | +) |
37 | 254 |
|
38 | | -inc_install_dir = get_option('includedir') / meson.project_name() / 'core' |
39 | | -install_symlink('libcamera_app.h', |
40 | | - install_dir: inc_install_dir, |
41 | | - pointing_to: 'rpicam_app.hpp') |
| 255 | +custom_target('post_build2', |
| 256 | + depends: exec, # Ensure the executable is built first |
| 257 | + input: exec, |
| 258 | + output: 'dummy_file2', # NOTE - command will execute in the build directory |
| 259 | + command: [ 'cp', '-f', './pitrac_lm.p/gs_e6_response.cpp.o', '..'], |
| 260 | + build_by_default : true |
| 261 | +) |
42 | 262 |
|
43 | | -install_symlink('libcamera_encoder.h', |
44 | | - install_dir: inc_install_dir, |
45 | | - pointing_to: 'rpicam_encoder.hpp') |
|
0 commit comments