From c8c089d21b923e7794c40a5a604af19d702019b1 Mon Sep 17 00:00:00 2001
From: Costas Argyris <costas.argyris@gmail.com>
Date: Sat, 25 Mar 2023 21:51:41 +0000
Subject: [PATCH] Add UTF-8 resource when building for Windows host, if a
 resource compiler is available.

When building with VS the resource compiler is
always available.

When building with GCC or TCC, it depends on the
availability of 'windres'.

The UTF-8 resource only has an effect starting at a
minimum target of Windows Version 1903 (May 2019 Update).
Earlier versions of Windows are unaffected by it.

Code page information gets output by --version to
tell what code pages are being used for any given
combination of Make build (with or without the UTF-8
resource) and Windows version that Make is running on
(earlier than 1903 or not).

Signed-off-by: Costas Argyris <costas.argyris@gmail.com>
---
 .gitignore            |  2 ++
 Makefile.am           | 11 ++++++++++
 README.git            |  2 +-
 build_w32.bat         | 47 +++++++++++++++++++++++++++++++++++++++++--
 configure.ac          |  5 +++++
 src/main.c            |  5 +++++
 src/w32/utf8.manifest |  8 ++++++++
 src/w32/utf8.rc       |  3 +++
 8 files changed, 80 insertions(+), 3 deletions(-)
 create mode 100644 src/w32/utf8.manifest
 create mode 100644 src/w32/utf8.rc

diff --git a/.gitignore b/.gitignore
index 1ea8c55c..cf4109d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,8 @@ WinDebug/
 WinRel/
 GccDebug/
 GccRel/
+TccDebug/
+TccRel/
 
 # Test artifacts
 makeerror-*
diff --git a/Makefile.am b/Makefile.am
index 23a48e47..dc519bf2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,6 +46,8 @@ w32_SRCS =	src/w32/pathstuff.c src/w32/w32os.c src/w32/compat/dirent.c \
 		src/w32/subproc/misc.c src/w32/subproc/proc.h \
 		src/w32/subproc/sub_proc.c src/w32/subproc/w32err.c
 
+w32_utf8_SRCS = src/w32/utf8.rc src/w32/utf8.manifest
+
 vms_SRCS =	src/vms_exit.c src/vms_export_symbol.c src/vms_progname.c \
 		src/vmsdir.h src/vmsfunctions.c src/vmsify.c
 
@@ -88,6 +90,15 @@ else
   make_SOURCES += src/posixos.c
 endif
 
+UTF8OBJ = src/w32/utf8.$(OBJEXT)
+
+if HAVE_WINDRES
+  make_LDADD += $(UTF8OBJ)
+endif
+
+$(UTF8OBJ) : $(w32_utf8_SRCS)
+	$(WINDRES) -o $@ -i $<
+
 if USE_CUSTOMS
   make_SOURCES += src/remote-cstms.c
 else
diff --git a/README.git b/README.git
index 03125fa9..0e0c327e 100644
--- a/README.git
+++ b/README.git
@@ -147,7 +147,7 @@ That is, you can just run:
 to build and test GNU Make.
 
 NOTE! This method builds GNU Make in "maintainer mode".  Make programs built
-      in this mode it will be slower, possibly MUCH slower: there are various
+      in this mode will be slower, possibly MUCH slower: there are various
       sanity checks enabled.  Further this mode assumes a modern GCC, GNU
       libc, and well-formed system headers and enables a high level of
       warnings AND enables -Werror to turn warnings into failures.
diff --git a/build_w32.bat b/build_w32.bat
index 3abc43ed..9526d0d9 100644
--- a/build_w32.bat
+++ b/build_w32.bat
@@ -34,6 +34,7 @@ echo.
 set MAKE=gnumake
 set GUILE=Y
 set COMPILER=cl.exe
+set RC=rc.exe
 set O=obj
 set ARCH=x64
 set DEBUG=N
@@ -81,6 +82,7 @@ goto ParseSW
 
 :SetCC
 set COMPILER=gcc
+set RC=windres
 set O=o
 echo - Building with GCC
 shift
@@ -88,6 +90,7 @@ goto ParseSW
 
 :SetTCC
 set COMPILER=tcc
+set RC=windres
 set O=o
 echo - Building with TinyC
 shift
@@ -174,6 +177,7 @@ set OUTDIR=.\WinRel
 set LNKOUT=./WinRel
 set "OPTS=/O2 /D NDEBUG"
 set LINKOPTS=
+set HAVE_RC=Y
 if "%DEBUG%" == "Y" set OUTDIR=.\WinDebug
 if "%DEBUG%" == "Y" set LNKOUT=./WinDebug
 if "%DEBUG%" == "Y" set "OPTS=/Zi /Od /D _DEBUG"
@@ -197,7 +201,7 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE"
 :: Show the compiler version that we found
 echo.
 call %COMPILER% --version
-if not ERRORLEVEL 1 goto Build
+if not ERRORLEVEL 1 goto FindWindres
 echo No %COMPILER% found.
 exit 1
 
@@ -212,11 +216,23 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE"
 :: Show the compiler version that we found
 echo.
 call %COMPILER% -v
-if not ERRORLEVEL 1 goto Build
+if not ERRORLEVEL 1 goto FindWindres
 echo No %COMPILER% found.
 exit 1
 
+:FindWindres
+set HAVE_RC=Y
+:: Show the windres version that we found, if any.
+echo.
+call %RC% --version
+if not ERRORLEVEL 1 goto Build
+echo.
+echo %RC% was not found. Building without UTF-8 resource.
+set HAVE_RC=N
+goto Build
+
 :Build
+echo.
 :: Clean the directory if it exists
 if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR%
 
@@ -285,6 +301,9 @@ call :Compile lib/getloadavg
 :: Compile dirent unless it is supported by compiler library (like with gcc).
 if "%DIRENT%" == "Y" call :Compile src\w32\compat\dirent
 
+:: Compile UTF-8 resource if a resource compiler is available.
+if "%HAVE_RC%" == "Y" call :ResourceCompile src/w32/utf8
+
 call :Link
 
 echo.
@@ -332,6 +351,30 @@ call %COMPILER% -mthreads -Wall -std=c11 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR
 @echo off
 goto CompileDone
 
+:ResourceCompile
+if "%VERBOSE%" == "N" echo - Compiling %1.rc
+echo %LNKOUT%/%1.%O% >>%OUTDIR%\link.sc
+if exist "%OUTDIR%\%1.%O%" del "%OUTDIR%\%1.%O%"
+if "%COMPILER%" == "gcc" goto GccResourceCompile
+if "%COMPILER%" == "tcc" goto TccResourceCompile
+
+:: MSVC Resource Compile
+if "%VERBOSE%" == "Y" echo on
+call %RC% /fo %OUTDIR%\%1.%O% %1.rc
+@echo off
+goto CompileDone
+
+:GccResourceCompile
+:: GCC Resource Compile
+if "%VERBOSE%" == "Y" echo on
+call %RC% -o %OUTDIR%/%1.%O% -i %1.rc
+@echo off
+goto CompileDone
+
+:TccResourceCompile
+:: TCC Resource Compile
+goto GccResourceCompile
+
 :CompileDone
 if not exist "%OUTDIR%\%1.%O%" exit 1
 goto :EOF
diff --git a/configure.ac b/configure.ac
index 645b4466..c6741003 100644
--- a/configure.ac
+++ b/configure.ac
@@ -444,6 +444,7 @@ AC_SUBST([MAKE_HOST])
 
 w32_target_env=no
 AM_CONDITIONAL([WINDOWSENV], [false])
+AM_CONDITIONAL([HAVE_WINDRES], [false])
 
 AS_CASE([$host],
   [*-*-mingw32],
@@ -451,6 +452,10 @@ AS_CASE([$host],
     w32_target_env=yes
     AC_DEFINE([MK_OS_W32], [1], [Build for the Windows32 API.])
     AC_DEFINE([HAVE_DOS_PATHS], [1], [Support DOS-style pathnames.])
+    # Windows host tools.
+    # If windres is available, make will use UTF-8.
+    AC_CHECK_TOOL([WINDRES], [windres], [:])
+    AM_CONDITIONAL([HAVE_WINDRES], [test "$WINDRES" != ':'])
   ])
 
 AC_DEFINE_UNQUOTED([PATH_SEPARATOR_CHAR],['$PATH_SEPARATOR'],
diff --git a/src/main.c b/src/main.c
index 6a94cfdb..da8b56c7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3686,6 +3686,11 @@ print_version (void)
     printf (_("%sBuilt for %s (%s)\n"),
             precede, make_host, remote_description);
 
+  #if MK_OS_W32
+    printf ("%sANSI code page: %u\n", precede, GetACP());
+    printf ("%sConsole code page: %u\n", precede, GetConsoleOutputCP());
+  #endif
+
   /* Print this untranslated.  The coding standards recommend translating the
      (C) to the copyright symbol, but this string is going to change every
      year, and none of the rest of it should be translated (including the
diff --git a/src/w32/utf8.manifest b/src/w32/utf8.manifest
new file mode 100644
index 00000000..dab929e1
--- /dev/null
+++ b/src/w32/utf8.manifest
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <application>
+    <windowsSettings>
+      <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
+    </windowsSettings>
+  </application>
+</assembly>
diff --git a/src/w32/utf8.rc b/src/w32/utf8.rc
new file mode 100644
index 00000000..62bdbdc3
--- /dev/null
+++ b/src/w32/utf8.rc
@@ -0,0 +1,3 @@
+#include <winuser.h>
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "utf8.manifest"
-- 
2.40.0

