Last active
March 2, 2024 14:29
-
-
Save gvanem/4de19f1e36edff9577173074787ea402 to your computer and use it in GitHub Desktop.
Python 3.x Makefile for MSVC and clang-cl (x86/x64)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# GNU-Makefile for Python 3.x. | |
# | |
# Targeting Windows 32 + 64-bits using MSVC-201x or clang-cl. | |
# | |
# By G. Vanem <gvanem@yahoo.no> 2015 - 2022. | |
# | |
THIS_FILE = Makefile.Windows | |
DATE := $(shell date +%d-%B-%Y) | |
NOW := $(shell date '+%d-%B-%Y (%T)') | |
comma := , | |
GREP1 := grep --max-count=1 | |
MAKEFLAGS += --warn-undefined-variables | |
default: all | |
# | |
# Do a 'make -f Makefile.Windows CC=[cl | clang-cl] vclean' after changing any of these: | |
# (except 'USE_ASTYLE'). | |
# | |
# Link with 'Wsock-trace' library and not 'ws2_32.lib'. | |
# Ref: https://github.com/gvanem/wsock-trace | |
# | |
USE_WSOCK_TRACE ?= 1 | |
# | |
# Enable Debug-code in Python's core code; '-DPy_DEBUG'. | |
# Not for production code. | |
# | |
USE_PY_DEBUG ?= 0 | |
# | |
# Enable "Dynamic Execution Profiling" | |
# | |
USE_DXP ?= 0 | |
# | |
# Enable "Emscripten". Unfinished. | |
# | |
USE_EMSCRIPTEN ?= 0 | |
# | |
# Compile for JIT (experimaental) | |
# | |
USE_JIT ?= 0 | |
# | |
# Compile with 'mimalloc'? | |
# | |
USE_MIMALLOC ?= 1 | |
# | |
# Compile with 'cl -MP' for MSVC. A lot faster. | |
# | |
USE_MP_COMPILE ?= 1 | |
# | |
# Use 'astyle' in the 'CXX_preprocess' macro below. | |
# | |
USE_ASTYLE ?= 1 | |
USE_MACRO_DEBUG ?= 1 | |
# | |
# '$(VCToolkitInstallDir)' should already be set if you installed MSVC the correct way. | |
# | |
VC_ROOT = $(realpath $(VCToolkitInstallDir)) | |
# | |
# Change these as needed: | |
# | |
CLANG_CL32_ROOT ?= f:/ProgramFiler/LLVM-17.0/win32 | |
CLANG_CL64_ROOT ?= f:/ProgramFiler/LLVM-17.0/win64 | |
CLANG_CL32_ROOT_WIN = $(subst /,\,$(CLANG_CL32_ROOT)) | |
CLANG_CL64_ROOT_WIN = $(subst /,\,$(CLANG_CL64_ROOT)) | |
# | |
# Find needed tools: | |
# | |
file_exist = $(word 1,$(wildcard $(1))) | |
path_find = $(call file_exist, $(addsuffix /$(1),$(subst ;, ,$(subst \,/,$(PATH))))) | |
echo_prog = $(subst /,\, $(call path_find,echo.exe)) | |
tee_prog = $(subst /,\, $(call path_find,tee.exe)) | |
# | |
# Used in the '%.c: %.i' and 'link_xx' rules below. | |
# | |
# Note: it MUST exist on PATH prior to generating a local 'py.exe' here. | |
# | |
PYTHON = $(call path_find,py.exe) | |
PYTHON3 = $(PYTHON) -3 | |
# | |
# For generated .bat-files in 'run_tests_1' and 'run_tests_2'. | |
# | |
TMP = $(realpath $(TEMP)) | |
# | |
# Microsoft's 'HTML Help Compiler' used in 'chm_doc_build'. | |
# | |
hhc_proc = $(call path_find, hhc.exe) | |
# | |
# These env-vars could confuse 'clang-cl'. Remove them. | |
# | |
export CL= | |
export C_INCLUDE_PATH= | |
export CPLUS_INCLUDE_PATH= | |
define Usage | |
Usage: "make -f $(THIS_FILE) <CPU=x86 | x64> CC=[cl | clang-cl] [all | clean | realclean | depend]" | |
Specify CC=cl - use MSVC | |
Specify CC=clang-cl - use clang-cl | |
endef | |
export Usage | |
ifeq ($(CPU),x86) | |
BITS = 32 | |
else ifeq ($(CPU),x64) | |
BITS = 64 | |
else | |
$(error Unsupported $$(CPU)-value: '$(CPU)'.) | |
endif | |
# | |
# The 64-bit libraries are in 'libs/x64'. | |
# | |
ifeq ($(BITS),64) | |
LIBS_DIR = libs/x64 | |
WIN_AMD = amd64 | |
else | |
LIBS_DIR = libs | |
WIN_AMD = win32 | |
endif | |
OBJ_DIR = obj/$(CPU) | |
ifeq ($(CC),cl) | |
BUILDER = MSVC | |
else ifeq ($(CC),clang-cl) | |
BUILDER = clang-cl | |
else | |
$(error $(Usage)) | |
endif | |
# | |
# Root directories for external packages. | |
# You may need to run 'cmd /c PCbuild\get_externals.bat' to get some of these: | |
# | |
# The below basenames should be the same as in 'PCbuild\get_externals.bat'. | |
# | |
BZIP2_ROOT = externals/bzip2-1.0.8 | |
LZMA_ROOT = externals/xz-5.2.5 | |
LIBFFI_ROOT = externals/libffi-3.4.4 | |
OPENSSL_ROOT = externals/openssl-bin-3.0.13/$(WIN_AMD) | |
SQLITE3_ROOT = externals/sqlite-3.45.1.0 | |
ZLIB_ROOT = externals/zlib-1.3.1 | |
TCLTK_ROOT = externals/tcltk-8.6.13.1/$(WIN_AMD) | |
TCL_CORE_ROOT = externals/tcl-core-8.6.13.1 | |
# | |
# A created directory to copy | |
# $(TCLTK_ROOT)/lib/tcl8.6/init.tcl -> Lib/tcl8.6 | |
# | |
TCL_ROOT = Lib/tcl8.6 | |
# | |
# Refer 'Include/patchlevel.h' for this mess: | |
# | |
PY_VER_MAJOR := $(shell $(GREP1) '#define PY_MAJOR_VERSION' Include/patchlevel.h | $(GREP1) -o '[0-9]*' | cut -d' ' -f1) | |
PY_VER_MINOR := $(shell $(GREP1) '#define PY_MINOR_VERSION' Include/patchlevel.h | $(GREP1) -o '[0-9]*' | cut -d' ' -f1) | |
PY_RELEASE_SERIAL := $(shell $(GREP1) '#define PY_RELEASE_SERIAL' Include/patchlevel.h | $(GREP1) -o '[0-9]*' | cut -d' ' -f1) | |
PY_VER_STR := $(shell $(GREP1) '#define PY_VERSION' Include/patchlevel.h | cut -d'"' -f2) | |
PY_VER := $(PY_VER_MAJOR).$(PY_VER_MINOR) | |
_PY_VER := $(PY_VER_MAJOR)$(PY_VER_MINOR) | |
ver_test py_ver_test: | |
$(call green_msg0,PY_VER_MAJOR: '$(PY_VER_MAJOR)'.) | |
$(call green_msg0,PY_VER_MINOR: '$(PY_VER_MINOR)'.) | |
$(call green_msg0,PY_VER: '$(PY_VER)'.) | |
$(call green_msg0,PY_VER_STR: '$(PY_VER_STR)'.) | |
$(call green_msg0,PY_RELEASE_SERIAL: '$(PY_RELEASE_SERIAL)'.) | |
# | |
# 'DLLs/sqlite.dll' has it's own rather complicated .rc-file. | |
# | |
SQLITE3_VERSION = $(shell $(GREP1) '#define SQLITE_VERSION' $(SQLITE3_ROOT)/sqlite3.h | \ | |
$(GREP1) -o '[0-9]*' | cut -d' ' -f1) | |
SQLITE3_MAJOR_VERSION = $(word 1, $(SQLITE3_VERSION)) | |
SQLITE3_MINOR_VERSION = $(word 2, $(SQLITE3_VERSION)) | |
SQLITE3_MICRO_VERSION = $(word 3, $(SQLITE3_VERSION)) | |
sq_ver_test: | |
@echo 'SQLITE3_VERSION: "$(SQLITE3_VERSION)".' | |
@echo 'SQLITE3_MAJOR_VERSION: "$(SQLITE3_MAJOR_VERSION)".' | |
@echo 'SQLITE3_MINOR_VERSION: "$(SQLITE3_MINOR_VERSION)".' | |
@echo 'SQLITE3_MICRO_VERSION: "$(SQLITE3_MICRO_VERSION)".' | |
VPATH = PC \ | |
Modules \ | |
$(addprefix Modules/, \ | |
cjkcodecs \ | |
expat \ | |
_blake2 \ | |
_blake2/impl \ | |
_ctypes \ | |
_decimal \ | |
_hacl \ | |
_io \ | |
_multiprocessing \ | |
_sre \ | |
_sqlite) \ | |
Objects \ | |
Parser \ | |
Parser/lexer \ | |
Parser/tokenizer \ | |
Programs \ | |
Python | |
VPATH += $(addprefix $(LZMA_ROOT)/src/, \ | |
common \ | |
liblzma \ | |
liblzma/check \ | |
liblzma/common \ | |
liblzma/delta \ | |
liblzma/lzma \ | |
liblzma/lz \ | |
liblzma/rangecoder \ | |
liblzma/simple) \ | |
\ | |
$(OBJ_DIR) \ | |
$(OPENSSL_ROOT)/include # for applink.c | |
OBJ_DIRS = $(addprefix $(OBJ_DIR)/, \ | |
bzip2 \ | |
core \ | |
ctypes \ | |
decimal \ | |
elementtree \ | |
lzma \ | |
pyexpat \ | |
sqlite3 \ | |
_sqlite3 \ | |
_testcapi \ | |
_testinternalcapi \ | |
zlib) | |
LDFLAGS = -nologo -verbose -incremental:no -map -debug -machine:$(CPU) -nodefaultlib:uuid.lib | |
CFLAGS = -nologo -Zi -arch:AVX2 -MD -O2 -GS -GF- -Ob2 -Oy -DHAVE_AVX2 -DHAVE_SSE2 | |
RCFLAGS = -nologo | |
# | |
# All 'DLLs/*.pyd', '$(PYTHON_DLL)', 'pythonw.exe', 'pyw.exe' | |
# and 'venvwlauncher.exe' are linked with this GUI link-flag. | |
# | |
GUI_LDFLAGS = -subsystem:windows | |
ifeq ($(CC),clang-cl) | |
CFLAGS += -fms-compatibility \ | |
-ferror-limit=5 | |
# | |
# '-Wall' generated a lot of warnings. | |
# | |
CFLAGS += -Wall | |
else | |
CFLAGS += -W3 | |
endif | |
ifeq ($(USE_WSOCK_TRACE),1) | |
WS2_32_LIB = wsock_trace-$(CPU).lib | |
else | |
WS2_32_LIB = ws2_32.lib | |
endif | |
c_to_i = $(addprefix $(2), $(notdir $(1:.c=.i))) | |
c_to_obj = $(addprefix $(OBJ_DIR)/$(strip $(2)), $(notdir $(1:.c=.obj))) | |
asm_to_obj = $(addprefix $(OBJ_DIR)/$(strip $(2)), $(notdir $(1:.asm=.obj))) | |
CFLAGS += -FI./Include/pyconfig.h \ | |
-I. \ | |
-I./Python \ | |
-I./Include \ | |
-I./Include/internal \ | |
-I./Modules/_blake2/impl \ | |
-I./Modules/_hacl/include \ | |
-I./PC \ | |
-I./$(OBJ_DIR) | |
# | |
# Keep these here. | |
# | |
CFLAGS += -I./$(ZLIB_ROOT) \ | |
-I./$(OPENSSL_ROOT)/include | |
ifeq ($(USE_PY_DEBUG),1) | |
CFLAGS += -DPy_DEBUG | |
else | |
CFLAGS += -DNDEBUG | |
endif | |
ifeq ($(USE_DXP),1) | |
CFLAGS += -DDYNAMIC_EXECUTION_PROFILE | |
endif | |
GENERATED = Include/pyconfig.h \ | |
$(OBJ_DIR)/pyconfig.h \ | |
$(OBJ_DIR)/pythonnt_rc.h \ | |
$(CC).args | |
# GENERATED += Modules/_sre/sre_constants.h \ | |
# Modules/_sre/sre_targets.h | |
ifeq ($(CC),clang-cl) | |
GENERATED += clang-cl-$(BITS).bat | |
endif | |
# | |
# .py-files used to generate the "frozen" module. | |
# I.e. the fixed byte-code is put into '$(FROZEN_GENERATED)' header files. | |
# | |
# Ref: https://wiki.python.org/moin/Freeze | |
# | |
FROZEN_FILES_PY = $(addprefix Lib/, \ | |
importlib/_bootstrap.py \ | |
importlib/_bootstrap_external.py \ | |
zipimport.py \ | |
abc.py \ | |
codecs.py \ | |
io.py \ | |
_collections_abc.py \ | |
_sitebuiltins.py \ | |
genericpath.py \ | |
ntpath.py \ | |
posixpath.py \ | |
os.py \ | |
site.py \ | |
stat.py \ | |
__hello__.py \ | |
__phello__/__init__.py \ | |
__phello__/ham/__init__.py \ | |
__phello__/ham/eggs.py \ | |
__phello__/spam.py) | |
# | |
# Map all above files: | |
# Lib/x/y.py | |
# | |
# file to: | |
# Python/frozen_modules/x.y.h | |
# | |
FROZEN_FILES_H = $(subst Lib.,,$(addprefix Python/frozen_modules/,$(notdir $(subst /,.,$(FROZEN_FILES_PY:.py=.h))))) | |
FROZEN_GENERATED = $(FROZEN_FILES_H) | |
# | |
# Since it does not fi in the above '$(subst ..)', add manually. | |
# | |
FROZEN_GENERATED += Python/frozen_modules/getpath.h | |
list_frozen: | |
$(call green_msg, FROZEN_GENERATED:) | |
@$(foreach f, $(FROZEN_GENERATED), echo -e ' $(BRIGHT_WHITE)$(f)\e[0m' ; ) | |
@echo | |
$(call green_msg, FROZEN_FILES_H:) | |
@$(foreach f, $(FROZEN_FILES_H), echo -e ' $(BRIGHT_WHITE)$(f)\e[0m' ; ) | |
@echo | |
gen_frozen: frozen_info $(FROZEN_GENERATED) | |
frozen_info: | |
$(call green_msg, Generating 'FROZEN_GENERATED' files.) | |
@echo | |
rm_frozen: | |
$(call green_msg, Deleting 'FROZEN_GENERATED' files.) | |
rm -f $(FROZEN_GENERATED) $(OBJ_DIR)/core/frozen.obj | |
@echo | |
# | |
# These are the Windows specific .c-sources for '$(PYTHON_DLL)': | |
# | |
PC_SRC = $(addprefix PC/, \ | |
config.c \ | |
dl_nt.c \ | |
invalid_parameter_handler.c \ | |
msvcrtmodule.c \ | |
winreg.c \ | |
winsound.c) | |
# PC_SRC += PC/empty.c | |
# | |
# These are the .c-sources for the built-in modules in '$(PYTHON_DLL)'. | |
# | |
MODULES_SRC = $(addprefix Modules/, \ | |
_abc.c \ | |
_bisectmodule.c \ | |
_codecsmodule.c \ | |
_collectionsmodule.c \ | |
_contextvarsmodule.c \ | |
_csv.c \ | |
_datetimemodule.c \ | |
_functoolsmodule.c \ | |
_heapqmodule.c \ | |
_io/_iomodule.c \ | |
_io/bufferedio.c \ | |
_io/bytesio.c \ | |
_io/fileio.c \ | |
_io/iobase.c \ | |
_io/stringio.c \ | |
_io/textio.c \ | |
_io/winconsoleio.c \ | |
_json.c \ | |
_localemodule.c \ | |
_lsprof.c \ | |
_opcode.c \ | |
_operator.c \ | |
_pickle.c \ | |
_randommodule.c \ | |
_stat.c \ | |
_statisticsmodule.c \ | |
_struct.c \ | |
_suggestions.c \ | |
_sysconfig.c \ | |
_threadmodule.c \ | |
_tracemalloc.c \ | |
_typingmodule.c \ | |
_weakref.c \ | |
_winapi.c \ | |
_xxinterpchannelsmodule.c \ | |
_xxinterpqueuesmodule.c \ | |
_xxsubinterpretersmodule.c \ | |
arraymodule.c \ | |
atexitmodule.c \ | |
binascii.c \ | |
cmathmodule.c \ | |
getbuildinfo.c \ | |
gcmodule.c \ | |
errnomodule.c \ | |
faulthandler.c \ | |
itertoolsmodule.c \ | |
main.c \ | |
mathmodule.c \ | |
md5module.c \ | |
mmapmodule.c \ | |
posixmodule.c \ | |
rotatingtree.c \ | |
sha1module.c \ | |
sha2module.c \ | |
sha3module.c \ | |
signalmodule.c \ | |
symtablemodule.c \ | |
timemodule.c \ | |
xxsubtype.c \ | |
zlibmodule.c \ | |
_sre/sre.c) | |
MODULES_SRC += $(addprefix Modules/cjkcodecs/, \ | |
_codecs_cn.c \ | |
_codecs_hk.c \ | |
_codecs_iso2022.c \ | |
_codecs_jp.c \ | |
_codecs_kr.c \ | |
_codecs_tw.c \ | |
multibytecodec.c) | |
MODULES_SRC += $(addprefix Modules/_blake2/, \ | |
blake2module.c \ | |
blake2b_impl.c \ | |
blake2s_impl.c) | |
MODULES_SRC += $(addprefix Modules/_blake2/impl/, \ | |
blake2b-ref.c \ | |
blake2s-ref.c) | |
MODULES_SRC += $(addprefix Modules/_hacl/, \ | |
Hacl_Hash_MD5.c \ | |
Hacl_Hash_SHA1.c \ | |
Hacl_Hash_SHA2.c \ | |
Hacl_Hash_SHA3.c) | |
OBJECTS_SRC = $(addprefix Objects/, \ | |
abstract.c \ | |
boolobject.c \ | |
bytearrayobject.c \ | |
bytes_methods.c \ | |
bytesobject.c \ | |
call.c \ | |
capsule.c \ | |
cellobject.c \ | |
classobject.c \ | |
codeobject.c \ | |
complexobject.c \ | |
descrobject.c \ | |
dictobject.c \ | |
enumobject.c \ | |
exceptions.c \ | |
fileobject.c \ | |
floatobject.c \ | |
frameobject.c \ | |
funcobject.c \ | |
genericaliasobject.c \ | |
genobject.c \ | |
interpreteridobject.c \ | |
iterobject.c \ | |
listobject.c \ | |
longobject.c \ | |
memoryobject.c \ | |
methodobject.c \ | |
moduleobject.c \ | |
namespaceobject.c \ | |
object.c \ | |
obmalloc.c \ | |
odictobject.c \ | |
picklebufobject.c \ | |
rangeobject.c \ | |
setobject.c \ | |
sliceobject.c \ | |
structseq.c \ | |
tupleobject.c \ | |
typeobject.c \ | |
typevarobject.c \ | |
unicodectype.c \ | |
unicodeobject.c \ | |
unionobject.c \ | |
weakrefobject.c) | |
ifeq ($(USE_MIMALLOC),1) | |
CFLAGS += -DUSE_MIMALLOC=1 \ | |
-DWITH_MIMALLOC=1 \ | |
-I./Include/internal/mimalloc | |
endif | |
ifeq ($(USE_JIT),1) | |
CFLAGS += -D_Py_JIT=1 | |
GENERATED += $(OBJ_DIR)/jit_stencils.h | |
endif | |
PARSER_SRC = $(addprefix Parser/, \ | |
action_helpers.c \ | |
myreadline.c \ | |
parser.c \ | |
peg_api.c \ | |
pegen.c \ | |
pegen_errors.c \ | |
string_parser.c \ | |
token.c) | |
PARSER_SRC += $(addprefix Parser/lexer/, \ | |
buffer.c \ | |
lexer.c \ | |
state.c) | |
PARSER_SRC += $(addprefix Parser/tokenizer/, \ | |
file_tokenizer.c \ | |
helpers.c \ | |
readline_tokenizer.c \ | |
string_tokenizer.c \ | |
utf8_tokenizer.c) | |
PYTHON_SRC = $(addprefix Python/, \ | |
_warnings.c \ | |
asdl.c \ | |
assemble.c \ | |
ast.c \ | |
ast_opt.c \ | |
ast_unparse.c \ | |
bltinmodule.c \ | |
bootstrap_hash.c \ | |
brc.c \ | |
ceval.c \ | |
ceval_gil.c \ | |
codecs.c \ | |
compile.c \ | |
context.c \ | |
critical_section.c \ | |
crossinterp.c \ | |
dtoa.c \ | |
dynamic_annotations.c \ | |
dynload_win.c \ | |
frame.c \ | |
errors.c \ | |
fileutils.c \ | |
flowgraph.c \ | |
formatter_unicode.c \ | |
future.c \ | |
gc.c \ | |
gc_free_threading.c \ | |
gc_gil.c \ | |
getargs.c \ | |
getcompiler.c \ | |
getcopyright.c \ | |
getopt.c \ | |
getplatform.c \ | |
getversion.c \ | |
hamt.c \ | |
hashtable.c \ | |
import.c \ | |
importdl.c \ | |
initconfig.c \ | |
instrumentation.c \ | |
intrinsics.c \ | |
jit.c \ | |
legacy_tracing.c \ | |
lock.c \ | |
marshal.c \ | |
modsupport.c \ | |
mysnprintf.c \ | |
mystrtoul.c \ | |
object_stack.c \ | |
optimizer.c \ | |
optimizer_analysis.c \ | |
optimizer_symbols.c \ | |
parking_lot.c \ | |
pathconfig.c \ | |
perf_trampoline.c \ | |
preconfig.c \ | |
pyarena.c \ | |
pyctype.c \ | |
pyfpe.c \ | |
pyhash.c \ | |
pylifecycle.c \ | |
pymath.c \ | |
pystate.c \ | |
pystrcmp.c \ | |
pystrhex.c \ | |
pystrtod.c \ | |
pytime.c \ | |
Python-ast.c \ | |
Python-tokenize.c \ | |
pythonrun.c \ | |
qsbr.c \ | |
specialize.c \ | |
structmember.c \ | |
suggestions.c \ | |
symtable.c \ | |
sysmodule.c \ | |
thread.c \ | |
traceback.c \ | |
tracemalloc.c) | |
# | |
# Unfinished. | |
# | |
ifeq ($(USE_EMSCRIPTEN),1) | |
PYTHON_SRC += Python/emscripten_signal.c \ | |
Python/emscripten_trampoline.c | |
endif | |
PY_IMP_LIB = $(LIBS_DIR)/python$(_PY_VER).lib | |
PY3_IMP_LIB = $(LIBS_DIR)/python3.lib | |
PY_SHELLEXT_LIB = $(LIBS_DIR)/pyshellext.lib | |
SQLITE3_LIB = $(LIBS_DIR)/sqlite3.lib | |
ZLIB_LIB = $(LIBS_DIR)/zlib.lib | |
# | |
# This library is pulled in via a '#pragma comment'. | |
# Do not add it by default. | |
# | |
LDFLAGS += -nodefaultlib:$(notdir $(PY_IMP_LIB)) | |
# | |
# Put this libpath before '$(VC_ROOT)/lib/$(CPU)' | |
# to avoid shadowing for the needed 'clang_rt.builtins-x86_64.lib' | |
# | |
ifeq ($(CC)_$(BITS),clang-cl_64) | |
# LDFLAGS += -libpath:$(CLANG_CL64_ROOT)/lib/clang/$(CLANG_VER)/lib/windows | |
endif | |
# | |
# No need to use a '$(VC_ROOT)/bin/HostX86/$(CPU)/link.exe' since the | |
# 'link.exe' on PATH is able to link both 32-bit and 64-bit programs. | |
# | |
# But we need to use the correct directory for CRT libraries (msvcrt.lib etc). | |
# | |
LDFLAGS += -libpath:$(VC_ROOT)/lib/$(CPU) | |
# | |
# 'WindowsKits' root is in '$(WK_ROOT)' and | |
# 'WindowsKits' version is in '$(WK_VER)'. | |
# | |
# E.g.: | |
# set WK_ROOT=f:\ProgramFiler-x86\WindowsKits | |
# set WK_VER=10.0.10586.0 | |
# | |
# Hence the User-Mode libraries for 'x86' is in: | |
# $(WK_ROOT)/Lib/$(WK_VER)/um/x86/ | |
# | |
LDFLAGS += -libpath:$(realpath $(WK_ROOT)/Lib/$(WK_VER)/um/$(CPU)) | |
# | |
# Ditto mess for the UCRT libraries: for 'x86' the UCRT libs are in: | |
# $(WK_ROOT)/Lib/$(WK_VER)/ucrt/x86/ | |
# | |
LDFLAGS += -libpath:$(realpath $(WK_ROOT)/Lib/$(WK_VER)/ucrt/$(CPU)) | |
# | |
# The path to our libraries: | |
# | |
LDFLAGS += -libpath:$(LIBS_DIR) | |
# | |
# The different chunks for '$(PYTHON_DLL)': | |
# | |
PC_OBJ = $(call c_to_obj, $(PC_SRC), core/) | |
OBJECTS_OBJ = $(call c_to_obj, $(OBJECTS_SRC), core/) | |
PARSER_OBJ = $(call c_to_obj, $(PARSER_SRC), core/) | |
PYTHON_OBJ = $(call c_to_obj, $(PYTHON_SRC), core/) | |
MODULES_OBJ = $(call c_to_obj, $(MODULES_SRC), core/) | |
PYTHON_DLL_OBJ = $(PC_OBJ) \ | |
$(OBJECTS_OBJ) \ | |
$(PARSER_OBJ) \ | |
$(PYTHON_OBJ) \ | |
$(MODULES_OBJ) \ | |
# $(OBJ_DIR)/core/_xxsubinterpretersmodule.obj | |
PYTHON_DLL_I = $(notdir $(PYTHON_DLL_OBJ:.obj=.i)) | |
# | |
# Handle this mess specially: | |
# | |
MODULES_SRC2 = $(filter-out Modules/_pickle.c, $(MODULES_SRC)) | |
MODULES_OBJ2 = $(filter-out $(OBJ_DIR)/core/_pickle.obj, $(MODULES_OBJ)) | |
# | |
# Targets | |
# | |
PYTHON_DLL = python$(_PY_VER).dll | |
# | |
# The programs that generates "frozen" modules | |
# | |
ifeq ($(CPU),x86) | |
FROZEN_MODULE = PCBuild/win32/_freeze_module.exe | |
BOOTSTRAP_PYTHON = PCBuild/win32/_bootstrap_python.exe | |
else | |
FROZEN_MODULE = PCBuild/amd64/_freeze_module.exe | |
BOOTSTRAP_PYTHON = PCBuild/amd64/_bootstrap_python.exe | |
endif | |
PROGRAMS = python.exe \ | |
pythonw.exe \ | |
py.exe \ | |
pyw.exe \ | |
venvlauncher.exe \ | |
venvwlauncher.exe \ | |
_testembed.exe \ | |
$(FROZEN_MODULE) | |
PYD_FILES = $(addprefix DLLs/, \ | |
pyexpat.pyd \ | |
select.pyd \ | |
unicodedata.pyd \ | |
winsound.pyd \ | |
xxlimited.pyd \ | |
_asyncio.pyd \ | |
_bz2.pyd \ | |
_contextvars.pyd \ | |
_ctypes.pyd \ | |
_ctypes_test.pyd \ | |
_decimal.pyd \ | |
_elementtree.pyd \ | |
_hashlib.pyd \ | |
_lzma.pyd \ | |
_multiprocessing.pyd \ | |
_overlapped.pyd \ | |
_queue.pyd \ | |
_random.pyd \ | |
_socket.pyd \ | |
_ssl.pyd \ | |
_sqlite3.pyd \ | |
_tkinter.pyd \ | |
_testbuffer.pyd \ | |
_testcapi.pyd \ | |
_testconsole.pyd \ | |
_testclinic.pyd \ | |
_testclinic_limited.pyd \ | |
_testinternalcapi.pyd \ | |
_testimportmultiple.pyd \ | |
_testmultiphase.pyd \ | |
_testsinglephase.pyd \ | |
_uuid.pyd \ | |
_wmi.pyd \ | |
_zoneinfo.pyd) | |
PYD_FILES := $(sort $(PYD_FILES)) | |
DLL_FILES = $(PYTHON_DLL) \ | |
python3.dll \ | |
DLLs/sqlite3.dll | |
# | |
# 'clang-cl' fail to compile 'PC/pyshellext.cpp'. | |
# | |
ifneq ($(CC),clang-cl) | |
DLL_FILES += pyshellext.dll | |
endif | |
TARGETS = $(DLL_FILES) \ | |
$(PYD_FILES) \ | |
$(PROGRAMS) \ | |
python.bat \ | |
pythonw.bat | |
all: check_py make_dirs $(GENERATED) $(FROZEN_GENERATED) $(TARGETS) copy_into_DLLs epilogue | |
help: | |
@echo "$$Usage" | |
$(call green_msg0,\n Extra targets: $(BRIGHT_GREEN)chm_doc$(comma) pdf_doc$(comma) pythoninfo_test$(comma) all_tests$(comma) regression_test) | |
epilogue: | |
$(call green_msg, Welcome to Python ver. $(PY_VER_STR) (bits:$(BITS)).) | |
make_dirs: | |
$(call create_dirs, $(OBJ_DIRS) $(LIBS_DIR) $(TCL_ROOT) PCBuild/win32 PCBuild/amd64 DLLs tmp) | |
$(OBJ_DIR) PCBuild/win32 PCBuild/amd64 tmp: | |
@mkdir --parents $@ | |
everything: all chm_doc pdf_doc | |
# | |
# Create a 'Python*.reg' file for the Registry keys under 'HKLM\SOFTWARE\Python\PythonCore\$(PY_VER)-$(BITS)'. | |
# Do it under the 32-bit registry; '-reg:32'. | |
# These keys are read by 'py.exe'. | |
# | |
# Use e.g.: | |
# reg delete HKLM\SOFTWARE\Python\PythonCore\3.9-32 to remove it. | |
# reg delete HKLM\SOFTWARE\Python\PythonCore\3.9-64 to remove it. | |
# | |
top_key = HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\$(PY_VER)-$(BITS) | |
reg_file: Python.reg | |
Python.reg: $(THIS_FILE) | |
$(call green_msg, Generating $@) | |
$(file > $@,$(Python_REG)) | |
# | |
# Note: The 'sphinx-build' called in 'make.bat' could be using Python 2.x. | |
# Fix your PATH or do a 'pip install python_doc_theme' for Python 2.x. | |
# | |
# Also, the 'sphinx-build' in 'make.bat' could be different from the one | |
# used in the 'pdf_doc_step_1' rule. | |
# | |
chm_doc: chm_doc_build chm_hhc_run | |
cp --update Doc/build/htmlhelp/python*.chm Python$(_PY_VER).chm | |
chm_doc_build: | |
cd Doc ; \ | |
cmd.exe /C make.bat htmlhelp | |
# | |
# Should be only one generated .hhp file here: | |
# | |
HHP_FILE = $(wildcard Doc/build/htmlhelp/*.hhp) | |
chm_hhc_run: | |
$(call green_msg, Running 'hhc' on '$(HHP_FILE)') | |
- ( cd Doc/build/htmlhelp ; \ | |
$(hhc_proc) $(notdir $(HHP_FILE)) ) | |
pdf_doc: pdf_doc_step_1 pdf_doc_step_2 | |
cp Doc/build/latex/library.pdf Python$(_PY_VER).pdf | |
# | |
# This needs the 'l3backend'. Use 'MikTeX-console.exe' to get it. | |
# | |
pdf_doc_step_1: | |
$(call green_msg, Step [1/3]; creating $(BRIGHT_WHITE)Doc/build/latex/library.tex) | |
cd Doc ; \ | |
cmd.exe /C make.bat latex | |
pdf_doc_step_2: | |
$(call green_msg, Step [3/3]; running $(BRIGHT_WHITE)xelatex$(BRIGHT_GREEN) 4 times with merging of index $(BRIGHT_WHITE)Doc/build/latex/library.pdf) | |
- (cd Doc/build/latex ; \ | |
xelatex -quiet library.tex ; \ | |
xelatex -quiet library.tex ; \ | |
makeindex -s python.ist library.idx ; \ | |
xelatex -quiet library.tex ; \ | |
xelatex -quiet library.tex) | |
clean_doc: | |
rm -f Doc/build/htmlhelp/python*.chm Python3*.{chm,pdf} | |
rm -fr Doc/build | |
############ Test targets ################################################################### | |
TESTS0 = $(addsuffix .py, \ | |
$(addprefix Lib/test/, \ | |
test_netrc \ | |
test_nntplib \ | |
test_ntpath \ | |
test_numeric_tower \ | |
test_operator \ | |
test_optparse \ | |
test_ordered_dict \ | |
test_os \ | |
test_ossaudiodev \ | |
test_osx_env \ | |
test_parser \ | |
test_pathlib \ | |
test_pdb \ | |
test_peepholer \ | |
test_pickle \ | |
test_pickletools \ | |
test_pipes \ | |
test_pkg \ | |
test_pkgimport \ | |
test_pkgutil \ | |
test_platform \ | |
test_plistlib \ | |
test_poll \ | |
test_popen \ | |
test_poplib \ | |
test_posix \ | |
test_posixpath \ | |
test_pow \ | |
test_pprint \ | |
test_print \ | |
test_profile \ | |
test_property \ | |
test_pstats \ | |
test_pty \ | |
test_pulldom \ | |
test_pwd \ | |
test_py_compile \ | |
test_pyclbr \ | |
test_pydoc \ | |
test_pyexpat \ | |
test_queue \ | |
test_quopri \ | |
test_raise \ | |
test_random \ | |
test_range \ | |
test_re \ | |
test_readline \ | |
test_reprlib \ | |
test_resource \ | |
test_richcmp \ | |
test_rlcompleter \ | |
test_robotparser \ | |
test_runpy \ | |
test_sax \ | |
test_sched \ | |
test_scope \ | |
test_script_helper \ | |
test_secrets \ | |
test_select \ | |
test_selectors \ | |
test_set \ | |
test_setcomps \ | |
test_shelve \ | |
test_shlex \ | |
test_shutil \ | |
test_signal \ | |
test_site \ | |
test_slice \ | |
test_smtpd \ | |
test_smtplib \ | |
test_smtpnet \ | |
test_sndhdr \ | |
test_socket \ | |
test_socketserver \ | |
test_sort \ | |
test_source_encoding \ | |
test_sqlite \ | |
test_ssl \ | |
test_startfile \ | |
test_stat \ | |
test_statistics \ | |
test_strftime \ | |
test_string \ | |
test_string_literals \ | |
test_stringprep \ | |
test_strptime \ | |
test_strtod \ | |
test_struct \ | |
test_structmembers \ | |
test_structseq \ | |
test_subclassinit \ | |
test_subprocess \ | |
test_sunau \ | |
test_sundry \ | |
test_super \ | |
test_symbol \ | |
test_symtable \ | |
test_syntax \ | |
test_sys \ | |
test_sys_setprofile \ | |
test_sys_settrace \ | |
test_sysconfig \ | |
test_tarfile \ | |
test_tcl \ | |
test_telnetlib \ | |
test_tempfile \ | |
test_textwrap \ | |
test_thread \ | |
test_threaded_import \ | |
test_threadedtempfile \ | |
test_threading \ | |
test_threading_local \ | |
test_threadsignals \ | |
test_time \ | |
test_timeit \ | |
test_timeout \ | |
test_tk \ | |
test_tokenize \ | |
test_tools \ | |
test_trace \ | |
test_traceback \ | |
test_tracemalloc \ | |
test_ttk_guionly \ | |
test_ttk_textonly \ | |
test_tuple \ | |
test_turtle \ | |
test_typechecks \ | |
test_typing \ | |
test_ucn \ | |
test_unary \ | |
test_unicode \ | |
test_unicode_file \ | |
test_unicode_file_functions \ | |
test_unicode_identifiers \ | |
test_unicodedata \ | |
test_univnewlines \ | |
test_unpack \ | |
test_unpack_ex \ | |
test_urllib \ | |
test_urllib2 \ | |
test_urllib2_localnet \ | |
test_urllib2net \ | |
test_urllib_response \ | |
test_urllibnet \ | |
test_urlparse \ | |
test_userdict \ | |
test_userlist \ | |
test_userstring \ | |
test_utf8source \ | |
test_uu \ | |
test_uuid \ | |
test_venv \ | |
test_warnings/__main__ \ | |
test_wave \ | |
test_weakref \ | |
test_weakset \ | |
test_webbrowser \ | |
test_winconsoleio \ | |
test_winreg \ | |
test_winsound \ | |
test_with \ | |
test_wsgiref \ | |
test_xdrlib \ | |
test_xml_dom_minicompat \ | |
test_xml_etree \ | |
test_xml_etree_c \ | |
test_xmlrpc \ | |
test_xmlrpc_net \ | |
test_yield_from \ | |
test_zipapp \ | |
test_zipfile \ | |
test_zipfile64 \ | |
test_zipimport \ | |
test_zipimport_support \ | |
test_zlib)) | |
TESTS1 = $(wildcard Lib/test/test_*.py) \ | |
Lib/test/test_warnings/__main__.py | |
TESTS1 := $(filter-out Lib/test/test_gdb.py, $(TESTS1)) | |
TESTS1 := $(filter-out Lib/test/test_regrtest.py, $(TESTS1)) | |
TESTS2 = $(addsuffix .py, \ | |
$(addprefix Lib/test/, \ | |
test_netrc \ | |
test_nntplib \ | |
test_ntpath \ | |
test_numeric_tower)) | |
# | |
# Test cases for '_testembed.exe' except 'test_audit_run_startup' | |
# that is interactive only (?) | |
# | |
TESTEMBED_CASES = test_audit \ | |
test_audit_run_command \ | |
test_audit_run_file \ | |
test_audit_run_interactivehook \ | |
test_audit_run_stdin \ | |
test_audit_subinterpreter \ | |
test_bpo20891 \ | |
test_forced_io_encoding \ | |
test_get_argc_argv \ | |
test_init_compat_config \ | |
test_init_compat_env \ | |
test_init_dev_mode \ | |
test_init_dont_configure_locale \ | |
test_init_dont_parse_argv \ | |
test_init_env_dev_mode \ | |
test_init_env_dev_mode_alloc \ | |
test_init_from_config \ | |
test_init_global_config \ | |
test_init_initialize_config \ | |
test_init_isolated_config \ | |
test_init_isolated_flag \ | |
test_init_main \ | |
test_init_parse_argv \ | |
test_init_python_config \ | |
test_init_python_env \ | |
test_init_read_set \ | |
test_init_run_main \ | |
test_init_set_config \ | |
test_init_setpath \ | |
test_init_setpath_config \ | |
test_init_setpythonhome \ | |
test_init_sys_add \ | |
test_init_warnoptions \ | |
test_initialize_pymain \ | |
test_initialize_twice \ | |
test_open_code_hook \ | |
test_pre_initialization_api \ | |
test_pre_initialization_sys_options \ | |
test_preinit_compat_config \ | |
test_preinit_dont_parse_argv \ | |
test_preinit_isolated1 \ | |
test_preinit_isolated2 \ | |
test_preinit_isolated_config \ | |
test_preinit_parse_argv \ | |
test_preinit_python_config \ | |
test_repeated_init_and_subinterpreters \ | |
test_run_main | |
.PHONY: check_py check_echo check_tee all_tests \ | |
run_tests_1 run_tests_2 run_tests_3 run_tests_4 \ | |
pythoninfo_test regression_test run_embedded_tests | |
check_echo: | |
ifeq ($(echo_prog),) | |
$(error Cygwin or MSys "echo.exe" not found on path. Edit $(THIS_FILE) manually.) | |
endif | |
echo_prog += -ne "$(strip $(1))\e[0m\n" | |
check_tee: | |
ifeq ($(tee_prog),) | |
$(error Cygwin or MSys "tee.exe" not found on path. Edit $(THIS_FILE) manually.) | |
endif | |
check_py: | |
ifeq ($(PYTHON),) | |
$(error 'py.exe' not found on PATH!) | |
else | |
$(call green_msg, 'py.exe' found at '$(PYTHON)') | |
endif | |
all_tests: all run_tests_1 run_tests_2 run_tests_3 run_tests_4 pythoninfo_test regression_test run_embedded_tests | |
$(TMP)/run_tests_1.bat: $(THIS_FILE) | |
$(call generate, $@, ::) | |
$(file >> $@,$(RUN_TESTS_BAT)) | |
$(foreach t, $(TESTS1), $(call write_single_test, $@, $(t), run_tests_1.results)) | |
$(file > run_tests_1.results) | |
$(TMP)/run_tests_2.bat: $(THIS_FILE) | |
$(call generate, $@, ::) | |
$(file >> $@,$(RUN_TESTS_BAT)) | |
$(foreach t, $(TESTS2), $(call write_single_test, $@, $(t), run_tests_2.results)) | |
$(file > run_tests_2.results) | |
run_tests_1: python.bat check_echo check_tee $(TMP)/run_tests_1.bat | |
cmd /C $(TEMP)\run_tests_1.bat | |
$(call green_msg, Look in run_tests_1.results for results.) | |
run_tests_2: python.bat check_echo check_tee $(TMP)/run_tests_2.bat | |
cmd /C $(TEMP)\run_tests_2.bat | |
$(call green_msg, Look in run_tests_2.results for results.) | |
run_tests_3: python.bat | |
$(file > run_tests_3.results) | |
python.bat -m test -j3 | run_tests_3.results | |
$(call green_msg, Look in run_tests_3.results for results.) | |
run_tests_4: python.bat | |
$(file > run_tests_4.results) | |
export PYTHON_EXTRA_PATH=$(realpath ./Lib/test) && \ | |
python.bat -m libregrtest -v | run_tests_4.results | |
$(call green_msg, Look in run_tests_4.results for results.) | |
pythoninfo_test: all python.bat | |
python.bat -m test.pythoninfo | |
# | |
# From a 'python.bat -m test -h' output: | |
# | |
audio_test: python.bat | |
python.bat -m test audio | |
cpu_test: python.bat | |
python.bat -m test cpu | |
curses_test: python.bat | |
python.bat -m test curses | |
decimal_test: python.bat | |
python.bat -m test decimal | |
gui_test: python.bat | |
python.bat -m test gui | |
network_test: python.bat | |
python.bat -m test network | |
subprocess_test: python.bat | |
python.bat -m test subprocess | |
tzdata_test: python.bat | |
python.bat -m test tzdata | |
urlfetch_test: python.bat | |
python.bat -m test urlfetch | |
regression_test: python.bat | |
python.bat -m test all | |
# python.bat -u -Wd -E -bb -m test | |
run_embedded_tests: _testembed.exe check_echo $(TMP)/embedded_tests.bat | |
cmd /C $(TEMP)\embedded_tests.bat | tee embedded_tests.results | |
run_regress_tests: python.bat | |
cd Lib/test ; \ | |
cmd.exe /C ../../python.bat test_regrtest.py | |
$(TMP)/embedded_tests.bat: $(THIS_FILE) | |
$(call generate, $@, ::) | |
$(file >> $@,$(EMBEDDED_TESTS_BAT)) | |
$(foreach t, $(TESTEMBED_CASES), $(call write_single_embed_test, $@, $(t)) ) | |
$(file >> $@, $(call echo_prog, $(BRIGHT_WHITE)Success! All $(words $(TESTEMBED_CASES)) tests passed.)) | |
python.bat: $(THIS_FILE) | |
$(call generate, $@, ::) | |
$(file >> $@,$(PYTHON_BAT_COMMON)) | |
$(file >> $@, %PYTHONHOME%\python.exe %*) | |
pythonw.bat: $(THIS_FILE) | |
$(call generate, $@, ::) | |
$(file >> $@,$(PYTHON_BAT_COMMON)) | |
$(file >> $@, %PYTHONHOME%\pythonw.exe %*) | |
############ python*.zip rules ################################################################### | |
files_for_zip = $(wildcard Lib/*.py) | |
PYTHON_ZIP = $(PYTHON_DLL:.dll=.zip) | |
# dir /bs *.py > t | |
# grep --invert-match --only '$(realpath .)' t | |
define make_zip | |
import shutil | |
shutil.make_archive ("test", "zip", "Lib", ".") | |
endef | |
make_zip: | |
$(call green_msg, Creating '$(PYTHON_ZIP)' with $(words $(files_for_zip)) files.) | |
# zip -qr $(PYTHON_ZIP) $(files_for_zip) | |
# | |
# Compile all 'Lib/*.py' files into 'tmp/*.pyc' files. | |
# Except any 'test_*.py' and 'unittest_*.py' files. | |
# | |
compile_lib_to_pyc: tmp python.bat | |
export PYTHONPYCACHEPREFIX=./tmp ; \ | |
cmd.exe /C python.bat Lib/compileall.py -x "test_*." -s $(realpath .)/Lib Lib | |
############ MSVC 'cl -MP' rules ################################################################# | |
ifeq ($(CC)-$(USE_MP_COMPILE),cl-1) | |
$(MODULES_OBJ2): $(MODULES_SRC2) | $(CC).args $(OBJ_DIR)/core | |
$(call C_compile_MP, $(OBJ_DIR)/core\\, $(MODULES_SRC2)) | |
$(OBJECTS_OBJ): $(OBJECTS_SRC) | $(CC).args $(OBJ_DIR)/core | |
$(call C_compile_MP, $(OBJ_DIR)/core\\, $(OBJECTS_SRC)) | |
$(PARSER_OBJ): $(PARSER_SRC) | $(CC).args $(OBJ_DIR)/core | |
$(call C_compile_MP, $(OBJ_DIR)/core\\, $(PARSER_SRC)) | |
$(PYTHON_OBJ): $(PYTHON_SRC) | $(CC).args $(OBJ_DIR)/core | |
$(call C_compile_MP, $(OBJ_DIR)/core\\, $(PYTHON_SRC)) | |
endif | |
############ Dynamic target rules ################################################################ | |
$(OBJ_DIR)/python.obj \ | |
$(PYTHON_DLL_OBJ) \ | |
$(PYTHON_DLL_I) \ | |
python.i: EXTRA_CFLAGS += -DPy_BUILD_CORE -DPy_BUILD_CORE_BUILTIN | |
$(OBJ_DIR)/_asynciomodule.obj \ | |
$(OBJ_DIR)/_queuemodule.obj \ | |
$(OBJ_DIR)/_randommodule.obj \ | |
_asynciomodule.i \ | |
_queuemodule.i \ | |
_randommodule.i: EXTRA_CFLAGS += -DPy_BUILD_CORE -DPy_BUILD_CORE_MODULE | |
$(OBJ_DIR)/_zoneinfo.obj \ | |
$(OBJ_DIR)/unicodedata.obj \ | |
_zoneinfo.i \ | |
unicodedata.i: EXTRA_CFLAGS += -DPy_BUILD_CORE_MODULE | |
$(PY_IMP_LIB): $(PYTHON_DLL) | |
$(PYTHON_DLL): $(PYTHON_DLL_OBJ) \ | |
$(OBJ_DIR)/getpath.obj \ | |
$(OBJ_DIR)/core/_bootstrap_python.obj \ | |
$(OBJ_DIR)/python$(_PY_VER).res \ | |
$(ZLIB_LIB) | check-for-unused-libs.py | |
$(call link_DLL, $@, $(GUI_LDFLAGS) $^ kernel32.lib user32.lib winmm.lib \ | |
bcrypt.lib advapi32.lib pathcch.lib version.lib \ | |
$(WS2_32_LIB), $(PY_IMP_LIB)) | |
python3.dll: $(OBJ_DIR)/python3dll.obj $(OBJ_DIR)/python3dll.res | check-for-unused-libs.py | |
$(call link_DLL, $@, $(GUI_LDFLAGS) $^, $(PY3_IMP_LIB)) | |
# | |
# Special 'LDFLAGS' for these: | |
# python.exe pythonw.exe: | |
# | |
PY_LDFLAGS = -stack:2000000 -base:0x1D000000 -dynamicbase -nxcompat | |
ifeq ($(BITS),32) | |
PY_LDFLAGS += -safeseh | |
endif | |
########### Program rules ######################################################################## | |
python.exe: $(OBJ_DIR)/python.obj $(OBJ_DIR)/python_exe.res $(PY_IMP_LIB) | check-for-unused-libs.py | |
$(call link_EXE, $@, $^ $(PY_LDFLAGS)) | |
pythonw.exe: $(OBJ_DIR)/WinMain.obj $(OBJ_DIR)/pythonw_exe.res $(PY_IMP_LIB) | check-for-unused-libs.py | |
$(call link_EXE_GUI, $@, $^ $(PY_LDFLAGS)) | |
py.exe: $(OBJ_DIR)/launcher.obj $(OBJ_DIR)/py.res | check-for-unused-libs.py | |
$(call link_EXE, $@, $^ advapi32.lib shell32.lib version.lib) | |
pyw.exe: $(OBJ_DIR)/launcher_w.obj $(OBJ_DIR)/pyw.res | check-for-unused-libs.py | |
$(call link_EXE_GUI, $@, $^ advapi32.lib shell32.lib user32.lib version.lib) | |
venvlauncher.exe: $(OBJ_DIR)/venvlauncher.obj $(OBJ_DIR)/venvlauncher.res | check-for-unused-libs.py | |
$(call link_EXE, $@, $^ pathcch.lib) | |
venvwlauncher.exe: $(OBJ_DIR)/venvwlauncher.obj $(OBJ_DIR)/venvwlauncher.res | check-for-unused-libs.py | |
$(call link_EXE_GUI, $@, $^ pathcch.lib user32.lib) | |
_testembed.exe: $(OBJ_DIR)/_testembed.obj $(PY_IMP_LIB) | check-for-unused-libs.py | |
$(call link_EXE, $@, $^) | |
################################################################################################## | |
$(OBJ_DIR)/core/_pickle.obj _pickle.i: EXTRA_CFLAGS = -DPy_BUILD_CORE_BUILTIN -DCOMPILING_PICKLE | |
# | |
# The Python launchers 'pyw.exe' and 'venvwlauncher.exe' should be Unicode and have GUI Message boxes: | |
# | |
$(OBJ_DIR)/launcher_w.obj launcher_w.i: EXTRA_CFLAGS = -DCOMPILING_LAUNCHER_W | |
$(OBJ_DIR)/launcher_w.obj: PC/launcher.c | $(CC).args $(OBJ_DIR) | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/venvlauncher.obj venvlauncher.i: EXTRA_CFLAGS = -DVENV_REDIRECT | |
$(OBJ_DIR)/venvwlauncher.obj venvwlauncher.i: EXTRA_CFLAGS = -DVENV_REDIRECT -DCOMPILING_LAUNCHER_W | |
# $(OBJ_DIR)/venvlauncher.obj: PC/venvlauncher.c | $(CC).args $(OBJ_DIR) | |
# $(call C_compile, $@, $<) | |
$(OBJ_DIR)/venvwlauncher.obj: PC/venvlauncher.c | $(CC).args $(OBJ_DIR) | |
$(call C_compile, $@, $<) | |
################################################################################################## | |
regen-frozen: Tools/build/freeze_modules.py $(FROZEN_FILES_PY) $(FROZEN_MODULE) | |
$(call green_msg, Running '$<') | |
$(PYTHON3) $< | |
@echo | |
$(OBJ_DIR)/core/frozen.obj: regen-frozen $(FROZEN_GENERATED) | |
$(OBJ_DIR)/core/frozen.obj \ | |
$(OBJ_DIR)/core/_freeze_module.obj \ | |
$(OBJ_DIR)/getpath_noop.obj \ | |
$(OBJ_DIR)/getpath.obj \ | |
frozen.i \ | |
_freeze_module.i \ | |
getpath.i \ | |
getpath_noop.i: EXTRA_CFLAGS += -DPy_BUILD_CORE -DPy_BUILD_CORE_BUILTIN | |
$(OBJ_DIR)/getpath.obj \ | |
getpath.i: EXTRA_CFLAGS += -DCOMPILING_GETPATH_C | |
frozen_module: $(FROZEN_MODULE) | |
FROZEN_OBJ = $(OBJ_DIR)/_freeze_module.obj \ | |
$(OBJ_DIR)/getpath_noop.obj \ | |
$(PYTHON_DLL_OBJ) | |
$(FROZEN_OBJ): EXTRA_CFLAGS += -DPy_BUILD_CORE | |
$(FROZEN_MODULE): $(FROZEN_OBJ) $(ZLIB_LIB) | PCBuild/amd64 PCBuild/win32 check-for-unused-libs.py | |
$(call link_EXE, $@, $^ bcrypt.lib advapi32.lib pathcch.lib user32.lib version.lib winmm.lib $(WS2_32_LIB)) | |
# | |
# An alternative "frozen" generation. | |
# Not used; only for testing. | |
# | |
_bootstrap_python: $(BOOTSTRAP_PYTHON) | |
_BOOTSTRAP_OBJ = $(OBJ_DIR)/core/_bootstrap_python.obj \ | |
$(OBJ_DIR)/core/main.obj \ | |
$(OBJ_DIR)/getpath.obj \ | |
$(PYTHON_DLL_OBJ) | |
_bootstrap_python.i \ | |
$(OBJ_DIR)/core/_bootstrap_python.obj \ | |
$(OBJ_DIR)/core/main.obj: EXTRA_CFLAGS = -DPy_BUILD_CORE | |
$(BOOTSTRAP_PYTHON): $(_BOOTSTRAP_OBJ) $(ZLIB_LIB) | check-for-unused-libs.py | |
$(call link_EXE, $@, $^ bcrypt.lib advapi32.lib pathcch.lib user32.lib version.lib winmm.lib $(WS2_32_LIB)) | |
_bootstrap_test: $(BOOTSTRAP_PYTHON) | |
$(call green_msg, Testing $< with 'Lib/abc.py') | |
export WSOCK_TRACE_LEVEL= && \ | |
$< ./Programs/_freeze_module.py abc ./Lib/abc.py Python/frozen_modules/abc.h | |
define gen_frozen_h | |
$(call green_msg, Generating$(BRIGHT_WHITE)$(2) $(BRIGHT_GREEN)from$(BRIGHT_WHITE)$(1)) | |
export WSOCK_TRACE_LEVEL= && \ | |
$(FROZEN_MODULE) $(strip $(notdir $(2:.h=)) $(1) $(2)) | |
@echo | |
endef | |
Python/frozen_modules/importlib._bootstrap.h: Lib/importlib/_bootstrap.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/importlib._bootstrap_external.h: Lib/importlib/_bootstrap_external.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/zipimport.h: Lib/zipimport.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/abc.h: Lib/abc.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/codecs.h: Lib/codecs.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/getpath.h: Modules/getpath.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/io.h: Lib/io.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/_collections_abc.h: Lib/_collections_abc.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/_sitebuiltins.h: Lib/_sitebuiltins.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/genericpath.h: Lib/genericpath.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/ntpath.h: Lib/ntpath.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/posixpath.h:Lib/posixpath.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/os.h: Lib/os.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/site.h: Lib/site.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/stat.h: Lib/stat.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/__hello__.h: Lib/__hello__.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/__phello__.__init__.h: Lib/__phello__/__init__.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/__phello__.ham.__init__.h: Lib/__phello__/ham/__init__.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/__phello__.ham.eggs.h: Lib/__phello__/ham/eggs.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
Python/frozen_modules/__phello__.spam.h: Lib/__phello__/spam.py $(FROZEN_MODULE) | |
$(call gen_frozen_h, $<, $@) | |
################################################################################################## | |
# | |
# First, the link rules for all the "easy" .PYD files: | |
# | |
DLLs/unicodedata.pyd: $(OBJ_DIR)/unicodedata.obj $(OBJ_DIR)/unicodedata.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
DLLs/_multiprocessing.pyd: $(OBJ_DIR)/multiprocessing.obj $(OBJ_DIR)/semaphore.obj $(OBJ_DIR)/_multiprocessing.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(WS2_32_LIB)) | |
DLLs/_overlapped.pyd: $(OBJ_DIR)/overlapped.obj $(OBJ_DIR)/_overlapped.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(WS2_32_LIB)) | |
DLLs/_queue.pyd: $(OBJ_DIR)/_queuemodule.obj $(OBJ_DIR)/_queue.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
DLLs/select.pyd: $(OBJ_DIR)/selectmodule.obj $(OBJ_DIR)/select.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ kernel32.lib $(WS2_32_LIB)) | |
DLLs/_socket.pyd: $(OBJ_DIR)/socketmodule.obj $(OBJ_DIR)/_socket.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(WS2_32_LIB) iphlpapi.lib rpcrt4.lib) | |
DLLs/_uuid.pyd: $(OBJ_DIR)/_uuidmodule.obj $(OBJ_DIR)/_uuid.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(PY_IMP_LIB) rpcrt4.lib) | |
DLLs/_zoneinfo.pyd: $(OBJ_DIR)/_zoneinfo.obj $(OBJ_DIR)/_zoneinfo.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(PY_IMP_LIB)) | |
DLLs/winsound.pyd: $(OBJ_DIR)/winsound.obj $(OBJ_DIR)/winsound.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ user32.lib winmm.lib) | |
DLLs/xxlimited.pyd: $(OBJ_DIR)/xxlimited.obj $(OBJ_DIR)/xxlimited.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
################################################################################################## | |
OPENSSL_LIBS = $(OPENSSL_ROOT)/libcrypto.lib \ | |
$(OPENSSL_ROOT)/libssl.lib | |
OPENSSL_DLLs = $(OPENSSL_ROOT)/libcrypto-3.dll \ | |
$(OPENSSL_ROOT)/libssl-3.dll | |
OPENSSL_PDBs = $(OPENSSL_DLLs:.dll=.pdb) | |
$(OBJ_DIR)/_hashopenssl.obj: EXTRA_CFLAGS += -DCOMPILING_HASH_OPENSSL | |
DLLs/_hashlib.pyd: $(OBJ_DIR)/_hashopenssl.obj $(OBJ_DIR)/_hashlib.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(OPENSSL_ROOT)/libcrypto.lib) | |
DLLs/_ssl.pyd: $(OBJ_DIR)/_ssl.obj $(OBJ_DIR)/applink.obj $(OBJ_DIR)/_ssl.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(OPENSSL_ROOT)/libcrypto.lib $(OPENSSL_ROOT)/libssl.lib crypt32.lib $(WS2_32_LIB)) | |
################################################################################################## | |
_testcapi_SRC = Modules/_testcapimodule.c | |
_testcapi_SRC += $(addprefix Modules/_testcapi/, \ | |
abstract.c \ | |
buffer.c \ | |
bytearray.c \ | |
bytes.c \ | |
code.c \ | |
codec.c \ | |
complex.c \ | |
datetime.c \ | |
dict.c \ | |
docstring.c \ | |
exceptions.c \ | |
file.c \ | |
float.c \ | |
gc.c \ | |
getargs.c \ | |
hash.c \ | |
heaptype.c \ | |
heaptype_relative.c \ | |
immortal.c \ | |
list.c \ | |
long.c \ | |
mem.c \ | |
numbers.c \ | |
pyatomic.c \ | |
pyos.c \ | |
set.c \ | |
structmember.c \ | |
sys.c \ | |
time.c \ | |
tuple.c \ | |
unicode.c \ | |
vectorcall.c \ | |
vectorcall_limited.c \ | |
watchers.c) | |
_testcapi_OBJ = $(call c_to_obj, $(_testcapi_SRC), _testcapi/) | |
$(OBJ_DIR)/_testcapi/_testcapimodule.obj: Modules/_testcapimodule.c | $(CC).args $(OBJ_DIR)/_testcapi | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/_testcapi/%.obj: Modules/_testcapi/%.c | $(CC).args $(OBJ_DIR)/_testcapi | |
$(call C_compile, $@, $<) | |
DLLs/_testcapi.pyd: $(_testcapi_OBJ) $(OBJ_DIR)/_testcapi.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, -export:PyInit__testcapi $^) | |
################################################################################################## | |
_testinternalcapi_SRC = Modules/_testinternalcapi.c | |
_testinternalcapi_SRC += $(addprefix Modules/_testinternalcapi/, \ | |
pytime.c \ | |
set.c \ | |
test_critical_sections.c \ | |
test_lock.c) | |
_testinternalcapi_OBJ = $(call c_to_obj, $(_testinternalcapi_SRC), _testinternalcapi/) | |
_testinternalcapi_I = $(call c_to_i, $(_testinternalcapi_SRC), _testinternalcapi_) | |
$(_testinternalcapi_OBJ) \ | |
$(_testinternalcapi_I): EXTRA_CFLAGS = -DPy_BUILD_CORE_BUILTIN -DPy_BUILD_CORE_MODULE | |
# | |
# How on earth does '-DPy_DEBUG' become effective here? | |
# | |
ifeq ($(USE_PY_DEBUG),0) | |
$(_testinternalcapi_OBJ) \ | |
$(_testinternalcapi_I): EXTRA_CFLAGS += -UPy_DEBUG | |
endif | |
$(OBJ_DIR)/_testinternalcapi/_testinternalcapi.obj: Modules/_testinternalcapi.c | $(CC).args $(OBJ_DIR)/_testinternalcapi | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/_testinternalcapi/%.obj: Modules/_testinternalcapi/%.c | $(CC).args $(OBJ_DIR)/_testinternalcapi | |
$(call C_compile, $@, $<) | |
DLLs/_testinternalcapi.pyd: $(_testinternalcapi_OBJ) $(OBJ_DIR)/_testinternalcapi.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, -export:PyInit__testinternalcapi $^) | |
################################################################################################## | |
_SQLITE3_SRC = $(addprefix Modules/_sqlite/, \ | |
blob.c \ | |
connection.c \ | |
cursor.c \ | |
microprotocols.c \ | |
module.c \ | |
prepare_protocol.c \ | |
row.c \ | |
statement.c \ | |
util.c) | |
_SQLITE3_OBJ = $(call c_to_obj, $(_SQLITE3_SRC), _sqlite3/) | |
_SQLITE3_I = $(call c_to_i, $(_SQLITE3_SRC),) | |
$(_SQLITE3_OBJ) $(_SQLITE3_I): EXTRA_CFLAGS = -I$(SQLITE3_ROOT) -DMODULE_NAME=\"sqlite3\" | |
ifeq ($(CC)-$(USE_MP_COMPILE),cl-1) | |
$(_SQLITE3_OBJ): $(_SQLITE3_SRC) | $(CC).args $(OBJ_DIR)/_sqlite3 | |
$(call C_compile_MP, $(OBJ_DIR)/_sqlite3\\, $(_SQLITE3_SRC)) | |
else | |
$(OBJ_DIR)/_sqlite3/%.obj: Modules/_sqlite/%.c | $(CC).args $(OBJ_DIR)/_sqlite3 | |
$(call C_compile, $@, $<) | |
endif | |
DLLs/_sqlite3.pyd: $(_SQLITE3_OBJ) $(OBJ_DIR)/_sqlite3.res $(SQLITE3_LIB) $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
$(OBJ_DIR)/_sqlite3.res: PC/python_nt.rc | |
$(call create_res_file, $@, _sqlite3.pyd, $<,) | |
################################################################################################## | |
SQLITE3_SRC = $(SQLITE3_ROOT)/sqlite3.c | |
SQLITE3_OBJ = $(call c_to_obj, $(SQLITE3_SRC), sqlite3/) | |
SQLITE3_I = $(call c_to_i, $(SQLITE3_SRC),) | |
$(SQLITE3_OBJ) $(SQLITE3_I): EXTRA_CFLAGS = -DCOMPILING_SQLITE3 | |
SQLITE3_RCFLAGS = -DSQLITE_MAJOR_VERSION=$(SQLITE3_MAJOR_VERSION) \ | |
-DSQLITE_MINOR_VERSION=$(SQLITE3_MINOR_VERSION) \ | |
-DSQLITE_MICRO_VERSION=$(SQLITE3_MICRO_VERSION) \ | |
-DSQLITE_PATCH_VERSION=0 \ | |
-DSQLITE_VERSION=$(SQLITE3_MAJOR_VERSION).$(SQLITE3_MINOR_VERSION).$(SQLITE3_MICRO_VERSION) | |
$(OBJ_DIR)/sqlite3/sqlite3.obj: $(SQLITE3_ROOT)/sqlite3.c | $(CC).args $(OBJ_DIR)/sqlite3 | |
$(call C_compile, $@, $<) | |
$(SQLITE3_LIB): DLLs/sqlite3.dll | |
DLLs/sqlite3.dll: $(OBJ_DIR)/sqlite3/sqlite3.obj $(OBJ_DIR)/sqlite3.res | check-for-unused-libs.py | |
$(call link_DLL, $@, -subsystem:console $^, $(SQLITE3_LIB)) | |
$(OBJ_DIR)/sqlite3.res: PC/sqlite3.rc | |
$(call create_res_file, $@, sqlite3.dll, $<, $(SQLITE3_RCFLAGS)) | |
################################################################################################## | |
BZIP2_SRC = Modules/_bz2module.c \ | |
$(addprefix $(BZIP2_ROOT)/, \ | |
blocksort.c \ | |
bzlib.c \ | |
compress.c \ | |
crctable.c \ | |
decompress.c \ | |
huffman.c \ | |
randtable.c) | |
BZIP2_OBJ = $(call c_to_obj, $(BZIP2_SRC), bzip2/) | |
BZIP2_I = $(call c_to_i, $(BZIP2_SRC),) | |
$(BZIP2_OBJ) $(BZIP2_I): EXTRA_CFLAGS = -I$(BZIP2_ROOT) | |
$(OBJ_DIR)/bzip2/_bz2module.obj: Modules/_bz2module.c | $(CC).args $(OBJ_DIR)/bzip2 | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/bzip2/%.obj: $(BZIP2_ROOT)/%.c | $(CC).args $(OBJ_DIR)/bzip2 | |
$(call C_compile, $@, $<) | |
DLLs/_bz2.pyd: $(BZIP2_OBJ) $(OBJ_DIR)/_bz2.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
################################################################################################## | |
ZLIB_SRC = $(addprefix $(ZLIB_ROOT)/, \ | |
adler32.c \ | |
compress.c \ | |
crc32.c \ | |
deflate.c \ | |
gzclose.c \ | |
gzlib.c \ | |
gzread.c \ | |
gzwrite.c \ | |
infback.c \ | |
inffast.c \ | |
inflate.c \ | |
inftrees.c \ | |
trees.c \ | |
uncompr.c \ | |
zutil.c) | |
# | |
# Drop most of 'Include/pyconfig.h' for '$(ZLIB_SRC)': | |
# | |
ZLIB_CFLAGS = -DCOMPILING_ZLIB -DHAVE_STDARG_H -DZLIB_CONST | |
ZLIB_OBJ = $(call c_to_obj, $(ZLIB_SRC), zlib/) | |
ZLIB_I = $(call c_to_i, $(ZLIB_SRC),) | |
$(ZLIB_OBJ) $(ZLIB_I): EXTRA_CFLAGS = $(ZLIB_CFLAGS) | |
$(ZLIB_LIB): $(ZLIB_OBJ) | |
$(call create_lib, $@, $^) | |
ifeq ($(CC)-$(USE_MP_COMPILE),cl-1) | |
$(ZLIB_OBJ): $(ZLIB_SRC) | $(CC).args $(OBJ_DIR)/zlib | |
$(call C_compile_MP, $(OBJ_DIR)/zlib\\, $(ZLIB_SRC)) | |
else | |
$(OBJ_DIR)/zlib/%.obj: $(ZLIB_ROOT)/%.c | $(CC).args $(OBJ_DIR)/zlib | |
$(call C_compile, $@, $<) | |
endif | |
################################################################################################## | |
ELEMENTTREE_SRC = $(addprefix Modules/expat/, \ | |
xmlparse.c \ | |
xmlrole.c \ | |
xmltok.c \ | |
xmltok_impl.c \ | |
xmltok_ns.c) | |
ELEMENTTREE_OBJ = $(call c_to_obj, $(ELEMENTTREE_SRC), elementtree/) | |
ELEMENTTREE_I = $(call c_to_i, $(ELEMENTTREE_SRC),) | |
# | |
# Also used for 'PYEXPAT_SRC': | |
# | |
EXPAT_CFLAGS = -I./Modules/expat -DCOMPILING_EXPAT | |
$(ELEMENTTREE_OBJ) \ | |
$(ELEMENTTREE_I): EXTRA_CFLAGS = $(EXPAT_CFLAGS) | |
$(OBJ_DIR)/elementtree/%.obj: %.c | $(CC).args $(OBJ_DIR)/elementtree | |
$(call C_compile, $@, $<) | |
DLLs/_elementtree.pyd: $(ELEMENTTREE_OBJ) $(OBJ_DIR)/_elementree.res | |
$(call link_PYD, $@, $^) | |
################################################################################################## | |
CTYPES_SRC = $(addprefix Modules/_ctypes/, \ | |
_ctypes.c \ | |
callbacks.c \ | |
callproc.c \ | |
cfield.c \ | |
malloc_closure.c \ | |
stgdict.c) | |
CTYPES_OBJ = $(call c_to_obj, $(CTYPES_SRC), ctypes/) | |
CTYPES_I = $(call c_to_i, $(CTYPES_SRC),) | |
CTYPES_CFLAGS = -DPy_BUILD_CORE_MODULE -DUSING_MALLOC_CLOSURE_DOT_C=1 -I$(LIBFFI_ROOT)/$(WIN_AMD)/include # -DFFI_BUILDING | |
CTYPES_LDFLAGS = -export:DllGetClassObject,PRIVATE \ | |
-export:DllCanUnloadNow,PRIVATE | |
$(CTYPES_OBJ) $(CTYPES_I): EXTRA_CFLAGS += $(CTYPES_CFLAGS) | |
LIBFFI_LIB = $(LIBFFI_ROOT)/$(WIN_AMD)/libffi-8.lib | |
LIBFFI_DLL = $(LIBFFI_ROOT)/$(WIN_AMD)/libffi-8.dll | |
$(OBJ_DIR)/ctypes/%.obj: %.c | $(CC).args $(OBJ_DIR)/ctypes | |
$(call C_compile, $@, $<) | |
DLLs/_ctypes.pyd: $(CTYPES_OBJ) $(OBJ_DIR)/_ctypes.res $(PY_IMP_LIB) $(LIBFFI_LIB) | |
$(call link_PYD, $@, $(CTYPES_LDFLAGS) $^ ole32.lib oleaut32.lib uuid.lib) | |
DLLs/_ctypes_test.pyd: $(OBJ_DIR)/_ctypes_test.obj $(OBJ_DIR)/_ctypes_test.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ oleaut32.lib uuid.lib) | |
################################################################################################## | |
DECIMAL_C_SRC = $(addprefix Modules/_decimal/, \ | |
_decimal.c \ | |
$(addprefix libmpdec/, \ | |
basearith.c \ | |
constants.c \ | |
context.c \ | |
convolute.c \ | |
crt.c \ | |
difradix2.c \ | |
fnt.c \ | |
fourstep.c \ | |
io.c \ | |
mpalloc.c \ | |
mpdecimal.c \ | |
numbertheory.c \ | |
sixstep.c \ | |
transpose.c)) | |
DECIMAL_C_SRC += $(OBJ_DIR)/decimal/hacks.c | |
DECIMAL_CFLAGS = -DMASM \ | |
-DCONFIG_$(BITS) \ | |
-I./Modules/_decimal/libmpdec | |
ifeq ($(BITS),64) | |
DECIMAL_ASM_SRC = Modules/_decimal/libmpdec/vcdiv64.asm | |
ifeq ($(CC),clang-cl) | |
# clang_runtime = clang_rt.builtins-x86_64.lib | |
endif | |
else | |
DECIMAL_CFLAGS += -DPPRO | |
DECIMAL_ASM_SRC = | |
endif | |
clang_runtime ?= | |
DECIMAL_C_OBJ = $(call c_to_obj, $(DECIMAL_C_SRC), decimal/) | |
DECIMAL_ASM_OBJ = $(call asm_to_obj, $(DECIMAL_ASM_SRC), decimal/) | |
DECIMAL_I = $(call c_to_i, $(DECIMAL_C_SRC), decimal_) | |
$(DECIMAL_C_OBJ) $(DECIMAL_I): EXTRA_CFLAGS = $(DECIMAL_CFLAGS) | |
ifeq ($(CC)-$(USE_MP_COMPILE),cl-1) | |
$(DECIMAL_C_OBJ): $(DECIMAL_C_SRC) | $(CC).args $(OBJ_DIR)/decimal | |
$(call C_compile_MP, $(OBJ_DIR)/decimal\\, $(DECIMAL_C_SRC)) | |
else | |
$(OBJ_DIR)/decimal/hacks.obj: $(OBJ_DIR)/decimal/hacks.c | $(CC).args $(OBJ_DIR)/decimal | |
$(call C_compile, $@, $<) | |
endif | |
$(OBJ_DIR)/decimal/%.obj: Modules/_decimal/%.c | $(CC).args $(OBJ_DIR)/decimal | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/decimal/%.obj: Modules/_decimal/libmpdec/%.c | $(CC).args $(OBJ_DIR)/decimal | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/decimal/vcdiv64.obj: Modules/_decimal/libmpdec/vcdiv64.asm $(OBJ_DIR)/decimal | |
$(call assemble_x64, $@, $<) | |
DLLs/_decimal.pyd: $(DECIMAL_C_OBJ) $(DECIMAL_ASM_OBJ) $(OBJ_DIR)/_decimal.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(clang_runtime)) | |
################################################################################################## | |
LZMA_SRC = Modules/_lzmamodule.c \ | |
$(addprefix $(LZMA_ROOT)/src/, \ | |
common/tuklib_cpucores.c \ | |
common/tuklib_physmem.c \ | |
liblzma/check/check.c \ | |
liblzma/check/crc32_fast.c \ | |
liblzma/check/crc32_table.c \ | |
liblzma/check/crc64_fast.c \ | |
liblzma/check/crc64_table.c \ | |
liblzma/check/sha256.c \ | |
liblzma/common/alone_decoder.c \ | |
liblzma/common/alone_encoder.c \ | |
liblzma/common/auto_decoder.c \ | |
liblzma/common/block_buffer_decoder.c \ | |
liblzma/common/block_buffer_encoder.c \ | |
liblzma/common/block_decoder.c \ | |
liblzma/common/block_encoder.c \ | |
liblzma/common/block_header_decoder.c \ | |
liblzma/common/block_header_encoder.c \ | |
liblzma/common/block_util.c \ | |
liblzma/common/common.c \ | |
liblzma/common/easy_buffer_encoder.c \ | |
liblzma/common/easy_decoder_memusage.c \ | |
liblzma/common/easy_encoder.c \ | |
liblzma/common/easy_encoder_memusage.c \ | |
liblzma/common/easy_preset.c \ | |
liblzma/common/filter_buffer_decoder.c \ | |
liblzma/common/filter_buffer_encoder.c \ | |
liblzma/common/filter_common.c \ | |
liblzma/common/filter_decoder.c \ | |
liblzma/common/filter_encoder.c \ | |
liblzma/common/filter_flags_decoder.c \ | |
liblzma/common/filter_flags_encoder.c \ | |
liblzma/common/hardware_physmem.c \ | |
liblzma/common/index.c \ | |
liblzma/common/index_decoder.c \ | |
liblzma/common/index_encoder.c \ | |
liblzma/common/index_hash.c \ | |
liblzma/common/outqueue.c \ | |
liblzma/common/stream_flags_common.c \ | |
liblzma/common/stream_buffer_decoder.c \ | |
liblzma/common/stream_encoder.c \ | |
liblzma/common/stream_buffer_encoder.c \ | |
liblzma/common/stream_decoder.c \ | |
liblzma/common/stream_flags_encoder.c \ | |
liblzma/common/stream_flags_decoder.c \ | |
liblzma/common/vli_decoder.c \ | |
liblzma/common/vli_encoder.c \ | |
liblzma/common/vli_size.c \ | |
liblzma/delta/delta_common.c \ | |
liblzma/delta/delta_decoder.c \ | |
liblzma/delta/delta_encoder.c \ | |
liblzma/lzma/fastpos_table.c \ | |
liblzma/lzma/lzma2_decoder.c \ | |
liblzma/lzma/lzma2_encoder.c \ | |
liblzma/lzma/lzma_decoder.c \ | |
liblzma/lzma/lzma_encoder.c \ | |
liblzma/lzma/lzma_encoder_optimum_fast.c \ | |
liblzma/lzma/lzma_encoder_optimum_normal.c \ | |
liblzma/lzma/lzma_encoder_presets.c \ | |
liblzma/lz/lz_decoder.c \ | |
liblzma/lz/lz_encoder.c \ | |
liblzma/lz/lz_encoder_mf.c \ | |
liblzma/rangecoder/price_table.c \ | |
liblzma/simple/arm.c \ | |
liblzma/simple/armthumb.c \ | |
liblzma/simple/ia64.c \ | |
liblzma/simple/powerpc.c \ | |
liblzma/simple/simple_coder.c \ | |
liblzma/simple/simple_decoder.c \ | |
liblzma/simple/simple_encoder.c \ | |
liblzma/simple/sparc.c \ | |
liblzma/simple/x86.c) | |
ifeq ($(CC),clang-cl) | |
LZMA_SRC += $(OBJ_DIR)/lzma/hacks.c | |
endif | |
LZMA_OBJ = $(call c_to_obj, $(LZMA_SRC), lzma/) | |
LZMA_I = $(call c_to_i, $(LZMA_SRC), lzma_) | |
LZMA_CFLAGS = -I$(LZMA_ROOT)/include \ | |
-I$(LZMA_ROOT)/src/common \ | |
-I$(LZMA_ROOT)/src/liblzma/common \ | |
-I$(LZMA_ROOT)/src/liblzma/api \ | |
-I$(LZMA_ROOT)/src/liblzma/check \ | |
-I$(LZMA_ROOT)/src/liblzma/lzma \ | |
-I$(LZMA_ROOT)/src/liblzma/lz \ | |
-I$(LZMA_ROOT)/src/liblzma/delta \ | |
-I$(LZMA_ROOT)/src/liblzma/simple \ | |
-I$(LZMA_ROOT)/src/liblzma/rangecoder \ | |
-I$(LZMA_ROOT)/windows \ | |
-DHAVE_CONFIG_H \ | |
-DLZMA_API_STATIC | |
$(LZMA_OBJ) $(LZMA_I): EXTRA_CFLAGS = $(LZMA_CFLAGS) | |
ifeq ($(CC)-$(USE_MP_COMPILE),cl-1) | |
$(LZMA_OBJ): $(LZMA_SRC) | $(CC).args $(OBJ_DIR)/lzma | |
$(call C_compile_MP, $(OBJ_DIR)/lzma\\, $(LZMA_SRC)) | |
else | |
$(OBJ_DIR)/lzma/%.obj: %.c | $(CC).args $(OBJ_DIR)/lzma | |
$(call C_compile, $@, $<) | |
endif | |
DLLs/_lzma.pyd: $(LZMA_OBJ) $(OBJ_DIR)/_lzma.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
################################################################################################## | |
PYEXPAT_SRC = $(addprefix Modules/, \ | |
pyexpat.c \ | |
expat/xmlparse.c \ | |
expat/xmlrole.c \ | |
expat/xmltok.c) | |
PYEXPAT_OBJ = $(call c_to_obj, $(PYEXPAT_SRC), pyexpat/) | |
PYEXPAT_I = $(call c_to_i, $(PYEXPAT_SRC), pyexpat_) | |
$(PYEXPAT_OBJ) $(PYEXPAT_I): EXTRA_CFLAGS = $(EXPAT_CFLAGS) | |
$(OBJ_DIR)/pyexpat/%.obj: %.c | $(CC).args $(OBJ_DIR)/pyexpat | |
$(call C_compile, $@, $<) | |
DLLs/pyexpat.pyd: $(PYEXPAT_OBJ) $(OBJ_DIR)/pyexpat.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
################################################################################################## | |
TKINTER_SRC = Modules/_tkinter.c \ | |
Modules/tkappinit.c | |
TKINTER_OBJ = $(call c_to_obj, $(TKINTER_SRC),) | |
TKINTER_I = $(call c_to_i, $(TKINTER_SRC),) | |
TCLTK_DLLs = $(TCLTK_ROOT)/bin/tk86t.dll \ | |
$(TCLTK_ROOT)/bin/tcl86t.dll | |
TKINTER_LIBS = $(TCLTK_ROOT)/lib/tcl86t.lib \ | |
$(TCLTK_ROOT)/lib/tk86t.lib | |
TKINTER_CFLAGS = -I$(TCLTK_ROOT)/include -DWITH_APPINIT | |
$(TKINTER_OBJ) $(TKINTER_I): EXTRA_CFLAGS = $(TKINTER_CFLAGS) | |
DLLs/_tkinter.pyd: $(TKINTER_OBJ) $(OBJ_DIR)/_tkinter.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^ $(TKINTER_LIBS)) | |
# | |
# The below $(SECONDARY_OBJ) will get deleted after 'all' is done. | |
# To prevent that, define them as a '.SECONDARY' list of files. | |
# | |
SECONDARY_OBJ = $(addprefix $(OBJ_DIR)/, \ | |
_asynciomodule.obj \ | |
_asynciomodule.res \ | |
_contextvarsmodule.obj \ | |
_contextvarsmodule.res \ | |
_ctypes_test.obj \ | |
_ctypes_test.res \ | |
_randommodule.obj \ | |
_randommodule.res \ | |
_testbuffer.obj \ | |
_testbuffer.res \ | |
_testimportmultiple.obj \ | |
_testimportmultiple.res \ | |
_testconsole.obj \ | |
_testconsole.res \ | |
_testclinic.obj \ | |
_testclinic.res \ | |
_testclinic_limited.obj \ | |
_testclinic_limited.res \ | |
_testinternalcapi.obj \ | |
_testinternalcapi.res \ | |
_testcapimodule.obj \ | |
_testcapimodule.res \ | |
_testmultiphase.obj \ | |
_testmultiphase.res \ | |
_testsinglephase.obj \ | |
_testsinglephase.res \ | |
_abcmodule.res) | |
# SECONDARY_OBJ += $(OBJ_DIR)/_xxsubinterpretersmodule.obj \ | |
# $(OBJ_DIR)/_xxsubinterpretersmodule.res | |
.SECONDARY: $(SECONDARY_OBJ) | |
# | |
# These rules will match the "easy" PYDs. | |
# Like 'DLLs/_asyncio.pyd' and 'DLLs/_testclinic*.pyd' etc. | |
# | |
DLLs/_%.pyd: $(OBJ_DIR)/%module.obj $(OBJ_DIR)/%module.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
DLLs/_%.pyd: $(OBJ_DIR)/_%module.obj $(OBJ_DIR)/_%module.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
DLLs/_%.pyd: $(OBJ_DIR)/_%.obj $(OBJ_DIR)/_%.res $(PY_IMP_LIB) | |
$(call link_PYD, $@, $^) | |
# | |
# All objects go into '$(OBJ_DIR)' or sub-dirs under it. | |
# | |
$(OBJ_DIR)/core/%.obj: %.c | $(CC).args $(OBJ_DIR)/core | |
$(call C_compile, $@, $<) | |
# | |
# For .c-files in the 'VPATH': | |
# | |
$(OBJ_DIR)/%.obj: %.c | $(CC).args $(OBJ_DIR) | |
$(call C_compile, $@, $<) | |
# | |
# Compile .res files from the generated '$(OBJ_DIR)/pythonnt_rc.h' and | |
# respective .rc-file. | |
# | |
# The .EXE-files have their own .rc-files, but all .DLLs (except 'DLLs/sqlite3.dll') and .PYDs depends | |
# simply on 'PC/python_nt.rc'. | |
# | |
$(OBJ_DIR)/python_exe.res: PC/python_exe.rc | |
$(call create_res_file, $@, python.exe, $<,) | |
$(OBJ_DIR)/pythonw_exe.res: PC/pythonw_exe.rc | |
$(call create_res_file, $@, pythonw.exe, $<,) | |
res_deps = PC/pylauncher.rc \ | |
PC/python_ver_rc.h \ | |
PC/python.manifest \ | |
$(wildcard PC/icons/*.ico) | |
$(OBJ_DIR)/py.res: $(res_deps) | |
$(call create_res_file, $@, py.exe, $<,) | |
$(OBJ_DIR)/pyw.res: $(res_deps) | |
$(call create_res_file, $@, pyw.exe, $<,) | |
$(OBJ_DIR)/python$(_PY_VER).res: PC/python_nt.rc | |
$(call create_res_file, $@, $(PYTHON_DLL), $<,) | |
$(OBJ_DIR)/python3dll.res: PC/python_nt.rc | |
$(call create_res_file, $@, python3.dll, $<,) | |
$(OBJ_DIR)/venvlauncher.res: $(res_deps) | |
$(call create_res_file, $@, venvlauncher.exe, $<, -DPY_ICON) | |
$(OBJ_DIR)/venvwlauncher.res: $(res_deps) | |
$(call create_res_file, $@, venvwlauncher.exe, $<, -DPYW_ICON) | |
# | |
# A "match all" rule for .res-files in PYD-files. | |
# E.g. a '$(OBJ_DIR)/_socket.res' uses this rule. | |
# | |
# TODO: add a 'create_rc_file' macro for more sensible " FileDescription". | |
# Not simply "FileDescription: Python Core" for most .PYDs | |
# | |
$(OBJ_DIR)/%.res: PC/python_nt.rc | |
$(call create_res_file, $@, $*.pyd, $<,) | |
$(OBJ_DIR)/pythonnt_rc.h: $(THIS_FILE) | $(OBJ_DIR) | |
$(call generate, $@, //) | |
$(file >> $@,$(PYTHONNT_RC_H)) | |
########################################################################## | |
pyshellext.i: EXTRA_CFLAGS = -DCOMPILING_PYSHELLEXT | |
pyshellext.dll: PC/pyshellext.def $(OBJ_DIR)/pyshellext.obj | check-for-unused-libs.py | |
$(call link_DLL, $@, -def:$^ user32.lib shell32.lib shlwapi.lib advapi32.lib mincore.lib, $(PY_SHELLEXT_LIB)) | |
$(OBJ_DIR)/pyshellext.obj: PC/pyshellext.cpp | $(CC).args | |
$(call CPP_compile, $@, -DCOMPILING_PYSHELLEXT $<) | |
########################################################################## | |
DLLs/_wmi.pyd: $(OBJ_DIR)/_wmimodule.obj $(OBJ_DIR)/_wmi.res $(PY_IMP_LIB) | check-for-unused-libs.py | |
$(call link_PYD, $@, -nodefaultlib:user32.lib $^ propsys.lib wbemuuid.lib) | |
$(OBJ_DIR)/_wmimodule.obj: PC/_wmimodule.cpp | $(CC).args | |
$(call CPP_compile, $@, $<) | |
########################################################################## | |
copy_into_DLLs: | |
$(call copy_files, ./DLLs, $(LIBFFI_DLL) $(OPENSSL_DLLs) $(OPENSSL_PDBs) $(TCLTK_DLLs)) | |
$(call copy_files, $(TCL_ROOT), $(TCLTK_ROOT)/lib/tcl8.6/init.tcl) | |
########################################################################## | |
clean: rm_frozen | |
rm -fr $(OBJ_DIR) | |
- rmdir obj | |
rm -f $(GENERATED) .depend.tmp cpp-filter.py check-for-unused-libs.py vc1*.pdb \ | |
link.args link.tmp Python.reg python.bat pythonw.bat \ | |
cl.args clang-cl.args clang-cl-32.bat clang-cl-64.bat install.bat | |
# | |
# Cleanup after a Cygwin build via 'gv-build-cygwin.bat'. | |
# Not called here. Use as needed. | |
# | |
clean_cygwin: | |
$(call green_msg, Cleaning up after Cygwin.) | |
rm -f config.log config.status Makefile.pre Misc/python-config.sh Misc/python-embed.pc Misc/python.pc | |
rm -f Modules/ld_so_aix Modules/Setup.bootstrap Modules/Setup.local Modules/Setup.stdlib | |
@echo | |
realclean vclean: clean clean_doc clean_tests clean_pycaches | |
rm -f python3*.{dll,map,pdb} pyshellext.{dll,map,pdb} .depend.Windows | |
rm -f $(PROGRAMS:.exe=.{exe,pdb,map}) $(BOOTSTRAP_PYTHON:.exe=.{exe,pdb,map}) | |
rm -fr $(TCL_ROOT) DLLs libs PCBuild/win32 PCBuild/amd64 | |
# | |
# Clean-up after running 'Lib/tests/test_*.py' and 'Lib/tests/libregrtest/*.py' scripts: | |
# | |
PYCACHE_DIRS = __pycache__ \ | |
Doc/tools/extensions/__pycache__ \ | |
Lib/__pycache__ \ | |
Parser/__pycache__ \ | |
Tools/scripts/__pycache__ \ | |
$(addprefix Lib/, \ | |
$(addsuffix /__pycache__, \ | |
asyncio \ | |
collections \ | |
concurrent \ | |
concurrent/futures \ | |
ctypes \ | |
email \ | |
email/mime \ | |
encodings \ | |
ensurepip \ | |
http \ | |
importlib \ | |
importlib/resources \ | |
json \ | |
logging \ | |
multiprocessing \ | |
multiprocessing/dummy \ | |
test \ | |
test/test_asyncio \ | |
test/encoded_modules \ | |
test/test_email \ | |
test/test_import \ | |
test/test_importlib \ | |
test/test_importlib/builtin \ | |
test/test_importlib/data \ | |
test/test_importlib/data/unwritable \ | |
test/test_importlib/data01 \ | |
test/test_importlib/data01/subdirectory \ | |
test/test_importlib/data02 \ | |
test/test_importlib/data02/one \ | |
test/test_importlib/data02/two \ | |
test/test_importlib/data03 \ | |
test/test_importlib/extension \ | |
test/test_importlib/frozen \ | |
test/test_importlib/import_ \ | |
test/test_importlib/source \ | |
test/test_importlib/zipdata01 \ | |
test/test_importlib/zipdata02 \ | |
test/test_json \ | |
test/leakers \ | |
test/libregrtest \ | |
test/support \ | |
test/test_tools \ | |
test/test_tools/test_c_analyzer \ | |
test/test_tools/test_c_analyzer/test_common \ | |
test/test_tools/test_c_analyzer/test_cpython \ | |
test/test_tools/test_c_analyzer/test_parser \ | |
test/test_tools/test_c_analyzer/test_symbols \ | |
test/test_tools/test_c_analyzer/test_variables \ | |
test/test_warnings \ | |
test/tracedmodules \ | |
unittest \ | |
urllib \ | |
xml \ | |
xml/etree)) | |
TEST_DATA_FILES = $(addprefix Lib/test/data/, \ | |
BIG5.TXT \ | |
BIG5HKSCS-2004.TXT \ | |
CP932.TXT \ | |
CP936.TXT \ | |
CP949.TXT \ | |
CP950.TXT \ | |
EUC-CN.TXT \ | |
EUC-JISX0213.TXT \ | |
EUC-JP.TXT \ | |
EUC-KR.TXT \ | |
gb-18030-2000.xml \ | |
JOHAB.TXT \ | |
SHIFT_JISX0213.TXT \ | |
SHIFTJIS.TXT \ | |
blake2b.txt \ | |
blake2s.txt \ | |
NamedSequences.txt \ | |
NormalizationTest.txt \ | |
sha3_224.txt \ | |
sha3_256.txt \ | |
sha3_384.txt \ | |
sha3_512.txt \ | |
shake_128.txt \ | |
shake_256.txt) | |
TEST_DATA_FILES += $(addprefix Lib/lib2to3/, \ | |
Grammar*.pickle \ | |
PatternGrammar*.pickle) | |
TEST_DATA_FILES += run_tests_1.results \ | |
run_tests_2.results \ | |
run_tests_3.results \ | |
run_tests_4.results \ | |
embedded_tests.results | |
define delete_dir | |
echo -e '$(BRIGHT_GREEN)Deleting $(BRIGHT_WHITE)$(strip $(1))/*\e[0m' | |
rm -fr $(strip $(1)) | |
endef | |
clean_tests: | |
- rmdir build | |
$(call green_msg, Deleting $(BRIGHT_WHITE)TEST_DATA_FILES) | |
rm -f $(TEST_DATA_FILES) | |
clean_pycaches: | |
@$(foreach d, $(PYCACHE_DIRS), $(call delete_dir, $(d)) ; ) | |
install: install.bat $(THIS_FILE) | |
install.bat: check_echo py.exe Python.reg | |
$(call generate, $@,::) | |
$(file >> $@,$(INSTALL_BAT)) | |
$(call green_msg, Execute '$@' at own risk.) | |
# | |
# Generate these .bat-files to compile with correct 'clang-cl'. | |
# | |
clang-cl-32.bat: $(THIS_FILE) | |
$(call generate, $@,::) | |
$(file >> $@, @$(_CMDPROC)) | |
$(file >> $@, @$(CLANG_CL32_ROOT_WIN)\bin\clang-cl.exe %*) | |
clang-cl-64.bat: $(THIS_FILE) | |
$(call generate, $@,::) | |
$(file >> $@, @$(_CMDPROC)) | |
$(file >> $@, @$(CLANG_CL64_ROOT_WIN)\bin\clang-cl.exe %*) | |
# | |
# MSVC 32/64-bit selection without the 'vcvarsall.bat' stupidity. | |
# Assumes Visual-Studio 2017+ layout. | |
# | |
ifeq ($(CC),cl) | |
_CC = $(VC_ROOT)/bin/HostX86/$(CPU)/cl.exe | |
else | |
# | |
# This .bat file is generated early in 'all:' | |
# | |
_CC = clang-cl-$(BITS).bat | |
endif | |
vpath %.c $(ZLIB_ROOT) $(BZIP2_ROOT) $(SQLITE3_ROOT) | |
# | |
# The resulting .c.i file could be compiled with 'cl -c -Tc foo.i' | |
# The resulting .cpp.i file could be compiled with 'cl -c -Tp foo.i' | |
# | |
# vpath %.i Modules/_decimal/libmpdec | |
%.i: Modules/_decimal/libmpdec/%.c FORCE cpp-filter.py $(GENERATED) # $(FROZEN_GENERATED) | |
$(call CXX_preprocess, $@, $<, c) | |
%.i: %.c FORCE cpp-filter.py $(GENERATED) # $(FROZEN_GENERATED) | |
$(call CXX_preprocess, $@, $<, c) | |
%.i: %.cpp FORCE cpp-filter.py $(GENERATED) $(FROZEN_GENERATED) | |
$(call CXX_preprocess, $@, -TP $<, cpp) | |
FORCE: | |
cpp-filter.py: $(THIS_FILE) | |
$(call generate_PY,$@,$(CPP_FILTER_PY)) | |
check-for-unused-libs.py: $(THIS_FILE) | |
$(call generate_PY,$@,$(CHECK_FOR_UNUSED_LIBS_PY)) | |
Include/pyconfig.h: $(THIS_FILE) | |
$(call generate, $@, //) | |
$(file >> $@,$(PY_CONFIG_H)) | |
$(OBJ_DIR)/pyconfig.h: PC/pyconfig.h.in $(THIS_FILE) | |
$(call generate, $@, //) | |
cat $< >> $@ | |
@echo | |
$(OBJ_DIR)/decimal/hacks.c: $(THIS_FILE) | |
$(call generate, $@, //) | |
$(file >> $@,$(DEC_HACKS_C)) | |
$(OBJ_DIR)/jit_stencils.h: $(THIS_FILE) Tools/jit/*.c Tools/jit/*.py Python/executor_cases.c.h Include/pyconfig.h | |
$(call green_msg, Generating '$@' using 'Tools/jit/build.py') | |
$(PYTHON) Tools/jit/build.py | |
@echo | |
$(OBJ_DIR)/lzma/hacks.c: $(THIS_FILE) | |
$(call generate, $@, //) | |
$(file >> $@,$(LZ_HACKS_C)) | |
$(CC).args: $(THIS_FILE) | |
$(call green_msg, Creating $@) | |
$(call create_resp_file, $@, -c $(CFLAGS)) | |
# | |
# GNU-make macros: | |
# | |
# The following codes used in macro 'colour_msg' assumes you have | |
# MSys/Cygwin's echo with colour support. | |
# | |
BRIGHT_RED = \e[1;31m | |
BRIGHT_GREEN = \e[1;32m | |
BRIGHT_WHITE = \e[1;37m | |
colour_msg = @echo -e "$(1)\e[0m" | |
green_msg = $(call colour_msg,$(BRIGHT_GREEN)$(strip $(1))) | |
green_msg0 = $(call colour_msg,$(BRIGHT_GREEN)$(1)) | |
white_msg = $(call colour_msg,$(BRIGHT_WHITE)$(strip $(1))) | |
define generate | |
$(call green_msg, Generating $(1)) | |
$(file > $(1), $(2)) | |
$(file >> $(1), $(2) DO NOT EDIT! This file was automatically generated) | |
$(file >> $(1), $(2) from $(realpath $(THIS_FILE))) | |
$(file >> $(1), $(2) at $(NOW). Edit that file instead.) | |
$(file >> $(1), $(2)) | |
endef | |
define generate_PY | |
$(call generate,$(1),#) | |
$(file >> $(1),from __future__ import print_function) | |
$(file >> $(1),if 1:) | |
$(file >> $(1),$(2)) | |
endef | |
EXTRA_CFLAGS ?= | |
CXXFLAGS ?= -std:c++20 -EHsc -permissive- | |
# | |
# C/C++ compile macros: | |
# | |
define C_compile | |
$(strip $(_CC) @$(CC).args $(sort $(EXTRA_CFLAGS)) -Fo./$(strip $(1)) $(2)) | |
@echo | |
endef | |
define CPP_compile | |
$(strip $(_CC) @$(CC).args $(CXXFLAGS) $(sort $(EXTRA_CFLAGS)) -Fo./$(strip $(1)) $(2)) | |
@echo | |
endef | |
define C_compile_MP | |
$(call green_msg, Compiling $(words $(2)) .c-files:) | |
$(call C_compile, $(1), -MP $(2)) | |
endef | |
# | |
# 32-bit assembly macro (currently not needed). | |
# | |
define assemble_x86 | |
$(call green_msg, Assembling $(2):) | |
ml -c -nologo -coff -safeseh -Zd -Zi -Fl./$(strip $(1:.obj=.lst)) -Fo./$(strip $(1)) $(2) | |
@echo | |
endef | |
# | |
# 64-bit assembly macro. Currently needed for 'Modules/_decimal/libmpdec/vcdiv64.asm' only. | |
# | |
define assemble_x64 | |
$(call green_msg, Assembling $(2):) | |
ml64 -c -nologo -Zd -Zi -Fo./$(strip $(1)) -Fl./$(strip $(1:.obj=.lst)) $(2) | |
@echo | |
endef | |
# | |
# Create a static library: | |
# | |
define create_lib | |
$(call green_msg, Creating $(1):) | |
lib -nologo -out:$(strip $(1)) $(2) | |
@echo | |
endef | |
# | |
# Use this Python script to check 'link.tmp' for unused libraries after | |
# a successful 'link'. | |
# | |
check_for_unused_libs = @$(PYTHON3) check-for-unused-libs.py link.tmp | |
define link_EXE | |
$(call green_msg, Linking $(1):) | |
$(call create_resp_file, link.args, $(LDFLAGS) $(2)) | |
link -out:$(strip $(1)) @link.args > link.tmp | |
@cat link.tmp >> $(1:.exe=.map) | |
$(check_for_unused_libs) | |
@rm -f $(1:.exe=.lib) $(1:.exe=.exp) | |
endef | |
define link_EXE_GUI | |
$(call link_EXE, $(1), $(GUI_LDFLAGS) $(2)) | |
endef | |
define link_DLL | |
$(call green_msg, Linking $(1):) | |
$(call create_resp_file, link.args, -dll $(LDFLAGS) -implib:$(strip $(3)) $(2)) | |
link -out:$(strip $(1)) @link.args > link.tmp | |
@cat link.tmp >> $(1:.dll=.map) | |
$(check_for_unused_libs) | |
@rm -f $(3:.lib=.exp) | |
endef | |
define link_PYD | |
$(call green_msg, Linking $(1):) | |
$(call create_resp_file, link.args, -dll $(LDFLAGS) $(2)) | |
link -out:$(strip $(1)) @link.args > link.tmp | |
@cat link.tmp >> $(1:.pyd=.map) | |
$(check_for_unused_libs) | |
@rm -f $(1:.pyd=.lib) $(1:.pyd=.exp) | |
endef | |
# | |
# Make a response file; Each word in $(2) is written on a separate line. | |
# | |
define create_resp_file | |
$(file > $(1)) | |
$(foreach f, $(2), $(file >> $(1),$(strip $(f))) ) | |
endef | |
# | |
# copy files macro: | |
# arg1, $(1): directory (must exist) | |
# arg2, $(2): files. | |
# | |
define copy_files | |
$(call green_msg, Copying these files into $(BRIGHT_WHITE)$(strip $(1)):) | |
@$(foreach f, $(1), echo ' $(f)' ; ) | |
@cp --update --preserve=timestamps $(2) $(1) | |
@echo | |
endef | |
# | |
# Create directories macro: | |
# arg1, $(1): list of directories; >= 1 | |
# | |
define create_dirs | |
$(call green_msg, Creating directories:) | |
@$(foreach d, $(1), echo -e ' $(BRIGHT_WHITE)$(d)\e[0m' ; ) | |
@mkdir --parents $(1) | |
@echo | |
endef | |
# | |
# Run a .rc-file through the resource compiler. | |
# $(1): the .res-file. | |
# $(2): the 'PYTHON_DLL_NAME'. | |
# $(3): the .rc-file | |
# $(4): optional '-Dxx' arguments. | |
# | |
define create_res_file | |
$(file > $(OBJ_DIR)/tmp.rc, /* Temporary .rc-file for creating '$(strip $(1))' */) | |
$(file >> $(OBJ_DIR)/tmp.rc, #include <windows.h>) | |
$(file >> $(OBJ_DIR)/tmp.rc,) | |
$(file >> $(OBJ_DIR)/tmp.rc, #define PYTHON_DLL_NAME "$(strip $(2))") | |
$(file >> $(OBJ_DIR)/tmp.rc, #define ORIGINAL_FILENAME "$(strip $(2))") | |
$(file >> $(OBJ_DIR)/tmp.rc,) | |
$(file >> $(OBJ_DIR)/tmp.rc, #define FIELD3 (100 + $(PY_RELEASE_SERIAL)) /* Will 'rc' parse this as '102'? */) | |
$(file >> $(OBJ_DIR)/tmp.rc, #include <$(notdir $(3))>) | |
$(call green_msg, Creating $(BRIGHT_WHITE)$(strip $(1)) $(BRIGHT_GREEN)via $(BRIGHT_WHITE)$(OBJ_DIR)/tmp.rc) | |
rc $(RCFLAGS) -I./include -I./PC $(4) -fo $(1) $(OBJ_DIR)/tmp.rc | |
@echo | |
endef | |
# | |
# '2>&1': redirect 'stderr' into 'stdout' and pipes through 'tee' | |
# | |
define write_single_test | |
$(file >> $(1), $(call echo_prog, \n$(BRIGHT_GREEN)====================================================================== \ | |
\nRunning $(BRIGHT_WHITE)$(strip $(2)) -v:) | $(tee_prog) --append $(3)) | |
$(file >> $(1), call python.bat $(2) -v 2>&1 | $(tee_prog) --append $(3)) | |
$(file >> $(1),) | |
endef | |
define write_single_embed_test | |
$(file >> $(1), $(call echo_prog, \n$(BRIGHT_GREEN)====================================================================== \ | |
\nRunning $(BRIGHT_WHITE)_testembed.exe $(strip $(2)):)) | |
$(file >> $(1), _testembed.exe $(strip $(2))) | |
$(file >> $(1), if NOT errorlevel 0 ($(call echo_prog, $(BRIGHT_RED)Failed) & exit /b 1)) | |
endef | |
# | |
# The "meat" of '$(OBJ_DIR)/pythonnt_rc.h': | |
# | |
define PYTHONNT_RC_H | |
/* | |
* The 'FIELD3' is needed only by 'PC/python_ver_rc.h' to define the | |
* 'PYVERSION64' variable. This is used for 'FILEVERSION' and | |
* 'PRODUCTVERSION' in the resource version section of each .res-file. | |
* | |
* In 'PCBuild/Python.props' it is defined as: | |
* Field3Value - 2101 for '3.5.2a1' (== 1000*2 + 10*10 ('a') + 1) | |
* | |
* But it seems to also be the same as '(100 + $$(PY_RELEASE_SERIAL))' | |
*/ | |
#if defined(RC_INVOKED) | |
#define FIELD3 (100 + $(PY_RELEASE_SERIAL)) /* Will 'rc' parse this as '102'? */ | |
#endif | |
#define MS_DLL_ID "$(PY_VER)-$(BITS)" | |
endef | |
# | |
# Make some pre-processed output of .c/.cpp-files to make sense of | |
# this mess :-) | |
# | |
# Optionally with the use of 'astyle'. | |
# Use as e.g. | |
# make -f Makefile.Windows CC=cl pythonrun.i | |
# | |
# clang-cl: /d1PP Retain macro definitions in /E mode | |
# | |
ifeq ($(CC)-$(USE_MACRO_DEBUG),clang-cl-1) | |
d1PP = -d1PP | |
else | |
d1PP = | |
endif | |
ifeq ($(USE_ASTYLE),1) | |
define CXX_preprocess | |
$(file > $(1),/* The preprocessed and AStyled output of '$(filter %.c %.cpp, $(2))':) | |
$(file >> $(1), * $(_CC) -E) | |
$(foreach f, $(CFLAGS) $(d1PP) $(EXTRA_CFLAGS), $(file >> $(1), * $(f))) | |
$(file >> $(1), *---------------------------------------------------------) | |
$(file >> $(1), */) | |
$(_CC) -E @$(CC).args $(EXTRA_CFLAGS) $(d1PP) $(2) | $(PYTHON3) cpp-filter.py | astyle >> $(1) | |
@echo | |
endef | |
else | |
define CXX_preprocess | |
$(file > $(1),/* The raw preprocessed output of '$(filter %.c %.cpp, $(2))':) | |
$(file >> $(1), * $(_CC) -E) | |
$(foreach f, $(CFLAGS) $(d1PP) $(EXTRA_CFLAGS), $(file >> $(1), * $(f))) | |
$(file >> $(1), *---------------------------------------------------------) | |
$(file >> $(1), */) | |
$(_CC) -E @$(CC).args $(EXTRA_CFLAGS) $(d1PP) $(2) | $(PYTHON3) cpp-filter.py | astyle >> $(1) | |
@echo | |
endef | |
endif | |
define PY_CONFIG_H | |
#ifndef Py_HACK_CONFIG_H | |
#define Py_HACK_CONFIG_H | |
/* Turn off a lot of clang-cl warnings with '-Wall': | |
*/ | |
#if defined(__clang__) | |
#pragma clang diagnostic ignored "-Wassign-enum" | |
#pragma clang diagnostic ignored "-Wbad-function-cast" | |
#pragma clang diagnostic ignored "-Wcast-align" | |
#pragma clang diagnostic ignored "-Wcast-qual" | |
#pragma clang diagnostic ignored "-Wcast-function-type" | |
#pragma clang diagnostic ignored "-Wcomma" | |
#pragma clang diagnostic ignored "-Wconstant-conversion" | |
#pragma clang diagnostic ignored "-Warray-bounds-pointer-arithmetic" | |
#pragma clang diagnostic ignored "-Wconditional-uninitialized" | |
#pragma clang diagnostic ignored "-Wcovered-switch-default" | |
#pragma clang diagnostic ignored "-Wdate-time" | |
#pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" | |
#pragma clang diagnostic ignored "-Wdocumentation" | |
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command" | |
#pragma clang diagnostic ignored "-Wdouble-promotion" | |
#pragma clang diagnostic ignored "-Wextra-semi-stmt" | |
#pragma clang diagnostic ignored "-Wfloat-conversion" | |
#pragma clang diagnostic ignored "-Wfloat-equal" | |
#pragma clang diagnostic ignored "-Wformat-non-iso" | |
#pragma clang diagnostic ignored "-Wformat-nonliteral" | |
#pragma clang diagnostic ignored "-Wignored-pragmas" | |
#pragma clang diagnostic ignored "-Wignored-pragma-optimize" | |
#pragma clang diagnostic ignored "-Wimplicit-int-conversion" | |
#pragma clang diagnostic ignored "-Wimplicit-float-conversion" | |
#pragma clang diagnostic ignored "-Wimplicitly-unsigned-literal" | |
#pragma clang diagnostic ignored "-Wincompatible-pointer-types" | |
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers" | |
#pragma clang diagnostic ignored "-Winvalid-noreturn" | |
#pragma clang diagnostic ignored "-Wlanguage-extension-token" | |
#pragma clang diagnostic ignored "-Wmicrosoft-include" | |
#pragma clang diagnostic ignored "-Wmissing-braces" | |
#pragma clang diagnostic ignored "-Wmissing-field-initializers" | |
#pragma clang diagnostic ignored "-Wmissing-noreturn" | |
#pragma clang diagnostic ignored "-Wmissing-prototypes" | |
#pragma clang diagnostic ignored "-Wmissing-variable-declarations" | |
#pragma clang diagnostic ignored "-Winconsistent-dllimport" | |
#pragma clang diagnostic ignored "-Wnewline-eof" | |
#pragma clang diagnostic ignored "-Wmacro-redefined" | |
#pragma clang diagnostic ignored "-Wnonportable-include-path" | |
#pragma clang diagnostic ignored "-Wnonportable-system-include-path" | |
#pragma clang diagnostic ignored "-Woverlength-strings" | |
#pragma clang diagnostic ignored "-Wparentheses" | |
#pragma clang diagnostic ignored "-Wpedantic" | |
#pragma clang diagnostic ignored "-Wpointer-sign" | |
#pragma clang diagnostic ignored "-Wpragma-pack" | |
#pragma clang diagnostic ignored "-Wsometimes-uninitialized" | |
#pragma clang diagnostic ignored "-Wreserved-id-macro" | |
#pragma clang diagnostic ignored "-Wshorten-64-to-32" | |
#pragma clang diagnostic ignored "-Wsign-compare" | |
#pragma clang diagnostic ignored "-Wsign-conversion" | |
#pragma clang diagnostic ignored "-Wstatic-in-inline" | |
#pragma clang diagnostic ignored "-Wstrict-prototypes" | |
#pragma clang diagnostic ignored "-Wswitch-enum" | |
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" | |
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" | |
#pragma clang diagnostic ignored "-Wtautological-pointer-compare" | |
#pragma clang diagnostic ignored "-Wtautological-type-limit-compare" | |
#pragma clang diagnostic ignored "-Wundef" | |
#pragma clang diagnostic ignored "-Wundefined-inline" | |
#pragma clang diagnostic ignored "-Wunknown-pragmas" | |
#pragma clang diagnostic ignored "-Wunreachable-code" | |
#pragma clang diagnostic ignored "-Wunreachable-code-break" | |
#pragma clang diagnostic ignored "-Wunreachable-code-return" | |
#pragma clang diagnostic ignored "-Wunused-function" | |
#pragma clang diagnostic ignored "-Wunused-macros" | |
#pragma clang diagnostic ignored "-Wunused-label" | |
#pragma clang diagnostic ignored "-Wunused-parameter" | |
#pragma clang diagnostic ignored "-Wunused-variable" | |
#pragma clang diagnostic ignored "-Wunused-but-set-variable" | |
#pragma clang diagnostic ignored "-Wimplicit-fallthrough" | |
#pragma clang diagnostic ignored "-Wvisibility" | |
#pragma clang diagnostic ignored "-Wreserved-identifier" | |
#pragma clang diagnostic ignored "-Wshadow" | |
#pragma clang diagnostic ignored "-Wdeclaration-after-statement" | |
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" | |
/* | |
* Warning-control for 'USE_MIMALLOC=1': | |
*/ | |
#if defined(USE_MIMALLOC) | |
#pragma clang diagnostic ignored "-Wclass-varargs" | |
#endif | |
/* | |
* Warning-control for C++: | |
*/ | |
#if defined(__cplusplus) | |
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" | |
#pragma clang diagnostic ignored "-Wc++98-compat" | |
#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi" | |
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" | |
#pragma clang diagnostic ignored "-Wold-style-cast" | |
#endif | |
#else | |
/* | |
* Turn off these warnings: | |
* warning C4028: formal parameter 1 different from declaration | |
* warning C4068: unknown pragma 'GCC' | |
* warning C4113: 'FARPROC' differs in parameter lists from 'BOOL (__stdcall *)(LPMEMORYSTATUSEX)' | |
* warning C4244: 'function': conversion from 'Py_ssize_t' to 'unsigned int', possible loss of data | |
* warning C4267: 'function': conversion from 'size_t' to 'unsigned int', possible loss of data | |
* warning C4311: 'type cast': pointer truncation from 'void *' to 'DWORD' | |
*/ | |
#pragma warning (disable: 4028 4068 4113 4244 4267 4311) | |
#endif | |
/* Turn off a lot of SDK warnings: | |
*/ | |
#undef _CRT_SECURE_NO_WARNINGS | |
#undef _CRT_SECURE_NO_DEPRECATE | |
#undef _CRT_NONSTDC_NO_DEPRECATE | |
#define _CRT_SECURE_NO_WARNINGS | |
#define _CRT_SECURE_NO_DEPRECATE | |
#define _CRT_NONSTDC_NO_DEPRECATE | |
#define Py_ENABLE_SHARED 1 /* Always create and use .DLLs */ | |
#define _Py_HAVE_ZLIB 1 /* We have an internal zlib */ | |
#define _FILE_OFFSET_BITS 64 /* Enable >2GB file support. Irrelevant on Windows? */ | |
#define BYTEORDER 1234 /* We are little-endian */ | |
#define HAVE_ACCEPT 1 | |
#define HAVE_BIND 1 | |
#define HAVE_BZLIB_H 1 | |
#define HAVE_CONNECT 1 | |
#define HAVE_CLOCK_T 1 | |
#define HAVE_DUP 1 | |
#define HAVE_GETHOSTBYADDR 1 | |
#define HAVE_GETHOSTNAME 1 | |
#define HAVE_GETPROTOBYNAME 1 | |
#define HAVE_GETSERVBYNAME 1 | |
#define HAVE_GETSERVBYPORT 1 | |
#define HAVE_GETSOCKNAME 1 | |
#define HAVE_INET_NTOA 1 | |
#define HAVE_INET_PTON 1 | |
#define HAVE_LIBB2 1 | |
#define HAVE_LIBSQLITE3 1 | |
#define HAVE_LISTEN 1 | |
#define HAVE_LONG_DOUBLE 1 | |
#define HAVE_RECVFROM 1 | |
#define HAVE_SENDTO 1 | |
#define HAVE_SETSOCKOPT 1 | |
#define HAVE_SOCKET 1 | |
#define HAVE_SOCKLEN_T 1 | |
#define HAVE_STDIO_H 1 | |
#define USE_ZLIB_CRC32 1 | |
#define VPATH "." | |
#ifndef PY_SQLITE_HAVE_SERIALIZE | |
#define PY_SQLITE_HAVE_SERIALIZE 1 | |
#endif | |
#ifndef PY_SQLITE_ENABLE_LOAD_EXTENSION | |
#define PY_SQLITE_ENABLE_LOAD_EXTENSION 1 | |
#endif | |
#ifndef WIN32 | |
#define WIN32 /* '#ifdef WIN32' (and not '_WIN32') is used in several places */ | |
#endif | |
#define PY3_DLLNAME L"python3.dll" | |
#define PYTHON_DLL_NAME "$(PYTHON_DLL)" | |
#if defined(COMPILING_GETPATH_C) | |
#define PREFIX "" | |
#define EXEC_PREFIX "" | |
#define PLATLIBDIR "lib" | |
#define VERSION "$(PY_VER_STR)" | |
#endif | |
#if defined(COMPILING_LAUNCHER_W) || defined(COMPILING_PYSHELLEXT) | |
#define UNICODE | |
#define _UNICODE | |
#define _WINDOWS | |
#else | |
/* Turn off the warning: | |
* 'GetVersion' is deprecated [-Wdeprecated-declarations] | |
*/ | |
#define BUILD_WINDOWS | |
/* I think this has the same effect as 'BUILD_WINDOWS'. | |
*/ | |
#define _WINSOCK_DEPRECATED_NO_WARNINGS | |
/* Win8; must match the value of 'Py_WINVER' in the below 'Include/pyconfig.h' | |
*/ | |
#if !defined(_WIN32_WINNT ) || (_WIN32_WINNT < 0x0602) | |
#undef _WIN32_WINNT | |
#define _WIN32_WINNT 0x0602 | |
#endif | |
#endif | |
#include "pythonnt_rc.h" /* Defines 'MS_DLL_ID' */ | |
#ifndef GITVERSION | |
#define GITVERSION "$(shell git --git-dir Git-Latest/.git rev-parse --short HEAD)" | |
#endif | |
#ifndef GITTAG | |
#define GITTAG "v$(PY_VER_STR)" | |
#endif | |
#ifndef GITBRANCH | |
#define GITBRANCH "master" | |
#endif | |
#if !defined(COMPILING_ZLIB) /* Rest of file */ | |
/* | |
* This file gets generated into './Include' and forcefully included as: | |
* "-FI./Include/pyconfig.h" when building ALL objects. | |
* | |
* The purpose of this file is just to tweak the normal MSVC '$$(OBJ_DIR)/pyconfig.h' | |
* with acceptable config-values for all compilers. Not just MSVC. | |
* Especially it fixes the horrid '_Py_STRINGIZE()' macro to work for '__clang__'. | |
* | |
* The '../PC/' directory should be relative to '$(realpath .)/Include' when using | |
* Python from outside Python's build directory. | |
* Ideally the below files should be 'cat'ed into place. | |
*/ | |
#include "$(OBJ_DIR)/pyconfig.h" | |
/* | |
* Just a hack for 'make depend' (gcc -MM). | |
* Python goes bananas if it does not see a '_MSC_VER' in many .c-files. | |
*/ | |
#if defined(DOING_CPP_PROCESSING) && defined(__GNUC__) | |
#define _MSC_VER 1800 | |
#define _S_IREAD 0400 | |
#define CONFIG_32 | |
#endif | |
#if !defined(RC_INVOKED) | |
#if !defined(DOING_CPP_PROCESSING) | |
#if defined(_MSC_VER) && defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_MODULE) | |
#if (_WIN32_WINNT != Py_WINVER) | |
#error "_WIN32_WINNT != Py_WINVER." | |
#endif | |
#endif | |
#if !defined(_MSC_VER) | |
#undef SIZEOF_TIME_T | |
#define SIZEOF_TIME_T 8 | |
#endif | |
#if (SIZEOF_TIME_T != 8) | |
#error "SIZEOF_TIME_T is not 8!!" | |
#endif | |
#endif /* !DOING_CPP_PROCESSING */ | |
#if defined(__clang__) | |
#undef _Py_PASTE_VERSION | |
#undef _Py_STRINGIZE | |
#undef _Py_STRINGIZE2 | |
#define _Py_STRINGIZE2(x) #x | |
#define _Py_STRINGIZE(x) _Py_STRINGIZE2(x) | |
#define _Py_PASTE_VERSION(SUFFIX) ("[Clang-cl v." _Py_STRINGIZE(__clang_major__) "." \ | |
_Py_STRINGIZE(__clang_minor__) "." \ | |
_Py_STRINGIZE(__clang_patchlevel__) " " \ | |
SUFFIX "]") | |
#endif | |
#define _CRT_RAND_S /* Needed for 'rand_s()' */ | |
#include <stdlib.h> | |
/* | |
* 'struct timeval' is needed ahead of '<Include/pytime.h>'. | |
* Otherwise clang-cl barfs. | |
* | |
* But when compiling 'Module/_pickle.c', do not include '<winsock2.h>' which | |
* includes '<windows.h>'. That causes 'FLOAT' etc. from '<minwindef.h>' to | |
* clash with the 'FLOAT' enums in 'Module/_pickle.c'. | |
*/ | |
#if !defined(COMPILING_PICKLE) && !defined(COMPILING_PYSHELLEXT) | |
#include <winsock2.h> | |
#endif | |
#include <limits.h> /* INT_MAX */ | |
#ifndef MAXINT | |
#define MAXINT INT_MAX /* Only needed in 'PC/launcher.c' */ | |
#endif | |
#if defined(_WINBASE_) | |
#undef Yield | |
#undef small | |
#endif | |
#if defined(COMPILING_SQLITE3) | |
#define SQLITE_ENABLE_FTS4 1 | |
#define SQLITE_ENABLE_FTS5 1 | |
#define SQLITE_ENABLE_JSON1 1 | |
#define SQLITE_ENABLE_MATH_FUNCTIONS 1 | |
#define SQLITE_ENABLE_RTREE 1 | |
#define SQLITE_API __declspec(dllexport) | |
#endif | |
#if defined(COMPILING_HASH_OPENSSL) | |
#define PY_OPENSSL_HAS_SHAKE 1 | |
#define PY_OPENSSL_HAS_SHA3 1 | |
#endif | |
#if defined(COMPILING_EXPAT) | |
#define ELEMENT_TYPE expat_ELEMENT_TYPE | |
// #define USE_PYEXPAT_CAPI 1 | |
#define HAVE_MEMMOVE 1 | |
#define HAVE_EXPAT_H 1 | |
#define XML_STATIC 1 | |
#define XML_NS 1 | |
#define XML_DTD 1 | |
#define XML_CONTEXT_BYTES 1024 | |
#endif | |
#endif /* !RC_INVOKED */ | |
#endif /* !COMPILING_ZLIB */ | |
#endif /* Py_HACK_CONFIG_H */ | |
endef | |
define DEC_HACKS_C | |
/* | |
* Gross hacks for '_decimal.pyd' in '_DEBUG' mode. | |
* But option '-MDd' is not supported yet. | |
*/ | |
#include <math.h> | |
#include <assert.h> | |
#include "Modules/_decimal/libmpdec/mpdecimal.h" | |
#include "Modules/_decimal/libmpdec/mpalloc.h" | |
#if defined(_DEBUG) | |
#if defined(_MSC_VER) && (defined(_M_IA64) || defined(_M_X64) || defined(_M_AMD64)) && 0 | |
int __cdecl __control87_2 (unsigned int NewValue, | |
unsigned int Mask, | |
unsigned int *X86ControlWord, | |
unsigned int *Sse2ControlWord) | |
{ | |
(void) X86ControlWord; | |
(void) Sse2ControlWord; | |
return _control87 (NewValue, Mask); | |
} | |
#endif | |
void mpd_del (mpd_t *dec) | |
{ | |
if (mpd_isdynamic_data(dec)) | |
mpd_free (dec->data); | |
if (mpd_isdynamic(dec)) | |
mpd_free (dec); | |
} | |
void mpd_uint_zero (mpd_uint_t *dest, mpd_size_t len) | |
{ | |
mpd_size_t i; | |
for (i = 0; i < len; i++) | |
dest[i] = 0; | |
} | |
int mpd_qresize (mpd_t *result, mpd_ssize_t nwords, uint32_t *status) | |
{ | |
assert (!mpd_isconst_data(result)); /* illegal operation for a const */ | |
assert (!mpd_isshared_data(result)); /* illegal operation for a shared */ | |
assert (MPD_MINALLOC <= result->alloc); | |
nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords; | |
if (nwords == result->alloc) | |
return (1); | |
if (mpd_isstatic_data(result)) | |
{ | |
if (nwords > result->alloc) | |
return mpd_switch_to_dyn (result, nwords, status); | |
return (1); | |
} | |
return mpd_realloc_dyn (result, nwords, status); | |
} | |
#endif /* _DEBUG */ | |
endef | |
define LZ_HACKS_C | |
/* | |
* Hacks around the link errors using 'clang-cl'; missing in < v8. | |
*/ | |
#if defined(__clang__) && (__clang_major__ < 8) | |
unsigned char _BitScanReverse (unsigned long *_Index, unsigned long _Mask) | |
{ | |
if (!_Mask) | |
return (0); | |
*_Index = (31 - __builtin_clzl (_Mask)); | |
return (1); | |
} | |
unsigned char _BitScanForward (unsigned long *_Index, unsigned long _Mask) | |
{ | |
if (!_Mask) | |
return (0); | |
*_Index = __builtin_ctzl (_Mask); | |
return (1); | |
} | |
#endif | |
endef | |
define CPP_FILTER_PY | |
import sys, os | |
empty_lines = 0 | |
while True: | |
line = sys.stdin.readline() | |
if not line: | |
break | |
line = line.rstrip() | |
if line == "": | |
empty_lines += 1 | |
continue | |
# | |
# MSVC or clang-cl 'line' directive | |
# | |
if line.startswith("#line") or line.startswith("# "): | |
line = line.replace (r"\\", "/") | |
print (line) | |
# | |
# Print a newline after a functions or structs | |
# | |
if line == "}" or line == "};": | |
print ("") | |
print ("Removed %d empty lines." % empty_lines, file=sys.stderr) | |
endef | |
define CHECK_FOR_UNUSED_LIBS_PY | |
# | |
# Check a MSVC .map-file for lines after a 'Unused libraries:' | |
# | |
import os, sys | |
ignore_libs = [ "oldnames.lib", "libcmt.lib" ] | |
class State(): | |
IDLE = 0 | |
UNUSED = 1 | |
class Colour(): | |
RED = WHITE = RESET = "" | |
try: | |
from colorama import init, Fore, Style | |
init() | |
Colour.RED = Fore.RED + Style.BRIGHT | |
Colour.WHITE = Fore.WHITE + Style.BRIGHT | |
Colour.RESET = Style.RESET_ALL | |
except: | |
pass | |
def report (map_file, unused): | |
num = len(unused) | |
plural = [ "library", "libraries" ] | |
if num > 0: | |
print ("%s%d unused %s in %s:%s" % (Colour.RED, num, plural[num > 1], map_file, Colour.RESET)) | |
for u in sorted(unused): | |
print (" " + u) | |
print ("%sDone%s\n" % (Colour.WHITE, Colour.RESET)) | |
def process_map (file, state): | |
unused_libs = [] | |
f = open (file, "rt") | |
lines = f.readlines() | |
f.close() | |
for l in lines: | |
l = l.strip() | |
if l == "Unused libraries:": | |
state = State.UNUSED | |
continue | |
if state == State.UNUSED: | |
if l == "": | |
break | |
if os.path.basename (l).lower() not in ignore_libs: | |
unused_libs.append (l) | |
return unused_libs | |
map_file = sys.argv[1] | |
report (map_file, process_map(map_file, State.IDLE)) | |
endef | |
PIP_WHL = $(word 1, $(wildcard Lib/ensurepip/_bundled/pip-*.whl)) | |
SETUPTOOLS_WHL = $(word 1, $(wildcard Lib/ensurepip/_bundled/setuptools-*.whl)) | |
_PIP_WHL = $(subst /,\,$(PIP_WHL)) | |
_SETUPTOOLS_WHL = $(subst /,\,$(SETUPTOOLS_WHL)) | |
_TCL_CORE_ROOT = $(subst /,\,$(TCL_CORE_ROOT)) | |
whl_test: | |
$(call green_msg0, Found pip*.whl: '$(PIP_WHL)') | |
$(call green_msg0, Found setuptools*.whl: '$(SETUPTOOLS_WHL)') | |
$(call green_msg0, _PIP_WHL: '$(_PIP_WHL)') | |
$(call green_msg0, _SETUPTOOLS_WHL: '$(_SETUPTOOLS_WHL)') | |
$(call green_msg0, _TCL_CORE_ROOT: '$(_TCL_CORE_ROOT)') | |
# | |
# The shells from JPsoft.com handles a '^C' in a .bat file with the | |
# below 'on break ()' statement. The CMD crap does not. | |
# | |
_CMDPROC = if %_cmdproc. == 4NT. .or. %_cmdproc. == TCMD32. .or. \ | |
%_cmdproc%. == TCC. .or. %_cmdproc. == TCCLE. \ | |
on break (echo Quitting %+ quit) | |
define RUN_TESTS_BAT | |
@echo off | |
setlocal | |
set WSOCK_TRACE_LEVEL=0 | |
$(_CMDPROC) | |
endef | |
# | |
# TODO: Rewrite this into a "py.exe -3 colorama-based-script.py" | |
# | |
define EMBEDDED_TESTS_BAT | |
:: | |
:: This .bat-file will try to run all the embedded tests | |
:: and exit on the first failure. Otherwise it will say "Success! ..." | |
:: | |
@echo off | |
setlocal | |
set WSOCK_TRACE_LEVEL=0 | |
$(call echo_prog, $(BRIGHT_WHITE)Running $(words $(TESTEMBED_CASES)) '$<' test-cases.) | |
$(_CMDPROC) | |
set TESTPATH=$(REG_LIB_DIR);$(REG_DLLs_DIR) | |
set TESTHOME=$(REG_THIS_DIR) | |
set PYTHONPATH=%~dp0%\DLLs;%PYTHONPATH% | |
endef | |
define PYTHON_BAT_COMMON | |
@echo off | |
setlocal | |
set PROMPT=$$P$$G | |
$(_CMDPROC) | |
:: | |
:: A 'set PYTHON_EXTRA_PATH=x;y;z' could be set from the outside. | |
:: | |
set PYTHONHOME=%~dp0% | |
set PYTHONPATH=%PYTHONHOME%\DLLs;%PYTHONHOME%\$(_SETUPTOOLS_WHL);%PYTHONHOME%\$(_PIP_WHL);%PYTHON_EXTRA_PATH% | |
:: | |
:: Do not write .pyc files. | |
:: | |
:: set PYTHONDONTWRITEBYTECODE=1 | |
:: | |
:: Path for WinDbg and dbghelp. | |
:: | |
set _NT_SYMBOL_PATH=%PYTHONHOME%\DLLs;%_NT_SYMBOL_PATH% | |
:: | |
:: In case '$(PYTHON_DLL)' was linked to 'wsock_trace-$(CPU).lib', shut it up. | |
:: | |
:: set WSOCK_TRACE_LEVEL=0 | |
:: set WSOCK_DUMP_MODULES=0 | |
:: set WSOCK_LUA_ENABLE=0 | |
:: set USE_LUA=0 | |
:: set TCLLIBPATH=%PYTHONHOME%\$(_TCL_CORE_ROOT)\lib\tcl8.6;%PYTHONHOME%\$(_TCL_CORE_ROOT)\library | |
:: | |
:: In case a Python 'test*.py' wants to use 'Lib\distutils\msvccompiler.py'. | |
:: | |
if exist libs\x64\python3.lib ( | |
set LIBPATH=%PYTHONHOME%\libs\x64;%LIBPATH% | |
) else ( | |
set LIBPATH=%PYTHONHOME%\libs;%LIBPATH% | |
) | |
:: | |
:: Some script will invoke 'PC\*.bat' files which are rather CMD centric. | |
:: So set COMSPEC accordingly. | |
:: | |
set COMSPEC=%WINDIR%\system32\cmd.exe | |
:: | |
:: Invoke our 'python.exe' (or 'pythonw.exe') with all arguments | |
:: | |
endef | |
# | |
# Stuff for updating the Registry while running 'install.bat': | |
# | |
REG_DOS_path = $(strip $(subst /,\\,$(realpath $(1)))) | |
REG_THIS_DIR = $(call REG_DOS_path, .) | |
# | |
# Since 'python*.chm' may not exist yet | |
# | |
REG_PYTHON_CHM = $(REG_THIS_DIR)\\Python$(_PY_VER).chm | |
REG_IDLE_PYW = $(call REG_DOS_path, Lib/idlelib/idle.pyw) | |
REG_LIB_DIR = $(call REG_DOS_path, Lib) | |
REG_DLLs_DIR = $(call REG_DOS_path, DLLs) | |
define Python_REG | |
REGEDIT4 | |
; | |
; DO NOT EDIT! This file was automatically generated) | |
; from $(realpath $(THIS_FILE))) | |
; at $(NOW). Edit that file instead.) | |
; | |
[$(top_key)] | |
"DisplayName"="Python $(PY_VER) ($(BITS)-bit, $(BUILDER) compiled)" | |
"SupportUrl"="http://www.python.org/" | |
"Version"="$(PY_VER_STR)" | |
"SysVersion"="$(PY_VER)" | |
"SysArchitecture"="$(BITS)bit" | |
[$(top_key)\Help] | |
[$(top_key)\Help\Main Python Documentation] | |
@="$(REG_PYTHON_CHM)" | |
[$(top_key)\Idle] | |
@="$(REG_IDLE_PYW)" | |
[$(top_key)\IdleShortcuts] | |
@=dword:00000001 | |
[$(top_key)\InstalledFeatures] | |
"core_pdb"="$(PY_VER_STR)" | |
"core_d"="$(PY_VER_STR)" | |
"dev"="$(PY_VER_STR)" | |
"Shortcuts"="$(PY_VER_STR)" | |
"exe"="$(PY_VER_STR)" | |
"lib"="$(PY_VER_STR)" | |
"test"="$(PY_VER_STR)" | |
"doc_shortcut"="$(PY_VER_STR)" | |
"doc"="$(PY_VER_STR)" | |
"tools"="$(PY_VER_STR)" | |
"tcltk"="$(PY_VER_STR)" | |
"pip"="$(PY_VER_STR)" | |
[$(top_key)\InstallPath] | |
@="$(REG_THIS_DIR)\\" | |
"ExecutablePath"="$(REG_THIS_DIR)\\python.exe" | |
"WindowedExecutablePath"="$(REG_THIS_DIR)\\pythonw.exe" | |
; | |
; Put a '$$(call REG_DOS_path, Python3*.zip)' first? | |
; | |
[$(top_key)\PythonPath] | |
@="$(REG_LIB_DIR);$(REG_DLLs_DIR)" | |
endef | |
PY_EXE = $(subst /,\,$(realpath py.exe)) -$(PY_VER)-$(BITS) | |
define INSTALL_BAT | |
@echo off | |
$(call echo_prog, $(BRIGHT_GREEN)Creating Registry keys:) | |
reg import $(call REG_DOS_path, Python.reg) -reg:32 2> NUL | |
$(call echo_prog, $(BRIGHT_GREEN)\nTest sys.version:) | |
$(PY_EXE) -c "import sys; print (' ' + sys.version)" | |
$(call echo_prog, $(BRIGHT_GREEN)Test sysconfig:) | |
$(PY_EXE) -c "import sysconfig; print (' ' + sysconfig.get_platform())" | |
endef | |
# | |
# Some fixed dependencies: | |
# | |
# $(OBJ_DIR)/core/sre.obj: Modules/_sre/sre_constants.h Modules/_sre/sre_targets.h | |
# $(OBJ_DIR)/core/sha3module.obj: Modules/sha3module.c | |
# | |
# Use 'gcc' to create dependencies: | |
# | |
dep_replace = sed -e 's@\(.*\)\.o: @\n$$(OBJ_DIR)\/$(strip $(1))\1.obj: @' | |
dep_final_replace = -e 's@$(SQLITE3_ROOT)@$$(SQLITE3_ROOT)@g' \ | |
-e 's@$(OPENSSL_ROOT)@$$(OPENSSL_ROOT)@g' \ | |
-e 's@$(LZMA_ROOT)@$$(LZMA_ROOT)@g' \ | |
-e 's@$(TCLTK_ROOT)@$$(TCLTK_ROOT)@g' \ | |
-e 's@$(BZIP2_ROOT)@$$(BZIP2_ROOT)@g' \ | |
-e 's@$(ZLIB_ROOT)@$$(ZLIB_ROOT)@g' | |
# | |
# Remove the generated 'Include/pyconfig.h' and '$(OBJ_DIR)/pythonnt_rc.h' from | |
# the dependencies as that would cause far too much to be rebuilt. | |
# | |
dep_final_replace += -e 's@Include/pyconfig.h @@g' \ | |
-e 's@$(OBJ_DIR)/pythonnt_rc.h @@g' | |
# | |
# Pass these CFLAGS to 'gcc -MM': | |
# Filter out any MSVC/clang specific CFLAGS; only '-D*' and '-I*' are | |
# essential to dependency generation. | |
# | |
dep_CFLAGS = -MM -m$(BITS) --include Include/pyconfig.h -DDOING_CPP_PROCESSING $(filter -D% -I%, $(1)) | |
# | |
# Make dependencies for a chunk of .c-files. | |
# Each chunk may need extra CFLAGS; like for 'Modules/_sqlite/*.c'. | |
# | |
# arg1: $(1): the list of .c-files. | |
# arg2: $(2): the extra CFLAGS for $(1). | |
# arg3: $(3): the .obj-file sub-directory (optional). | |
# | |
define create_deps | |
$(call white_msg, Generating dependencies for $(BRIGHT_GREEN)$(words $(1)) $(BRIGHT_WHITE)files...) | |
gcc $(call dep_CFLAGS, $(CFLAGS) $(3)) $(1) | $(call dep_replace, $(2)) >> .depend.tmp | |
@echo | |
endef | |
depend: make_dirs $(GENERATED) $(FROZEN_GENERATED) | |
$(call generate, .depend.tmp, #) | |
$(call create_deps, $(PC_SRC) $(OBJECTS_SRC) $(PARSER_SRC) $(PYTHON_SRC) $(MODULES_SRC), core/, -DPy_BUILD_CORE_BUILTIN) | |
$(call create_deps, $(BZIP2_SRC), bzip2/) | |
$(call create_deps, $(CTYPES_SRC), ctypes/, $(CTYPES_CFLAGS)) | |
$(call create_deps, $(ELEMENTTREE_SRC), elementtree/, $(EXPAT_CFLAGS)) | |
$(call create_deps, $(DECIMAL_C_SRC), decimal/, $(DECIMAL_CFLAGS)) | |
$(call create_deps, $(LZMA_SRC), lzma/, $(LZMA_CFLAGS)) | |
$(call create_deps, $(TKINTER_SRC),, $(TKINTER_CFLAGS)) | |
$(call create_deps, $(ZLIB_SRC), zlib/, $(ZLIB_CFLAGS)) | |
$(call create_deps, $(PYEXPAT_SRC), pyexpat/, $(EXPAT_CFLAGS)) | |
$(call create_deps, $(_SQLITE3_SRC), _sqlite3/) | |
$(call create_deps, $(SQLITE3_SRC), sqlite3/) | |
sed $(dep_final_replace) < .depend.tmp > .depend.Windows | |
rm -f .depend.tmp | |
-include .depend.Windows | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment