Skip to content

Commit e703a47

Browse files
committed
feat: build on arm64 using LLVM, use Visual Studio's CMake when available
1 parent 74daf27 commit e703a47

File tree

9 files changed

+490
-48
lines changed

9 files changed

+490
-48
lines changed

docs/guide/building-from-source.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,51 @@ If the build fails on macOS with the error `"/usr/bin/cc" is not able to compile
3434

3535
:::
3636

37+
::: details Dependencies for Windows x64
38+
If the build fails on your machine, ensure you have all the necessary build tools installed.
39+
40+
You can install all the dependencies via [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/) using these commands:
41+
```shell
42+
winget install --id Microsoft.VisualStudio.2022.BuildTools --force --override "--add Microsoft.VisualStudio.Component.VC.CMake.Project Microsoft.VisualStudio.Component.VC.CoreBuildTools Microsoft.VisualStudio.Component.VC.Tools.x86.x64 Microsoft.VisualStudio.Component.VC.ATL Microsoft.VisualStudio.Component.VC.ATLMFC Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset Microsoft.VisualStudio.Component.VC.Llvm.Clang Microsoft.VisualStudio.Component.VC.Redist.14.Latest Microsoft.Component.VC.Runtime.UCRTSDK Microsoft.VisualStudio.Component.Windows10SDK Microsoft.VisualStudio.Component.Windows10SDK.20348"
43+
```
44+
> WinGet is built-in on Windows 11 and modern Windows 10 versions
45+
46+
---
47+
48+
You can also install all the dependencies manually using the [Visual C++ Build Tools installer](https://visualstudio.microsoft.com/visual-cpp-build-tools/):
49+
* **`Workloads` tab:** select `Desktop development with C++`
50+
* **`Individual components` tab**: select the following:
51+
* C++ ATL for latest v143 build tools (x86 & x64)
52+
* C++ MFC for latest v143 build tools (x86 & x64)
53+
* C++ CMake tools for Windows
54+
* C++ Clang Compiler for Windows
55+
* MSBuild support for LLVM (clang-cl) toolset
56+
* Windows Universal CRT SDK
57+
:::
58+
59+
::: details Dependencies for Windows on Arm
60+
On Windows on Arm you need to install additional build tools to build `llama.cpp` from source.
61+
62+
You can install all the dependencies via [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/) using these commands:
63+
```shell
64+
winget install --id Microsoft.VisualStudio.2022.BuildTools --force --override "--add Microsoft.VisualStudio.Component.VC.CMake.Project Microsoft.VisualStudio.Component.VC.CoreBuildTools Microsoft.VisualStudio.Component.VC.Tools.x86.x64 Microsoft.VisualStudio.Component.VC.Tools.ARM64 Microsoft.VisualStudio.Component.VC.ATL Microsoft.VisualStudio.Component.VC.ATL.ARM64 Microsoft.VisualStudio.Component.VC.ATLMFC Microsoft.VisualStudio.Component.VC.MFC.ARM64 Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset Microsoft.VisualStudio.Component.VC.Llvm.Clang Microsoft.VisualStudio.Component.VC.Redist.14.Latest Microsoft.Component.VC.Runtime.UCRTSDK Microsoft.VisualStudio.Component.Windows10SDK Microsoft.VisualStudio.Component.Windows10SDK.20348"
65+
```
66+
> WinGet is built-in on Windows 11 and modern Windows 10 versions
67+
68+
---
69+
70+
You can also install all the dependencies manually using the [Visual C++ Build Tools installer](https://visualstudio.microsoft.com/visual-cpp-build-tools/):
71+
* **`Workloads` tab:** select `Desktop development with C++`
72+
* **`Individual components` tab**: select the following:
73+
* MSVC v143 - VS 2022 C++ ARM64 build tools (latest)
74+
* C++ ATL for latest v143 build tools (ARM64/ARM64EC)
75+
* C++ MFC for latest v143 build tools (ARM64/ARM64EC)
76+
* C++ CMake tools for Windows
77+
* C++ Clang Compiler for Windows
78+
* MSBuild support for LLVM (clang-cl) toolset
79+
* Windows Universal CRT SDK
80+
:::
81+
3782
## `source download` and `source build` Commands
3883
The difference between the [`source download`](../cli/source/download.md) and [`source build`](../cli/source/build.md) commands
3984
is that the `source download` command downloads a release of `llama.cpp` and builds it,

llama/CMakeLists.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
cmake_minimum_required(VERSION 3.14)
22

3+
if (NLC_TARGET_PLATFORM STREQUAL "win-arm64" AND (CMAKE_GENERATOR STREQUAL "Ninja" OR CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") AND NOT MINGW)
4+
if(NLC_CURRENT_PLATFORM STREQUAL "win-x64")
5+
get_filename_component(INCLUDE_PROFILE_ABS "./profiles/llvm.win32.host-x64.target-arm64.cmake" ABSOLUTE)
6+
include("${INCLUDE_PROFILE_ABS}")
7+
elseif(NLC_CURRENT_PLATFORM STREQUAL "win-arm64")
8+
get_filename_component(INCLUDE_PROFILE_ABS "./profiles/llvm.win32.host-arm64.target-arm64.cmake" ABSOLUTE)
9+
include("${INCLUDE_PROFILE_ABS}")
10+
endif()
11+
endif()
12+
313
project("llama-addon" C CXX)
414

515
if (MSVC)
@@ -24,8 +34,8 @@ execute_process(COMMAND node -p "require('node-addon-api').include.slice(1,-1)"
2434

2535
set(LLAMA_BUILD_COMMON ON)
2636

27-
if (NOT MINGW)
28-
set(GGML_BACKEND_DL ON)
37+
if (MINGW)
38+
set(GGML_BACKEND_DL OFF)
2939
set(BUILD_SHARED_LIBS ON)
3040
endif()
3141

@@ -46,7 +56,6 @@ endif()
4656
include_directories(${NODE_ADDON_API_DIR} ${CMAKE_JS_INC})
4757

4858
add_subdirectory("llama.cpp")
49-
include_directories("gpuInfo")
5059
include_directories("llama.cpp")
5160
include_directories("./llama.cpp/common")
5261

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
set(PROGRAMFILES_ARM64 "$ENV{ProgramFiles\(Arm\)}")
2+
set(PROGRAMFILES "$ENV{ProgramFiles}")
3+
set(PROGRAMFILES_X86 "$ENV{ProgramFiles\(x86\)}")
4+
set(PROGRAMFILES_PATHS
5+
"${PROGRAMFILES_ARM64}"
6+
"${PROGRAMFILES}"
7+
"${PROGRAMFILES_X86}"
8+
"C:/Program Files (Arm)"
9+
"C:/Program Files"
10+
"C:/Program Files (x86)"
11+
)
12+
13+
if (CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
14+
if (NOT DEFINED NODE_LIB_CMAKE_AR)
15+
foreach(PATH IN LISTS PROGRAMFILES_PATHS)
16+
if(NODE_LIB_CMAKE_AR)
17+
break()
18+
endif()
19+
20+
file(GLOB_RECURSE FOUND_LIB_EXE
21+
"${PATH}/Microsoft Visual Studio/*/VC/Tools/MSVC/*/bin/Hostarm64/arm64/lib.exe"
22+
"${PATH}/Microsoft Visual Studio/**/*/VC/Tools/MSVC/*/bin/Hostarm64/arm64/lib.exe")
23+
24+
if(FOUND_LIB_EXE)
25+
list(GET FOUND_LIB_EXE 0 NODE_LIB_CMAKE_AR)
26+
break()
27+
endif()
28+
endforeach()
29+
endif()
30+
31+
if (EXISTS "${NODE_LIB_CMAKE_AR}")
32+
# Generate node.lib
33+
execute_process(COMMAND ${NODE_LIB_CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS} /MACHINE:ARM64 /nologo)
34+
else()
35+
message(FATAL_ERROR "Windows Resource Compiler (lib.exe) not found. Please install Visual Studio Build Tools.")
36+
endif()
37+
endif()
38+
39+
# adapt cmake-js to work with llvm in GNU mode
40+
if (NOT CMAKE_SHARED_LINKER_FLAGS MATCHES "-Xlinker /DELAYLOAD:NODE.EXE")
41+
string(REPLACE "/DELAYLOAD:NODE.EXE" "-Xlinker /DELAYLOAD:NODE.EXE -Xlinker /defaultlib:delayimp"
42+
CMAKE_SHARED_LINKER_FLAGS
43+
"${CMAKE_SHARED_LINKER_FLAGS}")
44+
endif()
45+
46+
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
47+
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Xclang --dependent-lib=msvcrt")
48+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Xclang --dependent-lib=msvcrt")
49+
50+
# ensure CMAKE_AR is configured
51+
if (NOT DEFINED CMAKE_AR OR NOT EXISTS "${CMAKE_AR}")
52+
set(LLVM_INSTALL_PATHS "")
53+
foreach(PATH IN LISTS PROGRAMFILES_PATHS)
54+
list(APPEND LLVM_INSTALL_PATHS "${PATH}/LLVM")
55+
56+
file(GLOB_RECURSE FOUND_LLVM_ROOT
57+
"${PATH}/Microsoft Visual Studio/*/VC/Tools/Llvm/ARM64"
58+
"${PATH}/Microsoft Visual Studio/**/*/VC/Tools/Llvm/ARM64")
59+
60+
if(FOUND_LLVM_ROOT)
61+
list(APPEND LLVM_INSTALL_PATHS ${FOUND_LLVM_ROOT})
62+
endif()
63+
endforeach()
64+
65+
if(DEFINED LLVM_ROOT AND EXISTS "${LLVM_ROOT}")
66+
list(INSERT LLVM_INSTALL_PATHS 0 "${LLVM_ROOT}")
67+
endif()
68+
69+
foreach(PATH IN LISTS LLVM_INSTALL_PATHS)
70+
if(EXISTS "${PATH}/bin/llvm-ar.exe" AND EXISTS "${PATH}/bin/llvm-ar.exe")
71+
set(CMAKE_AR "${PATH}/bin/llvm-ar.exe")
72+
break()
73+
endif()
74+
endforeach()
75+
endif()
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
set(PROGRAMFILES "$ENV{ProgramFiles}")
2+
set(PROGRAMFILES_X86 "$ENV{ProgramFiles\(x86\)}")
3+
set(PROGRAMFILES_PATHS
4+
"${PROGRAMFILES}"
5+
"${PROGRAMFILES_X86}"
6+
"C:/Program Files"
7+
"C:/Program Files (x86)"
8+
)
9+
10+
if (CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
11+
if (NOT DEFINED NODE_LIB_CMAKE_AR)
12+
foreach(PATH IN LISTS PROGRAMFILES_PATHS)
13+
if(NODE_LIB_CMAKE_AR)
14+
break()
15+
endif()
16+
17+
file(GLOB_RECURSE FOUND_LIB_EXE
18+
"${PATH}/Microsoft Visual Studio/*/VC/Tools/MSVC/*/bin/Hostx64/arm64/lib.exe"
19+
"${PATH}/Microsoft Visual Studio/**/*/VC/Tools/MSVC/*/bin/Hostx64/arm64/lib.exe")
20+
21+
if(FOUND_LIB_EXE)
22+
list(GET FOUND_LIB_EXE 0 NODE_LIB_CMAKE_AR)
23+
break()
24+
endif()
25+
endforeach()
26+
endif()
27+
28+
if (EXISTS "${NODE_LIB_CMAKE_AR}")
29+
# Generate node.lib
30+
execute_process(COMMAND ${NODE_LIB_CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS} /MACHINE:ARM64 /nologo)
31+
else()
32+
message(FATAL_ERROR "Windows Resource Compiler (lib.exe) not found. Please install Visual Studio Build Tools.")
33+
endif()
34+
endif()
35+
36+
# adapt cmake-js to work with llvm in GNU mode
37+
if (NOT CMAKE_SHARED_LINKER_FLAGS MATCHES "-Xlinker /DELAYLOAD:NODE.EXE")
38+
string(REPLACE "/DELAYLOAD:NODE.EXE" "-Xlinker /DELAYLOAD:NODE.EXE -Xlinker /defaultlib:delayimp"
39+
CMAKE_SHARED_LINKER_FLAGS
40+
"${CMAKE_SHARED_LINKER_FLAGS}")
41+
endif()
42+
43+
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
44+
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Xclang --dependent-lib=msvcrt")
45+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Xclang --dependent-lib=msvcrt")
46+
47+
# ensure CMAKE_AR is configured
48+
if (NOT DEFINED CMAKE_AR OR NOT EXISTS "${CMAKE_AR}")
49+
set(LLVM_INSTALL_PATHS "")
50+
foreach(PATH IN LISTS PROGRAMFILES_PATHS)
51+
list(APPEND LLVM_INSTALL_PATHS "${PATH}/LLVM")
52+
53+
file(GLOB_RECURSE FOUND_LLVM_ROOT
54+
"${PATH}/Microsoft Visual Studio/*/VC/Tools/Llvm/x64"
55+
"${PATH}/Microsoft Visual Studio/**/*/VC/Tools/Llvm/x64")
56+
57+
if(FOUND_LLVM_ROOT)
58+
list(APPEND LLVM_INSTALL_PATHS ${FOUND_LLVM_ROOT})
59+
endif()
60+
endforeach()
61+
62+
if(DEFINED LLVM_ROOT AND EXISTS "${LLVM_ROOT}")
63+
list(INSERT LLVM_INSTALL_PATHS 0 "${LLVM_ROOT}")
64+
endif()
65+
66+
foreach(PATH IN LISTS LLVM_INSTALL_PATHS)
67+
if(EXISTS "${PATH}/bin/llvm-ar.exe" AND EXISTS "${PATH}/bin/llvm-ar.exe")
68+
set(CMAKE_AR "${PATH}/bin/llvm-ar.exe")
69+
break()
70+
endif()
71+
endforeach()
72+
endif()
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
set(CMAKE_SYSTEM_NAME Windows)
2+
set(CMAKE_SYSTEM_PROCESSOR arm64)
3+
4+
set(target arm64-pc-windows-msvc)
5+
set(CMAKE_C_COMPILER_TARGET ${target})
6+
set(CMAKE_CXX_COMPILER_TARGET ${target})
7+
8+
set(CMAKE_C_COMPILER clang)
9+
set(CMAKE_CXX_COMPILER clang++)
10+
set(CMAKE_RC_COMPILER llvm-rc)
11+
12+
set(LLVM_INSTALLATION_URL "https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.5")
13+
14+
set(PROGRAMFILES_ARM64 "$ENV{ProgramFiles\(Arm\)}")
15+
set(PROGRAMFILES "$ENV{ProgramFiles}")
16+
set(PROGRAMFILES_X86 "$ENV{ProgramFiles\(x86\)}")
17+
set(PROGRAMFILES_PATHS
18+
"${PROGRAMFILES_ARM64}"
19+
"${PROGRAMFILES}"
20+
"${PROGRAMFILES_X86}"
21+
"C:/Program Files (Arm)"
22+
"C:/Program Files"
23+
"C:/Program Files (x86)"
24+
)
25+
26+
set(LLVM_INSTALL_PATHS "")
27+
foreach(PATH IN LISTS PROGRAMFILES_PATHS)
28+
list(APPEND LLVM_INSTALL_PATHS "${PATH}/LLVM")
29+
30+
file(GLOB_RECURSE FOUND_LLVM_ROOT
31+
"${PATH}/Microsoft Visual Studio/*/VC/Tools/Llvm/ARM64"
32+
"${PATH}/Microsoft Visual Studio/**/*/VC/Tools/Llvm/ARM64")
33+
34+
if(FOUND_LLVM_ROOT)
35+
list(APPEND LLVM_INSTALL_PATHS ${FOUND_LLVM_ROOT})
36+
endif()
37+
endforeach()
38+
39+
if(DEFINED LLVM_ROOT AND EXISTS "${LLVM_ROOT}")
40+
list(INSERT LLVM_INSTALL_PATHS 0 "${LLVM_ROOT}")
41+
endif()
42+
43+
set(LLVM_ROOT "")
44+
foreach(PATH IN LISTS LLVM_INSTALL_PATHS)
45+
if(EXISTS "${PATH}/bin/clang.exe" AND EXISTS "${PATH}/bin/clang++.exe" AND EXISTS "${PATH}/bin/llvm-rc.exe")
46+
set(LLVM_ROOT "${PATH}")
47+
break()
48+
endif()
49+
endforeach()
50+
51+
if(LLVM_ROOT STREQUAL "")
52+
message(FATAL_ERROR "LLVM installation was not found. Please install LLVM for WoA (Windows on Arm): ${LLVM_INSTALLATION_URL}")
53+
endif()
54+
55+
if (NOT EXISTS "${CMAKE_C_COMPILER}" OR NOT EXISTS "${CMAKE_CXX_COMPILER}" OR NOT EXISTS "${CMAKE_RC_COMPILER}")
56+
set(CMAKE_C_COMPILER "${LLVM_ROOT}/bin/clang.exe")
57+
set(CMAKE_CXX_COMPILER "${LLVM_ROOT}/bin/clang++.exe")
58+
set(CMAKE_RC_COMPILER "${LLVM_ROOT}/bin/llvm-rc.exe")
59+
endif()
60+
61+
if (NOT EXISTS "${CMAKE_C_COMPILER}")
62+
message(FATAL_ERROR "Clang compiler not found at ${CMAKE_C_COMPILER}. Please reinstall LLVM for WoA (Windows on Arm): ${LLVM_INSTALLATION_URL}")
63+
endif()
64+
if (NOT EXISTS "${CMAKE_CXX_COMPILER}")
65+
message(FATAL_ERROR "Clang++ compiler not found at ${CMAKE_CXX_COMPILER}. Please reinstall LLVM for WoA (Windows on Arm): ${LLVM_INSTALLATION_URL}")
66+
endif()
67+
if (NOT EXISTS "${CMAKE_RC_COMPILER}")
68+
message(FATAL_ERROR "LLVM Resource Compiler not found at ${CMAKE_RC_COMPILER}. Please reinstall LLVM for WoA (Windows on Arm): ${LLVM_INSTALLATION_URL}")
69+
endif()
70+
71+
set(arch_c_flags "-march=armv8.7-a -fvectorize -ffp-model=fast -fno-finite-math-only")
72+
set(warn_c_flags "-Wno-format -Wno-unused-variable -Wno-unused-function -Wno-gnu-zero-variadic-macro-arguments")
73+
74+
set(CMAKE_C_FLAGS_INIT "${arch_c_flags} ${warn_c_flags}")
75+
set(CMAKE_CXX_FLAGS_INIT "${arch_c_flags} ${warn_c_flags}")
76+
77+
if ((NOT DEFINED CMAKE_MAKE_PROGRAM OR NOT EXISTS CMAKE_MAKE_PROGRAM) AND (CMAKE_GENERATOR STREQUAL "Ninja" OR CMAKE_GENERATOR STREQUAL "Ninja Multi-Config"))
78+
find_program(NINJA_EXECUTABLE ninja)
79+
80+
if(NINJA_EXECUTABLE AND EXISTS "${NINJA_EXECUTABLE}")
81+
set(CMAKE_MAKE_PROGRAM "${NINJA_EXECUTABLE}")
82+
else()
83+
foreach(PATH IN LISTS PROGRAMFILES_PATHS)
84+
file(GLOB_RECURSE FOUND_NINJA_EXE
85+
"${PATH}/Microsoft Visual Studio/*/CMake/Ninja/ninja.exe"
86+
"${PATH}/Microsoft Visual Studio/**/*/CMake/Ninja/ninja.exe")
87+
88+
if(FOUND_NINJA_EXE)
89+
list(GET FOUND_NINJA_EXE 0 CMAKE_MAKE_PROGRAM)
90+
break()
91+
endif()
92+
endforeach()
93+
endif()
94+
95+
if (NOT CMAKE_MAKE_PROGRAM OR NOT EXISTS "${CMAKE_MAKE_PROGRAM}")
96+
message(FATAL_ERROR "Ninja build system not found. Please install Ninja or Visual Studio Build Tools.")
97+
endif()
98+
endif()

0 commit comments

Comments
 (0)