File size: 2,640 Bytes
26bead7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
"""Compilation and tests module for the AI Python C Extensions Generator application."""

import os
import subprocess
import sys
from logging import getLogger


_logger = getLogger(__name__)


# Define a function to write outputs to a file with a given filename.
def write_file(data, filename):
    """Write data to a file with the specified filename."""
    with open(filename, "w") as file:
        file.write(data)


# Extension compilation function.
def build_extension():
    """Compile the C extension using 'setup.py' and return the compilation output."""
    # Set default COMSPEC to cmd.exe on Windows to avoid issues with some C compilers.
    if sys.platform == "win32":
        _logger.info('PATCHING COMSPEC FOR WINDOWS COMPILATION COMPATIBILITY...')
        preset_comspec = os.environ.get("COMSPEC")
        os.environ["COMSPEC"] = "C:\\Windows\\System32\\cmd.exe"
    try:
        _logger.info('STARTING COMPILATION PROCESS...')
        compile_cmd = ["python", "setup.py", "build_ext", "--inplace"]
        compile_result = subprocess.run(compile_cmd, env=os.environ,
                                        check=True, text=True, capture_output=True)
    except subprocess.CalledProcessError as ex:
        _logger.error(f"COMPILATION FAILED WITH ERROR:\n{ex.stdout}\n{ex.stderr}")
        raise Exception(f"An error occurred while building:\n{ex.stdout}\n{ex.stderr}")
    finally:
        # Restore original COMSPEC on Windows.
        if sys.platform == "win32":
            _logger.info('RESTORING ORIGINAL COMSPEC...')
            os.environ["COMSPEC"] = preset_comspec
    _logger.info('COMPILATION COMPLETED SUCCESSFULLY.')
    return compile_result.stdout


# Extension compilation function.
def compile_extension(c_code, setup_code, module_name):
    """Build the C extension from the provided codes."""
    try:  # Write the provided codes to their respective files.
        _logger.info('WRITING GENERATED C CODE TO FILE...')
        write_file(c_code, f"{module_name}.c")
        _logger.info('WRITING GENERATED SETUP CODE TO FILE...')
        write_file(setup_code, "setup.py")
    except Exception as ex:
        _logger.error(f"ERROR WHILE WRITING FILES:\n{ex}")
        return f"An error occurred while writing files:\n{ex}"
    try:  # Build the extension and capture the output.
        _logger.info('BUILDING THE EXTENSION...')
        build_output = build_extension()
    except Exception as ex:  # If build fails, return the error message.
        _logger.error(f"ERROR WHILE BUILDING EXTENSION:\n{ex}")
        return str(ex)
    _logger.info('EXTENSION BUILT SUCCESSFULLY.')
    return build_output