blob: 9d72b0d9b4ab10f059bf77e8d18c0feeff7159f5 [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2012 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Generate a mig server and client pair from migs.def
# Emitting:
# nacl_exc_server.c
# nacl_exc.h
import argparse
import os
import re
import subprocess
import sys
import tempfile
def MkDirs(path):
try:
os.makedirs(path)
except OSError:
pass
def Generate(src_defs, dst_header, dst_server, sdk):
"""Generate interface headers and server from a .defs file using MIG.
Args:
src_defs: Most likely /usr/include/mach/exc.defs.
dst_header: Output generated header for the interface.
dst_server: Output generated server for the interface.
sdk: If not none, the argument to pass to isysroot.
"""
dst_header = os.path.abspath(dst_header)
dst_server = os.path.abspath(dst_server)
# Create directories containing output.
MkDirs(os.path.dirname(dst_header))
MkDirs(os.path.dirname(dst_server))
# Load exc.defs (input)
fh = open(src_defs, 'r')
defs = fh.read()
fh.close()
# Modify exc.defs to isolate its namespace.
# Change the catch_ prefix on each handler to nacl_cach_.
(defs, count) = re.subn('ServerPrefix catch_;',
'ServerPrefix nacl_catch_;', defs)
assert count == 1
# Change the message name from exc to nacl_exc to avoid other collisions.
# (But keep the message id base 2401 the same to match the OS.)
(defs, count) = re.subn('exc 2401;',
'nacl_exc 2401;', defs)
assert count == 1
nacl_exc_defs_path = None
try:
# Write out to a temporary file.
(nacl_exc_defs, nacl_exc_defs_path) = tempfile.mkstemp(
suffix='.defs', prefix='run_mig')
os.write(nacl_exc_defs, defs)
os.close(nacl_exc_defs)
# Run the 'Mach Interface Generator'.
args = ['mig',
'-server', dst_server,
'-user', '/dev/null',
'-header', dst_header]
# If SDKROOT is set to an SDK that Xcode doesn't know about, it might
# interfere with mig's ability to find a valid compiler (via xcrun -sdk ...
# -find cc). Clear out SDKROOT if set to avoid this problem, but pass it to
# mig as its -isysroot argument so that the desired SDK is used.
if 'SDKROOT' in os.environ:
args.append('-isysroot')
args.append(os.environ['SDKROOT'])
del os.environ['SDKROOT']
elif sdk:
args.append('-isysroot')
args.append(sdk)
args.append(nacl_exc_defs_path)
subprocess.check_call(args)
finally:
if nacl_exc_defs_path and os.path.exists(nacl_exc_defs_path):
os.remove(nacl_exc_defs_path)
def Main(args):
parser = argparse.ArgumentParser()
parser.add_argument('--sdk', help='Path to SDK')
parser.add_argument('src_defs')
parser.add_argument('dst_header')
parser.add_argument('dst_server')
parser.add_argument('developer_dir', nargs='?')
parsed = parser.parse_args(args)
if parsed.developer_dir is not None:
os.environ['DEVELOPER_DIR'] = parsed.developer_dir
Generate(args[0], args[1], args[2], parsed.sdk)
if __name__ == '__main__':
Main(sys.argv[1:])