Skip to content

mingw: use strftime() directly in UCRT builds#6130

Open
dscho wants to merge 1 commit intomainfrom
use-strftime-directly-in-ucrt-builds
Open

mingw: use strftime() directly in UCRT builds#6130
dscho wants to merge 1 commit intomainfrom
use-strftime-directly-in-ucrt-builds

Conversation

@dscho
Copy link
Member

@dscho dscho commented Mar 17, 2026

Currently, Git for Windows is built off of the MINGW64 tool chain. But this will have to change because the MSYS2 project deprecated this tool chain in favor of UCRT64. Of course, that's only possible because they dropped support for Windows 8.1, which Git for Windows will probably have to do relatively soon. The best time to do that is probably the Git 3.0 inflection point when we already promised to drop support for older Windows versions.

To prepare for such a huge change, I investigated what needs to be changed in Git for Windows' source code. And the good news is there's actually not very much. This here patch seems to be the only change that's necessary, and not even strictly necessary: the mingw_strftime() wrapper would still do the right thing. It would just uselessly load the same function that's already loaded, dynamically, again.

The `mingw_strftime()` wrapper exists to work around msvcrt.dll's
incomplete `strftime()` implementation by dynamically loading the
version from ucrtbase.dll at runtime via `LoadLibrary()` +
`GetProcAddress()`. When the binary is already linked against UCRT
(i.e. when building in the UCRT64 environment), the linked-in
`strftime()` is the ucrtbase.dll version, making the dynamic loading
needless churn: It's calling the very same code.

Simply guard both the declaration and implementation so that the
unnecessary work-around is skipped in UCRT builds.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho dscho requested review from mjcheetham and rimrul March 17, 2026 07:38
@dscho dscho self-assigned this Mar 17, 2026
@rimrul
Copy link
Member

rimrul commented Mar 17, 2026

I think this might regress #863 on UCRT.

/* a pointer to the original strftime in case we can't find the UCRT version */
static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime;
size_t ret;
DECLARE_PROC_ADDR(ucrtbase.dll, size_t, __cdecl, strftime, char *, size_t,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just

Suggested change
#ifndef _UCRT
DECLARE_PROC_ADDR(ucrtbase.dll, size_t, __cdecl, strftime, char *, size_t,
const char *, const struct tm *);
if (INIT_PROC_ADDR(strftime))
ret = strftime(s, max, format, tm);
else
#endif

without any other #ifndef?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right @rimrul ! I had forgotten about 9ee0540.

But I'd rather avoid defining the strftime local variable at all, i.e. have this instead:

#ifdef _UCRT
	size_t ret = strftime(s, max, format, tm);
#else
	[...]
#endif

	if (!ret && errno == EINVAL)
		die("invalid strftime format: '%s'", format);
	return ret;

Wouldn't you agree?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that would be nicer. And I even thought to myself "having it called fallback on UCRT is a bit clunky".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants