1
1
:: Build script for scipy_openblas wheel on Windows on ARM64
2
2
3
- :: Usage: build_steps_win_arm64.bat [build_bits]
4
- :: e.g build_steps_win_arm64.bat 64
3
+ :: Usage: build_steps_win_arm64.bat [build_bits] [if_bits]
4
+ :: e.g build_steps_win_arm64.bat 64 64
5
5
6
- :: BUILD_BITS (default binary architecture, 32 or 64, unspec -> 64).
6
+ :: build_bits (default binary architecture, 32 or 64, unspec -> 64).
7
+ :: if_bits (default interface size, 32 or 64, unspec -> 32)
8
+ :: If INTERFACE64 environment variable is 1, then if_bits defaults to 64
7
9
:: Expects these binaries on the PATH:
8
- :: clang-cl, flang-new, cmake, perl
10
+ :: clang-cl, flang-new, cmake, perl
11
+ :: Uses environment variable:
12
+ :: OPENBLAS_COMMIT (unspec -> current submodule commit, if contains
13
+ :: Windows on ARM build fixes (see below), otherwise earliest commit
14
+ :: with those fixes).
15
+
16
+ :: First commit containing WoA build fixes.
17
+ :: Minimum OpenBLAS commit to build; we'll update to this if commit not
18
+ :: present.
19
+ set first_woa_buildable_commit = " de2380e5a6149706a633322a16a0f66faa5591fc"
9
20
10
21
@ echo off
11
22
setlocal enabledelayedexpansion
12
23
13
24
if " %1 " == " " (
14
- set BUILD_BIT = 64
25
+ set build_bits = 64
26
+ ) else (
27
+ set build_bits = %1
28
+ )
29
+ if " %INTERFACE64% " == " 1" (
30
+ set " if_default = 64"
31
+ ) else (
32
+ set " if_default = 32"
33
+ )
34
+ if " %2 " == " " (
35
+ set " if_bits = %if_default% "
15
36
) else (
16
- set BUILD_BIT = %1
37
+ set " if_bits = %2 "
17
38
)
18
- echo Building for %BUILD_BIT % -bit configuration ...
39
+ echo Building for %build_bits % -bit binary, %if_bits% -bit interface ...
19
40
20
41
:: Define destination directory
21
- move " ..\local\scipy_openblas64" " ..\local\scipy_openblas32"
22
- set " DEST_DIR = %CD% \..\local\scipy_openblas32"
23
- cd ..
24
-
25
- :: Check if 'openblas' folder exists and is empty
26
- if exist " openblas" (
27
- dir /b " openblas" | findstr . > nul
28
- if errorlevel 1 (
29
- echo OpenBLAS folder exists but is empty. Deleting and recloning...
30
- rmdir /s /q " openblas"
42
+ pushd " %~dp0 \.."
43
+ set " ob_out_root = %CD% \local\scipy_openblas"
44
+ set " ob_64 = %ob_out_root% 64"
45
+ set " ob_32 = %ob_out_root% 32"
46
+ set " local_dir = %CD% \local"
47
+ for /d %%D in (" %local_dir% \*" ) do (
48
+ if /I not " %%~nxD " == " scipy_openblas64" (
49
+ rmdir /S /Q " %%D "
31
50
)
32
51
)
33
-
34
- :: Clone OpenBLAS if not present
35
- if not exist " openblas" (
36
- echo Cloning OpenBLAS repository with submodules...
37
- git clone --recursive https://github.com/OpenMathLib/OpenBLAS.git OpenBLAS
38
- if errorlevel 1 exit /b 1
52
+ if " %if_bits% " == " 64" (
53
+ set " DEST_DIR = %ob_64% "
54
+ ) else (
55
+ if exist " %ob_64% " (
56
+ xcopy /Y /H " %ob_64% \*.py" " %CD% \ob64_backup\"
57
+ move " %ob_64% " " %ob_32% "
58
+ set " DEST_DIR = %ob_32% "
59
+ )
39
60
)
61
+
62
+ :: Clone OpenBLAS
63
+ echo Cloning OpenBLAS repository with submodules...
64
+ git submodule update --init --recursive OpenBLAS
65
+ if errorlevel 1 exit /b 1
40
66
41
- :: Enter OpenBLAS directory and checkout develop branch
42
- cd openblas
43
- git checkout develop
44
-
45
- echo Checked out to the latest branch of OpenBLAS.
67
+ :: Enter OpenBLAS directory and checkout buildable commit
68
+ cd OpenBLAS
69
+ if defined OPENBLAS_COMMIT (
70
+ echo Checking out OpenBLAS commit %OPENBLAS_COMMIT%
71
+ git checkout %OPENBLAS_COMMIT%
72
+ )
73
+ git merge-base --is-ancestor %first_woa_buildable_commit% HEAD 2 > NUL
74
+ if errorlevel 1 (
75
+ echo OpenBLAS commit does not contain WoA build fixes.
76
+ echo Commit needs to contain %first_woa_buildable_commit% .
77
+ exit /b 2
78
+ )
46
79
80
+ :: Set suffixed-ILP64 flags
81
+ if " %if_bits% " == " 64" (
82
+ set " interface_flags = -DINTERFACE64=1 -DSYMBOLSUFFIX=64_"
83
+ ) else (
84
+ set " interface_flags = "
85
+ )
86
+
47
87
:: Create build directory and navigate to it
48
- if not exist build mkdir build
49
- cd build
88
+ if exist build (rmdir /S /Q build || exit /b 1)
89
+ mkdir build || exit /b 1 & cd build || exit /b 1
50
90
51
91
echo Setting up ARM64 Developer Command Prompt and running CMake...
52
92
@@ -55,36 +95,42 @@ for /f "usebackq tokens=*" %%i in (`"C:\Program Files (x86)\Microsoft Visual Stu
55
95
56
96
:: Run CMake and Ninja build
57
97
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DTARGET=ARMV8 -DBUILD_SHARED_LIBS=ON -DARCH=arm64 ^
58
- -DBINARY=%BUILD_BIT % -DCMAKE_SYSTEM_PROCESSOR=ARM64 -DCMAKE_C_COMPILER=clang-cl ^
59
- -DCMAKE_Fortran_COMPILER=flang-new -DSYMBOLPREFIX=" scipy_" -DLIBNAMEPREFIX=" scipy_"
98
+ -DBINARY=%build_bits % -DCMAKE_SYSTEM_PROCESSOR=ARM64 -DCMAKE_C_COMPILER=clang-cl ^
99
+ -DCMAKE_Fortran_COMPILER=flang-new -DSYMBOLPREFIX=" scipy_" -DLIBNAMEPREFIX=" scipy_" %interface_flags%
60
100
if errorlevel 1 exit /b 1
61
-
101
+
62
102
ninja
63
103
if errorlevel 1 exit /b 1
64
104
65
105
echo Build complete. Returning to Batch.
66
106
67
- :: Rewrite the name of the project to scipy-openblas32
68
- echo Rewrite to scipy_openblas32
69
- cd ../..
70
- powershell -Command " (Get-Content 'pyproject.toml') -replace 'openblas64', 'openblas32' | Set-Content 'pyproject.toml'"
71
- powershell -Command " (Get-Content 'local\scipy_openblas32\__main__.py') -replace 'openblas64', 'openblas32' | Out-File 'local\scipy_openblas32\__main__.py' -Encoding utf8"
72
- powershell -Command " (Get-Content 'local\scipy_openblas32\__init__.py') -replace 'openblas64', 'openblas32' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8"
73
- powershell -Command " (Get-Content 'local\scipy_openblas32\__init__.py') -replace 'openblas_get_config64_', 'openblas_get_config' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8"
74
- powershell -Command " (Get-Content 'local\scipy_openblas32\__init__.py') -replace 'cflags =.*', 'cflags = \" -DBLAS_SYMBOL_PREFIX=scipy_\" ' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8"
107
+ if " %if_bits% " == " 32" (
108
+ echo Rewrite to scipy_openblas32
109
+ cd ../..
110
+ set out_pyproject = pyproject_64_32.toml
111
+ powershell -Command " (Get-Content 'pyproject.toml') -replace 'openblas64', 'openblas32' | Set-Content !out_pyproject! "
112
+ powershell -Command " (Get-Content 'local\scipy_openblas32\__main__.py') -replace 'openblas64', 'openblas32' | Out-File 'local\scipy_openblas32\__main__.py' -Encoding utf8"
113
+ powershell -Command " (Get-Content 'local\scipy_openblas32\__init__.py') -replace 'openblas64', 'openblas32' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8"
114
+ powershell -Command " (Get-Content 'local\scipy_openblas32\__init__.py') -replace 'openblas_get_config64_', 'openblas_get_config' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8"
115
+ powershell -Command " (Get-Content 'local\scipy_openblas32\__init__.py') -replace 'cflags =.*', 'cflags = \" -DBLAS_SYMBOL_PREFIX=scipy_\" ' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8"
116
+ )
75
117
76
118
:: Prepare destination directory
77
119
cd OpenBLAS/build
78
120
echo Preparing destination directory at %DEST_DIR% ...
79
- if not exist " %DEST_DIR% \lib\cmake\openblas " mkdir " %DEST_DIR% \lib\cmake\openblas "
121
+ if not exist " %DEST_DIR% \lib\cmake\OpenBLAS " mkdir " %DEST_DIR% \lib\cmake\OpenBLAS "
80
122
if not exist " %DEST_DIR% \include" mkdir " %DEST_DIR% \include"
81
123
82
124
:: Move library files
83
125
echo Moving library files...
84
126
if exist lib\release (
85
127
move /Y lib\release\*.dll " %DEST_DIR% \lib\"
86
128
if errorlevel 1 exit /b 1
87
- move /Y lib\release\*.dll.a " %DEST_DIR% \lib\scipy_openblas.lib"
129
+ for %%f in (lib\release\*.dll.a) do (
130
+ set " orig_name = %%~nxf "
131
+ call set " base_name = %%o rig_name:.dll.a=%% "
132
+ move /Y " %%f " " %DEST_DIR% \lib\!base_name! .lib"
133
+ )
88
134
if errorlevel 1 exit /b 1
89
135
) else (
90
136
echo Error: lib/release directory not found!
@@ -99,7 +145,7 @@ if exist openblasconfigversion.cmake copy /Y openblasconfigversion.cmake "%DEST_
99
145
:: Copy header files
100
146
echo Copying generated header files...
101
147
if exist generated xcopy /E /Y generated " %DEST_DIR% \include\"
102
- if exist lapacke_mangling copy /Y lapacke_mangling " %DEST_DIR% \include\"
148
+ if exist lapacke_mangling.h copy /Y lapacke_mangling.h " %DEST_DIR% \include\"
103
149
if exist openblas_config.h copy /Y openblas_config.h " %DEST_DIR% \include\"
104
150
105
151
@@ -113,12 +159,32 @@ cd ../..
113
159
114
160
:: Build the Wheel & Install It
115
161
echo Running 'python -m build' to build the wheel...
116
- python -m build
117
- if errorlevel 1 exit /b 1
118
-
162
+ python -c " import build" 2 > NUL || pip install build
163
+ if " %if_bits% " == " 64" (
164
+ python -m build
165
+ if errorlevel 1 exit /b 1
166
+ ) else (
167
+ move /Y pyproject.toml pyproject.toml.bak
168
+ move /Y %out_pyproject% pyproject.toml
169
+ python -m build
170
+ if errorlevel 1 exit /b 1
171
+ move /Y pyproject.toml.bak pyproject.toml
172
+ )
173
+ if " %if_bits% " == " 32" (
174
+ move /Y " %CD% \ob64_backup" " %ob_64% "
175
+ )
176
+
177
+ :: Rename the wheel
178
+ for %%f in (dist\*any.whl) do (
179
+ set WHEEL_FILE = dist\%%f
180
+ set " filename = %%~nxf "
181
+ set " newname = !filename:any.whl =win_arm64.whl ! "
182
+ ren " dist\!filename! " " !newname! "
183
+ )
184
+
119
185
:: Locate the built wheel
120
186
for /f %%f in ('dir /b dist\scipy_openblas*.whl 2^ > nul ') do set WHEEL_FILE = dist\%%f
121
-
187
+
122
188
if not defined WHEEL_FILE (
123
189
echo Error: No wheel file found in dist folder.
124
190
exit /b 1
@@ -129,4 +195,4 @@ pip install "%WHEEL_FILE%"
129
195
if errorlevel 1 exit /b 1
130
196
131
197
echo Done.
132
- exit /b 0
198
+ exit /b 0
0 commit comments