forked from OSchip/llvm-project
145 lines
4.5 KiB
Python
145 lines
4.5 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
SWIG generation server. Listens for connections from swig generation clients
|
|
and runs swig in the requested fashion, sending back the results.
|
|
"""
|
|
|
|
# Future imports
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
|
|
# Python modules
|
|
import argparse
|
|
import io
|
|
import logging
|
|
import os
|
|
import select
|
|
import shutil
|
|
import socket
|
|
import struct
|
|
import sys
|
|
import tempfile
|
|
import traceback
|
|
|
|
# LLDB modules
|
|
import use_lldb_suite
|
|
from lldbsuite.support import fs
|
|
from lldbsuite.support import sockutil
|
|
|
|
# package imports
|
|
from . import local
|
|
from . import remote
|
|
|
|
default_port = 8537
|
|
|
|
|
|
def add_subparser_args(parser):
|
|
parser.add_argument(
|
|
"--port",
|
|
action="store",
|
|
default=default_port,
|
|
help=("The local port to bind to"))
|
|
|
|
parser.add_argument(
|
|
"--swig-executable",
|
|
action="store",
|
|
default=fs.find_executable("swig"),
|
|
dest="swig_executable")
|
|
|
|
|
|
def finalize_subparser_options(options):
|
|
pass
|
|
|
|
|
|
def initialize_listening_socket(options):
|
|
logging.debug("Creating socket...")
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
logging.info("Binding to ip address '', port {}".format(options.port))
|
|
s.bind(('', options.port))
|
|
|
|
logging.debug("Putting socket in listen mode...")
|
|
s.listen()
|
|
return s
|
|
|
|
|
|
def accept_once(sock, options):
|
|
logging.debug("Waiting for connection...")
|
|
while True:
|
|
rlist, wlist, xlist = select.select([sock], [], [], 0.5)
|
|
if not rlist:
|
|
continue
|
|
|
|
client, addr = sock.accept()
|
|
logging.info("Received connection from {}".format(addr))
|
|
data_size = struct.unpack("!I", sockutil.recvall(client, 4))[0]
|
|
logging.debug("Expecting {} bytes of data from client"
|
|
.format(data_size))
|
|
data = sockutil.recvall(client, data_size)
|
|
logging.info("Received {} bytes of data from client"
|
|
.format(len(data)))
|
|
|
|
pack_location = None
|
|
try:
|
|
tempfolder = os.path.join(tempfile.gettempdir(), "swig-bot")
|
|
os.makedirs(tempfolder, exist_ok=True)
|
|
|
|
pack_location = tempfile.mkdtemp(dir=tempfolder)
|
|
logging.debug("Extracting archive to {}".format(pack_location))
|
|
|
|
local.unpack_archive(pack_location, data)
|
|
logging.debug("Successfully unpacked archive...")
|
|
|
|
config_file = os.path.normpath(os.path.join(pack_location,
|
|
"config.json"))
|
|
parsed_config = remote.parse_config(io.open(config_file))
|
|
config = local.LocalConfig()
|
|
config.languages = parsed_config["languages"]
|
|
config.swig_executable = options.swig_executable
|
|
config.src_root = pack_location
|
|
config.target_dir = os.path.normpath(
|
|
os.path.join(config.src_root, "output"))
|
|
logging.info(
|
|
"Running swig. languages={}, swig={}, src_root={}, target={}"
|
|
.format(config.languages, config.swig_executable,
|
|
config.src_root, config.target_dir))
|
|
|
|
status = local.generate(config)
|
|
logging.debug("Finished running swig. Packaging up files {}"
|
|
.format(os.listdir(config.target_dir)))
|
|
zip_data = io.BytesIO()
|
|
zip_file = local.pack_archive(zip_data, config.target_dir, None)
|
|
response_status = remote.serialize_response_status(status)
|
|
logging.debug("Sending response status {}".format(response_status))
|
|
logging.info("(swig output) -> swig_output.json")
|
|
zip_file.writestr("swig_output.json", response_status)
|
|
|
|
zip_file.close()
|
|
response_data = zip_data.getvalue()
|
|
logging.info("Sending {} byte response".format(len(response_data)))
|
|
client.sendall(struct.pack("!I", len(response_data)))
|
|
client.sendall(response_data)
|
|
finally:
|
|
if pack_location is not None:
|
|
logging.debug("Removing temporary folder {}"
|
|
.format(pack_location))
|
|
shutil.rmtree(pack_location)
|
|
|
|
|
|
def accept_loop(sock, options):
|
|
while True:
|
|
try:
|
|
accept_once(sock, options)
|
|
except Exception as e:
|
|
error = traceback.format_exc()
|
|
logging.error("An error occurred while processing the connection.")
|
|
logging.error(error)
|
|
|
|
|
|
def run(options):
|
|
print(options)
|
|
sock = initialize_listening_socket(options)
|
|
accept_loop(sock, options)
|
|
return options
|