1project('qt4 and 5 build test', 'cpp', 2 # Qt5 now requires C++ 11 support 3 default_options : ['cpp_std=c++11']) 4 5qt5_modules = ['Widgets'] 6qt6_modules = ['Widgets'] 7foreach qt : ['qt4', 'qt5', 'qt6'] 8 qt_modules = ['Core', 'Gui'] 9 if qt == 'qt5' 10 qt_modules += qt5_modules 11 elif qt == 'qt6' 12 qt_modules += qt6_modules 13 endif 14 15 # Test that invalid modules are indeed not found 16 fakeqtdep = dependency(qt, modules : ['DefinitelyNotFound'], required : false, method : get_option('method')) 17 if fakeqtdep.found() 18 error('Invalid qt dep incorrectly found!') 19 endif 20 21 # Test that partially-invalid modules are indeed not found 22 fakeqtdep = dependency(qt, modules : ['Core', 'DefinitelyNotFound'], required : false, method : get_option('method')) 23 if fakeqtdep.found() 24 error('Invalid qt dep incorrectly found!') 25 endif 26 27 # This test should be skipped if the required version of Qt isn't found 28 # 29 # (In the CI environment, the specified version of Qt is definitely present. 30 # An unexpected skip here is treated as a failure, so we are testing that the 31 # detection mechanism is able to find Qt.) 32 needed_qt = get_option('required').to_lower() 33 required = (qt == needed_qt) 34 if required 35 dep = dependency(qt, modules : ['Core'], required : false, method : get_option('method')) 36 if not dep.found() 37 error('MESON_SKIP_TEST @0@ not found.'.format(needed_qt)) 38 endif 39 endif 40 41 # Ensure that the "no-Core-module-specified" code branch is hit 42 nocoredep = dependency(qt, modules : ['Gui'], required : required, method : get_option('method')) 43 44 # If 'qt' modules are found, test that. 45 qtdep = dependency(qt, modules : qt_modules, main : true, private_headers: true, required : required, method : get_option('method')) 46 if qtdep.found() 47 qtmodule = import(qt) 48 assert(qtmodule.has_tools()) 49 50 # The following has two resource files because having two in one target 51 # requires you to do it properly or you get linker symbol clashes. 52 53 prep = qtmodule.preprocess( 54 moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use. 55 method : get_option('method') 56 ) 57 # XML files that need to be compiled with the uic tol. 58 prep += qtmodule.compile_ui(sources : 'mainWindow.ui', method: get_option('method')) 59 60 qtmodule.preprocess( 61 ui_files : 'mainWindow.ui', 62 method: get_option('method')) 63 64 # Resource file(s) for rcc compiler 65 extra_cpp_args = [] 66 if meson.is_unity() 67 extra_cpp_args += '-DUNITY_BUILD' 68 prep_rcc = qtmodule.preprocess(qt + '_unity_ressource', qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) 69 else 70 prep_rcc = qtmodule.preprocess(qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) 71 endif 72 73 # Test that setting a unique name with a positional argument works 74 qtmodule.compile_resources( 75 name : qt + 'teststuff', 76 sources : files(['stuff.qrc', 'stuff2.qrc']), 77 method : get_option('method') 78 ) 79 80 # Test that passing extra arguments to rcc works 81 # qt4-rcc and qt5-rcc take different arguments, for example qt4: ['-compress', '3']; qt5: '--compress=3' 82 qtmodule.preprocess(qt + 'testrccarg', qresources : files(['stuff.qrc', 'stuff2.qrc']), rcc_extra_arguments : '--compress=3', method : get_option('method')) 83 84 translations_cpp = qtmodule.compile_translations(qresource: qt+'_lang.qrc') 85 # unity builds suck and definitely cannot handle two qrc embeds in one compilation unit 86 unityproof_translations = static_library('unityproof_translations', translations_cpp) 87 88 extra_cpp_args += '-DQT="@0@"'.format(qt) 89 qexe = executable(qt + 'app', 90 sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing. 91 prep, prep_rcc], 92 dependencies : qtdep, 93 link_with: unityproof_translations, 94 cpp_args: extra_cpp_args, 95 gui_app : true) 96 97 # We need a console test application because some test environments 98 # do not have an X server. 99 100 translations = qtmodule.compile_translations(ts_files : qt+'core_fr.ts', build_by_default : true) 101 102 qtcore = dependency(qt, modules : 'Core', method : get_option('method')) 103 104 qtcoreapp = executable(qt + 'core', 'q5core.cpp', 105 cpp_args: '-DQT="@0@"'.format(qt), 106 dependencies : qtcore) 107 108 test(qt + 'test', qtcoreapp) 109 110 # The build system needs to include the cpp files from 111 # headers but the user must manually include moc 112 # files from sources. 113 qtmodule.preprocess( 114 moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` 115 moc_sources : 'manualinclude.cpp', 116 moc_headers : 'manualinclude.h', 117 method : get_option('method')) 118 119 manpreprocessed = qtmodule.compile_moc( 120 extra_args : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` 121 sources : 'manualinclude.cpp', 122 headers : 'manualinclude.h', 123 method : get_option('method')) 124 125 qtmaninclude = executable(qt + 'maninclude', 126 sources : ['manualinclude.cpp', manpreprocessed], 127 dependencies : qtcore) 128 129 test(qt + 'maninclude', qtmaninclude) 130 131 # building Qt plugins implies to give include path to moc 132 plugin_includes = include_directories('pluginInterface', 'plugin') 133 pluginpreprocess = qtmodule.preprocess( 134 moc_headers : 'plugin/plugin.h', 135 include_directories : plugin_includes 136 ) 137 plugin = library(qt + 'plugin', 'plugin/plugin.cpp', pluginpreprocess, 138 include_directories : plugin_includes, 139 dependencies : qtcore) 140 141 # implementing Qt interfaces requires passing Qt include paths to moc 142 qtinterfacepreprocess = qtmodule.preprocess( 143 moc_sources : 'qtinterface.cpp', 144 dependencies : qtdep 145 ) 146 qtinterface = library(qt + 'qtinterface', 147 sources : ['qtinterface.cpp', qtinterfacepreprocess], 148 dependencies : qtdep) 149 150 if qt == 'qt5' 151 subdir('subfolder') 152 endif 153 154 # Check we can apply a version constraint 155 dependency(qt, modules: qt_modules, version: '>=@0@'.format(qtdep.version()), method : get_option('method')) 156 157 endif 158endforeach 159