1project('babl', 'c', 2 license: 'LGPL3+', 3 version: '0.1.88', 4 meson_version: '>=0.54.0', 5 default_options: [ 6 'buildtype=debugoptimized' 7 ], 8 # https://gitlab.gnome.org/GNOME/babl/issues/ 9) 10 11# Making releases on the stable branch: 12# BABL_MICRO_VERSION += 1; 13# BABL_INTERFACE_AGE += 1; 14# BABL_BINARY_AGE += 1; 15# if any functions have been added, 16# set BABL_INTERFACE_AGE to 0. 17# if backwards compatibility has been broken, 18# set BABL_BINARY_AGE _and_ BABL_INTERFACE_AGE to 0. 19 20conf = configuration_data() 21 22pkgconfig = import('pkgconfig') 23gnome = import('gnome') 24python = import('python').find_installation() 25 26cc = meson.get_compiler('c') 27prefix = get_option('prefix') 28buildtype = get_option('buildtype') 29 30babl_prefix = get_option('prefix') 31babl_libdir = join_paths(babl_prefix, get_option('libdir')) 32 33project_build_root = meson.current_build_dir() 34project_source_root = meson.current_source_dir() 35 36################################################################################ 37# Projects infos 38 39version = meson.project_version() 40array_version = version.split('.') 41major_version = array_version[0].to_int() 42minor_version = array_version[1].to_int() 43micro_version = array_version[2].to_int() 44interface_age = 1 45 46binary_age = 100 * minor_version + micro_version 47 48lt_current = binary_age - interface_age 49 50api_version = '@0@.@1@'.format(major_version, minor_version) 51lib_version = '@0@:@1@:@2@'.format(lt_current, interface_age, lt_current) 52so_version = '@0@.@1@.@2@'.format(0, lt_current, interface_age) 53lib_name = meson.project_name() + '-' + api_version 54 55stability_version_number = (major_version != 0 ? minor_version : micro_version) 56stable = (stability_version_number % 2 == 0) 57 58conf.set10('BABL_UNSTABLE', not stable, Description: 59 'Define to 1 if this is an unstable version of BABL.') 60 61conf.set ('BABL_MAJOR_VERSION', '@0@'.format(major_version)) 62conf.set ('BABL_MINOR_VERSION', '@0@'.format(minor_version)) 63conf.set ('BABL_MICRO_VERSION', '@0@'.format(micro_version)) 64conf.set_quoted('BABL_INTERFACE_AGE', '@0@'.format(interface_age)) 65conf.set_quoted('BABL_BINARY_AGE', '@0@'.format(binary_age)) 66conf.set_quoted('BABL_VERSION', '@0@'.format(version)) 67conf.set_quoted('BABL_REAL_VERSION', '@0@'.format(version)) 68conf.set_quoted('BABL_API_VERSION', '@0@'.format(api_version)) 69conf.set_quoted('BABL_RELEASE', '@0@'.format(api_version)) 70conf.set_quoted('BABL_LIBRARY_VERSION', '@0@'.format(lib_version)) 71conf.set_quoted('BABL_CURRENT_MINUS_AGE','@0@'.format(0)) 72conf.set_quoted('BABL_LIBRARY', '@0@'.format(lib_name)) 73 74################################################################################ 75# Host system environment 76 77platform_android = false 78platform_osx = false 79platform_win32 = false 80 81host_cpu_family = host_machine.cpu_family() 82if host_cpu_family == 'x86' 83 have_x86 = true 84 conf.set10('ARCH_X86', true) 85elif host_cpu_family == 'x86_64' 86 have_x86 = true 87 conf.set10('ARCH_X86', true) 88 conf.set10('ARCH_X86_64', true) 89elif host_cpu_family == 'ppc' 90 have_ppc = true 91 conf.set10('ARCH_PPC', true) 92elif host_cpu_family == 'ppc64' 93 have_ppc = true 94 conf.set10('ARCH_PPC', true) 95 conf.set10('ARCH_PPC64', true) 96endif 97 98host_os = host_machine.system() 99message('Host os: ' + host_os) 100 101platform_win32 = (host_os.startswith('mingw') or 102 host_os.startswith('cygwin') or 103 host_os.startswith('windows')) 104 105platform_osx = host_os.startswith('darwin') 106if platform_osx 107 if cc.get_id() != 'clang' 108 error('You should use Clang/Clang++ on OSX.') 109 endif 110endif 111 112platform_android = host_os.contains('android') 113 114path_sep = ( platform_win32 ? ';' : ':' ) 115dirs_sep = ( platform_win32 ? '\\\\' : '/' ) 116if platform_win32 117 lib_ext = '.dll' 118elif platform_osx 119 lib_ext = '.dylib' 120else 121 lib_ext = '.so' 122endif 123 124conf.set('BABL_PATH_SEPARATOR', '\'' + path_sep + '\'', description: 125 'separator between paths in BABL_PATH') 126conf.set_quoted('BABL_DIR_SEPARATOR', dirs_sep, description: 127 'separator between directories in BABL_PATH') 128conf.set_quoted('SHREXT', lib_ext, description: 129 'File extension for shared libraries') 130 131# assume *nix if not android/osx/win32 132platform_unix = not ( 133 platform_android or 134 platform_osx or 135 platform_win32 136) 137 138# Build system environment 139build_os = build_machine.system() 140message('Build os: ' + build_os) 141 142build_platform_win32 = (build_os.startswith('mingw') or 143 build_os.startswith('cygwin') or 144 build_os.startswith('windows')) 145 146# Only try to run compiled programs if native compile or cross-compile 147# and have exe wrapper. If we don't need a wrapper (e.g. 32 bit build in 148# 64-bit environment) then set proprty has_exe_wrapper=true in cross 149# file 150can_run_host_binaries = meson.has_exe_wrapper() 151 152 153################################################################################ 154# Compiler arguments 155 156common_c_flags = [] 157 158if buildtype == 'debugoptimized' or buildtype == 'release' 159 common_c_flags += cc.get_supported_arguments(['-Ofast']) 160endif 161common_c_flags += cc.get_supported_arguments( 162 ['-fno-unsafe-math-optimizations'] 163) 164 165extra_warnings_list = [ 166 '-Wdeclaration-after-statement', 167 '-Winit-self', 168 '-Wmissing-declarations', 169 '-Wmissing-prototypes', 170 '-Wold-style-definition', 171 '-Wpointer-arith', 172] 173common_c_flags += cc.get_supported_arguments(extra_warnings_list) 174 175add_project_arguments(common_c_flags, language: 'c') 176 177# Linker arguments 178if platform_win32 and cc.has_link_argument('-Wl,--no-undefined') 179 no_undefined = '-Wl,--no-undefined' 180else 181 no_undefined = [] 182endif 183 184 185################################################################################ 186# Check for compiler CPU extensions 187 188# intialize these to nothing, so meson doesn't complain on non-x86 189 190have_mmx = false 191have_sse = false 192have_sse2 = false 193have_sse4_1 = false 194have_avx2 = false 195have_f16c = false 196 197sse2_cflags = [] 198f16c_cflags = [] 199sse4_1_cflags = [] 200avx2_cflags = [] 201 202# mmx assembly 203if get_option('enable-mmx') and cc.has_argument('-mmmx') 204 if cc.compiles('asm ("movq 0, %mm0");') 205 message('mmx assembly available') 206 add_project_arguments('-mmmx', language: 'c') 207 conf.set('USE_MMX', 1, description: 208 'Define to 1 if MMX assembly is available.') 209 have_mmx = true 210 211 # sse assembly 212 if get_option('enable-sse') and cc.has_argument('-msse') 213 if cc.compiles('asm ("movntps %xmm0, 0");') 214 add_project_arguments('-msse', language: 'c') 215 message('sse assembly available') 216 conf.set('USE_SSE', 1, description: 217 'Define to 1 if SSE assembly is available.') 218 have_sse = true 219 sse_args = ['-mfpmath=sse'] 220 if platform_win32 221 sse_args += '-mstackrealign' 222 endif 223 224 foreach sse_arg : sse_args 225 if cc.has_argument(sse_arg) 226 add_project_arguments(sse_arg, language: 'c') 227 endif 228 endforeach 229 230 # sse2 assembly 231 if get_option('enable-sse2') and cc.has_argument('-msse2') 232 if cc.compiles('asm ("punpckhwd %xmm0,%xmm1");') 233 message('sse2 assembly available') 234 sse2_cflags = '-msse2' 235 conf.set('USE_SSE2', 1, description: 236 'Define to 1 if sse2 assembly is available.') 237 have_sse2 = true 238 239 # sse4.1 assembly 240 if get_option('enable-sse4_1') and cc.has_argument('-msse4.1') 241 if cc.compiles('asm ("pmovzxbd %xmm0,%xmm1");') 242 message('sse4.1 assembly available') 243 sse4_1_cflags = '-msse4.1' 244 conf.set('USE_SSE4_1', 1, description: 245 'Define to 1 if sse4.1 assembly is available.') 246 have_sse4_1 = true 247 endif 248 249 # avx2 assembly 250 if get_option('enable-avx2') and cc.has_argument('-mavx2') 251 if cc.compiles('asm ("vpgatherdd %ymm0,(%eax,%ymm1,4),%ymm2");') 252 message('avx2 assembly available') 253 avx2_cflags = '-mavx2' 254 conf.set('USE_AVX2', 1, description: 255 'Define to 1 if avx2 assembly is available.') 256 have_avx2 = true 257 endif 258 endif 259 endif 260 endif 261 endif 262 endif 263 if get_option('enable-f16c') and cc.has_argument('-mf16c') 264 if cc.compiles( 265 'asm ("#include <immintrin.h>],' + 266 '[__m128 val = _mm_cvtph_ps ((__m128i)_mm_setzero_ps());' + 267 ' __m128i val2 = _mm_insert_epi64((__m128i)_mm_setzero_ps(),0,0);");' 268 ) 269 message('Can compile half-floating point code (f16c)') 270 f16c_cflags = '-mf16c' 271 conf.set('USE_F16C', 1, description: 272 'Define to 1 if f16c intrinsics are available.') 273 have_f16c = true 274 endif 275 endif 276 endif 277 endif 278endif 279 280################################################################################ 281# Check environment 282 283# Check headers 284check_headers = [ 285 ['HAVE_STDATOMIC_H', 'stdatomic.h'] 286] 287# Don't check for dynamic load on windows 288if not platform_win32 289 check_headers += [ 290 ['HAVE_DLFCN_H', 'dlfcn.h'], 291 ['HAVE_DL_H', 'dl.h'], 292 ] 293endif 294foreach header: check_headers 295 if cc.has_header(header[1]) 296 conf.set(header[0], 1, description: 297 'Define to 1 if the <@0@> header is available'.format(header[1])) 298 endif 299endforeach 300 301 302# Check functions 303# general 304check_functions = [ 305 ['HAVE_GETTIMEOFDAY', 'gettimeofday', '<sys/time.h>'], 306 ['HAVE_RINT', 'rint' , '<math.h>'], 307 ['HAVE_SRANDOM', 'srandom' , '<stdlib.h>'], 308] 309foreach func: check_functions 310 if cc.has_function(func[1], prefix: '#include ' + func[2]) 311 conf.set(func[0], 1, description: 312 'Define to 1 if the @0@() function is available'.format(func[1])) 313 endif 314endforeach 315 316 317# Check for uncommon features 318 319# babl_fish_reference(), create_name() would like this 320if cc.compiles('int main() { static __thread char buf[1024]; }') 321 conf.set('HAVE_TLS', 1, description: 322 'Define to 1 if compiler supports __thread') 323endif 324 325 326################################################################################ 327# Dependencies 328 329math = cc.find_library('m', required: false) 330thread = dependency('threads', required: false) 331if platform_android 332 log = cc.find_library('log', required: false) 333else 334 log = [] 335endif 336if platform_win32 337 dl = [] 338else 339 dl = cc.find_library('dl', required: false) 340endif 341 342 343# gobject introspection 344g_ir = dependency('gobject-introspection-1.0', version: '>=1.32.0', 345 required: false) 346 347# lcms 348if get_option('with-lcms') 349 lcms = dependency('lcms2', version: '>=2.8', required: true) 350 if lcms.found() 351 conf.set('HAVE_LCMS', 1, description: 352 'Define to 1 if liblcms2 is available') 353 endif 354else 355 lcms = declare_dependency() 356endif 357 358# vapigen 359vapigen = dependency('vapigen', version:'>=0.20.0', required: false) 360 361 362################################################################################ 363# Build utilities 364 365# build from git repo 366git_bin = find_program('git', required: false, native: true) 367 368# docs 369env_bin = find_program('env', required: false, native: true) 370rsvg_convert_bin = find_program('rsvg-convert', required: false, 371 native: true) 372w3m_bin = find_program('w3m', required: false, native: true) 373 374 375################################################################################ 376# Build flags 377 378# Docs - don't build by default in cross-build environments 379# can't build if no env binary 380build_docs = true 381if get_option('with-docs') != 'false' and not env_bin.found() 382 build_docs = false 383 warning('env is required to build documentation') 384elif get_option('with-docs') == 'auto' 385 if meson.is_cross_build() 386 build_docs = false 387 message( 388 'configure with -Ddocs=true to cross-build documentation' 389 ) 390 endif 391elif get_option('with-docs') == 'false' 392 build_docs = false 393endif 394 395# Introspection - don't build by default on cross-build environments 396if get_option('enable-gir') == 'auto' 397 build_gir = meson.is_cross_build() ? false : true 398else 399 build_gir = get_option('enable-gir') == 'true' ? true : false 400endif 401if not g_ir.found() 402 build_gir = false 403endif 404 405# Vapi - only build if building introspection 406if build_gir and get_option('enable-vapi') and vapigen.found() 407 build_vapi = true 408else 409 build_vapi = false 410endif 411 412################################################################################ 413# Configuration files 414 415# This should not be made visible in babl_dep due to possible name clash 416# when built as a sub-project. 417rootInclude = include_directories('.') 418 419# config.h 420configure_file( 421 output: 'config.h', 422 configuration: conf 423) 424 425# If git is available, always check if git-version.h should be 426# updated. If git is not available, don't do anything if git-version.h 427# already exists because then we are probably working with a tarball 428# in which case the git-version.h we ship is correct. 429if git_bin.found() and run_command( 430 git_bin, 431 'rev-parse', 432 '--is-inside-work-tree', 433).returncode() == 0 434 git_version_h = vcs_tag( 435 input : 'git-version.h.in', 436 output: 'git-version.h', 437 replace_string: '@BABL_GIT_VERSION@', 438 command: [ git_bin.path(), 'describe', '--always' ], 439 ) 440 441 if not meson.is_subproject() 442 meson.add_dist_script( 443 [ 'ninja', 'git-version.h', ], 444 ) 445 meson.add_dist_script( 446 [ 'sh', '-c', ' '.join( 447 [ 'cp', git_version_h.full_path(), '${MESON_DIST_ROOT}' ] 448 )] 449 ) 450 endif 451else 452 git_version_h = files('git-version.h') 453endif 454 455################################################################################ 456# Global variables 457 458xml_insert_file = files('tools' / 'xml-insert.py') 459authors_file = files('AUTHORS') 460news_file = files('NEWS') 461todo_file = files('TODO') 462export_symbols_file = files('export-symbols') 463gen_babl_map_file = files('gen_babl_map.py') 464 465################################################################################ 466# Subdirs 467 468subdir('babl') 469subdir('extensions') 470subdir('tests') 471subdir('tools') 472if build_docs 473 subdir('docs') 474endif 475 476# Create README file from web page 477if w3m_bin.found() and build_docs 478 custom_target('README', 479 input: index_html, 480 output: 'README', 481 command: [ 482 w3m_bin, 483 '-cols', '72', 484 '-dump', 485 '@INPUT@', 486 ], 487 capture: true, 488 build_by_default: true 489 ) 490endif 491 492 493# pkg-config file 494pkgconfig.generate( 495 babl, 496 filebase: 'babl', 497 name: 'babl', 498 description: 'Pixel encoding and color space conversion engine.', 499 version: meson.project_version(), 500 subdirs: lib_name, 501 uninstalled_variables: [ 502 'babl_path=@0@'.format(babl_extensions_build_dir), 503 'babl_libdir=@0@'.format(babl_library_build_dir), 504 ], 505) 506 507# dependency for wrap builds 508babl_dep = declare_dependency( 509 include_directories: bablInclude, 510 link_with : babl, 511 sources: [ 512 babl_version_h, 513 is_variable('babl_gir') ? babl_gir : [] 514 ], 515 variables: { 516 'babl_path' : babl_extensions_build_dir, 517 'babl_libdir' : babl_library_build_dir, 518 }, 519) 520 521################################################################################ 522# Build summary 523summary( 524 { 525 'prefix': babl_prefix, 526 'libdir': get_option('libdir'), 527 }, section: 'Directories' 528) 529summary( 530 { 531 'BABL docs' : build_docs, 532 'Introspection' : build_gir, 533 'VALA support' : build_vapi, 534 }, section: 'Optional features' 535) 536summary( 537 { 538 'mmx' : have_mmx, 539 'sse' : have_sse, 540 'sse2' : have_sse2, 541 'sse4_1' : have_sse4_1, 542 'avx2' : have_avx2, 543 'f16c (half fp)' : have_f16c, 544 }, section: 'Processor extensions' 545) 546summary( 547 { 548 'lcms' : get_option('with-lcms'), 549 }, section: 'Optional dependencies' 550) 551