Skip to content

gh-100086: Add build details to sys.version #100087

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,10 @@ sys
with contributions from Gregory P. Smith [Google] and Mark Shannon
in :gh:`96123`.)

* Add more build details about how Python was configured in
:data:`sys.version`, like "debug" or "release" build.
(Contributed by Victor Stinner in :gh:`100086`.)


Optimizations
=============
Expand Down
8 changes: 5 additions & 3 deletions Lib/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,9 @@ def processor():
r'([\w.+]+)\s*' # "version<space>"
r'\(#?([^,]+)' # "(#buildno"
r'(?:,\s*([\w ]*)' # ", builddate"
r'(?:,\s*([\w :]*))?)?\)\s*' # ", buildtime)<space>"
r'(?:,\s*([\w :]*))?)?' # ", buildtime"
r'(?:,\s*([\w :]*))?' # ", build details"
r'\)\s*' # ")<space>"
r'\[([^\]]+)\]?', re.ASCII) # "[compiler]"

_ironpython_sys_version_parser = re.compile(
Expand Down Expand Up @@ -1114,7 +1116,7 @@ def _sys_version(sys_version=None):
raise ValueError(
'failed to parse Jython sys.version: %s' %
repr(sys_version))
version, buildno, builddate, buildtime, _ = match.groups()
version, buildno, builddate, buildtime, _, _ = match.groups()
if builddate is None:
builddate = ''
compiler = sys.platform
Expand All @@ -1136,7 +1138,7 @@ def _sys_version(sys_version=None):
raise ValueError(
'failed to parse CPython sys.version: %s' %
repr(sys_version))
version, buildno, builddate, buildtime, compiler = \
version, buildno, builddate, buildtime, _, compiler = \
match.groups()
name = 'CPython'
if builddate is None:
Expand Down
7 changes: 6 additions & 1 deletion Lib/test/test_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def tearDown(self):
sys.platform = self.save_platform

def test_sys_version(self):
# Old test.
# Test platform._sys_version()
for input, output in (
('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]',
('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')),
Expand All @@ -143,6 +143,11 @@ def test_sys_version(self):
('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
('2.4.3 (truncation) \n[GCC]',
('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
('3.12.0a3+ (heads/py_build_str:f9be94491f, '
'Dec 7 2022, 21:57:04, debug build) '
'[GCC 12.2.1 20221121 (Red Hat 12.2.1-4)]',
('CPython', '3.12.0a3+', '', '', 'heads/py_build_str:f9be94491f',
'Dec 7 2022 21:57:04', 'GCC 12.2.1 20221121 (Red Hat 12.2.1-4)')),
):
# branch and revision are not "parsed", but fetched
# from sys._git. Ignore them
Expand Down
4 changes: 3 additions & 1 deletion Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ PY_CORE_CFLAGS= $(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE
PY_CORE_LDFLAGS=$(PY_LDFLAGS) $(PY_LDFLAGS_NODIST)
# Strict or non-strict aliasing flags used to compile dtoa.c, see above
CFLAGS_ALIASING=@CFLAGS_ALIASING@

# String describing the Python build used by sys.version (ex: "debug build")
PY_BUILD_STR=@PY_BUILD_STR@

# Machine-dependent subdirectories
MACHDEP= @MACHDEP@
Expand Down Expand Up @@ -1245,6 +1246,7 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
-DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \
-DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \
-DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \
-DPY_BUILD_STR="\"$(PY_BUILD_STR)\"" \
-o $@ $(srcdir)/Modules/getbuildinfo.c

Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h Makefile $(PYTHON_HEADERS)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add more build details about how Python was configured in :data:`sys.version`,
like "debug" or "release" build. Patch by Victor Stinner.
19 changes: 16 additions & 3 deletions Modules/getbuildinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,23 @@
#ifndef GITBRANCH
#define GITBRANCH ""
#endif
#ifndef PY_BUILD_STR
// On Windows, only provide basic info
# ifdef Py_DEBUG
# define PY_BUILD_STR "debug build"
# else
# define PY_BUILD_STR "release build"
# endif
#endif

// len(", release+assert+tracerefs+pystats asan msan ubsan lto=thin+pgo framework shared build")
#define PY_BUILD_STR_MAXLEN 86

static int initialized = 0;
static char buildinfo[50 + sizeof(GITVERSION) +
((sizeof(GITTAG) > sizeof(GITBRANCH)) ?
sizeof(GITTAG) : sizeof(GITBRANCH))];
sizeof(GITTAG) : sizeof(GITBRANCH))
+ PY_BUILD_STR_MAXLEN];

const char *
Py_GetBuildInfo(void)
Expand All @@ -50,8 +62,9 @@ Py_GetBuildInfo(void)
gitid = "main";
}
PyOS_snprintf(buildinfo, sizeof(buildinfo),
"%s%s%s, %.20s, %.9s", gitid, sep, revision,
DATE, TIME);
"%s%s%s, %.20s, %.9s, %s",
gitid, sep, revision, DATE, TIME,
PY_BUILD_STR);
return buildinfo;
}

Expand Down
71 changes: 71 additions & 0 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 70 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3093,12 +3093,15 @@ case $ac_sys_system/$ac_sys_release in
;;
esac

SANITIZERS=""

AC_MSG_CHECKING(for --with-address-sanitizer)
AC_ARG_WITH(address_sanitizer,
AS_HELP_STRING([--with-address-sanitizer],
[enable AddressSanitizer memory error detector, 'asan' (default is no)]),
[
AC_MSG_RESULT($withval)
SANITIZERS="$SANITIZERS asan"
BASECFLAGS="-fsanitize=address -fno-omit-frame-pointer $BASECFLAGS"
LDFLAGS="-fsanitize=address $LDFLAGS"
# ASan works by controlling memory allocation, our own malloc interferes.
Expand All @@ -3113,6 +3116,7 @@ AC_ARG_WITH(memory_sanitizer,
[
AC_MSG_RESULT($withval)
AX_CHECK_COMPILE_FLAG([-fsanitize=memory],[
SANITIZERS="$SANITIZERS msan"
BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS"
LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS"
],[AC_MSG_ERROR([The selected compiler doesn't support memory sanitizer])])
Expand All @@ -3127,6 +3131,7 @@ AC_ARG_WITH(undefined_behavior_sanitizer,
[enable UndefinedBehaviorSanitizer undefined behaviour detector, 'ubsan' (default is no)]),
[
AC_MSG_RESULT($withval)
SANITIZERS="$SANITIZERS ubsan"
BASECFLAGS="-fsanitize=undefined $BASECFLAGS"
LDFLAGS="-fsanitize=undefined $LDFLAGS"
with_ubsan="yes"
Expand All @@ -3136,6 +3141,10 @@ AC_MSG_RESULT(no)
with_ubsan="no"
])

# strip leading space
SANITIZERS=$(echo $SANITIZERS | sed 's/^ //')


# Set info about shared libraries.
AC_SUBST(SHLIB_SUFFIX)
AC_SUBST(LDSHARED)
Expand Down Expand Up @@ -7374,6 +7383,67 @@ PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no"], [test "$ac_cv_fu
# substitute multiline block, must come after last PY_STDLIB_MOD()
AC_SUBST([MODULE_BLOCK])


# String describing the Python build used by sys.version (ex: "debug build")
# Short string containing most important configure options.
# Examples:
# - "debug+tracerefs build"
# - "release+assert shared build"
# - "release lto+pgo build"
#
# If the PY_BUILD_STR format changes, PY_BUILD_STR_MAXLEN in
# Modules/getbuildinfo.c should be updated.
AC_SUBST(PY_BUILD_STR)
if test "$Py_DEBUG" = 'true' ; then
PY_BUILD_STR="debug"
else
PY_BUILD_STR="release"
if test "$assertions" = 'true'; then
PY_BUILD_STR="$PY_BUILD_STR+assert"
fi
fi
if test "$with_trace_refs" = "yes"; then
PY_BUILD_STR="$PY_BUILD_STR+tracerefs"
fi
if test "$enable_pystats" = "yes"; then
PY_BUILD_STR="$PY_BUILD_STR+pystats"
fi
if test -n "${SANITIZERS}"; then
PY_BUILD_STR="$PY_BUILD_STR $SANITIZERS"
fi
if test "$Py_LTO" = 'true' ; then
LTO_BUILD_STR="lto"
if test "$Py_LTO_POLICY" = 'thin' ; then
LTO_BUILD_STR="lto=thin"
fi
else
LTO_BUILD_STR=""
fi
if test "$Py_OPT" = 'true' ; then
PGO_BUILD_STR="pgo"
else
PGO_BUILD_STR=""
fi
if test -n "${LTO_BUILD_STR}"; then
if test -n "${PGO_BUILD_STR}"; then
PY_BUILD_STR="$PY_BUILD_STR $LTO_BUILD_STR+$PGO_BUILD_STR"
else
PY_BUILD_STR="$PY_BUILD_STR $LTO_BUILD_STR"
fi
else
if test -n "${PGO_BUILD_STR}"; then
PY_BUILD_STR="$PY_BUILD_STR $PGO_BUILD_STR"
fi
fi
if test "$enable_framework"; then
PY_BUILD_STR="$PY_BUILD_STR framework"
fi
if test "$PY_ENABLE_SHARED" = 1; then
PY_BUILD_STR="$PY_BUILD_STR shared"
fi
PY_BUILD_STR="$PY_BUILD_STR build"


# generate output files
AC_CONFIG_FILES(Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh)
AC_CONFIG_FILES([Modules/Setup.bootstrap Modules/Setup.stdlib])
Expand Down