-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix CMake import's linker args sorting algorithm mangling -framework arguments #14099
base: master
Are you sure you want to change the base?
Conversation
mesonbuild/dependencies/cmake.py
Outdated
iter = libraries.__iter__() | ||
_libraries = set() | ||
|
||
while True: | ||
try: | ||
next = iter.__next__() | ||
except StopIteration: | ||
break | ||
|
||
# Frameworks '-framework ...' are two arguments that need to stay together | ||
if next == '-framework': | ||
_libraries.add((next, iter.__next__())) | ||
else: | ||
_libraries.add((next,)) | ||
|
||
libraries = [x for xs in sorted(_libraries) for x in xs] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're reaching in to touch "dunder" methods, your' missing something. In this case you want iter(libraries)
and next(iter)
. Of course, there's a hand helper that we could move from cargo/cfg.py
to utils/universal.py
called lookahead, which would simplify things, you'd just do:
_libraries: T.List[T.List[str]] = []
for v1, v2 in mesonlib.lookahead(libraries):
if v1 == '-framework':
_libraries.append([v1])
else:
if v2 is None:
raise MesonException(...)add((v1, ))
_libraries.append([v1, v2])
libraries = ...
I'm pointing this out because there's a potential that -framework
doesn't have the required argument after it, and now there will be an unhandled python exception.
The other thing that concerns me here is that using set()
here is that it may lead to invalid de-duplication of arguments, we run into this from time time that arguments cannot be safely de-duplicated. The sorting itself makes me slightly nervous in fact...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks, iter() and next() are much better. Also handled that extra StopIteration (by throwing a MesonException, the other way would be just to log a warning and add it on its own).
I don't think using lookahead here will improve much, since it still needs to actually consume that second argument; the way you wrote it, after adding the -framework argument plus name, the next run of the loop will get the same framework name argument on its own so it will be handled twice, leading to the same issue again, i.e. effectively
_libraries.append(['-framework', 'Foo'])
_libraries.append(['Foo'])
(also note that my using tuples here instead of lists is intentianal, as lists don't seem to have a defined ordering)
Of course as you say, the alternative here is to do nothing at all, I wanted to keep this as close to doing what it was doing before, just handling this extra case. How is this handled for the normal case, passing a framework to build_target(dependencies: [..])?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you're correct about lookahead returning [(0, 1), (1, 2), (2, 3), (3, None)]
, which isn't what we want.
Lists do have a defined order, the only containers in Python that don't have ordering guarantees are sets(), everything else has a guaranteed order, each item in a list will be in insertion order, and you can index into the list to get elements by index, which requires ordering guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, not defined order, sorry, defined hash:
TypeError: unhashable type: 'list'
f0aa271
to
e46227a
Compare
mesonbuild/dependencies/cmake.py
Outdated
|
||
def sort_link_args(args: T.List[str]) -> T.List[str]: | ||
itr = iter(args) | ||
result = set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to help the type checker out here:
result = set() | |
result: T.Set[T.Union[T.Tuple[str], T.Tuple[str, str]]] = set() |
e46227a
to
80b16db
Compare
80b16db
to
eba0712
Compare
Previous sorting algorithm mangles -framework args. Seems like it was already thought of in resolve_cmake_trace_targets (
meson/mesonbuild/cmake/tracetargets.py
Lines 158 to 161 in c508b26
Previous output:
New output: