diff --git a/ChangeLog.txt b/ChangeLog.txt index 2754ccf4db..6f0bc033b9 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -7,6 +7,41 @@ Entries may not always be in chronological/commit order. See license at the end of file. */ +2024-10-10 14:21 UTC+0200 Aleksander Czajczynski (hb fki.pl) + + config/win/clang-noauto.mk + + additional clang flavour checking when the compiler is specified + via set HB_COMPILER=clang (not auto-detected) + + This is important for distributions of clang that bundle both + gcc and clang in the same directory. Harbour 3.2 by default + prioritize gcc over clang. + + For example you should be now able to build from winlibs.com by + Brecht Sanders with environment setup such as: + PATH=C:\winlibs\mingw64\bin;%PATH% + HB_COMPILER=clang + win-make + + * config/global.mk + ! added workaround for common GNU Make issue with + $(dir path with spaces/file) macro, commonly striking on Windows + systems under "Program Files", but also possible in other setups. + Workaround is to call $(call dir_with_spaces,$(HB_COMP_PATH)). + I have only used this workaround in clang detection, but keep + this in mind while revisiting detection of another compiler. + + * config/win/clang.mk + * utils/hbmk2/hbmk2.prg + * another rework of Clang on Windows detection (ARM64, x86_64, x86), + solved problems with different availability of resource compiler, + They are now probed in order: windres, llvm-windres, llvm-rc. + + * added option to use MinGW INPUT(file.o) link scripts for old tools + To apply workaround with clang, set HB_USER_DFLAGS=--mingw-script + It is not supported in at least some of current clang toolchains, + but it's still needed to succesfully build on old ones (those + using GNU ld on Windows). + 2024-10-07 11:40 UTC+0200 Aleksander Czajczynski (hb fki.pl) * config/global.mk ! detect ARM64 CPU on Windows also under non-native shell (MSYS2 sh) diff --git a/config/global.mk b/config/global.mk index ead7c80c31..936317dbb1 100644 --- a/config/global.mk +++ b/config/global.mk @@ -40,6 +40,8 @@ endif # Arbitrary pattern which we do not expect to occur in real-world path names substpat := !@!@ +# On the other hand a very common pattern +chr_space := $(subst ,, ) # This is not strictly necessary, but it does significantly reduce # the number of rules that make has to evaluate otherwise, which may give @@ -79,6 +81,7 @@ find_in_path = $(strip $(subst $(substpat), ,$(firstword $(subst |, ,$(subst find_in_path_raw = $(strip $(subst $(substpat), ,$(firstword $(subst |, ,$(subst $(subst x, ,x),$(substpat),$(filter-out |,$(foreach dir, $(subst $(PTHSEP), ,$(subst $(subst x, ,x),$(substpat),$(PATH))),|$(wildcard $(subst //,/,$(subst $(substpat),\ ,$(subst \,/,$(dir)))/$(1)))))))))) find_in_path_par = $(strip $(subst $(substpat), ,$(firstword $(subst |, ,$(subst $(subst x, ,x),$(substpat),$(filter-out |,$(foreach dir, $(subst $(PTHSEP), ,$(subst $(subst x, ,x),$(substpat),$(2))),|$(wildcard $(subst //,/,$(subst $(substpat),\ ,$(subst \,/,$(dir)))/$(1))$(HB_HOST_BIN_EXT))))))))) find_in_path_prw = $(strip $(subst $(substpat), ,$(firstword $(subst |, ,$(subst $(subst x, ,x),$(substpat),$(filter-out |,$(foreach dir, $(subst $(PTHSEP), ,$(subst $(subst x, ,x),$(substpat),$(2))),|$(wildcard $(subst //,/,$(subst $(substpat),\ ,$(subst \,/,$(dir)))/$(1)))))))))) +dir_with_spaces = $(subst $(substpat), ,$(dir $(subst $(chr_space),$(substpat),$(1)))) # Some presets based on HB_BUILD_NAME ifneq ($(HB_BUILD_NAME),) @@ -708,39 +711,90 @@ ifeq ($(HB_COMPILER),) endif endif else - HB_COMP_PATH := $(call find_in_path,clang) + HB_COMP_PATH := $(call find_in_path_raw,clang.exe) + HB_COMP_PWD := $(call dir_with_spaces,$(HB_COMP_PATH)) ifneq ($(HB_COMP_PATH),) - HB_COMPILER = clang - ifneq ($(wildcard $(dir $(HB_COMP_PATH))aarch64-w64-mingw32-clang$(HB_HOST_BIN_EXT)),) + HB_COMPILER := clang + ifneq ($(wildcard $(HB_COMP_PWD)aarch64-w64-mingw32-clang$(HB_HOST_BIN_EXT)),) HB_CPU := arm64 - ifeq ($(HB_BUILD_NAME),) - export HB_BUILD_NAME := arm64 - endif - ifneq ($(MSYSTEM),) - export MSYSTEM := CLANGARM64 - endif + MSYSTEM := CLANGARM64 else - ifneq ($(wildcard $(dir $(HB_COMP_PATH))x86_64-w64-mingw32-clang$(HB_HOST_BIN_EXT)),) + ifneq ($(wildcard $(HB_COMP_PWD)x86_64-w64-mingw32-clang$(HB_HOST_BIN_EXT)),) HB_CPU := x86_64 - ifeq ($(HB_BUILD_NAME),) - export HB_BUILD_NAME := 64 - endif - ifneq ($(MSYSTEM),) - export MSYSTEM := CLANG64 - endif + MSYSTEM := CLANG64 else - ifneq ($(wildcard $(dir $(HB_COMP_PATH))i686-w64-mingw32-clang$(HB_HOST_BIN_EXT)),) - ifneq ($(MSYSTEM),) - export MSYSTEM := CLANG32 - endif + ifneq ($(wildcard $(HB_COMP_PWD)i686-w64-mingw32-clang$(HB_HOST_BIN_EXT)),) HB_CPU := x86 + MSYSTEM := CLANG32 else - ifneq ($(wildcard $(dir $(HB_COMP_PATH))lldb-vscode$(HB_HOST_BIN_EXT)),) - export MSYSTEM := + ifneq ($(findstring /VC/Tools/Llvm/ARM64/,$(HB_COMP_PATH)),) + MSYSTEM := + HB_CPU := arm64 + else + ifneq ($(findstring /VC/Tools/Llvm/x64/,$(HB_COMP_PATH)),) + MSYSTEM := + HB_CPU := x86_64 + else + ifneq ($(findstring mingw64,$(HB_COMP_PATH)),) + HB_CPU := x86_64 + MSYSTEM := CLANG64 + else + ifneq ($(findstring mingw32,$(HB_COMP_PATH)),) + HB_CPU := x86 + MSYSTEM := CLANG32 + else + MSYSTEM := $(shell clang --version) + ifneq ($(findstring x86_64-pc-windows-msvc,$(MSYSTEM)),) + MSYSTEM := + HB_CPU := x86_64 + else + ifneq ($(findstring i686-pc-windows-msvc,$(MSYSTEM)),) + MSYSTEM := + HB_CPU := x86 + else + ifneq ($(findstring aarch64-pc-windows-msvc,$(MSYSTEM)),) + MSYSTEM := + HB_CPU := arm64 + ifneq ($(findstring x86_64-w64-windows-gnu,$(MSYSTEM)),) + HB_CPU := x86_64 + MSYSTEM := CLANG64 + else + ifneq ($(findstring i686-w64-windows-gnu,$(MSYSTEM)),) + HB_CPU := x86 + MSYSTEM := CLANG32 + else + ifneq ($(findstring aarch64-w64-windows-gnu,$(MSYSTEM)),) + HB_CPU := arm64 + MSYSTEM := CLANGARM64 + else + ifneq ($(findstring -windows-gnu,$(MSYSTEM)),) + MSYSTEM := CLANG + else + MSYSTEM := + endif + endif + endif + endif + endif + endif + endif + endif endif endif endif endif + endif + endif + export MSYSTEM + ifneq ($(HB_CPU),$(HB_HOST_CPU)) + ifeq ($(HB_BUILD_NAME),) + ifeq ($(HB_CPU),x86_64) + export HB_BUILD_NAME := 64 + else + export HB_BUILD_NAME := HB_CPU + endif + endif + endif else HB_COMP_PATH := $(call find_in_path,wcc386) ifneq ($(HB_COMP_PATH),) @@ -1077,6 +1131,10 @@ ifeq ($(HB_COMPILER),) endif endif endif +else + ifneq ($(wildcard $(TOP)$(ROOT)config/$(HB_PLATFORM)/$(HB_COMPILER)-noauto.mk),) + include $(TOP)$(ROOT)config/$(HB_PLATFORM)/$(HB_COMPILER)-noauto.mk + endif endif # auto-detect CC values for given platform/compiler diff --git a/config/win/clang-noauto.mk b/config/win/clang-noauto.mk new file mode 100644 index 0000000000..4bd552e4df --- /dev/null +++ b/config/win/clang-noauto.mk @@ -0,0 +1,90 @@ +# Brecht Sanders winlibs clang distribution and possiblty others are impossible +# to detect from path alone as clang.exe resides in the same directory with gcc, +# in Harbour 3.2 gcc has priority over clang for backwards compatibility + +# supp. actions if the set HB_COMPILER=clang was specified, not auto-detected +ifneq ($(HB_COMPILER_ORI),) + HB_COMP_PATH := $(call find_in_path_raw,clang.exe) + HB_COMP_PWD := $(call dir_with_spaces,$(HB_COMP_PATH)) + ifneq ($(HB_COMP_PATH),) + ifneq ($(wildcard $(HB_COMP_PWD)../x86_64-w64-mingw32/lib/lib*.a),) + MSYSTEM := CLANG64 + HB_CPU := x86_64 + else + ifneq ($(wildcard $(HB_COMP_PWD)../i686-w64-mingw32/lib/lib*.a),) + MSYSTEM := CLANG32 + HB_CPU := x86 + else + ifneq ($(wildcard $(HB_COMP_PWD)../aarch64-w64-mingw32/lib/lib*.a),) + MSYSTEM := CLANGARM64 + HB_CPU := arm64 + else + ifneq ($(findstring /VC/Tools/Llvm/ARM64/,$(HB_COMP_PATH)),) + MSYSTEM := + HB_CPU := arm64 + else + ifneq ($(findstring /VC/Tools/Llvm/x64/,$(HB_COMP_PATH)),) + MSYSTEM := + HB_CPU := x86_64 + else + ifneq ($(findstring mingw64,$(HB_COMP_PWD)),) + MSYSTEM := CLANG64 + else + ifneq ($(findstring mingw32,$(HB_COMP_PWD)),) + MSYSTEM := CLANG32 + HB_CPU := x86 + else + MSYSTEM := $(shell clang --version) + ifneq ($(findstring x86_64-pc-windows-msvc,$(MSYSTEM)),) + MSYSTEM := + HB_CPU := x86_64 + else + ifneq ($(findstring i686-pc-windows-msvc,$(MSYSTEM)),) + MSYSTEM := + HB_CPU := x86 + else + ifneq ($(findstring aarch64-pc-windows-msvc,$(MSYSTEM)),) + MSYSTEM := + HB_CPU := arm64 + ifneq ($(findstring x86_64-w64-windows-gnu,$(MSYSTEM)),) + HB_CPU := x86_64 + MSYSTEM := CLANG64 + else + ifneq ($(findstring i686-w64-windows-gnu,$(MSYSTEM)),) + HB_CPU := x86 + MSYSTEM := CLANG32 + else + ifneq ($(findstring aarch64-w64-windows-gnu,$(MSYSTEM)),) + HB_CPU := arm64 + MSYSTEM := CLANGARM64 + else + ifneq ($(findstring -windows-gnu,$(MSYSTEM)),) + MSYSTEM := CLANG + else + MSYSTEM := + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + export MSYSTEM + ifneq ($(HB_CPU),$(HB_HOST_CPU)) + ifeq ($(HB_BUILD_NAME),) + ifeq ($(HB_CPU),x86_64) + export HB_BUILD_NAME := 64 + else + export HB_BUILD_NAME := HB_CPU + endif + endif + endif + endif +endif diff --git a/config/win/clang.mk b/config/win/clang.mk index 0c1aba9453..708ed48116 100644 --- a/config/win/clang.mk +++ b/config/win/clang.mk @@ -54,6 +54,8 @@ AR := $(HB_CCPREFIX)llvm-ar AR_RULE = ( $(AR) $(ARFLAGS) $(HB_AFLAGS) $(HB_USER_AFLAGS) rcs $(LIB_DIR)/$@ $(^F) $(ARSTRIP) ) || ( $(RM) $(subst /,$(DIRSEP),$(LIB_DIR)/$@) && $(FALSE) ) +# TODO: add resource compiler detect chain in this stage: GNU windres, llvm-windres, llvm-rc + DY := $(CC) DFLAGS += -shared $(LIBPATHS) DY_OUT := -o$(subst x,x, ) @@ -84,24 +86,37 @@ else endef endif +TMPSPEC := @__dyn__.tmp + +# setting HB_USER_DFLAGS=--mingw-script[...] +# may help to workaround if old clang + MinGW linker is in use, +# build may fail either with too long command line or unrecognized argument +ifneq ($(filter --mingw-script, $(HB_USER_DFLAGS)),) + HB_USER_DFLAGS := $(subst --mingw-script,,$(HB_USER_DFLAGS)) + # NOTE: The empty line directly before 'endef' HAS TO exist! + override define dynlib_object + @$(ECHO) $(ECHOQUOTE)INPUT($(subst \,/,$(file)))$(ECHOQUOTE) >> __dyn__.tmp + endef + TMPSPEC := __dyn__.tmp +endif + +define create_dynlib + $(if $(wildcard __dyn__.tmp),@$(RM) __dyn__.tmp,) + $(foreach file,$^,$(dynlib_object)) + $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ $(TMPSPEC) $(DLIBS) $(IMPLIBFLAGS) $(DYSTRIP) $(DYSTRIP) + $(dynlib_ln) +endef + # clang distributed by MS uses lld-link, libs are *.lib not lib*.a # in opposite MSYS/MinGW needs args to actually make an implib ifeq ($(MSYSTEM),) - define create_dynlib - $(if $(wildcard __dyn__.tmp),@$(RM) __dyn__.tmp,) - $(foreach file,$^,$(dynlib_object)) - $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ @__dyn__.tmp $(DLIBS) $(DYSTRIP) $(DYSTRIP) - $(dynlib_ln) - endef + LDFLAGS += -Wl,-subsystem:console + DFLAGS += -Wl,-subsystem:console else - define create_dynlib - $(if $(wildcard __dyn__.tmp),@$(RM) __dyn__.tmp,) - $(foreach file,$^,$(dynlib_object)) - $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ @__dyn__.tmp $(DLIBS) -Wl,--out-implib,$(IMP_FILE),--output-def,$(DYN_DIR)/$(basename $@).def $(DYSTRIP) $(DYSTRIP) - $(dynlib_ln) - endef + IMPLIBFLAGS = -Wl,--out-implib,$(IMP_FILE),--output-def,$(DYN_DIR)/$(basename $@).def endif + DY_RULE = $(create_dynlib) include $(TOP)$(ROOT)config/rules.mk diff --git a/utils/hbmk2/hbmk2.prg b/utils/hbmk2/hbmk2.prg index cbe59d55fa..84bd1bcdf7 100644 --- a/utils/hbmk2/hbmk2.prg +++ b/utils/hbmk2/hbmk2.prg @@ -4368,6 +4368,11 @@ STATIC FUNCTION __hbmk( aArgs, nArgTarget, nLevel, /* @ */ lPause, /* @ */ lExit IF hb_fileExists( hb_DirSepAdd( hbmk[ _HBMK_cHB_INSTALL_LIB ] ) + "hbrtl.lib" ) /* selfcheck if clang ld emits .lib extension */ cLibLibPrefix := "" cLibLibExt := ".lib" + IF hbmk[ _HBMK_lGUI ] + AAdd( hbmk[ _HBMK_aOPTL ], "-Wl,-subsystem:windows" ) + ELSE + AAdd( hbmk[ _HBMK_aOPTL ], "-Wl,-subsystem:console" ) + ENDIF ENDIF CASE hbmk[ _HBMK_cCOMP ] == "tcc" cBin_CompCPP := "tcc.exe" @@ -4571,6 +4576,15 @@ STATIC FUNCTION __hbmk( aArgs, nArgTarget, nLevel, /* @ */ lPause, /* @ */ lExit cBin_Res := hbmk[ _HBMK_cCCPREFIX ] + "windres" + hbmk[ _HBMK_cCCEXT ] cResExt := ".reso" cOpt_Res := "{FR} {IR} -O coff -o {OS}" + IF hbmk[ _HBMK_cCOMP ] == "clang" .AND. FindInPath( cBin_Res ) == NIL + IF FindInPath( cBin_Res := "llvm-" + cBin_Res ) == NIL + cBin_Res := "llvm-rc" + cResExt := ".res" + /* codepage default in llvm-rc is confusing, a .rc file could be multi-language */ + cOpt_Res := "/C 1252 {FR} /FO {OS} {IR}" + ENDIF + ENDIF + IF ! Empty( hbmk[ _HBMK_cCCPATH ] ) cBin_Res := FNameEscape( hbmk[ _HBMK_cCCPATH ] + hb_ps() + cBin_Res, hbmk[ _HBMK_nCmd_Esc ] ) ENDIF