mirror of
https://github.com/Nuitka/Nuitka.git
synced 2025-12-14 20:35:49 +01:00
Scons: Make zig work for Windows too (WIP)
* Need to consider if using mingw, clang, or zig more carefully. * With this standalone and onefile mode are working. * Also added control over zig cache file locations to be below Nuitka's cache directory.
This commit is contained in:
@@ -34,6 +34,7 @@ def _cleanCacheDirectory(cache_name, cache_dir):
|
||||
def cleanCaches():
|
||||
_cleanCacheDirectory("ccache", getCacheDir("ccache"))
|
||||
_cleanCacheDirectory("clcache", getCacheDir("clcache"))
|
||||
_cleanCacheDirectory("zig", getCacheDir("zig"))
|
||||
_cleanCacheDirectory("bytecode", getBytecodeCacheDir())
|
||||
_cleanCacheDirectory("dll-dependencies", getCacheDir("library_dependencies"))
|
||||
|
||||
|
||||
@@ -2086,7 +2086,7 @@ def getMsvcVersion():
|
||||
def shallCleanCache(cache_name):
|
||||
""":returns: bool derived from ``--clean-cache``"""
|
||||
|
||||
if cache_name == "clcache":
|
||||
if cache_name in ("clcache", "zig"):
|
||||
cache_name = "ccache"
|
||||
|
||||
return "all" in options.clean_caches or cache_name in options.clean_caches
|
||||
|
||||
@@ -89,7 +89,6 @@ from .SconsUtils import (
|
||||
isGccName,
|
||||
isZigName,
|
||||
makeResultPathFileSystemEncodable,
|
||||
prepareEnvironment,
|
||||
provideStaticSourceFile,
|
||||
raiseNoCompilerFoundErrorExit,
|
||||
scanSourceDir,
|
||||
@@ -284,9 +283,6 @@ enableSconsProgressBar(progress_bar)
|
||||
# Amount of jobs to use.
|
||||
job_count = GetOption("num_jobs")
|
||||
|
||||
# Prepare environment for compiler detection.
|
||||
mingw_mode = prepareEnvironment(mingw_mode=mingw_mode)
|
||||
|
||||
# Patch the compiler detection.
|
||||
Environment.Detect = getEnhancedToolDetect()
|
||||
|
||||
@@ -360,8 +356,8 @@ env.zig_mode = isZigName(env.the_cc_name)
|
||||
|
||||
|
||||
# Only use MSVC if not already clear, we are using MinGW.
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode and not env.zig_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode and not env.zig_mode
|
||||
env.clangcl_mode = clangcl_mode
|
||||
|
||||
# For Python3.13, we need to enforce it for now to use MSVC
|
||||
@@ -854,7 +850,7 @@ if env.module_mode and python_sysflag_verbose:
|
||||
# Hack to make Scons use tempfile for gcc linking, to avoid line length limits,
|
||||
# which can make linking fail with many modules otherwise. Most needed on Windows,
|
||||
# but useful on other platforms too.
|
||||
if env.gcc_mode:
|
||||
if env.gcc_mode and (not env.clang_mode or env.zig_mode):
|
||||
makeGccUseLinkerFile(
|
||||
env=env,
|
||||
source_files=source_files,
|
||||
|
||||
@@ -60,7 +60,6 @@ from .SconsUtils import (
|
||||
isClangName,
|
||||
isGccName,
|
||||
isZigName,
|
||||
prepareEnvironment,
|
||||
setArguments,
|
||||
)
|
||||
|
||||
@@ -143,28 +142,6 @@ cf_protection = getArgumentDefaulted("cf_protection", "auto")
|
||||
# Amount of jobs to use.
|
||||
job_count = GetOption("num_jobs")
|
||||
|
||||
# Prepare environment for compiler detection.
|
||||
mingw_mode = prepareEnvironment(mingw_mode=mingw_mode)
|
||||
|
||||
# TODO: Merge to prepareEnvironment as well.
|
||||
if "CXX" in os.environ:
|
||||
os.environ["CXX"] = os.path.normpath(os.environ["CXX"])
|
||||
|
||||
if os.path.isdir(os.environ["CXX"]):
|
||||
sys.exit("Error, the CXX variable must point to file, not directory.")
|
||||
|
||||
cxx_dirname = os.path.dirname(os.environ["CXX"])
|
||||
|
||||
if os.name == "nt" and isGccName(os.path.basename(os.environ["CXX"])):
|
||||
if show_scons_mode:
|
||||
my_print("Scons: Environment CXX seems to be a gcc, enable mingw_mode.")
|
||||
mingw_mode = True
|
||||
|
||||
if os.path.isdir(cxx_dirname):
|
||||
os.environ["PATH"] = os.pathsep.join(
|
||||
[cxx_dirname] + os.environ["PATH"].split(os.pathsep)
|
||||
)
|
||||
|
||||
# Patch the compiler detection.
|
||||
Environment.Detect = getEnhancedToolDetect()
|
||||
|
||||
@@ -234,8 +211,8 @@ env.clang_mode = clang_mode
|
||||
env.zig_mode = isZigName(env.the_cc_name)
|
||||
|
||||
# Only use MSVC if not already clear, we are using MinGW.
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode and not env.zig_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode and not env.zig_mode
|
||||
env.clangcl_mode = clangcl_mode
|
||||
|
||||
# gcc compiler cf_protection option
|
||||
|
||||
@@ -75,7 +75,6 @@ from .SconsUtils import (
|
||||
isGccName,
|
||||
isZigName,
|
||||
makeResultPathFileSystemEncodable,
|
||||
prepareEnvironment,
|
||||
provideStaticSourceFile,
|
||||
raiseNoCompilerFoundErrorExit,
|
||||
setArguments,
|
||||
@@ -175,9 +174,6 @@ enableSconsProgressBar(progress_bar)
|
||||
# Amount of jobs to use.
|
||||
job_count = GetOption("num_jobs")
|
||||
|
||||
# Prepare environment for compiler detection.
|
||||
mingw_mode = prepareEnvironment(mingw_mode=mingw_mode)
|
||||
|
||||
# Patch the compiler detection.
|
||||
Environment.Detect = getEnhancedToolDetect()
|
||||
|
||||
@@ -249,8 +245,8 @@ env.clang_mode = clang_mode
|
||||
env.zig_mode = isZigName(env.the_cc_name)
|
||||
|
||||
# Only use MSVC if not already clear, we are using MinGW.
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode and not env.zig_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode and not env.zig_mode
|
||||
env.clangcl_mode = clangcl_mode
|
||||
|
||||
# For Python3.13, we need to enforce it for now to use MSVC
|
||||
|
||||
@@ -69,7 +69,6 @@ from .SconsUtils import (
|
||||
isClangName,
|
||||
isGccName,
|
||||
isZigName,
|
||||
prepareEnvironment,
|
||||
provideStaticSourceFile,
|
||||
raiseNoCompilerFoundErrorExit,
|
||||
scanSourceDir,
|
||||
@@ -203,28 +202,6 @@ enableSconsProgressBar(progress_bar)
|
||||
# Amount of jobs to use.
|
||||
job_count = GetOption("num_jobs")
|
||||
|
||||
# Prepare environment for compiler detection.
|
||||
mingw_mode = prepareEnvironment(mingw_mode=mingw_mode)
|
||||
|
||||
# TODO: Merge to prepareEnvironment as well.
|
||||
if "CXX" in os.environ:
|
||||
os.environ["CXX"] = os.path.normpath(os.environ["CXX"])
|
||||
|
||||
if os.path.isdir(os.environ["CXX"]):
|
||||
sys.exit("Error, the CXX variable must point to file, not directory.")
|
||||
|
||||
cxx_dirname = os.path.dirname(os.environ["CXX"])
|
||||
|
||||
if os.name == "nt" and isGccName(os.path.basename(os.environ["CXX"])):
|
||||
if show_scons_mode:
|
||||
my_print("Scons: Environment CXX seems to be a gcc, enable mingw_mode.")
|
||||
mingw_mode = True
|
||||
|
||||
if os.path.isdir(cxx_dirname):
|
||||
os.environ["PATH"] = os.pathsep.join(
|
||||
[cxx_dirname] + os.environ["PATH"].split(os.pathsep)
|
||||
)
|
||||
|
||||
# Patch the compiler detection.
|
||||
Environment.Detect = getEnhancedToolDetect()
|
||||
|
||||
@@ -295,8 +272,8 @@ env.clang_mode = clang_mode
|
||||
env.zig_mode = isZigName(env.the_cc_name)
|
||||
|
||||
# Only use MSVC if not already clear, we are using MinGW.
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode
|
||||
env.msvc_mode = os.name == "nt" and not env.gcc_mode and not env.zig_mode
|
||||
env.mingw_mode = os.name == "nt" and env.gcc_mode and not env.zig_mode
|
||||
env.clangcl_mode = clangcl_mode
|
||||
|
||||
# gcc compiler cf_protection option
|
||||
|
||||
@@ -30,7 +30,6 @@ from .SconsProgress import updateSconsProgressBar
|
||||
from .SconsUtils import (
|
||||
getExecutablePath,
|
||||
getSconsReportValue,
|
||||
isZigName,
|
||||
setEnvironmentVariable,
|
||||
)
|
||||
|
||||
@@ -144,7 +143,7 @@ def _injectCcache(env, cc_path, python_prefix, assume_yes_for_downloads):
|
||||
def enableCcache(
|
||||
env, source_dir, python_prefix, assume_yes_for_downloads, disable_ccache
|
||||
):
|
||||
inject_ccache = not disable_ccache
|
||||
inject_ccache = not disable_ccache and not env.zig_mode
|
||||
|
||||
if inject_ccache:
|
||||
# The ccache needs absolute path, otherwise it will not work.
|
||||
@@ -198,12 +197,31 @@ def enableCcache(
|
||||
|
||||
# If we failed to inject zig argument into ccache command line, we need to
|
||||
# do it now.
|
||||
if env.zig_mode and inject_ccache is False:
|
||||
if env.zig_mode:
|
||||
cc_path = getExecutablePath(env.the_compiler, env=env)
|
||||
|
||||
env["CXX"] = env["CC"] = '"%s" "%s"' % (
|
||||
cc_path,
|
||||
"cc" if env.c11_mode else "c++",
|
||||
)
|
||||
|
||||
if "CCACHE_DIR" not in os.environ:
|
||||
zig_cache_dir = getCacheDir("zig")
|
||||
|
||||
if not os.getenv("ZIG_LOCAL_CACHE_DIR"):
|
||||
makePath(zig_cache_dir)
|
||||
zig_cache_dir = getExternalUsePath(zig_cache_dir)
|
||||
setEnvironmentVariable(
|
||||
env, "ZIG_LOCAL_CACHE_DIR", os.path.join(zig_cache_dir, "local")
|
||||
)
|
||||
|
||||
if not os.getenv("ZIG_GLOBAL_CACHE_DIR"):
|
||||
makePath(zig_cache_dir)
|
||||
zig_cache_dir = getExternalUsePath(zig_cache_dir)
|
||||
setEnvironmentVariable(
|
||||
env, "ZIG_GLOBAL_CACHE_DIR", os.path.join(zig_cache_dir, "global")
|
||||
)
|
||||
|
||||
|
||||
def enableClcache(env, source_dir):
|
||||
# We allow using Python2 still
|
||||
|
||||
@@ -91,7 +91,7 @@ def _enableC11Settings(env):
|
||||
bool - c11_mode flag
|
||||
"""
|
||||
|
||||
# Lots of cases to deal with, pylint: disable=too-many-branches
|
||||
# Lots of cases to deal with
|
||||
|
||||
if "force-c11-mode" in env.experimental_flags:
|
||||
c11_mode = True
|
||||
@@ -287,7 +287,7 @@ def checkWindowsCompilerFound(
|
||||
"""Remove compiler of wrong arch or too old gcc and replace with downloaded winlibs gcc."""
|
||||
# Many cases to deal with, pylint: disable=too-many-branches,too-many-statements
|
||||
|
||||
if os.name == "nt":
|
||||
if os.name == "nt" and not isZigName(env["CC"]):
|
||||
# On Windows, in case MSVC was not found and not previously forced, use the
|
||||
# winlibs MinGW64 as a download, and use it as a fallback.
|
||||
compiler_path = getExecutablePath(env["CC"], env=env)
|
||||
@@ -682,8 +682,9 @@ def _enableWin32TargetSettings(env):
|
||||
"""Set up environment for Windows target settings."""
|
||||
assert isWin32Windows()
|
||||
# The MinGW64 and ClangCL do not default for API level properly, so
|
||||
# help it.
|
||||
env.Append(CPPDEFINES=["_WIN32_WINNT=0x0601"])
|
||||
# help it. For zig, it is hard coded.
|
||||
if not env.zig_mode:
|
||||
env.Append(CPPDEFINES=["_WIN32_WINNT=0x0601"])
|
||||
|
||||
|
||||
def enableWindowsStackSize(env, target_arch):
|
||||
@@ -767,7 +768,8 @@ def setupCCompiler(env, lto_mode, pgo_mode, job_count, exe_target, onefile_compi
|
||||
|
||||
if isWin32Windows() and hasattr(env, "source_dir"):
|
||||
# On Windows, exporting to DLL need to be controlled.
|
||||
env.Append(LINKFLAGS=["-Wl,--exclude-all-symbols"])
|
||||
if not env.zig_mode:
|
||||
env.Append(LINKFLAGS=["-Wl,--exclude-all-symbols"])
|
||||
|
||||
# Make sure we handle import library on our own and put it into the
|
||||
# build directory.
|
||||
@@ -791,10 +793,10 @@ def setupCCompiler(env, lto_mode, pgo_mode, job_count, exe_target, onefile_compi
|
||||
env.Append(CCFLAGS=["-fcf-protection=%s" % env.cf_protection])
|
||||
|
||||
# Support for clang.
|
||||
if env.clang_mode:
|
||||
if env.clang_mode or env.clangcl_mode:
|
||||
env.Append(CCFLAGS=["-Wno-deprecated-declarations"])
|
||||
|
||||
if not isClangName(env.the_cc_name):
|
||||
if not isZigName(env.the_cc_name):
|
||||
env.Append(CPPDEFINES=["_XOPEN_SOURCE"])
|
||||
|
||||
if isClangName(env.the_cc_name):
|
||||
@@ -845,7 +847,7 @@ def setupCCompiler(env, lto_mode, pgo_mode, job_count, exe_target, onefile_compi
|
||||
_enableWin32TargetSettings(env)
|
||||
|
||||
# Unicode entry points for programs.
|
||||
if env.mingw_mode:
|
||||
if env.mingw_mode or (env.zig_mode and isWin32Windows()):
|
||||
env.Append(LINKFLAGS=["-municode"])
|
||||
|
||||
# Detect the gcc version
|
||||
|
||||
@@ -23,7 +23,7 @@ from nuitka.utils.Execution import executeProcess
|
||||
from nuitka.utils.FileOperations import openTextFile
|
||||
from nuitka.utils.Utils import isLinux, isMacOS
|
||||
|
||||
from .SconsUtils import decodeData, getExecutablePath, isGccName
|
||||
from .SconsUtils import decodeData, getExecutablePath, isGccName, isZigName
|
||||
|
||||
# Cache for detected versions.
|
||||
v_cache = {}
|
||||
@@ -74,7 +74,7 @@ _blocked_tools = (
|
||||
|
||||
|
||||
def _myDetectVersion(cc):
|
||||
if isGccName(cc) or "clang" in cc:
|
||||
if isGccName(cc) or "clang" in cc or isZigName(cc):
|
||||
command = (
|
||||
cc,
|
||||
"-dumpversion",
|
||||
|
||||
@@ -149,36 +149,54 @@ def _enableFlagSettings(env, name, experimental_flags):
|
||||
env.Append(CPPDEFINES=["_NUITKA_%s" % flag_name])
|
||||
|
||||
|
||||
def prepareEnvironment(mingw_mode):
|
||||
def _prepareFromEnvironmentVar(var_name):
|
||||
mingw_mode = False
|
||||
zig_mode = False
|
||||
|
||||
# Add environment specified compilers to the PATH variable.
|
||||
if "CC" in os.environ:
|
||||
scons_details_logger.info("CC='%s'" % os.environ["CC"])
|
||||
if var_name in os.environ:
|
||||
scons_details_logger.info("%s='%s'" % (var_name, os.environ[var_name]))
|
||||
|
||||
os.environ["CC"] = os.path.normpath(os.path.expanduser(os.environ["CC"]))
|
||||
os.environ[var_name] = os.path.normpath(
|
||||
os.path.expanduser(os.environ[var_name])
|
||||
)
|
||||
|
||||
if os.path.isdir(os.environ["CC"]):
|
||||
if os.path.isdir(os.environ[var_name]):
|
||||
scons_logger.sysexit(
|
||||
"Error, the 'CC' variable must point to file, not directory."
|
||||
"Error, the '%s' variable must point to file, not directory." % var_name
|
||||
)
|
||||
|
||||
if os.path.sep in os.environ["CC"]:
|
||||
cc_dirname = os.path.dirname(os.environ["CC"])
|
||||
if os.path.sep in os.environ[var_name]:
|
||||
cc_dirname = os.path.dirname(os.environ[var_name])
|
||||
if os.path.isdir(cc_dirname):
|
||||
addToPATH(None, cc_dirname, prefix=True)
|
||||
|
||||
if os.name == "nt" and isGccName(os.path.basename(os.environ["CC"])):
|
||||
if os.name == "nt" and isGccName(os.path.basename(os.environ[var_name])):
|
||||
scons_details_logger.info(
|
||||
"Environment CC seems to be a gcc, enabling mingw_mode."
|
||||
"Environment %s seems to be a gcc, enabling mingw_mode." % var_name
|
||||
)
|
||||
mingw_mode = True
|
||||
else:
|
||||
anaconda_python = getArgumentBool("anaconda_python", False)
|
||||
|
||||
if isLinux() and anaconda_python:
|
||||
python_prefix = getArgumentRequired("python_prefix")
|
||||
addToPATH(None, os.path.join(python_prefix, "bin"), prefix=True)
|
||||
if isZigName(os.path.basename(os.environ[var_name])):
|
||||
scons_details_logger.info(
|
||||
"Environment %s seems to be a gcc, enabling zig_mode." % var_name
|
||||
)
|
||||
zig_mode = True
|
||||
|
||||
return mingw_mode
|
||||
return mingw_mode, zig_mode
|
||||
|
||||
|
||||
def _prepareEnvironment(mingw_mode):
|
||||
mingw_mode, zig_mode = _prepareFromEnvironmentVar("CC")
|
||||
_prepareFromEnvironmentVar("CXX")
|
||||
|
||||
anaconda_python = getArgumentBool("anaconda_python", False)
|
||||
|
||||
if isLinux() and anaconda_python:
|
||||
python_prefix = getArgumentRequired("python_prefix")
|
||||
addToPATH(None, os.path.join(python_prefix, "bin"), prefix=True)
|
||||
|
||||
return mingw_mode, zig_mode
|
||||
|
||||
|
||||
def createEnvironment(
|
||||
@@ -187,6 +205,9 @@ def createEnvironment(
|
||||
# Many settings are directly handled here, getting us a lot of code in here.
|
||||
# pylint: disable=too-many-branches,too-many-statements
|
||||
|
||||
# Prepare environment for compiler detection.
|
||||
mingw_mode, zig_mode = _prepareEnvironment(mingw_mode=mingw_mode)
|
||||
|
||||
from SCons.Script import Environment # pylint: disable=I0021,import-error
|
||||
|
||||
args = {}
|
||||
@@ -204,13 +225,14 @@ def createEnvironment(
|
||||
if (
|
||||
os.name == "nt"
|
||||
and not mingw_mode
|
||||
and not zig_mode
|
||||
and msvc_version is None
|
||||
and msvc_version != "latest"
|
||||
and (getExecutablePath("cl", env=None) is not None)
|
||||
):
|
||||
args["MSVC_USE_SCRIPT"] = False
|
||||
|
||||
if mingw_mode or isPosixWindows():
|
||||
if mingw_mode or zig_mode or isPosixWindows():
|
||||
# Force usage of MinGW64, not using MSVC tools.
|
||||
tools = ["mingw"]
|
||||
|
||||
@@ -222,6 +244,8 @@ def createEnvironment(
|
||||
SCons.Tool.msvc.msvc_exists = SCons.Tool.MSCommon.vc.msvc_exists = (
|
||||
lambda *args: False
|
||||
)
|
||||
elif zig_mode:
|
||||
tools = ["gcc"]
|
||||
else:
|
||||
# Everything else should use default, that is MSVC tools, but not MinGW64.
|
||||
tools = ["default"]
|
||||
@@ -655,6 +679,8 @@ def addClangClPathFromMSVC(env):
|
||||
|
||||
|
||||
def isGccName(cc_name):
|
||||
cc_name = os.path.normcase(os.path.basename(cc_name))
|
||||
|
||||
return (
|
||||
"gcc" in cc_name
|
||||
or "g++" in cc_name
|
||||
@@ -664,10 +690,14 @@ def isGccName(cc_name):
|
||||
|
||||
|
||||
def isClangName(cc_name):
|
||||
cc_name = os.path.normcase(os.path.basename(cc_name))
|
||||
|
||||
return ("clang" in cc_name and "-cl" not in cc_name) or isZigName(cc_name)
|
||||
|
||||
|
||||
def isZigName(cc_name):
|
||||
cc_name = os.path.normcase(os.path.basename(cc_name))
|
||||
|
||||
return "zig" in cc_name
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user