meson.build 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. project('clanker-saddle', ['c', 'vala'],
  2. version: '1.1',
  3. )
  4. glib_dep = dependency('glib-2.0')
  5. gobject_dep = dependency('gobject-2.0')
  6. gio_dep = dependency('gio-2.0')
  7. json_glib_dep = dependency('json-glib-1.0')
  8. soup_dep = dependency('libsoup-3.0')
  9. libxml_dep = dependency('libxml-2.0')
  10. sqlite_dep = dependency('sqlite3')
  11. invercargill_dep = dependency('invercargill-1')
  12. invercargill_json_dep = dependency('invercargill-json')
  13. invercargill_sql_dep = dependency('invercargill-sql')
  14. invercargill_sql_inversion_dep = dependency('invercargill-sql-inversion')
  15. inversion_dep = dependency('inversion-0.1')
  16. astralis_dep = dependency('astralis-0.1')
  17. statum_dep = dependency('statum-0.1')
  18. spry_dep = dependency('spry-0.2')
  19. # The dev stack (spry 0.2 and co) lives in a non-standard prefix on
  20. # development machines (~/.local): meson's automatic build rpath makes
  21. # the BUILD-tree binary run, but `meson install` strips it, leaving the
  22. # installed binary unable to load libspry outside the build tree (the
  23. # canon_deploy bundle's deployed-boot check). Carry the dependency's
  24. # pkg-config libdir as the INSTALL rpath — inside a usm container the
  25. # same expression resolves the (harmless, existing) system libdir.
  26. devstack_libdir = spry_dep.get_variable(pkgconfig: 'libdir', default_value: '')
  27. # Web Push crypto primitives (P-256 ECDH/ECDSA + AES-128-GCM for VAPID
  28. # and RFC 8291 payload encryption — plan 11 task E). Found via the C
  29. # compiler (no Vala vapi exists for libcrypto; the shim is C-only).
  30. libcrypto_dep = meson.get_compiler('c').find_library('crypto')
  31. # Statum build tools — statum-mkpstm compiles pages, statum-mkres embeds
  32. # resources. Resolved from PATH at setup time.
  33. statum_mkpstm = find_program('statum-mkpstm')
  34. statum_mkres = find_program('statum-mkres')
  35. # =============================================================================
  36. # Statum pages (statum-mkpstm): HTML → StatumPage subclass. Every page
  37. # composes the shared layout (main.html), which the tool discovers next to
  38. # the pages.
  39. # =============================================================================
  40. template_deps = files(
  41. 'src/pages/main.html',
  42. # Partials (plan 16 R3, arch 16): inlined into pages at compile
  43. # time via <pstm-fragment>; discovered next to the pages.
  44. 'src/pages/goal_branches.html',
  45. 'src/pages/goal_compare.html',
  46. 'src/pages/progress_feed.html',
  47. 'src/pages/task_log_feed.html',
  48. 'src/pages/block_answer.html',
  49. 'src/pages/block_reply.html',
  50. 'src/pages/breadcrumb.html',
  51. )
  52. # spry:pages-begin
  53. home_page = custom_target('home-page',
  54. input: 'src/pages/home.html',
  55. output: 'HomePage.vala',
  56. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'HomePage', '--ns', 'ClankerSaddle', '@INPUT@'],
  57. depend_files: template_deps
  58. )
  59. login_page = custom_target('login-page',
  60. input: 'src/pages/login.html',
  61. output: 'LoginPage.vala',
  62. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'LoginPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  63. depend_files: template_deps
  64. )
  65. projects_page = custom_target('projects-page',
  66. input: 'src/pages/projects.html',
  67. output: 'ProjectsPage.vala',
  68. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'ProjectsPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  69. depend_files: template_deps
  70. )
  71. project_detail_page = custom_target('project-detail-page',
  72. input: 'src/pages/project_detail.html',
  73. output: 'ProjectDetailPage.vala',
  74. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'ProjectDetailPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  75. depend_files: template_deps
  76. )
  77. tasks_page = custom_target('tasks-page',
  78. input: 'src/pages/tasks.html',
  79. output: 'TasksPage.vala',
  80. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'TasksPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  81. depend_files: template_deps
  82. )
  83. task_detail_page = custom_target('task-detail-page',
  84. input: 'src/pages/task_detail.html',
  85. output: 'TaskDetailPage.vala',
  86. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'TaskDetailPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  87. depend_files: template_deps
  88. )
  89. task_log_page = custom_target('task-log-page',
  90. input: 'src/pages/task_log.html',
  91. output: 'TaskLogPage.vala',
  92. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'TaskLogPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  93. depend_files: template_deps
  94. )
  95. goals_page = custom_target('goals-page',
  96. input: 'src/pages/goals.html',
  97. output: 'GoalsPage.vala',
  98. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'GoalsPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  99. depend_files: template_deps
  100. )
  101. goal_detail_page = custom_target('goal-detail-page',
  102. input: 'src/pages/goal_detail.html',
  103. output: 'GoalDetailPage.vala',
  104. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'GoalDetailPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  105. depend_files: template_deps
  106. )
  107. saddles_page = custom_target('saddles-page',
  108. input: 'src/pages/saddles.html',
  109. output: 'SaddlesPage.vala',
  110. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'SaddlesPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  111. depend_files: template_deps
  112. )
  113. stacks_page = custom_target('stacks-page',
  114. input: 'src/pages/stacks.html',
  115. output: 'StacksPage.vala',
  116. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'StacksPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  117. depend_files: template_deps
  118. )
  119. stack_detail_page = custom_target('stack-detail-page',
  120. input: 'src/pages/stack_detail.html',
  121. output: 'StackDetailPage.vala',
  122. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'StackDetailPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  123. depend_files: template_deps
  124. )
  125. rules_page = custom_target('rules-page',
  126. input: 'src/pages/rules.html',
  127. output: 'RulesPage.vala',
  128. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'RulesPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  129. depend_files: template_deps
  130. )
  131. discoveries_page = custom_target('discoveries-page',
  132. input: 'src/pages/discoveries.html',
  133. output: 'DiscoveriesPage.vala',
  134. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'DiscoveriesPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  135. depend_files: template_deps
  136. )
  137. chats_page = custom_target('chats-page',
  138. input: 'src/pages/chats.html',
  139. output: 'ChatsPage.vala',
  140. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'ChatsPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  141. depend_files: template_deps
  142. )
  143. chat_detail_page = custom_target('chat-detail-page',
  144. input: 'src/pages/chat_detail.html',
  145. output: 'ChatDetailPage.vala',
  146. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'ChatDetailPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  147. depend_files: template_deps
  148. )
  149. users_page = custom_target('users-page',
  150. input: 'src/pages/users.html',
  151. output: 'UsersPage.vala',
  152. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'UsersPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  153. depend_files: template_deps
  154. )
  155. model_settings_page = custom_target('model-settings-page',
  156. input: 'src/pages/model_settings.html',
  157. output: 'ModelSettingsPage.vala',
  158. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'ModelSettingsPage', '--ns', 'ClankerSaddle', '@INPUT@'],
  159. depend_files: template_deps
  160. )
  161. profile_page = custom_target('profile-page',
  162. input: 'src/pages/profile.html',
  163. output: 'ProfilePage.vala',
  164. command: [statum_mkpstm, '-o', '@OUTPUT@', '-n', 'ProfilePage', '--ns', 'ClankerSaddle', '@INPUT@'],
  165. depend_files: template_deps
  166. )
  167. # spry:pages-end
  168. # =============================================================================
  169. # Embedded resources (statum-mkres): the stylesheet precompressed at build
  170. # time and served from /_statum/resource/app.css.
  171. # =============================================================================
  172. app_css = custom_target('app-css',
  173. input: 'src/pages/app.css',
  174. output: 'AppCss.vala',
  175. command: [statum_mkres, '-o', '@OUTPUT@', '-n', 'app.css', '--class-name', 'AppCss',
  176. '--ns', 'ClankerSaddle', '-c', 'text/css', '@INPUT@'],
  177. )
  178. app_js = custom_target('app-js',
  179. input: 'src/pages/app.js',
  180. output: 'AppJs.vala',
  181. command: [statum_mkres, '-o', '@OUTPUT@', '-n', 'app.js', '--class-name', 'AppJs',
  182. '--ns', 'ClankerSaddle', '-c', 'text/javascript', '@INPUT@'],
  183. )
  184. task_log_js = custom_target('task-log-js-res',
  185. input: 'src/pages/task_log.js',
  186. output: 'TaskLogJs.vala',
  187. command: [statum_mkres, '-o', '@OUTPUT@', '-n', 'task_log.js', '--class-name', 'TaskLogJs',
  188. '--ns', 'ClankerSaddle', '-c', 'text/javascript', '@INPUT@'],
  189. )
  190. favicon_png = custom_target('favicon-png',
  191. input: 'src/clanker-saddle.png',
  192. output: 'FaviconResource.vala',
  193. command: [statum_mkres, '-o', '@OUTPUT@', '-n', 'clanker-saddle.png',
  194. '--class-name', 'FaviconResource', '--ns', 'ClankerSaddle',
  195. '-c', 'image/png', '@INPUT@'],
  196. )
  197. emblem_png = custom_target('emblem-png',
  198. input: 'src/clanker-saddle-emblem.png',
  199. output: 'EmblemResource.vala',
  200. command: [statum_mkres, '-o', '@OUTPUT@', '-n', 'clanker-saddle-emblem.png',
  201. '--class-name', 'EmblemResource', '--ns', 'ClankerSaddle',
  202. '-c', 'image/png', '@INPUT@'],
  203. )
  204. # =============================================================================
  205. # Sources
  206. # =============================================================================
  207. app_sources = files(
  208. # spry:sources-begin
  209. 'src/main.vala',
  210. 'src/Json.vala',
  211. 'src/Format.vala',
  212. 'src/Data/Entities.vala',
  213. 'src/Data/Migrations/M0001_Initial.vala',
  214. 'src/Data/Migrations/M0002_BatchImprovements.vala',
  215. 'src/Data/Migrations/M0003_EventIndexes.vala',
  216. 'src/Data/Migrations/M0004_ProjectUnderstandings.vala',
  217. 'src/Data/Migrations/M0005_Discoveries.vala',
  218. 'src/Data/Migrations/M0006_Advisor.vala',
  219. 'src/Data/Migrations/M0007_ParkingGuard.vala',
  220. 'src/Data/Migrations/M0008_AnswerWake.vala',
  221. 'src/Data/Migrations/M0009_TurnCapPark.vala',
  222. 'src/Data/Migrations/M0010_ModelConfig.vala',
  223. 'src/Data/Migrations/M0011_UserPreferences.vala',
  224. 'src/Services/ProjectService.vala',
  225. 'src/Services/TaskService.vala',
  226. 'src/Services/GoalService.vala',
  227. 'src/Services/SaddleService.vala',
  228. 'src/Services/EventService.vala',
  229. 'src/Services/LifecycleService.vala',
  230. 'src/Services/SaddlePollState.vala',
  231. 'src/Services/AnswerDeliveryHub.vala',
  232. 'src/Services/AllocationService.vala',
  233. 'src/Services/StatePulse.vala',
  234. 'src/Services/Dispatcher.vala',
  235. 'src/Services/RuleService.vala',
  236. 'src/Services/StackService.vala',
  237. 'src/Services/NoteService.vala',
  238. 'src/Services/UnderstandingService.vala',
  239. 'src/Services/DiscoveryService.vala',
  240. 'src/Services/CapabilityService.vala',
  241. 'src/Services/TimelineService.vala',
  242. 'src/Services/PushService.vala',
  243. 'src/Services/ChatService.vala',
  244. 'src/Services/ModelConfigService.vala',
  245. 'src/Services/UserPreferenceService.vala',
  246. 'src/Services/CanonService.vala',
  247. 'src/Services/AdvisorService.vala',
  248. 'src/Services/AdvisorCallback.vala',
  249. 'src/Api/SaddleApi.vala',
  250. 'src/Api/ProjectApi.vala',
  251. 'src/Api/AdvisorApi.vala',
  252. 'src/Api/EventLogApi.vala',
  253. 'src/Api/PushApi.vala',
  254. 'src/actions/Forms.vala',
  255. 'src/actions/LoginAction.vala',
  256. 'src/actions/ProjectActions.vala',
  257. 'src/actions/TaskActions.vala',
  258. 'src/actions/GoalActions.vala',
  259. 'src/actions/DashboardActions.vala',
  260. 'src/actions/SaddleActions.vala',
  261. 'src/actions/RuleActions.vala',
  262. 'src/actions/DiscoveryActions.vala',
  263. 'src/actions/AdvisorActions.vala',
  264. 'src/actions/StackActions.vala',
  265. 'src/actions/NoteActions.vala',
  266. 'src/actions/CapabilityActions.vala',
  267. 'src/actions/UserActions.vala',
  268. 'src/actions/ModelActions.vala',
  269. 'src/actions/ProfileActions.vala',
  270. 'src/actions/PushActions.vala',
  271. 'src/entrypoints/HomeEntrypoint.vala',
  272. 'src/entrypoints/LoginEntrypoint.vala',
  273. 'src/entrypoints/ProjectsEntrypoint.vala',
  274. 'src/entrypoints/TasksEntrypoint.vala',
  275. 'src/entrypoints/TaskDetailEntrypoint.vala',
  276. 'src/entrypoints/TaskLogEntrypoint.vala',
  277. 'src/entrypoints/GoalDetailEntrypoint.vala',
  278. 'src/entrypoints/SaddlesEntrypoint.vala',
  279. 'src/entrypoints/RulesEntrypoint.vala',
  280. 'src/entrypoints/DiscoveriesEntrypoint.vala',
  281. 'src/entrypoints/ChatsEntrypoint.vala',
  282. 'src/entrypoints/ChatDetailEntrypoint.vala',
  283. 'src/entrypoints/StacksEntrypoint.vala',
  284. 'src/entrypoints/UsersEntrypoint.vala',
  285. 'src/entrypoints/ModelSettingsEntrypoint.vala',
  286. 'src/entrypoints/ProfileEntrypoint.vala',
  287. # spry:sources-end
  288. )
  289. # Web Push crypto shim (plan 11 task E): C over OpenSSL's libcrypto —
  290. # P-256 keygen/ECDH/ECDSA + AES-128-GCM behind web-push-crypto.vapi.
  291. push_crypto = files('src/Push/web-push-crypto.c')
  292. app_generated = [
  293. # spry:generated-begin
  294. home_page,
  295. login_page,
  296. projects_page,
  297. project_detail_page,
  298. tasks_page,
  299. task_detail_page,
  300. task_log_page,
  301. goals_page,
  302. goal_detail_page,
  303. saddles_page,
  304. rules_page,
  305. discoveries_page,
  306. chats_page,
  307. chat_detail_page,
  308. stacks_page,
  309. stack_detail_page,
  310. users_page,
  311. model_settings_page,
  312. profile_page,
  313. # spry:generated-end
  314. ]
  315. clanker_saddle_exe = executable('clanker-saddle',
  316. app_sources + app_generated + [app_css, app_js, task_log_js, favicon_png, emblem_png, push_crypto],
  317. include_directories: include_directories('src/Push'),
  318. vala_args: ['--vapidir=' + join_paths(meson.current_source_dir(), 'vapi')],
  319. dependencies: [
  320. spry_dep,
  321. statum_dep,
  322. astralis_dep,
  323. inversion_dep,
  324. invercargill_sql_inversion_dep,
  325. invercargill_sql_dep,
  326. invercargill_json_dep,
  327. invercargill_dep,
  328. sqlite_dep,
  329. libxml_dep,
  330. soup_dep,
  331. json_glib_dep,
  332. gio_dep,
  333. gobject_dep,
  334. glib_dep,
  335. libcrypto_dep,
  336. ],
  337. install: true,
  338. install_rpath: devstack_libdir
  339. )
  340. # The canonical texts ride the install into
  341. # datadir/clanker-saddle/canon; the service resolves that layout at
  342. # run time with a source-tree fallback (the Saddle daemon mirror —
  343. # the web is the canon's owner now).
  344. canon_files = files(
  345. 'canon/gnu-manifesto.md',
  346. 'canon/free-software-definition.md',
  347. 'canon/open-source-misses-the-point.md',
  348. 'canon/right-to-read.md',
  349. 'canon/selling-free-software.md',
  350. 'canon/selling-exceptions.md',
  351. 'canon/words-to-avoid.md',
  352. 'canon/misinterpreting-copyright.md',
  353. 'canon/university-and-the-web.md',
  354. 'canon/plato-apology.md',
  355. 'canon/plato-republic-vi.md',
  356. 'canon/aristotle-nicomachean-ethics-i-ii.md',
  357. 'canon/aquinas-treatise-on-happiness.md',
  358. 'canon/lewis-abolition-of-man-i-ii.md',
  359. 'canon/magnifica-humanitas-summary.md')
  360. install_data(canon_files,
  361. install_dir: get_option('datadir') / 'clanker-saddle' / 'canon')
  362. # =============================================================================
  363. # Tests: the web-stack suite is a package (plan 16 R5, arch 18) —
  364. # test/web_stack_test.py is the entry shim meson invokes; the shared
  365. # machinery (fake saddle daemon, wire helpers, fixtures, the runner)
  366. # lives in test/harness.py and one module per scenario bundle
  367. # in test/bundles/. The default run is SEQUENTIAL (the unbounded
  368. # parallel fan-out OOM'd the machine; --parallel N opts back in with a
  369. # concurrency cap), so the timeout covers the summed bundle times.
  370. # =============================================================================
  371. python_test = import('python').find_installation('python3')
  372. test('web-stack', python_test,
  373. args: [files('test/web_stack_test.py'), clanker_saddle_exe],
  374. timeout: 3600,
  375. )
  376. # The event-log page's client JS: static source checks plus a python
  377. # port of the ingest/ordering/scroll-stick logic. Standalone by
  378. # design - it must run where the app binary cannot be built (the
  379. # statum toolchain is a build-time dependency that not every
  380. # container carries), so it reads src/pages/task_log.html directly
  381. # instead of driving a live server.
  382. test('task-log-js', python_test,
  383. args: [files('test/test_task_log_js.py')],
  384. timeout: 120,
  385. )