]> git.ipfire.org Git - thirdparty/make.git/commitdiff
Add a UTF-8 resource when building for Windows
authorCostas Argyris <costas.argyris@gmail.com>
Mon, 19 Jun 2023 13:51:13 +0000 (09:51 -0400)
committerPaul Smith <psmith@gnu.org>
Mon, 19 Jun 2023 17:29:52 +0000 (13:29 -0400)
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.

.gitignore
Basic.mk.template
Makefile.am
README.git
build_w32.bat
configure.ac
mk/Windows32.mk
src/main.c
src/w32/utf8.manifest [new file with mode: 0644]
src/w32/utf8.rc [new file with mode: 0644]

index 1ea8c55cd22dc5c02b745e4aa534e70047076d9b..cf4109d501f1297d47896afc9344fb36425c44c9 100644 (file)
@@ -59,6 +59,8 @@ WinDebug/
 WinRel/
 GccDebug/
 GccRel/
+TccDebug/
+TccRel/
 
 # Test artifacts
 makeerror-*
index e3a83a205ceeaa703d28bfdd931b32cdaf29ae80..ce273a1f326497f56e8ae402604ba3914e61bfdc 100644 (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
index 23a48e4729039fd5f57edb731a72367d5b68b2f0..5b4686b29ad8985b03c4ef55a2b00186ca5fc07a 100644 (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
 
index 03125fa98fa78d11f08980773384dc0a42e8ef11..0e0c327ea40b76cca648fd0c61c4face57a4960f 100644 (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.
index 3abc43ed21f813bb611e290f344f56ec9d2bd9c0..ce7dcab582aca23e481f24d6f22c766e71cbac72 100644 (file)
@@ -34,6 +34,7 @@ echo.
 set MAKE=gnumake\r
 set GUILE=Y\r
 set COMPILER=cl.exe\r
+set RC=rc.exe\r
 set O=obj\r
 set ARCH=x64\r
 set DEBUG=N\r
@@ -81,6 +82,7 @@ goto ParseSW
 \r
 :SetCC\r
 set COMPILER=gcc\r
+set RC=windres\r
 set O=o\r
 echo - Building with GCC\r
 shift\r
@@ -88,6 +90,7 @@ goto ParseSW
 \r
 :SetTCC\r
 set COMPILER=tcc\r
+set RC=windres\r
 set O=o\r
 echo - Building with TinyC\r
 shift\r
@@ -103,7 +106,7 @@ if "%COMPILER%" == "tcc" goto FindTcc
 call %COMPILER% >nul 2>&1\r
 if not ERRORLEVEL 1 goto FoundMSVC\r
 \r
-:: Visual Studio 17 and above provides the "vswhere" tool\r
+:: Visual Studio 15 2017 and above provides the "vswhere" tool\r
 call :FindVswhere\r
 if ERRORLEVEL 1 goto LegacyVS\r
 \r
@@ -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.\r
 echo.\r
 call %COMPILER%\r
-goto Build\r
+goto FindRC\r
 \r
 :FindGcc\r
 set OUTDIR=.\GccRel\r
@@ -197,7 +200,7 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE"
 :: Show the compiler version that we found\r
 echo.\r
 call %COMPILER% --version\r
-if not ERRORLEVEL 1 goto Build\r
+if not ERRORLEVEL 1 goto FindRC\r
 echo No %COMPILER% found.\r
 exit 1\r
 \r
@@ -212,11 +215,20 @@ if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE"
 :: Show the compiler version that we found\r
 echo.\r
 call %COMPILER% -v\r
-if not ERRORLEVEL 1 goto Build\r
+if not ERRORLEVEL 1 goto FindRC\r
 echo No %COMPILER% found.\r
 exit 1\r
 \r
+:FindRC\r
+set HAVE_RC=Y\r
+call where %RC% >nul 2>&1\r
+if not ERRORLEVEL 1 goto Build\r
+echo.\r
+echo %RC% was not found. Building without UTF-8 resource.\r
+set HAVE_RC=N\r
+\r
 :Build\r
+echo.\r
 :: Clean the directory if it exists\r
 if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR%\r
 \r
@@ -285,6 +297,9 @@ call :Compile lib/getloadavg
 :: Compile dirent unless it is supported by compiler library (like with gcc).\r
 if "%DIRENT%" == "Y" call :Compile src\w32\compat\dirent\r
 \r
+:: Compile UTF-8 resource if a resource compiler is available.\r
+if "%HAVE_RC%" == "Y" call :ResourceCompile src/w32/utf8\r
+\r
 call :Link\r
 \r
 echo.\r
@@ -332,6 +347,30 @@ call %COMPILER% -mthreads -Wall -std=c11 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR
 @echo off\r
 goto CompileDone\r
 \r
+:ResourceCompile\r
+if "%VERBOSE%" == "N" echo - Compiling %1.rc\r
+echo %LNKOUT%/%1.%O% >>%OUTDIR%\link.sc\r
+if exist "%OUTDIR%\%1.%O%" del "%OUTDIR%\%1.%O%"\r
+if "%COMPILER%" == "gcc" goto GccResourceCompile\r
+if "%COMPILER%" == "tcc" goto TccResourceCompile\r
+\r
+:: MSVC Resource Compile\r
+if "%VERBOSE%" == "Y" echo on\r
+call %RC% /fo %OUTDIR%\%1.%O% %1.rc\r
+@echo off\r
+goto CompileDone\r
+\r
+:GccResourceCompile\r
+:: GCC Resource Compile\r
+if "%VERBOSE%" == "Y" echo on\r
+call %RC% -o %OUTDIR%/%1.%O% -i %1.rc\r
+@echo off\r
+goto CompileDone\r
+\r
+:TccResourceCompile\r
+:: TCC Resource Compile\r
+goto GccResourceCompile\r
+\r
 :CompileDone\r
 if not exist "%OUTDIR%\%1.%O%" exit 1\r
 goto :EOF\r
index 645b4466da7bf036cee667a386a6bf855301e9ac..c67410030679bf2c1fadd22f9e2948212f228866 100644 (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'],
index 57226eb184b889fa30847a883e3a7fb8b5f01121..6e357ea7e28c865c8c0fdca10f5ed9ec0ebea8e2 100644 (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
index 1fba1c2108d578915b24ab6e426e231b6ee19cb3..9ec8f20a0030e5653abac80b4d94a1067c6d3e7c 100644 (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
diff --git a/src/w32/utf8.manifest b/src/w32/utf8.manifest
new file mode 100644 (file)
index 0000000..dab929e
--- /dev/null
@@ -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 (file)
index 0000000..62bdbdc
--- /dev/null
@@ -0,0 +1,3 @@
+#include <winuser.h>
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "utf8.manifest"