Read a response file, and returns the list of cmdline params found in the file. The encoding that the response filename should be read with can be specified as a suffix to the file, e.g. "foo.rsp.utf-8" or "foo.rsp.cp1252". If not specified, first UTF-8 and then Python locale.getpreferredenco
(arg)
| 59 | |
| 60 | |
| 61 | def expand_response_file(arg): |
| 62 | """Read a response file, and returns the list of cmdline params found in the file. |
| 63 | |
| 64 | The encoding that the response filename should be read with can be specified |
| 65 | as a suffix to the file, e.g. "foo.rsp.utf-8" or "foo.rsp.cp1252". If not |
| 66 | specified, first UTF-8 and then Python locale.getpreferredencoding() are |
| 67 | attempted. |
| 68 | |
| 69 | The parameter `arg` is the command line argument to be expanded. |
| 70 | """ |
| 71 | if arg.startswith('@'): |
| 72 | response_filename = arg[1:] |
| 73 | elif arg.startswith('-Wl,@'): |
| 74 | response_filename = arg[5:] |
| 75 | else: |
| 76 | response_filename = None |
| 77 | |
| 78 | # Is the argument is not a response file, or if the file does not exist |
| 79 | # just return original argument. |
| 80 | if not response_filename or not os.path.exists(response_filename): |
| 81 | return [arg] |
| 82 | |
| 83 | # Guess encoding based on the file suffix |
| 84 | components = os.path.basename(response_filename).split('.') |
| 85 | encoding_suffix = components[-1].lower() |
| 86 | if len(components) > 1 and (encoding_suffix.startswith(('utf', 'cp', 'iso')) or encoding_suffix in {'ascii', 'latin-1'}): |
| 87 | guessed_encoding = encoding_suffix |
| 88 | else: |
| 89 | # On windows, recent version of CMake emit rsp files containing |
| 90 | # a BOM. Using 'utf-8-sig' works on files both with and without |
| 91 | # a BOM. |
| 92 | guessed_encoding = 'utf-8-sig' |
| 93 | |
| 94 | try: |
| 95 | # First try with the guessed encoding |
| 96 | with open(response_filename, encoding=guessed_encoding) as f: |
| 97 | args = f.read() |
| 98 | except (ValueError, LookupError): # UnicodeDecodeError is a subclass of ValueError, and Python raises either a ValueError or a UnicodeDecodeError on decode errors. LookupError is raised if guessed encoding is not an encoding. |
| 99 | if DEBUG: |
| 100 | logging.warning(f'failed to parse response file {response_filename} with guessed encoding "{guessed_encoding}". Trying default system encoding...') |
| 101 | # If that fails, try with the Python default locale.getpreferredencoding() |
| 102 | with open(response_filename) as f: # noqa: PLW1514 |
| 103 | args = f.read() |
| 104 | |
| 105 | args = shlex.split(args) |
| 106 | |
| 107 | if DEBUG: |
| 108 | logging.warning(f'read response file {response_filename}: {args}') |
| 109 | |
| 110 | # Response file can be recursive so call substitute_response_files on the arguments |
| 111 | return substitute_response_files(args) |
| 112 | |
| 113 | |
| 114 | def substitute_response_files(args): |
no test coverage detected