From 4fe07afd62feb3f2390f21bb4095540674680087 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 11 May 2024 17:26:43 +0300 Subject: [PATCH 1/4] Support building TBB on Windows arm64 --- R/tbb.R | 4 --- R/zzz.R | 6 +---- src/Makevars.in | 34 +++++++++++++------------ src/tbb/build/Makefile.tbb | 6 ++++- src/tbb/build/Makefile.tbbmalloc | 6 ++++- src/tbb/src/tbbmalloc/TypeDefinitions.h | 2 +- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/R/tbb.R b/R/tbb.R index d881fd8f5..00fccd3b6 100644 --- a/R/tbb.R +++ b/R/tbb.R @@ -81,10 +81,6 @@ tbbLdFlags <- function() { return(sprintf(fmt, asBuildPath(tbbLib))) } - # on Aarch64 builds, use the version of TBB provided by Rtools - if (is_windows() && R.version$arch == "aarch64") - return("-ltbb12 -ltbbmalloc") - # on Mac, Windows and Solaris, we need to explicitly link (#206) needsExplicitFlags <- is_mac() || is_windows() || (is_solaris() && !is_sparc()) if (needsExplicitFlags) { diff --git a/R/zzz.R b/R/zzz.R index 2e2847052..31c40a3e0 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -27,12 +27,8 @@ loadTbbLibrary <- function(name) { .onLoad <- function(libname, pkgname) { - tbbLibraryName <- "tbb" - if (is_windows() && R.version$arch == "aarch64") - tbbLibraryName <- "tbb12" - # load tbb, tbbmalloc - .tbbDllInfo <<- loadTbbLibrary(tbbLibraryName) + .tbbDllInfo <<- loadTbbLibrary("tbb") .tbbMallocDllInfo <<- loadTbbLibrary("tbbmalloc") # load tbbmalloc_proxy, but only if requested diff --git a/src/Makevars.in b/src/Makevars.in index af771924a..c510139ba 100644 --- a/src/Makevars.in +++ b/src/Makevars.in @@ -21,6 +21,14 @@ ifeq ($(OS), Windows_NT) USE_TBB=Windows TBB_COPY_PATTERN=tbb*.dll + ARCH=$(shell "${R_HOME}/bin/R" --vanilla -s -e 'cat(R.version$$arch)') + TBB_CXXFLAGS = @CXX11FLAGS@ -DTBB_NO_LEGACY=1 + ifeq "$(ARCH)" "aarch64" + WINARM64=true + PKG_CPPFLAGS += -DTBB_USE_GCC_BUILTINS + TBB_CXXFLAGS += -DTBB_USE_GCC_BUILTINS + endif + MAKE = make MAKEFLAGS = -e -j1 MAKE_CMD = \ @@ -28,9 +36,10 @@ ifeq ($(OS), Windows_NT) CYGWIN=nodosfilewarning \ CONLY="@WINDOWS_CC@" \ CPLUS="@WINDOWS_CXX11@" \ - CXXFLAGS="@CXX11FLAGS@ -DTBB_NO_LEGACY=1" \ + CXXFLAGS="$(TBB_CXXFLAGS)" \ PIC_KEY="@CXX11PICFLAGS@" \ WARNING_SUPPRESS="" \ + WINARM64="$(WINARM64)" \ $(MAKE) else @@ -77,26 +86,19 @@ ifeq ($(USE_TBB), Windows) # rtools: turn on hacks to compensate for make and shell differences rtools<=>MinGW # compiler: overwrite default (which is cl = MS compiler) MAKE_ARGS += rtools=true compiler=gcc - ifeq ($(WIN), 64) - MAKE_ARGS += arch=intel64 runtime=mingw - ARCH_DIR=x64/ - else - MAKE_ARGS += arch=ia32 runtime=mingw - ARCH_DIR=i386/ + ifneq ($(WINARM64), true) + ifeq ($(WIN), 64) + MAKE_ARGS += arch=intel64 runtime=mingw + ARCH_DIR=x64/ + else + MAKE_ARGS += arch=ia32 runtime=mingw + ARCH_DIR=i386/ + endif endif # Linker needs access to the tbb dll; otherwise you get errors such as: # "undefined reference to `tbb::task_scheduler_init::terminate()'" PKG_LIBS += -Ltbb/build/lib_release -ltbb -ltbbmalloc - - # override for aarch64 (experimental) to use Rtools TBB - ARCH=$(shell "${R_HOME}/bin/R" --vanilla -s -e 'cat(R.version$$arch)') - ifeq "$(ARCH)" "aarch64" - TBB_LIB = ${R_TOOLS_SOFT} - TBB_INC = ${R_TOOLS_SOFT} - PKG_LIBS = -ltbb12 -ltbbmalloc - endif - endif # write compiler if set diff --git a/src/tbb/build/Makefile.tbb b/src/tbb/build/Makefile.tbb index 8d155f803..bd3c94205 100644 --- a/src/tbb/build/Makefile.tbb +++ b/src/tbb/build/Makefile.tbb @@ -91,7 +91,11 @@ ifneq (,$(TBB.DEF)) tbb.def: $(TBB.DEF) $(TBB.LST) $(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@ -LIB_LINK_FLAGS += $(EXPORT_KEY)tbb.def +# LLVM on Windows doesn't need --version-script export +# https://reviews.llvm.org/D63743 +ifeq (, $(WINARM64)) + LIB_LINK_FLAGS += $(EXPORT_KEY)tbb.def +endif $(TBB.DLL): tbb.def endif diff --git a/src/tbb/build/Makefile.tbbmalloc b/src/tbb/build/Makefile.tbbmalloc index 421e95c54..e21920ffe 100644 --- a/src/tbb/build/Makefile.tbbmalloc +++ b/src/tbb/build/Makefile.tbbmalloc @@ -74,7 +74,11 @@ ifneq (,$(MALLOC.DEF)) tbbmalloc.def: $(MALLOC.DEF) $(CPLUS) $(PREPROC_ONLY) $< $(M_CPLUS_FLAGS) $(WARNING_SUPPRESS) $(INCLUDES) > $@ -MALLOC_LINK_FLAGS += $(EXPORT_KEY)tbbmalloc.def +# LLVM on Windows doesn't need --version-script export +# https://reviews.llvm.org/D63743 +ifeq (, $(WINARM64)) + MALLOC_LINK_FLAGS += $(EXPORT_KEY)tbbmalloc.def +endif $(MALLOC.DLL): tbbmalloc.def endif diff --git a/src/tbb/src/tbbmalloc/TypeDefinitions.h b/src/tbb/src/tbbmalloc/TypeDefinitions.h index 3178442e9..fd4b7956d 100644 --- a/src/tbb/src/tbbmalloc/TypeDefinitions.h +++ b/src/tbb/src/tbbmalloc/TypeDefinitions.h @@ -25,7 +25,7 @@ # define __ARCH_ipf 1 # elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support # define __ARCH_x86_32 1 -# elif defined(_M_ARM) +# elif defined(_M_ARM) || defined(__aarch64__) # define __ARCH_other 1 # else # error Unknown processor architecture for Windows From 8d0215e94f3a0a5d4142f7ee038013d2593e94c9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 11 May 2024 17:42:48 +0300 Subject: [PATCH 2/4] Add winarm64 flags to Rcpp --- R/tbb.R | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/R/tbb.R b/R/tbb.R index 00fccd3b6..49b425912 100644 --- a/R/tbb.R +++ b/R/tbb.R @@ -49,8 +49,14 @@ tbbCxxFlags <- function() { flags <- character() # opt-in to TBB on Windows - if (is_windows()) + if (is_windows()) { flags <- c(flags, "-DRCPP_PARALLEL_USE_TBB=1") + if (R.version$arch == "aarch64") { + # TBB does not have assembly code for Windows ARM64 + # so we need to use compiler builtins + flags <- c(flags, "-DTBB_USE_GCC_BUILTINS") + } + } # if TBB_INC is set, apply those library paths tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC) From 07e23e91b2f655d700387ef545491c40a84b2cb6 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 20 May 2024 08:53:46 +0300 Subject: [PATCH 3/4] Make check clang-specific, fix downstream usage --- inst/include/RcppParallel.h | 3 +++ src/Makevars.in | 11 ++++++++--- src/tbb/build/Makefile.tbb | 2 +- src/tbb/build/Makefile.tbbmalloc | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/inst/include/RcppParallel.h b/inst/include/RcppParallel.h index 637c16d4b..cbd5ef457 100644 --- a/inst/include/RcppParallel.h +++ b/inst/include/RcppParallel.h @@ -18,6 +18,9 @@ #endif #if RCPP_PARALLEL_USE_TBB +#if defined(WINNT) && defined(__aarch64__) && !defined(TBB_USE_GCC_BUILTINS) +#define TBB_USE_GCC_BUILTINS 1 +#endif # include "RcppParallel/TBB.h" #endif diff --git a/src/Makevars.in b/src/Makevars.in index c510139ba..7fa02e1f1 100644 --- a/src/Makevars.in +++ b/src/Makevars.in @@ -24,9 +24,12 @@ ifeq ($(OS), Windows_NT) ARCH=$(shell "${R_HOME}/bin/R" --vanilla -s -e 'cat(R.version$$arch)') TBB_CXXFLAGS = @CXX11FLAGS@ -DTBB_NO_LEGACY=1 ifeq "$(ARCH)" "aarch64" - WINARM64=true PKG_CPPFLAGS += -DTBB_USE_GCC_BUILTINS TBB_CXXFLAGS += -DTBB_USE_GCC_BUILTINS + CLANG_CHECK := $(shell echo | $(CC) -E -dM - | findstr __clang__) + ifneq ($(CLANG_CHECK), ) + WINARM64_CLANG=true + endif endif MAKE = make @@ -39,7 +42,7 @@ ifeq ($(OS), Windows_NT) CXXFLAGS="$(TBB_CXXFLAGS)" \ PIC_KEY="@CXX11PICFLAGS@" \ WARNING_SUPPRESS="" \ - WINARM64="$(WINARM64)" \ + WINARM64_CLANG="$(WINARM64_CLANG)" \ $(MAKE) else @@ -86,7 +89,9 @@ ifeq ($(USE_TBB), Windows) # rtools: turn on hacks to compensate for make and shell differences rtools<=>MinGW # compiler: overwrite default (which is cl = MS compiler) MAKE_ARGS += rtools=true compiler=gcc - ifneq ($(WINARM64), true) + # TBB configure will detect mingw runtime with unknown arch on WINARM64_CLANG but not an + # issue as we are using compiler built-ins instead of arch-specific code + ifneq ($(WINARM64_CLANG), true) ifeq ($(WIN), 64) MAKE_ARGS += arch=intel64 runtime=mingw ARCH_DIR=x64/ diff --git a/src/tbb/build/Makefile.tbb b/src/tbb/build/Makefile.tbb index bd3c94205..c58f4fb18 100644 --- a/src/tbb/build/Makefile.tbb +++ b/src/tbb/build/Makefile.tbb @@ -93,7 +93,7 @@ tbb.def: $(TBB.DEF) $(TBB.LST) # LLVM on Windows doesn't need --version-script export # https://reviews.llvm.org/D63743 -ifeq (, $(WINARM64)) +ifeq (, $(WINARM64_CLANG)) LIB_LINK_FLAGS += $(EXPORT_KEY)tbb.def endif $(TBB.DLL): tbb.def diff --git a/src/tbb/build/Makefile.tbbmalloc b/src/tbb/build/Makefile.tbbmalloc index e21920ffe..e7c38fa4b 100644 --- a/src/tbb/build/Makefile.tbbmalloc +++ b/src/tbb/build/Makefile.tbbmalloc @@ -76,7 +76,7 @@ tbbmalloc.def: $(MALLOC.DEF) # LLVM on Windows doesn't need --version-script export # https://reviews.llvm.org/D63743 -ifeq (, $(WINARM64)) +ifeq (, $(WINARM64_CLANG)) MALLOC_LINK_FLAGS += $(EXPORT_KEY)tbbmalloc.def endif $(MALLOC.DLL): tbbmalloc.def From f59d3bf37c4ee4f78400084b56ab621ab18f6820 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 20 May 2024 08:58:58 +0300 Subject: [PATCH 4/4] Add diff/patch file for TBB changes --- .Rbuildignore | 1 + patches/windows_arm64.diff | 47 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 patches/windows_arm64.diff diff --git a/.Rbuildignore b/.Rbuildignore index 493e59bbf..82fd49b57 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -17,3 +17,4 @@ ^tests/testthat/pkg/RcppParallelTest/src/.*\.s?o$ ^tools/tbb$ ^\.github$ +^patches \ No newline at end of file diff --git a/patches/windows_arm64.diff b/patches/windows_arm64.diff new file mode 100644 index 000000000..ff883e82f --- /dev/null +++ b/patches/windows_arm64.diff @@ -0,0 +1,47 @@ +diff --git a/src/tbb/build/Makefile.tbb b/src/tbb/build/Makefile.tbb +index 8d155f80..c58f4fb1 100644 +--- a/src/tbb/build/Makefile.tbb ++++ b/src/tbb/build/Makefile.tbb +@@ -91,7 +91,11 @@ ifneq (,$(TBB.DEF)) + tbb.def: $(TBB.DEF) $(TBB.LST) + $(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@ + +-LIB_LINK_FLAGS += $(EXPORT_KEY)tbb.def ++# LLVM on Windows doesn't need --version-script export ++# https://reviews.llvm.org/D63743 ++ifeq (, $(WINARM64_CLANG)) ++ LIB_LINK_FLAGS += $(EXPORT_KEY)tbb.def ++endif + $(TBB.DLL): tbb.def + endif + +diff --git a/src/tbb/build/Makefile.tbbmalloc b/src/tbb/build/Makefile.tbbmalloc +index 421e95c5..e7c38fa4 100644 +--- a/src/tbb/build/Makefile.tbbmalloc ++++ b/src/tbb/build/Makefile.tbbmalloc +@@ -74,7 +74,11 @@ ifneq (,$(MALLOC.DEF)) + tbbmalloc.def: $(MALLOC.DEF) + $(CPLUS) $(PREPROC_ONLY) $< $(M_CPLUS_FLAGS) $(WARNING_SUPPRESS) $(INCLUDES) > $@ + +-MALLOC_LINK_FLAGS += $(EXPORT_KEY)tbbmalloc.def ++# LLVM on Windows doesn't need --version-script export ++# https://reviews.llvm.org/D63743 ++ifeq (, $(WINARM64_CLANG)) ++ MALLOC_LINK_FLAGS += $(EXPORT_KEY)tbbmalloc.def ++endif + $(MALLOC.DLL): tbbmalloc.def + endif + +diff --git a/src/tbb/src/tbbmalloc/TypeDefinitions.h b/src/tbb/src/tbbmalloc/TypeDefinitions.h +index 3178442e..fd4b7956 100644 +--- a/src/tbb/src/tbbmalloc/TypeDefinitions.h ++++ b/src/tbb/src/tbbmalloc/TypeDefinitions.h +@@ -25,7 +25,7 @@ + # define __ARCH_ipf 1 + # elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support + # define __ARCH_x86_32 1 +-# elif defined(_M_ARM) ++# elif defined(_M_ARM) || defined(__aarch64__) + # define __ARCH_other 1 + # else + # error Unknown processor architecture for Windows