diff --git a/pylib/gyp/common.py b/pylib/gyp/common.py index fbf1024f..35a64b1e 100644 --- a/pylib/gyp/common.py +++ b/pylib/gyp/common.py @@ -421,8 +421,9 @@ def EnsureDirExists(path): except OSError: pass -def GetCrossCompilerPredefines(): # -> dict +def GetCompilerPredefines(): # -> dict cmd = [] + defines = {} # shlex.split() will eat '\' in posix mode, but # setting posix=False will preserve extra '"' cause CreateProcess fail on Windows @@ -439,7 +440,7 @@ def replace_sep(s): if CXXFLAGS := os.environ.get("CXXFLAGS"): cmd += shlex.split(replace_sep(CXXFLAGS)) else: - return {} + return defines if sys.platform == "win32": fd, input = tempfile.mkstemp(suffix=".c") @@ -450,17 +451,33 @@ def replace_sep(s): real_cmd, shell=True, capture_output=True, check=True ).stdout + except subprocess.CalledProcessError as e: + print( + "Warning: failed to get compiler predefines\n" + "cmd: %s\n" + "status: %d" % (e.cmd, e.returncode), + file=sys.stderr + ) + return defines finally: os.unlink(input) else: input = "/dev/null" real_cmd = [*cmd, "-dM", "-E", "-x", "c", input] - stdout = subprocess.run( - real_cmd, shell=False, - capture_output=True, check=True - ).stdout + try: + stdout = subprocess.run( + real_cmd, shell=False, + capture_output=True, check=True + ).stdout + except subprocess.CalledProcessError as e: + print( + "Warning: failed to get compiler predefines\n" + "cmd: %s\n" + "status: %d" % (e.cmd, e.returncode), + file=sys.stderr + ) + return defines - defines = {} lines = stdout.decode("utf-8").replace("\r\n", "\n").split("\n") for line in lines: if (line or "").startswith("#define "): @@ -499,7 +516,7 @@ def GetFlavor(params): if "flavor" in params: return params["flavor"] - defines = GetCrossCompilerPredefines() + defines = GetCompilerPredefines() if "__EMSCRIPTEN__" in defines: return "emscripten" if "__wasm__" in defines: diff --git a/pylib/gyp/common_test.py b/pylib/gyp/common_test.py index bd7172af..d25e621a 100755 --- a/pylib/gyp/common_test.py +++ b/pylib/gyp/common_test.py @@ -7,6 +7,7 @@ """Unit tests for the common.py file.""" import os +import subprocess import sys import unittest from unittest.mock import MagicMock, patch @@ -85,22 +86,34 @@ def decode(self, encoding): @patch("os.close") @patch("os.unlink") @patch("tempfile.mkstemp") - def test_GetCrossCompilerPredefines(self, mock_mkstemp, mock_unlink, mock_close): + def test_GetCompilerPredefines(self, mock_mkstemp, mock_unlink, mock_close): mock_close.return_value = None mock_unlink.return_value = None mock_mkstemp.return_value = (0, "temp.c") - def mock_run(env, defines_stdout, expected_cmd): + def mock_run(env, defines_stdout, expected_cmd, throws=False): with patch("subprocess.run") as mock_run: - mock_process = MagicMock() - mock_process.returncode = 0 - mock_process.stdout = TestGetFlavor.MockCommunicate(defines_stdout) - mock_run.return_value = mock_process expected_input = "temp.c" if sys.platform == "win32" else "/dev/null" + if throws: + mock_run.side_effect = subprocess.CalledProcessError( + returncode=1, + cmd=[ + *expected_cmd, + "-dM", "-E", "-x", "c", expected_input + ] + ) + else: + mock_process = MagicMock() + mock_process.returncode = 0 + mock_process.stdout = TestGetFlavor.MockCommunicate(defines_stdout) + mock_run.return_value = mock_process with patch.dict(os.environ, env): - defines = gyp.common.GetCrossCompilerPredefines() + try: + defines = gyp.common.GetCompilerPredefines() + except Exception as e: + self.fail(f"GetCompilerPredefines raised an exception: {e}") flavor = gyp.common.GetFlavor({}) - if env.get("CC_target"): + if env.get("CC_target") or env.get("CC"): mock_run.assert_called_with( [ *expected_cmd, @@ -110,6 +123,9 @@ def mock_run(env, defines_stdout, expected_cmd): capture_output=True, check=True) return [defines, flavor] + [defines0, _] = mock_run({ "CC": "cl.exe" }, "", ["cl.exe"], True) + assert defines0 == {} + [defines1, _] = mock_run({}, "", []) assert defines1 == {}