Check that some C code can be compiled and run
(code, extra_preargs=[], extra_postargs=[])
| 16 | |
| 17 | |
| 18 | def compile_test_program(code, extra_preargs=[], extra_postargs=[]): |
| 19 | """Check that some C code can be compiled and run""" |
| 20 | ccompiler = _get_compiler() |
| 21 | |
| 22 | # extra_(pre/post)args can be a callable to make it possible to get its |
| 23 | # value from the compiler |
| 24 | if callable(extra_preargs): |
| 25 | extra_preargs = extra_preargs(ccompiler) |
| 26 | if callable(extra_postargs): |
| 27 | extra_postargs = extra_postargs(ccompiler) |
| 28 | |
| 29 | start_dir = os.path.abspath(".") |
| 30 | |
| 31 | with tempfile.TemporaryDirectory() as tmp_dir: |
| 32 | try: |
| 33 | os.chdir(tmp_dir) |
| 34 | |
| 35 | # Write test program |
| 36 | with open("test_program.c", "w") as f: |
| 37 | f.write(code) |
| 38 | |
| 39 | os.mkdir("objects") |
| 40 | |
| 41 | # Compile, test program |
| 42 | ccompiler.compile( |
| 43 | ["test_program.c"], output_dir="objects", extra_postargs=extra_postargs |
| 44 | ) |
| 45 | |
| 46 | # Link test program |
| 47 | objects = glob.glob(os.path.join("objects", "*" + ccompiler.obj_extension)) |
| 48 | ccompiler.link_executable( |
| 49 | objects, |
| 50 | "test_program", |
| 51 | extra_preargs=extra_preargs, |
| 52 | extra_postargs=extra_postargs, |
| 53 | ) |
| 54 | |
| 55 | if "PYTHON_CROSSENV" not in os.environ: |
| 56 | # Run test program if not cross compiling |
| 57 | # will raise a CalledProcessError if return code was non-zero |
| 58 | output = subprocess.check_output("./test_program") |
| 59 | output = output.decode(sys.stdout.encoding or "utf-8").splitlines() |
| 60 | else: |
| 61 | # Return an empty output if we are cross compiling |
| 62 | # as we cannot run the test_program |
| 63 | output = [] |
| 64 | except Exception: |
| 65 | raise |
| 66 | finally: |
| 67 | os.chdir(start_dir) |
| 68 | |
| 69 | return output, extra_postargs |