Skip to content
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 an error when using /MANIFEST:NO with VS backend #13054

Merged
merged 2 commits into from
May 1, 2024

Conversation

matyalatte
Copy link
Contributor

Closes #13041

#12472 disabled the EmbedManifest node in .vcxproj.
But it conflicts with the /MANIFEST:NO option, or the GenerateManifest node should be disabled.

This PR make meson set false to GenerateManifest when target.link_args disables the manifest creation with /MANIFEST:NO.

Comment on lines 135 to 137
upper_args = [arg.upper() for arg in target.link_args]
manifest_args = [arg for arg in upper_args if arg == '/MANIFEST' or arg.startswith('/MANIFEST:')]
return len(manifest_args) == 0 or manifest_args[-1] != '/MANIFEST:NO'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSVC command line options are case sensitive. I don't think you need to transform to upper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review but I think it's necessary.
I tried /ManIfesT:NO and got the same error as #13041.
Also, I can see /ManifestFile in linker options that VS adds automatically, though the document says /MANIFESTFILE.
Seems that some options are case-insensitive.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. Options for the compiler are case-sensitive, but options for the link are not. That's weird.

I don't really like the fact that you do 2 list comprehensions, but I understand why you do it. Maybe should the first line be a generative expression instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the test for emptyness should use the bool operator, not the len function.

Suggested change
upper_args = [arg.upper() for arg in target.link_args]
manifest_args = [arg for arg in upper_args if arg == '/MANIFEST' or arg.startswith('/MANIFEST:')]
return len(manifest_args) == 0 or manifest_args[-1] != '/MANIFEST:NO'
upper_args = (arg.upper() for arg in target.link_args)
manifest_args = [arg for arg in upper_args if arg == '/MANIFEST' or arg.startswith('/MANIFEST:')]
return not manifest_args or manifest_args[-1] != '/MANIFEST:NO'

@bruchar1 bruchar1 added the backend:visualstudio Visual Studio project backends label Apr 8, 2024
if isinstance(target, build.BuildTarget):
upper_args = [arg.upper() for arg in target.link_args]
manifest_args = [arg for arg in upper_args if arg == '/MANIFEST' or arg.startswith('/MANIFEST:')]
return len(manifest_args) == 0 or manifest_args[-1] != '/MANIFEST:NO'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does /MANIFEST have to be the last argument, or could there be another argument after that?

Copy link
Contributor Author

@matyalatte matyalatte Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/MANIFEST, /MANIFEST:EMBED, and /MANIFEST:EMBED,ID=xxx can enable the manifest creation.
I got the same error as #12472 when ignoring /MANIFEST:EMBED in the get_gen_manifest function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is that if your link args are:

['/somearg', '/MANIFEST:NO', '/someother-arg']

that this will fail. And (assumine that link.exe is sane):

['/somearg', '/MANIFEST:NO', '/MANIFEST', '/someother-arg']

makes this more complicated. I think we really need to do something like:

for x in reversed(manifest_args):
    if x == '/MANIFEST:NO':
        break
    if x.startswith('/MANIFEST'):
        return False
return True

So that we look at the last occurance of the /MANIFEST argument, and properly handle it being not the last argument in the link_args

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He already filtered non-MANIFEST args in the list comprehension, so I think the proposed code is ok. But I thought about proposing a similar explicit for loop instead of list comprehensions. I think it would be more efficient, because it can stop at the first occurence found.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I missed that somehow. derp.

Yeah, I think I'd prefer a single loop instead of the two comprehensions as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, should it be like this?

# Returns if a target generates a manifest or not.
def get_gen_manifest(target):
    if isinstance(target, build.BuildTarget):
        for arg in reversed(target.link_args):
            arg = arg.upper()
            if arg == '/MANIFEST:NO':
                return False
            if arg == '/MANIFEST' or arg.startswith('/MANIFEST:'):
                break
    return True

if arg.startswith('/MANIFEST'): doesn't work because there are other options that start with /MANIFEST.

@matyalatte
Copy link
Contributor Author

I noticed my code ignores global and project args.
I'd prefer to revert #12472 rather than check linker options...
meson 1.3.2 already supports custom manifests because /MANIFEST:NO can disable the manifest embedding.
As mentioned in #13041, you will get warnings when disabling some manifest options but you can just ignore them and it's the simplest way to fix the issue.

@matyalatte
Copy link
Contributor Author

Replaced the list comprehensions with a for loop.
and fixed a bug that it ignored some linker options e.g. global link arguments.

@bruchar1 bruchar1 added this to the 1.4.1 milestone May 1, 2024
@bruchar1
Copy link
Member

bruchar1 commented May 1, 2024

@dcbaker I think this one is ready

@dcbaker dcbaker merged commit f1f2481 into mesonbuild:master May 1, 2024
33 checks passed
@eli-schwartz
Copy link
Member

Please remember in future that PRs like this should NOT be merged until the fixup commit is squashed into the original commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:visualstudio Visual Studio project backends
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Custom manifest does not work with VS backend
4 participants