mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-21 22:20:48 -06:00
Compiler arguments coming from CC environment variables or multi-element CMAKE_<LANG>_COMPILER variables set by toolchain files were previously not exposed in the file API. Among other possible problems, this caused clients to determine wrong system include paths and built-in preprocessor macros by calling the compiler without these important arguments. This is fixed by adding an optional "commandFragment" attribute to the compiler description in the `toolchains` object, containing these arguments as a command line fragment. This is already the form in which they are internally stored in the CMAKE_<LANG>_COMPILER_ARG1 variable, so all that is required is adding this variable to the set of exported variables, besides some logic to omit it if empty. Issue: #22568
96 lines
3.7 KiB
Python
96 lines
3.7 KiB
Python
from check_index import *
|
|
import os
|
|
|
|
class ExpectedVar(object):
|
|
def __init__(self, name, omitEmpty=False):
|
|
self.name = name
|
|
self.omitEmpty = omitEmpty
|
|
|
|
class ExpectedList(object):
|
|
def __init__(self, name, omitEmpty=False):
|
|
self.name = name
|
|
self.omitEmpty = omitEmpty
|
|
|
|
EXPECTED_TOOLCHAIN = {
|
|
"language": "CXX",
|
|
"compiler": {
|
|
"path": ExpectedVar("CMAKE_CXX_COMPILER"),
|
|
"commandFragment": ExpectedVar("CMAKE_CXX_COMPILER_ARG1", omitEmpty=True),
|
|
"id": ExpectedVar("CMAKE_CXX_COMPILER_ID"),
|
|
"version": ExpectedVar("CMAKE_CXX_COMPILER_VERSION"),
|
|
"target": ExpectedVar("CMAKE_CXX_COMPILER_TARGET"),
|
|
"implicit": {
|
|
"includeDirectories": \
|
|
ExpectedList("CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES"),
|
|
"linkDirectories": \
|
|
ExpectedList("CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES"),
|
|
"linkFrameworkDirectories": \
|
|
ExpectedList(
|
|
"CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"),
|
|
"linkLibraries": \
|
|
ExpectedList("CMAKE_CXX_IMPLICIT_LINK_LIBRARIES"),
|
|
}
|
|
},
|
|
"sourceFileExtensions": \
|
|
ExpectedList("CMAKE_CXX_SOURCE_FILE_EXTENSIONS"),
|
|
}
|
|
|
|
def check_objects(o):
|
|
assert is_list(o)
|
|
assert len(o) == 1
|
|
check_index_object(o[0], "toolchains", 1, 1, check_object_toolchains)
|
|
|
|
def check_object_toolchains(o):
|
|
assert sorted(o.keys()) == ["kind", "toolchains", "version"]
|
|
# The "kind" and "version" members are handled by check_index_object.
|
|
toolchains = o["toolchains"]
|
|
assert is_list(toolchains)
|
|
|
|
# Other platform-specific toolchains may exist (like RC on Windows).
|
|
has_cxx_toolchain = False
|
|
for toolchain in toolchains:
|
|
assert is_dict(toolchain)
|
|
assert "language" in toolchain
|
|
if toolchain["language"] == "CXX":
|
|
check_object_toolchain(toolchain, EXPECTED_TOOLCHAIN)
|
|
has_cxx_toolchain = True
|
|
|
|
assert has_cxx_toolchain
|
|
|
|
def check_object_toolchain(o, expected):
|
|
expected_keys = [
|
|
key for (key, value) in expected.items()
|
|
if is_string(value) or is_dict(value)
|
|
or (type(value) in (ExpectedVar, ExpectedList)
|
|
and variables[value.name]["defined"]
|
|
and not (value.omitEmpty and variables[value.name]["value"] == ''))]
|
|
assert sorted(o.keys()) == sorted(expected_keys), "actual object {!r}, expected keys {!r}".format(o, sorted(expected_keys))
|
|
|
|
for key in expected_keys:
|
|
value = expected[key]
|
|
if is_string(value):
|
|
assert o[key] == value, "{!r}: actual {!r}, expected {!r}".format(key, o[key], value)
|
|
elif is_dict(value):
|
|
check_object_toolchain(o[key], value)
|
|
elif type(value) == ExpectedVar:
|
|
assert o[key] == variables[value.name]["value"], "{!r}: actual {!r}, expected {!r} (from {})".format(key, o[key], variables[value.name]["value"], value.name)
|
|
elif type(value) == ExpectedList:
|
|
expected_items = filter(
|
|
None, variables[value.name]["value"].split(";"))
|
|
check_list_match(lambda a, b: a == b, o[key], expected_items)
|
|
else:
|
|
assert False
|
|
|
|
with open(os.path.join(args.build_dir, "toolchain_variables.json")) as f:
|
|
variables = json.load(f)
|
|
|
|
assert is_dict(variables)
|
|
if variables.get("TOOLCHAINSV1_COMPILERARGS", 0) == 1:
|
|
del EXPECTED_TOOLCHAIN["compiler"]["commandFragment"]
|
|
elif variables.get("TOOLCHAINSV1_COMPILERARGS", 0) == 2:
|
|
EXPECTED_TOOLCHAIN["compiler"]["commandFragment"] = "--hello world --something=other"
|
|
|
|
assert is_dict(index)
|
|
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
|
check_objects(index["objects"])
|