nasm: use the correct flag for response file support, try 2

This commit reenables and implements correct response file support for
Nasm.

Fortified with the knowledge of #15867 and #15872, and with a quick chat
with @nirbheek, I realised that the easiest way to fix this (since Ninja
does not support custom argument spacing) is to do it the obvious way,
with Meson's custom command support.

This commit implements an abridged version of that: when a non-standard
RspFileSyntax value is detected, the active NinjaBuildRule is temporarily
resolved to the corresponding NinjaRule on the fly and if the latter says
that a response file will be used, the NinjaBuildRule is immediately
converted into a CUSTOM_COMMAND, completing the arguments with
the bits for infile and outfile and triggering the executable
serialization. That serializes the response file and pickles the command.

Fixes building mpv with MSVC 2022+ and fdk-aac enabled.
This commit is contained in:
L. E. Segovia
2026-06-05 00:33:56 -03:00
committed by Paolo Bonzini
parent d23570a90b
commit 739e86f3e4
4 changed files with 40 additions and 12 deletions

View File

@@ -549,10 +549,11 @@ class Backend:
feed: T.Optional[str] = None,
env: T.Optional[mesonlib.EnvironmentVariables] = None,
can_use_rsp_file: bool = False,
separator: str = ' ',
rsp_file_flag: str = '@',
tag: T.Optional[str] = None,
verbose: bool = False,
installdir_map: T.Optional[T.Dict[str, str]] = None) -> 'ExecutableSerialisation':
# XXX: cmd_args either need to be lowered to strings, or need to be checked for non-string arguments, right?
exe, *raw_cmd_args = cmd
if isinstance(exe, build.LocalProgram):
@@ -618,14 +619,14 @@ class Backend:
if needs_rsp_file:
hasher = hashlib.sha1()
args = ' '.join(mesonlib.quote_arg(arg) for arg in cmd_args)
args = separator.join(mesonlib.quote_arg(arg) for arg in cmd_args)
hasher.update(args.encode(encoding='utf-8', errors='ignore'))
digest = hasher.hexdigest()
scratch_file = f'meson_rsp_{digest}.rsp'
rsp_file = os.path.join(self.environment.get_scratch_dir(), scratch_file)
with open(rsp_file, 'w', encoding='utf-8', newline='\n') as f:
f.write(args)
cmd_args = [f'@{rsp_file}']
cmd_args = [f'{rsp_file_flag}{rsp_file}']
return ExecutableSerialisation(exe_cmd + cmd_args, env,
exe_wrapper, workdir,
@@ -640,6 +641,8 @@ class Backend:
force_serialize: bool = False,
env: T.Optional[mesonlib.EnvironmentVariables] = None,
can_use_rsp_file: bool = False,
separator: str = ' ',
rsp_file_flag: str = '@',
verbose: bool = False) -> T.Tuple[T.List[str], str]:
'''
Serialize an executable for running with a generator or a custom target
@@ -647,7 +650,7 @@ class Backend:
cmd: T.List[build.CommandTypes] = []
cmd.append(exe)
cmd.extend(cmd_args)
es = self.get_executable_serialisation(cmd, workdir, extra_bdeps, capture, feed, env, can_use_rsp_file, verbose=verbose)
es = self.get_executable_serialisation(cmd, workdir, extra_bdeps, capture, feed, env, can_use_rsp_file, separator=separator, rsp_file_flag=rsp_file_flag, verbose=verbose)
reasons: T.List[str] = []
if es.extra_paths:
reasons.append('to set PATH')
@@ -664,6 +667,9 @@ class Backend:
if env and env.varnames:
reasons.append('to set env')
if separator != ' ':
reasons.append('to use a custom argument separator')
# force_serialize passed to this function means that the VS backend has
# decided it absolutely cannot use real commands. This is "always",
# because it's not clear what will work (other than compilers) and so
@@ -673,7 +679,7 @@ class Backend:
# It's also overridden for a few conditions that can't be handled
# inside a command line
can_use_env = env.can_use_env and not force_serialize
can_use_env = env and env.can_use_env and not force_serialize
force_serialize = force_serialize or bool(reasons)
if capture:
@@ -687,7 +693,7 @@ class Backend:
envlist.append(f'{k}={v}')
return ['env'] + envlist + es.cmd_args, ', '.join(reasons)
if any(a.startswith('@') for a in es.cmd_args):
if can_use_rsp_file and any(a.startswith(rsp_file_flag) for a in es.cmd_args):
reasons.append('because command is too long')
if not force_serialize:

View File

@@ -365,6 +365,9 @@ class NinjaBuildElement:
if self.rulename == 'phony':
return False
if not self.rule:
raise MesonBugException(f"build statement for {self.outfilenames} references unmapped rule {self.rulename}")
return self.rule.should_use_rspfile(self)
def count_rule_references(self) -> None:
@@ -3370,7 +3373,27 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
result += c
return result
element.add_item('CUDA_ESCAPED_TARGET', quote_make_target(rel_obj))
element.add_item('ARGS', commands)
if self.ninja.should_use_rspfile(element) and compiler.rsp_file_syntax() == RSPFileSyntax.NASM:
exe = compiler.get_exelist()
# Add to commands the args created by generate_compile_rule_for().
# commands remain separate from exelist because they must stay
# a CompilerArgs.
if dep_file:
commands += compiler.get_dependency_gen_args(rel_obj, dep_file)
commands += [*compiler.get_output_args(rel_obj), *compiler.get_compile_only_args(), rel_src]
element.rulename = 'CUSTOM_COMMAND'
meson_exe_cmd, reason = self.as_meson_exe_cmdline(exe[0],
exe[1:] + commands.to_native(),
separator='\n',
rsp_file_flag='-@',
can_use_rsp_file=True,
verbose=True)
cmd_type = f' (wrapped by meson {reason})' if reason else ''
element.add_item('COMMAND', meson_exe_cmd)
element.add_item('description', f'Compiling {compiler.get_display_language()} object {rel_obj}{cmd_type}')
else:
element.add_item('ARGS', commands)
self.add_dependency_scanner_entries_to_element(target, compiler, element, src)
self.add_build(element)

View File

@@ -6,6 +6,7 @@ import typing as T
from ..mesonlib import EnvironmentException, get_meson_command
from ..options import OptionKey
from .compilers import Compiler
from ..linkers import RSPFileSyntax
from ..linkers.linkers import VisualStudioLikeLinkerMixin
from .mixins.metrowerks import MetrowerksCompiler, mwasmarm_instruction_set_args, mwasmeppc_instruction_set_args
from .mixins.ti import TICompiler
@@ -159,11 +160,8 @@ class NasmCompiler(ASMCompiler):
return []
return self.crt_args[self.get_crt_val(crt_val)]
def can_linker_accept_rsp(self) -> bool:
"""
Determines whether the linker can accept arguments using the @rsp syntax.
"""
return False
def rsp_file_syntax(self) -> RSPFileSyntax:
return RSPFileSyntax.NASM
class YasmCompiler(NasmCompiler):
id = 'yasm'

View File

@@ -19,6 +19,7 @@ class RSPFileSyntax(enum.Enum):
MSVC = enum.auto()
GCC = enum.auto()
TASKING = enum.auto()
NASM = enum.auto()
class ArLikeLinker: