bpo-31536: Avoid wholesale rebuild after `make regen-all` (#3678)
* bpo-31536: Avoid wholesale rebuild after `make regen-all` * Add NEWS
This commit is contained in:
parent
aaf6fc0982
commit
b091bec824
|
@ -230,6 +230,7 @@ PYTHON= python$(EXE)
|
||||||
BUILDPYTHON= python$(BUILDEXE)
|
BUILDPYTHON= python$(BUILDEXE)
|
||||||
|
|
||||||
PYTHON_FOR_REGEN=@PYTHON_FOR_REGEN@
|
PYTHON_FOR_REGEN=@PYTHON_FOR_REGEN@
|
||||||
|
UPDATE_FILE=@PYTHON_FOR_REGEN@ $(srcdir)/Tools/scripts/update_file.py
|
||||||
PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@
|
PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@
|
||||||
_PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@
|
_PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@
|
||||||
BUILD_GNU_TYPE= @build@
|
BUILD_GNU_TYPE= @build@
|
||||||
|
@ -691,12 +692,14 @@ regen-importlib: Programs/_freeze_importlib
|
||||||
# from Lib/importlib/_bootstrap_external.py using _freeze_importlib
|
# from Lib/importlib/_bootstrap_external.py using _freeze_importlib
|
||||||
./Programs/_freeze_importlib \
|
./Programs/_freeze_importlib \
|
||||||
$(srcdir)/Lib/importlib/_bootstrap_external.py \
|
$(srcdir)/Lib/importlib/_bootstrap_external.py \
|
||||||
$(srcdir)/Python/importlib_external.h
|
$(srcdir)/Python/importlib_external.h.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Python/importlib_external.h $(srcdir)/Python/importlib_external.h.new
|
||||||
# Regenerate Python/importlib.h from Lib/importlib/_bootstrap.py
|
# Regenerate Python/importlib.h from Lib/importlib/_bootstrap.py
|
||||||
# using _freeze_importlib
|
# using _freeze_importlib
|
||||||
./Programs/_freeze_importlib \
|
./Programs/_freeze_importlib \
|
||||||
$(srcdir)/Lib/importlib/_bootstrap.py \
|
$(srcdir)/Lib/importlib/_bootstrap.py \
|
||||||
$(srcdir)/Python/importlib.h
|
$(srcdir)/Python/importlib.h.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib.h.new
|
||||||
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
@ -770,8 +773,10 @@ regen-grammar: $(PGEN)
|
||||||
# from Grammar/Grammar using pgen
|
# from Grammar/Grammar using pgen
|
||||||
@$(MKDIR_P) Include
|
@$(MKDIR_P) Include
|
||||||
$(PGEN) $(srcdir)/Grammar/Grammar \
|
$(PGEN) $(srcdir)/Grammar/Grammar \
|
||||||
$(srcdir)/Include/graminit.h \
|
$(srcdir)/Include/graminit.h.new \
|
||||||
$(srcdir)/Python/graminit.c
|
$(srcdir)/Python/graminit.c.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Include/graminit.h $(srcdir)/Include/graminit.h.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Python/graminit.c $(srcdir)/Python/graminit.c.new
|
||||||
|
|
||||||
Parser/grammar.o: $(srcdir)/Parser/grammar.c \
|
Parser/grammar.o: $(srcdir)/Parser/grammar.c \
|
||||||
$(srcdir)/Include/token.h \
|
$(srcdir)/Include/token.h \
|
||||||
|
@ -789,13 +794,15 @@ regen-ast:
|
||||||
# Regenerate Include/Python-ast.h using Parser/asdl_c.py -h
|
# Regenerate Include/Python-ast.h using Parser/asdl_c.py -h
|
||||||
$(MKDIR_P) $(srcdir)/Include
|
$(MKDIR_P) $(srcdir)/Include
|
||||||
$(PYTHON_FOR_REGEN) $(srcdir)/Parser/asdl_c.py \
|
$(PYTHON_FOR_REGEN) $(srcdir)/Parser/asdl_c.py \
|
||||||
-h $(srcdir)/Include \
|
-h $(srcdir)/Include/Python-ast.h.new \
|
||||||
$(srcdir)/Parser/Python.asdl
|
$(srcdir)/Parser/Python.asdl
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Include/Python-ast.h $(srcdir)/Include/Python-ast.h.new
|
||||||
# Regenerate Python/Python-ast.c using Parser/asdl_c.py -c
|
# Regenerate Python/Python-ast.c using Parser/asdl_c.py -c
|
||||||
$(MKDIR_P) $(srcdir)/Python
|
$(MKDIR_P) $(srcdir)/Python
|
||||||
$(PYTHON_FOR_REGEN) $(srcdir)/Parser/asdl_c.py \
|
$(PYTHON_FOR_REGEN) $(srcdir)/Parser/asdl_c.py \
|
||||||
-c $(srcdir)/Python \
|
-c $(srcdir)/Python/Python-ast.c.new \
|
||||||
$(srcdir)/Parser/Python.asdl
|
$(srcdir)/Parser/Python.asdl
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Python/Python-ast.c $(srcdir)/Python/Python-ast.c.new
|
||||||
|
|
||||||
.PHONY: regen-opcode
|
.PHONY: regen-opcode
|
||||||
regen-opcode:
|
regen-opcode:
|
||||||
|
@ -803,7 +810,8 @@ regen-opcode:
|
||||||
# using Tools/scripts/generate_opcode_h.py
|
# using Tools/scripts/generate_opcode_h.py
|
||||||
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/generate_opcode_h.py \
|
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/generate_opcode_h.py \
|
||||||
$(srcdir)/Lib/opcode.py \
|
$(srcdir)/Lib/opcode.py \
|
||||||
$(srcdir)/Include/opcode.h
|
$(srcdir)/Include/opcode.h.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Include/opcode.h $(srcdir)/Include/opcode.h.new
|
||||||
|
|
||||||
Python/compile.o Python/symtable.o Python/ast.o: $(srcdir)/Include/graminit.h $(srcdir)/Include/Python-ast.h
|
Python/compile.o Python/symtable.o Python/ast.o: $(srcdir)/Include/graminit.h $(srcdir)/Include/Python-ast.h
|
||||||
|
|
||||||
|
@ -860,7 +868,8 @@ regen-opcode-targets:
|
||||||
# Regenerate Python/opcode_targets.h from Lib/opcode.py
|
# Regenerate Python/opcode_targets.h from Lib/opcode.py
|
||||||
# using Python/makeopcodetargets.py
|
# using Python/makeopcodetargets.py
|
||||||
$(PYTHON_FOR_REGEN) $(srcdir)/Python/makeopcodetargets.py \
|
$(PYTHON_FOR_REGEN) $(srcdir)/Python/makeopcodetargets.py \
|
||||||
$(srcdir)/Python/opcode_targets.h
|
$(srcdir)/Python/opcode_targets.h.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/opcode_targets.h.new
|
||||||
|
|
||||||
Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h
|
Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h
|
||||||
|
|
||||||
|
@ -887,7 +896,8 @@ regen-typeslots:
|
||||||
# using Objects/typeslots.py
|
# using Objects/typeslots.py
|
||||||
$(PYTHON_FOR_REGEN) $(srcdir)/Objects/typeslots.py \
|
$(PYTHON_FOR_REGEN) $(srcdir)/Objects/typeslots.py \
|
||||||
< $(srcdir)/Include/typeslots.h \
|
< $(srcdir)/Include/typeslots.h \
|
||||||
$(srcdir)/Objects/typeslots.inc
|
$(srcdir)/Objects/typeslots.inc.new
|
||||||
|
$(UPDATE_FILE) $(srcdir)/Objects/typeslots.inc $(srcdir)/Objects/typeslots.inc.new
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
# Header files
|
# Header files
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Avoid wholesale rebuild after `make regen-all` if nothing changed.
|
|
@ -1285,59 +1285,55 @@ def main(srcfile, dump_module=False):
|
||||||
print(mod)
|
print(mod)
|
||||||
if not asdl.check(mod):
|
if not asdl.check(mod):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if INC_DIR:
|
if H_FILE:
|
||||||
p = "%s/%s-ast.h" % (INC_DIR, mod.name)
|
with open(H_FILE, "w") as f:
|
||||||
f = open(p, "w")
|
f.write(auto_gen_msg)
|
||||||
f.write(auto_gen_msg)
|
f.write('#include "asdl.h"\n\n')
|
||||||
f.write('#include "asdl.h"\n\n')
|
c = ChainOfVisitors(TypeDefVisitor(f),
|
||||||
c = ChainOfVisitors(TypeDefVisitor(f),
|
StructVisitor(f),
|
||||||
StructVisitor(f),
|
PrototypeVisitor(f),
|
||||||
PrototypeVisitor(f),
|
)
|
||||||
)
|
c.visit(mod)
|
||||||
c.visit(mod)
|
f.write("PyObject* PyAST_mod2obj(mod_ty t);\n")
|
||||||
f.write("PyObject* PyAST_mod2obj(mod_ty t);\n")
|
f.write("mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode);\n")
|
||||||
f.write("mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode);\n")
|
f.write("int PyAST_Check(PyObject* obj);\n")
|
||||||
f.write("int PyAST_Check(PyObject* obj);\n")
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if SRC_DIR:
|
if C_FILE:
|
||||||
p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c")
|
with open(C_FILE, "w") as f:
|
||||||
f = open(p, "w")
|
f.write(auto_gen_msg)
|
||||||
f.write(auto_gen_msg)
|
f.write('#include <stddef.h>\n')
|
||||||
f.write('#include <stddef.h>\n')
|
f.write('\n')
|
||||||
f.write('\n')
|
f.write('#include "Python.h"\n')
|
||||||
f.write('#include "Python.h"\n')
|
f.write('#include "%s-ast.h"\n' % mod.name)
|
||||||
f.write('#include "%s-ast.h"\n' % mod.name)
|
f.write('\n')
|
||||||
f.write('\n')
|
f.write("static PyTypeObject AST_type;\n")
|
||||||
f.write("static PyTypeObject AST_type;\n")
|
v = ChainOfVisitors(
|
||||||
v = ChainOfVisitors(
|
PyTypesDeclareVisitor(f),
|
||||||
PyTypesDeclareVisitor(f),
|
PyTypesVisitor(f),
|
||||||
PyTypesVisitor(f),
|
Obj2ModPrototypeVisitor(f),
|
||||||
Obj2ModPrototypeVisitor(f),
|
FunctionVisitor(f),
|
||||||
FunctionVisitor(f),
|
ObjVisitor(f),
|
||||||
ObjVisitor(f),
|
Obj2ModVisitor(f),
|
||||||
Obj2ModVisitor(f),
|
ASTModuleVisitor(f),
|
||||||
ASTModuleVisitor(f),
|
PartingShots(f),
|
||||||
PartingShots(f),
|
)
|
||||||
)
|
v.visit(mod)
|
||||||
v.visit(mod)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import getopt
|
import getopt
|
||||||
|
|
||||||
INC_DIR = ''
|
H_FILE = ''
|
||||||
SRC_DIR = ''
|
C_FILE = ''
|
||||||
dump_module = False
|
dump_module = False
|
||||||
opts, args = getopt.getopt(sys.argv[1:], "dh:c:")
|
opts, args = getopt.getopt(sys.argv[1:], "dh:c:")
|
||||||
for o, v in opts:
|
for o, v in opts:
|
||||||
if o == '-h':
|
if o == '-h':
|
||||||
INC_DIR = v
|
H_FILE = v
|
||||||
if o == '-c':
|
if o == '-c':
|
||||||
SRC_DIR = v
|
C_FILE = v
|
||||||
if o == '-d':
|
if o == '-d':
|
||||||
dump_module = True
|
dump_module = True
|
||||||
if INC_DIR and SRC_DIR:
|
if H_FILE and C_FILE:
|
||||||
print('Must specify exactly one output file')
|
print('Must specify exactly one output file')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
elif len(args) != 1:
|
elif len(args) != 1:
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
"""
|
||||||
|
A script that replaces an old file with a new one, only if the contents
|
||||||
|
actually changed. If not, the new file is simply deleted.
|
||||||
|
|
||||||
|
This avoids wholesale rebuilds when a code (re)generation phase does not
|
||||||
|
actually change the in-tree generated code.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main(old_path, new_path):
|
||||||
|
with open(old_path, 'rb') as f:
|
||||||
|
old_contents = f.read()
|
||||||
|
with open(new_path, 'rb') as f:
|
||||||
|
new_contents = f.read()
|
||||||
|
if old_contents != new_contents:
|
||||||
|
os.replace(new_path, old_path)
|
||||||
|
else:
|
||||||
|
os.unlink(new_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Usage: %s <path to be updated> <path with new contents>" % (sys.argv[0],))
|
||||||
|
sys.exit(1)
|
||||||
|
main(sys.argv[1], sys.argv[2])
|
Loading…
Reference in New Issue