glib-mkenums: Support reading @rspfiles for arguments

This is needed on Windows where the argument list can exceed the
maximum command-line length when lots of sources are passed to
glib-mkenums.
This commit is contained in:
Nirbheek Chauhan 2018-11-20 14:25:23 +05:30
parent d4cc0b32fd
commit 17316b2c16
3 changed files with 62 additions and 3 deletions

View File

@ -375,6 +375,15 @@ Write output to FILE instead of stdout.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>@RSPFILE</option></term>
<listitem><para>
When passed as the sole argument, read and parse the actual arguments from
<literal>RSPFILE</literal>. Useful on systems with a low command-line length
limit. For example, Windows has a limit of 8191 characters.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -69,6 +69,29 @@ def print_info(msg):
print_color(msg, color=Color.GREEN, prefix='INFO')
def get_rspfile_args(rspfile):
'''
Response files are useful on Windows where there is a command-line character
limit of 8191 because when passing sources as arguments to glib-mkenums this
limit can be exceeded in large codebases.
There is no specification for response files and each tool that supports it
generally writes them out in slightly different ways, but some sources are:
https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-response-files
https://docs.microsoft.com/en-us/windows/desktop/midl/the-response-file-command
'''
import shlex
if not os.path.isfile(rspfile):
sys.exit('Response file {!r} does not exist'.format(rspfile))
try:
with open(rspfile, 'r') as f:
cmdline = f.read()
except OSError as e:
sys.exit('Response file {!r} could not be read: {}'
.format(rspfile, e.strerror))
return shlex.split(cmdline)
def write_output(output):
global output_stream
print(output, file=output_stream)
@ -326,9 +349,17 @@ parser.add_argument('--output', default=None, dest='output')
parser.add_argument('--version', '-v', default=False, action='store_true', dest='version',
help='Print version information')
parser.add_argument('args', nargs='*',
help='Input files')
help='One or more input files, or a single argument @rspfile_path '
'pointing to a file that contains the actual arguments')
options = parser.parse_args()
# Support reading an rspfile of the form @filename which contains the args
# to be parsed
if len(sys.argv) == 2 and sys.argv[1].startswith('@'):
args = get_rspfile_args(sys.argv[1][1:])
else:
args = sys.argv[1:]
options = parser.parse_args(args)
if options.version:
print(VERSION_STR)

View File

@ -45,6 +45,7 @@ class TestMkenums(unittest.TestCase):
parsing and generation code out into a library and unit test that, and
convert this test to just check command line behaviour.
"""
rspfile = False
def setUp(self):
self.timeout_seconds = 10 # seconds per test
@ -57,12 +58,25 @@ class TestMkenums(unittest.TestCase):
'glib-mkenums')
else:
self.__mkenums = os.path.join('/', 'usr', 'bin', 'glib-mkenums')
print('mkenums:', self.__mkenums)
print('rspfile: {}, mkenums:'.format(self.rspfile), self.__mkenums)
def tearDown(self):
self.tmpdir.cleanup()
def _write_rspfile(self, argv):
import shlex
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name, mode='w',
delete=False) as f:
contents = ' '.join([shlex.quote(arg) for arg in argv])
print('Response file contains:', contents)
f.write(contents)
f.flush()
return f.name
def runMkenums(self, *args):
if self.rspfile:
rspfile = self._write_rspfile(args)
args = ['@' + rspfile]
argv = [self.__mkenums]
argv.extend(args)
print('Running:', argv)
@ -448,5 +462,10 @@ comment: {standard_bottom_comment}
'''.format(**result.subs).strip(), result.out)
class TestRspMkenums(TestMkenums):
'''Run all tests again in @rspfile mode'''
rspfile = True
if __name__ == '__main__':
unittest.main(testRunner=taptestrunner.TAPTestRunner())