mirror of
https://github.com/mesonbuild/meson.git
synced 2026-11-06 05:16:42 +00:00
build|interpreter: Allow Cython to be initialized without explicit C or C++
This allows Cython to be initialized and used without explicitly
enabling C or C++, though only as an implementation detail of Cython.
Attempts to build non-cython C or C++ targets will fail, and an attempt
to use `meson.get_compiler('c')` (or `cpp`) will still result in a
warning that you shouldn't do that.
This fixes an issue where using `cython_langauge=cpp` when a project
doesn't enable it by default can result in an exception, and make cython
easier to use without having to understand the implementation details.
This commit is contained in:
1 parent
4df89cc133
commit
aee7f375b2
7 files changed
+81
-18
No files matched your search
@@ -0,0 +1,4 @@
|
||||
## Cython no longer requires explicitly enabling C or C++
|
||||
|
||||
This only provides these languages as an implementation detail of Cython, so
|
||||
native C/C++ targets cannot be compiled.
|
||||
+28
-10
@@ -1037,7 +1037,19 @@ class BuildTarget(Target):
|
||||
which compiler to use if one hasn't been selected already.
|
||||
"""
|
||||
for lang in self.missing_languages:
|
||||
self.compilers[lang] = self.all_compilers[lang]
|
||||
try:
|
||||
self.compilers[lang] = self.all_compilers[lang]
|
||||
except KeyError:
|
||||
# In the case of cython it's possible that we have an
|
||||
# implementation detail language
|
||||
#
|
||||
# It is intentional not to update self.all_compilers here, since
|
||||
# that is a reference to Interpreter.compilers, which should
|
||||
# only contain the compilers enabled explicilty by the project
|
||||
if self.uses_cython() and lang == self.environment.coredata.get_option_for_target(self, 'cython_language'):
|
||||
self.compilers[lang] = self.environment.coredata.compilers[self.for_machine][lang]
|
||||
else:
|
||||
raise
|
||||
|
||||
# did user override clink_langs for this target?
|
||||
link_langs = (self.link_language, ) if self.link_language else clink_langs
|
||||
@@ -1161,18 +1173,21 @@ class BuildTarget(Target):
|
||||
if 'vala' in self.compilers and 'c' not in self.compilers:
|
||||
self.compilers['c'] = self.all_compilers['c']
|
||||
if 'cython' in self.compilers:
|
||||
# Not great, but we can't ask for the override value from "the system"
|
||||
# because this object is currently being constructed so it is not
|
||||
# yet placed in the data store. Grab it directly from override strings
|
||||
# instead.
|
||||
value = T.cast('T.Optional[Language]', self.get_override('cython_language'))
|
||||
if value is None:
|
||||
key = OptionKey('cython_language', machine=self.for_machine)
|
||||
value = T.cast('T.Optional[Language]', self.environment.coredata.optstore.get_value_for(key))
|
||||
_value = self.environment.coredata.get_option_for_target(self, 'cython_language')
|
||||
assert isinstance(_value, str), 'for mypy'
|
||||
value = T.cast('Language', _value)
|
||||
try:
|
||||
self.compilers[value] = self.all_compilers[value]
|
||||
except KeyError:
|
||||
missing_languages.append(value)
|
||||
# This might be an implementation detail (C or C++)
|
||||
#
|
||||
# It is intentional not to update self.all_compilers here, since
|
||||
# that is a reference to Interpreter.compilers, which should
|
||||
# only contain the compilers enabled explicilty by the project
|
||||
try:
|
||||
self.compilers[value] = self.environment.coredata.compilers[self.for_machine][value]
|
||||
except KeyError:
|
||||
missing_languages.append(value)
|
||||
|
||||
return missing_languages
|
||||
|
||||
@@ -1720,6 +1735,9 @@ class BuildTarget(Target):
|
||||
def uses_fortran(self) -> bool:
|
||||
return 'fortran' in self.compilers
|
||||
|
||||
def uses_cython(self) -> bool:
|
||||
return 'cython' in self.compilers
|
||||
|
||||
def uses_vala(self) -> bool:
|
||||
return 'vala' in self.compilers
|
||||
|
||||
|
||||
@@ -1511,15 +1511,33 @@ class Interpreter(InterpreterBase, HoldableObject):
|
||||
def add_languages_for(self, args: T.List[Language], required: bool, for_machine: MachineChoice) -> bool:
|
||||
langs = set(self.compilers[for_machine])
|
||||
langs.update(args)
|
||||
# We'd really like to add cython's default language here, but it can't
|
||||
# actually be done because the cython compiler hasn't been initialized,
|
||||
# so we can't actually get the option yet. Because we can't know what
|
||||
# compiler to add by default, and we don't want to add unnecessary
|
||||
# compilers we don't add anything for cython here, and instead do it
|
||||
# When the first cython target using a particular language is used.
|
||||
|
||||
# Some languages are added only as implementation details of other
|
||||
# languages. When that happens, we don't want to add those languages to
|
||||
# the project enabled languages, as they are implementation details, not
|
||||
# something the user explicitly asked for, and we don't want to be
|
||||
# forced to keep them forever if the implementation changes.
|
||||
internal: T.Set[Language] = set()
|
||||
|
||||
if 'vala' in langs and 'c' not in langs:
|
||||
FeatureNew.single_use('Adding Vala language without C', '0.59.0', self.subproject, location=self.current_node)
|
||||
args.append('c')
|
||||
|
||||
# We need to initialize the default cython language here, as we need it
|
||||
# for sanity checking. We may need to initialize a different language later
|
||||
# if a target has the `cython_language` overridden. We only want to
|
||||
# initialize a default if cython is a new language, not if it's an
|
||||
# existing one from `self.compilers`.
|
||||
if 'cython' in args:
|
||||
_lang = self.coredata.optstore.get_pending_value(OptionKey('cython_language', None, for_machine), 'c')
|
||||
assert isinstance(_lang, str), 'for mypy'
|
||||
cython_lang = T.cast('Language', _lang)
|
||||
if cython_lang not in langs:
|
||||
FeatureNew.single_use(f'Adding Cython language without {cython_lang}', '1.11',
|
||||
self.subproject, location=self.current_node)
|
||||
args.append(cython_lang)
|
||||
internal.add(cython_lang)
|
||||
|
||||
if 'nasm' in langs:
|
||||
FeatureNew.single_use('Adding NASM language', '0.64.0', self.subproject, location=self.current_node)
|
||||
|
||||
@@ -1564,7 +1582,8 @@ class Interpreter(InterpreterBase, HoldableObject):
|
||||
logger_fun(comp.get_display_language(), 'linker for the', machine_name, 'machine:',
|
||||
mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version)
|
||||
self.build.ensure_static_linker(comp)
|
||||
self.compilers[for_machine][lang] = comp
|
||||
if lang not in internal:
|
||||
self.compilers[for_machine][lang] = comp
|
||||
|
||||
return success
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
project('my project', 'cython', 'cpp',
|
||||
project('my project', 'cython',
|
||||
default_options : ['buildtype=release'])
|
||||
|
||||
py = import('python').find_installation(pure: false)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
int foo(void) { return 0; }
|
||||
@@ -0,0 +1,14 @@
|
||||
project(
|
||||
'cython leaking implementation details',
|
||||
default_options : ['warning_level=3', 'buildtype=release'],
|
||||
)
|
||||
|
||||
if meson.backend() != 'ninja'
|
||||
error('MESON_SKIP_TEST: Ninja backend required')
|
||||
endif
|
||||
|
||||
if not add_languages('cython', required : false)
|
||||
error('MESON_SKIP_TEST: Cython langauge required')
|
||||
endif
|
||||
|
||||
static_library('foo', 'foo.c')
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"stdout": [
|
||||
{
|
||||
"line": "test cases/failing/137 cython using implicit c explicitly/meson.build:14:0: ERROR: No host machine compiler for 'foo.c'"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user