Add a UTF-8 resource when building for Windows

If a resource compiler is available, use it to add a UTF-8 resource
to the GNU Make executable on Windows.  As a result, GNU Make will
use UTF-8 as its ANSI code page, enabling it to work with UTF-8
encoded Makefiles, understand UTF-8 paths passed to it, etc.

These build process changes apply to all 3 ways that GNU Make can
be built for Windows:

1) configure
2) Basic.mk
3) build_w32.bat

When building with Visual Studio the resource compiler should always
be available.

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

If a resource compiler is not available, don't fail the build but
just proceed without the UTF-8 resource, effectively ignoring this
feature.

The UTF-8 resource only has an effect when GNU Make is running on a
minimum target version of Windows Version 1903 (May 2019 Update).
When the built GNU Make is running on an earlier version of Windows,
the embedded UTF-8 resource has no effect.

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

* README.git: Fix a typo.
* configure.ac: Search for windres and set WINDRES / HAVE_WINDRES.
* Makefile.am: Add manifest and resource files to EXTRA_DIST and
add a windres invocation to build them.
* build_w32.bat: Add support to build resource files.
* src/main.c (print_version): Add codepage info to Windows output.
* src/w32/utf8.manifest: Add a windres manifest file.
* src/w32/utf8.rc: Add a windres resource file.
* Basic.mk.template: Add support for building resource files.
* mk/Windows32.mk: Support windres resource files.
* .gitignore: Ignore TCC output directories.
This commit is contained in:
Costas Argyris 2023-06-19 09:51:13 -04:00 committed by Paul Smith
parent 04f4c2b8d9
commit b2bf660abc
10 changed files with 100 additions and 8 deletions

2
.gitignore vendored
View file

@ -59,6 +59,8 @@ WinDebug/
WinRel/
GccDebug/
GccRel/
TccDebug/
TccRel/
# Test artifacts
makeerror-*

View file

@ -59,6 +59,8 @@ BUILT_SOURCES =
OBJECTS = $(patsubst %.c,$(OUTDIR)%.$(OBJEXT),$(prog_SOURCES))
RESOURCE_OBJECTS =
OBJDIRS = $(addsuffix .,$(sort $(dir $(OBJECTS))))
# Use the default value of CC
@ -99,7 +101,7 @@ RM.cmd = rm -f $1
# $(call CP.cmd,<from>,<to>)
CP.cmd = cp $1 $2
CLEANSPACE = $(call RM.cmd,$(OBJECTS) $(PROG) $(BUILT_SOURCES))
CLEANSPACE = $(call RM.cmd,$(OBJECTS) $(RESOURCE_OBJECTS) $(PROG) $(BUILT_SOURCES))
# Load overrides for the above variables.
include $(firstword $(wildcard $(SRCDIR)/mk/$(lastword $(subst -, ,$(MAKE_HOST)).mk)))
@ -108,7 +110,7 @@ VPATH = $(SRCDIR)
all: $(PROG)
$(PROG): $(OBJECTS)
$(PROG): $(OBJECTS) $(RESOURCE_OBJECTS)
$(call LINK.cmd,$^)
$(OBJECTS): $(OUTDIR)%.$(OBJEXT): %.c

View file

@ -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
@ -116,7 +127,7 @@ EXTRA_DIST = ChangeLog INSTALL README build.sh build.cfg.in $(man_MANS) \
README.VMS makefile.com src/config.h-vms src/vmsjobs.c \
vms_export_symbol_test.com \
src/gmk-default.scm src/gmk-default.h \
$(mk_FILES) $(m4_FILES) $(test_FILES)
$(mk_FILES) $(m4_FILES) $(test_FILES) $(w32_utf8_SRCS)
# --------------- Generate the Guile default module content

View file

@ -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.

View file

@ -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
@ -103,7 +106,7 @@ if "%COMPILER%" == "tcc" goto FindTcc
call %COMPILER% >nul 2>&1
if not ERRORLEVEL 1 goto FoundMSVC
:: Visual Studio 17 and above provides the "vswhere" tool
:: Visual Studio 15 2017 and above provides the "vswhere" tool
call :FindVswhere
if ERRORLEVEL 1 goto LegacyVS
@ -183,7 +186,7 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% /D MAKE_MAINTAINER_MODE"
:: Unfortunately this also shows a "usage" note; I can't find anything better.
echo.
call %COMPILER%
goto Build
goto FindRC
:FindGcc
set OUTDIR=.\GccRel
@ -197,7 +200,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 FindRC
echo No %COMPILER% found.
exit 1
@ -212,11 +215,20 @@ 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 FindRC
echo No %COMPILER% found.
exit 1
:FindRC
set HAVE_RC=Y
call where %RC% >nul 2>&1
if not ERRORLEVEL 1 goto Build
echo.
echo %RC% was not found. Building without UTF-8 resource.
set HAVE_RC=N
:Build
echo.
:: Clean the directory if it exists
if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR%
@ -285,6 +297,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 +347,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

View file

@ -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'],

View file

@ -30,6 +30,8 @@ P2W = $(subst /,\,$1)
prog_SOURCES += $(loadavg_SOURCES) $(glob_SOURCES) $(w32_SOURCES)
utf8_SOURCES = $(src)w32/utf8.rc $(src)w32/utf8.manifest
BUILT_SOURCES += $(lib)alloca.h $(lib)fnmatch.h $(lib)glob.h
w32_LIBS = kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 \
@ -41,6 +43,7 @@ LDFLAGS =
# --- Visual Studio
msvc_CC = cl.exe
msvc_RC = rc.exe
msvc_LD = link.exe
msvc_CPPFLAGS = /DHAVE_CONFIG_H /DMK_OS_W32=1 /DWIN32 /D_CONSOLE
@ -54,6 +57,7 @@ msvc_LDFLAGS = /nologo /SUBSYSTEM:console /PDB:$(BASE_PROG).pdb
msvc_LDLIBS = $(addsuffix .lib,$(w32_LIBS))
msvc_C_SOURCE = /c
msvc_RC_SOURCE =
msvc_OUTPUT_OPTION = /Fo$@
msvc_LINK_OUTPUT = /OUT:$@
@ -68,6 +72,7 @@ debug_msvc_LDFLAGS = /DEBUG
# --- GCC
gcc_CC = gcc
gcc_RC = windres
gcc_LD = $(gcc_CC)
release_gcc_OUTDIR = ./GccRel/
@ -79,6 +84,7 @@ gcc_LDFLAGS = -mthreads -gdwarf-2 -g3
gcc_LDLIBS = $(addprefix -l,$(w32_libs))
gcc_C_SOURCE = -c
gcc_RC_SOURCE = -i
gcc_OUTPUT_OPTION = -o $@
gcc_LINK_OUTPUT = -o $@
@ -87,6 +93,7 @@ release_gcc_CFLAGS = -O2
# ---
RES_COMPILE.cmd = $(RC) $(OUTPUT_OPTION) $(RC_SOURCE) $1
LINK.cmd = $(LD) $(extra_LDFLAGS) $(LDFLAGS) $(TARGET_ARCH) $1 $(LDLIBS) $(LINK_OUTPUT)
CHECK.cmd = cmd /c cd tests \& .\run_make_tests.bat -make ../$(PROG)
@ -96,9 +103,11 @@ RM.cmd = cmd /c del /F /Q $(call P2W,$1)
CP.cmd = cmd /c copy /Y $(call P2W,$1 $2)
CC = $($(TOOLCHAIN)_CC)
RC = $($(TOOLCHAIN)_RC)
LD = $($(TOOLCHAIN)_LD)
C_SOURCE = $($(TOOLCHAIN)_C_SOURCE)
RC_SOURCE = $($(TOOLCHAIN)_RC_SOURCE)
OUTPUT_OPTION = $($(TOOLCHAIN)_OUTPUT_OPTION)
LINK_OUTPUT = $($(TOOLCHAIN)_LINK_OUTPUT)
@ -120,3 +129,11 @@ LDLIBS = $(call _CUSTOM,LDLIBS)
$(OUTDIR)src/config.h: $(SRCDIR)/src/config.h.W32
$(call CP.cmd,$<,$@)
w32_UTF8OBJ = $(OUTDIR)src/w32/utf8.$(OBJEXT)
$(w32_UTF8OBJ): $(utf8_SOURCES)
$(call RES_COMPILE.cmd,$<)
ifneq (, $(shell where $(RC) 2>nul))
RESOURCE_OBJECTS = $(w32_UTF8OBJ)
endif

View file

@ -3708,6 +3708,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

8
src/w32/utf8.manifest Normal file
View file

@ -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>

3
src/w32/utf8.rc Normal file
View file

@ -0,0 +1,3 @@
#include <winuser.h>
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "utf8.manifest"