cc.py 3.43 KB
Newer Older
1
"""Util to invoke c++ compilers in the system."""
2
# pylint: disable=invalid-name
3 4 5
from __future__ import absolute_import as _abs
import sys
import subprocess
Hu Shiwen committed
6
import os
7 8

from .._ffi.base import py_str
Hu Shiwen committed
9 10 11
from .util import tempdir


12 13 14 15
def create_shared(output,
                  objects,
                  options=None,
                  cc="g++"):
16 17 18 19
    """Create shared library.

    Parameters
    ----------
20
    output : str
21 22 23 24 25
        The target shared library.

    objects : list
        List of object files.

26 27
    options : list
        The list of additional options string.
28

29
    cc : str, optional
30 31
        The compile string.
    """
Hu Shiwen committed
32 33 34 35 36 37 38 39 40
    if sys.platform == "darwin" or sys.platform.startswith('linux'):
        _linux_shared(output, objects, options, cc)
    elif sys.platform == "win32":
        _windows_shared(output, objects, options)
    else:
        raise ValueError("Unsupported platform")


def _linux_shared(output, objects, options, cc="g++"):
41
    cmd = [cc]
42
    cmd += ["-shared", "-fPIC"]
43 44
    if sys.platform == "darwin":
        cmd += ["-undefined", "dynamic_lookup"]
45 46 47 48 49
    cmd += ["-o", output]
    if isinstance(objects, str):
        cmd += [objects]
    else:
        cmd += objects
50 51 52
    if options:
        cmd += options
    proc = subprocess.Popen(
53
        cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
54
    (out, _) = proc.communicate()
Hu Shiwen committed
55 56
    if proc.returncode != 0:
        msg = "Compilation error:\n"
57
        msg += py_str(out)
Hu Shiwen committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
        raise RuntimeError(msg)


def _windows_shared(output, objects, options):
    cl_cmd = ["cl"]
    cl_cmd += ["-c"]
    if isinstance(objects, str):
        objects = [objects]
    cl_cmd += objects
    if options:
        cl_cmd += options

    temp = tempdir()
    dllmain_path = temp.relpath("dllmain.cc")
    with open(dllmain_path, "w") as dllmain_obj:
        dllmain_obj.write('#include <windows.h>\
BOOL APIENTRY DllMain( HMODULE hModule,\
                       DWORD  ul_reason_for_call,\
                       LPVOID lpReserved)\
{return TRUE;}')

    cl_cmd += [dllmain_path]

    temp_path = dllmain_path.replace("dllmain.cc", "")
    cl_cmd += ["-Fo:" + temp_path]
83 84 85 86 87 88 89
    try:
        proc = subprocess.Popen(
            cl_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        (out, _) = proc.communicate()
    except FileNotFoundError:
        raise RuntimeError("can not found cl.exe,"
                           "please run this in Vistual Studio Command Prompt.")
Hu Shiwen committed
90 91
    if proc.returncode != 0:
        msg = "Compilation error:\n"
92
        msg += py_str(out)
Hu Shiwen committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        raise RuntimeError(msg)
    link_cmd = ["link"]
    link_cmd += ["-dll", "-FORCE:MULTIPLE"]

    for obj in objects:
        if obj.endswith(".cc"):
            (_, temp_file_name) = os.path.split(obj)
            (shot_name, _) = os.path.splitext(temp_file_name)
            link_cmd += [os.path.join(temp_path, shot_name + ".obj")]
        if obj.endswith(".o"):
            link_cmd += [obj]

    link_cmd += ["-EXPORT:__tvm_main__"]
    link_cmd += [temp_path + "dllmain.obj"]
    link_cmd += ["-out:" + output]
108

109 110 111 112 113 114 115
    try:
        proc = subprocess.Popen(
            link_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        (out, _) = proc.communicate()
    except FileNotFoundError:
        raise RuntimeError("can not found link.exe,"
                           "please run this in Vistual Studio Command Prompt.")
116
    if proc.returncode != 0:
117
        msg = "Compilation error:\n"
118
        msg += py_str(out)
Hu Shiwen committed
119

120
        raise RuntimeError(msg)