diff options
-rw-r--r-- | docs/markdown/Syntax.md | 70 | ||||
-rw-r--r-- | docs/markdown/Users.md | 1 | ||||
-rw-r--r-- | mesonbuild/dependencies/boost.py | 93 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 2 | ||||
-rw-r--r-- | mesonbuild/interpreterbase.py | 2 | ||||
-rw-r--r-- | test cases/common/163 disabler/meson.build | 28 | ||||
-rw-r--r-- | test cases/frameworks/1 boost/meson.build | 2 | ||||
-rwxr-xr-x | tools/boost_names.py | 56 |
8 files changed, 195 insertions, 59 deletions
diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index cf0516c..666d50e 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -588,3 +588,73 @@ FAQ](FAQ.md#why-is-meson-not-just-a-python-module-so-i-could-code-my-build-setup because of this limitation you find yourself copying and pasting code a lot you may be able to use a [`foreach` loop instead](#foreach-statements). + +Stability Promises +-- + +Meson is very actively developed and continuously improved. There is a +possibility that future enhancements to the Meson build system will require +changes to the syntax. Such changes might be the addition of new reserved +keywords, changing the meaning of existing keywords or additions around the +basic building blocks like statements and fundamental types. It is planned +to stabilize the syntax with the 1.0 release. + +Grammar +-- + +This is the full Meson grammar, as it is used to parse Meson build definition files: + +``` +additive_expression: multiplicative_expression | (additive_expression additive_operator multiplicative_expression) +additive_operator: "+" | "-" +argument_list: positional_arguments ["," keyword_arguments] | keyword_arguments +array_literal: "[" [expression_list] "]" +assignment_expression: conditional_expression | (logical_or_expression assignment_operator assignment_expression) +assignment_operator: "=" | "*=" | "/=" | "%=" | "+=" | "-=" +boolean_literal: "true" | "false" +build_definition: (NEWLINE | statement)* +condition: expression +conditional_expression: logical_or_expression | (logical_or_expression "?" expression ":" assignment_expression +decimal_literal: DECIMAL_NUMBER +DECIMAL_NUMBER: /[1-9][0-9]*/ +dictionary_literal: "{" [key_value_list] "}" +equality_expression: relational_expression | (equality_expression equality_operator relational_expression) +equality_operator: "==" | "!=" +expression: assignment_expression +expression_list: expression ("," expression)* +expression_statememt: expression +function_expression: id_expression "(" [argument_list] ")" +hex_literal: "0x" HEX_NUMBER +HEX_NUMBER: /[a-fA-F0-9]+/ +id_expression: IDENTIFIER +IDENTIFIER: /[a-zA-Z_][a-zA-Z_0-9]*/ +identifier_list: id_expression ("," id_expression)* +integer_literal: decimal_literal | octal_literal | hex_literal +iteration_statement: "foreach" identifier_list ":" id_expression NEWLINE (statement | jump_statement)* "endforeach" +jump_statement: ("break" | "continue") NEWLINE +key_value_item: expression ":" expression +key_value_list: key_value_item ("," key_value_item)* +keyword_item: id_expression ":" expression +keyword_arguments: keyword_item ("," keyword_item)* +literal: integer_literal | string_literal | boolean_literal | array_literal | dictionary_literal +logical_and_expression: equality_expression | (logical_and_expression "and" equality_expression) +logical_or_expression: logical_and_expression | (logical_or_expression "or" logical_and_expression) +method_expression: postfix_expression "." function_expression +multiplicative_expression: unary_expression | (multiplicative_expression multiplicative_operator unary_expression) +multiplicative_operator: "*" | "/" | "%" +octal_literal: "0o" OCTAL_NUMBER +OCTAL_NUMBER: /[0-7]+/ +positional_arguments: expression ("," expression)* +postfix_expression: primary_expression | subscript_expression | function_expression | method_expression +primary_expression: literal | ("(" expression ")") | id_expression +relational_expression: additive_expression | (relational_expression relational_operator additive_expression) +relational_operator: ">" | "<" | ">=" | "<=" | "in" | ("not" "in") +selection_statement: "if" condition NEWLINE (statement)* ("elif" condition NEWLINE (statement)*)* ["else" (statement)*] "endif" +statement: (expression_statement | selection_statement | iteration_statement) NEWLINE +string_literal: ("'" STRING_SIMPLE_VALUE "'") | ("'''" STRING_MULTILINE_VALUE "'''") +STRING_MULTILINE_VALUE: \.*?(''')\ +STRING_SIMPLE_VALUE: \.*?(?<!\\)(\\\\)*?'\ +subscript_expression: postfix_expression "[" expression "]" +unary_expression: postfix_expression | (unary_operator unary_expression) +unary_operator: "not" | "+" | "-" +``` diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index bfc8a7a..41d8dfa 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -124,6 +124,7 @@ format files - [Terminology](https://github.com/billiob/terminology), a terminal emulator based on the Enlightenment Foundation Libraries - [Tilix](https://github.com/gnunn1/tilix), a tiling terminal emulator for Linux using GTK+ 3 - [Tizonia](https://github.com/tizonia/tizonia-openmax-il), a command-line cloud music player for Linux with support for Spotify, Google Play Music, YouTube, SoundCloud, TuneIn, Plex servers and Chromecast devices + - [Vala Language Server](https://github.com/benwaffle/vala-language-server), code intelligence engine for the Vala and Genie programming languages - [Valum](https://github.com/valum-framework/valum), a micro web framework written in Vala - [Venom](https://github.com/naxuroqa/Venom), a modern Tox client for the GNU/Linux desktop - [VMAF](https://github.com/Netflix/vmaf) (by Netflix), a perceptual video quality assessment based on multi-method fusion diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 13054f5..33408c1 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -665,9 +665,9 @@ boost_arch_map = { #### ---- BEGIN GENERATED ---- #### # # # Generated with tools/boost_names.py: -# - boost version: 1.72.0 -# - modules found: 158 -# - libraries found: 42 +# - boost version: 1.73.0 +# - modules found: 159 +# - libraries found: 43 # class BoostLibrary(): @@ -690,16 +690,16 @@ class BoostModule(): boost_libraries = { 'boost_atomic': BoostLibrary( name='boost_atomic', - shared=[], - static=[], + shared=['-DBOOST_ATOMIC_DYN_LINK=1'], + static=['-DBOOST_ATOMIC_STATIC_LINK=1'], single=[], multi=[], ), 'boost_chrono': BoostLibrary( name='boost_chrono', - shared=['-DBOOST_ALL_DYN_LINK=1'], - static=['-DBOOST_All_STATIC_LINK=1'], - single=[], + shared=['-DBOOST_CHRONO_DYN_LINK=1'], + static=['-DBOOST_CHRONO_STATIC_LINK=1'], + single=['-DBOOST_CHRONO_THREAD_DISABLED'], multi=[], ), 'boost_container': BoostLibrary( @@ -711,28 +711,28 @@ boost_libraries = { ), 'boost_context': BoostLibrary( name='boost_context', - shared=[], + shared=['-DBOOST_CONTEXT_DYN_LINK=1'], static=[], single=[], multi=[], ), 'boost_contract': BoostLibrary( name='boost_contract', - shared=[], - static=[], - single=[], + shared=['-DBOOST_CONTRACT_DYN_LINK'], + static=['-DBOOST_CONTRACT_STATIC_LINK'], + single=['-DBOOST_CONTRACT_DISABLE_THREADS'], multi=[], ), 'boost_coroutine': BoostLibrary( name='boost_coroutine', - shared=[], + shared=['-DBOOST_COROUTINES_DYN_LINK=1'], static=[], single=[], multi=[], ), 'boost_date_time': BoostLibrary( name='boost_date_time', - shared=[], + shared=['-DBOOST_DATE_TIME_DYN_LINK=1'], static=[], single=[], multi=[], @@ -746,14 +746,14 @@ boost_libraries = { ), 'boost_fiber': BoostLibrary( name='boost_fiber', - shared=[], + shared=['-DBOOST_FIBERS_DYN_LINK=1'], static=[], single=[], multi=[], ), 'boost_fiber_numa': BoostLibrary( name='boost_fiber_numa', - shared=[], + shared=['-DBOOST_FIBERS_DYN_LINK=1'], static=[], single=[], multi=[], @@ -767,84 +767,91 @@ boost_libraries = { ), 'boost_graph': BoostLibrary( name='boost_graph', - shared=['-DBOOST_GRAPH_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_iostreams': BoostLibrary( name='boost_iostreams', - shared=['-DBOOST_IOSTREAMS_DYN_LINK=1', '-DBOOST_IOSTREAMS_DYN_LINK=1'], + shared=['-DBOOST_IOSTREAMS_DYN_LINK=1'], static=[], single=[], multi=[], ), 'boost_locale': BoostLibrary( name='boost_locale', - shared=['-DBOOST_LOCALE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_log': BoostLibrary( name='boost_log', - shared=['-DBOOST_LOG_DLL', '-DBOOST_LOG_DYN_LINK=1'], + shared=['-DBOOST_LOG_DYN_LINK=1'], static=[], - single=['BOOST_LOG_NO_THREADS'], + single=['-DBOOST_LOG_NO_THREADS'], multi=[], ), 'boost_log_setup': BoostLibrary( name='boost_log_setup', - shared=['-DBOOST_LOG_DYN_LINK=1', '-DBOOST_LOG_SETUP_DLL', '-DBOOST_LOG_SETUP_DYN_LINK=1'], + shared=['-DBOOST_LOG_SETUP_DYN_LINK=1'], static=[], - single=['BOOST_LOG_NO_THREADS'], + single=['-DBOOST_LOG_NO_THREADS'], multi=[], ), 'boost_math_c99': BoostLibrary( name='boost_math_c99', - shared=['-DBOOST_MATH_TR1_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_math_c99f': BoostLibrary( name='boost_math_c99f', - shared=['-DBOOST_MATH_TR1_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_math_c99l': BoostLibrary( name='boost_math_c99l', - shared=['-DBOOST_MATH_TR1_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_math_tr1': BoostLibrary( name='boost_math_tr1', - shared=['-DBOOST_MATH_TR1_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_math_tr1f': BoostLibrary( name='boost_math_tr1f', - shared=['-DBOOST_MATH_TR1_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_math_tr1l': BoostLibrary( name='boost_math_tr1l', - shared=['-DBOOST_MATH_TR1_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_mpi': BoostLibrary( name='boost_mpi', - shared=['-DBOOST_MPI_DYN_LINK=1'], + shared=[], + static=[], + single=[], + multi=[], + ), + 'boost_nowide': BoostLibrary( + name='boost_nowide', + shared=['-DBOOST_NOWIDE_DYN_LINK=1'], static=[], single=[], multi=[], @@ -865,63 +872,63 @@ boost_libraries = { ), 'boost_random': BoostLibrary( name='boost_random', - shared=[], + shared=['-DBOOST_RANDOM_DYN_LINK'], static=[], single=[], multi=[], ), 'boost_regex': BoostLibrary( name='boost_regex', - shared=['-DBOOST_REGEX_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_serialization': BoostLibrary( name='boost_serialization', - shared=['-DBOOST_SERIALIZATION_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_stacktrace_addr2line': BoostLibrary( name='boost_stacktrace_addr2line', - shared=['-DBOOST_STACKTRACE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_stacktrace_backtrace': BoostLibrary( name='boost_stacktrace_backtrace', - shared=['-DBOOST_STACKTRACE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_stacktrace_basic': BoostLibrary( name='boost_stacktrace_basic', - shared=['-DBOOST_STACKTRACE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_stacktrace_noop': BoostLibrary( name='boost_stacktrace_noop', - shared=['-DBOOST_STACKTRACE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_stacktrace_windbg': BoostLibrary( name='boost_stacktrace_windbg', - shared=['-DBOOST_STACKTRACE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], ), 'boost_stacktrace_windbg_cached': BoostLibrary( name='boost_stacktrace_windbg_cached', - shared=['-DBOOST_STACKTRACE_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], @@ -942,8 +949,8 @@ boost_libraries = { ), 'boost_thread': BoostLibrary( name='boost_thread', - shared=['-DBOOST_THREAD_USE_DLL=1'], - static=['-DBOOST_THREAD_USE_LIB=1'], + shared=['-DBOOST_THREAD_BUILD_DLL=1', '-DBOOST_THREAD_USE_DLL=1'], + static=['-DBOOST_THREAD_BUILD_LIB=1', '-DBOOST_THREAD_USE_LIB=1'], single=[], multi=[], ), @@ -956,7 +963,7 @@ boost_libraries = { ), 'boost_type_erasure': BoostLibrary( name='boost_type_erasure', - shared=[], + shared=['-DBOOST_TYPE_ERASURE_DYN_LINK'], static=[], single=[], multi=[], @@ -977,7 +984,7 @@ boost_libraries = { ), 'boost_wserialization': BoostLibrary( name='boost_wserialization', - shared=['-DBOOST_SERIALIZATION_DYN_LINK=1'], + shared=[], static=[], single=[], multi=[], diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index dd1e57b..441f3c4 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -4661,6 +4661,8 @@ This will become a hard error in the future.''', location=self.current_node) if len(args) < 1 or len(args) > 2: raise InvalidCode('Get_variable takes one or two arguments.') varname = args[0] + if isinstance(varname, Disabler): + return varname if not isinstance(varname, str): raise InterpreterException('First argument must be a string.') try: diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 1a7aa38..6246a06 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -819,7 +819,7 @@ The result of this is undefined and will become a hard error in a future Meson r def function_call(self, node: mparser.FunctionNode) -> T.Optional[TYPE_var]: func_name = node.func_name (posargs, kwargs) = self.reduce_arguments(node.args) - if is_disabled(posargs, kwargs) and func_name != 'set_variable' and func_name != 'is_disabler': + if is_disabled(posargs, kwargs) and func_name not in {'get_variable', 'set_variable', 'is_disabler'}: return Disabler() if func_name in self.funcs: func = self.funcs[func_name] diff --git a/test cases/common/163 disabler/meson.build b/test cases/common/163 disabler/meson.build index 5554f14..d132e2b 100644 --- a/test cases/common/163 disabler/meson.build +++ b/test cases/common/163 disabler/meson.build @@ -9,6 +9,7 @@ d2 = dependency(d) d3 = (d == d2) d4 = d + 0 d5 = d2 or true +set_variable('d6', disabler()) has_not_changed = false if is_disabler(d) @@ -23,12 +24,14 @@ assert(is_disabler(d2), 'Function laundered disabler was not identified correctl assert(is_disabler(d3), 'Disabler comparison should yield disabler.') assert(is_disabler(d4), 'Disabler addition should yield disabler.') assert(is_disabler(d5), 'Disabler logic op should yield disabler.') +assert(is_disabler(d6), 'set_variable with a disabler should set variable to disabler.') assert(d, 'Disabler did not cause this to be skipped.') assert(d2, 'Function laundered disabler did not cause this to be skipped.') assert(d3, 'Disabler comparison should yield disabler and thus this would not be called.') assert(d4, 'Disabler addition should yield disabler and thus this would not be called.') assert(d5, 'Disabler logic op should yield disabler and thus this would not be called.') +assert(d6, 'set_variable with a disabler did not cause this to be skipped.') number = 0 @@ -80,6 +83,31 @@ else endif assert(has_not_changed, 'App has changed.') +assert(not is_disabler(is_variable('d6')), 'is_variable should not return a disabler') +assert(is_variable('d6'), 'is_variable for a disabler should return true') + +if_is_not_disabled = false +if is_variable('d6') + if_is_not_disabled = true +else + if_is_not_disabled = true +endif +assert(if_is_not_disabled, 'Disabler in is_variable should not skip blocks') + +get_d = get_variable('d6') +assert(is_disabler(get_d), 'get_variable should yield a disabler') + +get_fallback_d = get_variable('nonexistant', disabler()) +assert(is_disabler(get_fallback_d), 'get_variable fallback should yield a disabler') + +var_true = true +get_no_fallback_d = get_variable('var_true', disabler()) +assert(not is_disabler(get_no_fallback_d), 'get_variable should not fallback to disabler') +assert(get_no_fallback_d, 'get_variable should yield true') + +assert(is_disabler(get_variable(disabler())), 'get_variable should yield a disabler') +assert(is_disabler(get_variable(disabler(), var_true)), 'get_variable should yield a disabler') + if_is_disabled = true if disabler() if_is_disabled = false diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index 501ed29..6c23360 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -13,7 +13,7 @@ endif # within one project. The need to be independent of each other. # Use one without a library dependency and one with it. -linkdep = dependency('boost', static: s, modules : ['thread', 'system']) +linkdep = dependency('boost', static: s, modules : ['thread', 'system', 'date_time']) testdep = dependency('boost', static: s, modules : ['unit_test_framework']) nomoddep = dependency('boost', static: s) extralibdep = dependency('boost', static: s, modules : ['thread', 'system', 'date_time', 'log_setup', 'log', 'filesystem', 'regex']) diff --git a/tools/boost_names.py b/tools/boost_names.py index d26d34b..b66c6cc 100755 --- a/tools/boost_names.py +++ b/tools/boost_names.py @@ -43,10 +43,10 @@ export_modules = False class BoostLibrary(): def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]): self.name = name - self.shared = shared - self.static = static - self.single = single - self.multi = multi + self.shared = sorted(set(shared)) + self.static = sorted(set(static)) + self.single = sorted(set(single)) + self.multi = sorted(set(multi)) def __lt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']: if isinstance(other, BoostLibrary): @@ -99,15 +99,35 @@ def get_libraries(jamfile: Path) -> T.List[BoostLibrary]: cmds = raw.split(';') # Commands always terminate with a ; (I hope) cmds = [x.strip() for x in cmds] # Some cleanup + project_usage_requirements: T.List[str] = [] + # "Parse" the relevant sections for i in cmds: parts = i.split(' ') - parts = [x for x in parts if x not in ['', ':']] + parts = [x for x in parts if x not in ['']] if not parts: continue - # Parese libraries - if parts[0] in ['lib', 'boost-lib']: + # Parse project + if parts[0] in ['project']: + attributes: T.Dict[str, T.List[str]] = {} + curr: T.Optional[str] = None + + for j in parts: + if j == ':': + curr = None + elif curr is None: + curr = j + else: + if curr not in attributes: + attributes[curr] = [] + attributes[curr] += [j] + + if 'usage-requirements' in attributes: + project_usage_requirements = attributes['usage-requirements'] + + # Parse libraries + elif parts[0] in ['lib', 'boost-lib']: assert len(parts) >= 2 # Get and check the library name @@ -117,28 +137,36 @@ def get_libraries(jamfile: Path) -> T.List[BoostLibrary]: if not lname.startswith('boost_'): continue + # Count `:` to only select the 'usage-requirements' + # See https://boostorg.github.io/build/manual/master/index.html#bbv2.main-target-rule-syntax + colon_counter = 0 + usage_requirements: T.List[str] = [] + for j in parts: + if j == ':': + colon_counter += 1 + elif colon_counter >= 4: + usage_requirements += [j] + # Get shared / static defines shared: T.List[str] = [] static: T.List[str] = [] single: T.List[str] = [] multi: T.List[str] = [] - for j in parts: + for j in usage_requirements + project_usage_requirements: m1 = re.match(r'<link>shared:<define>(.*)', j) m2 = re.match(r'<link>static:<define>(.*)', j) m3 = re.match(r'<threading>single:<define>(.*)', j) m4 = re.match(r'<threading>multi:<define>(.*)', j) if m1: - shared += [m1.group(1)] + shared += [f'-D{m1.group(1)}'] if m2: - static += [m2.group(1)] + static += [f'-D{m2.group(1)}'] if m3: - single += [m3.group(1)] + single +=[f'-D{m3.group(1)}'] if m4: - multi += [m4.group(1)] + multi += [f'-D{m4.group(1)}'] - shared = [f'-D{x}' for x in shared] - static = [f'-D{x}' for x in static] libs += [BoostLibrary(lname, shared, static, single, multi)] return libs |