Files
BlitzLLVM/cmake/toolchains/llvm.cmake
T

400 lines
10 KiB
CMake
Raw Normal View History

2025-04-17 13:14:57 +02:00
# Copyright (C) 2019-2025 Michael Fabian 'Xaymar' Dirks
2025-04-18 15:31:59 +02:00
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
2025-04-18 15:31:59 +02:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
2025-04-18 15:31:59 +02:00
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This is a (mostly) self-contained toolchain file that sets up everything necessary to compile with LLVM/Clang.
# cmake --fresh -C cmake/generators/ninja.cmake --preset windows-x64-llvm
2025-04-20 15:49:33 +02:00
# !BUG: try_compile downloads the whole thing again, which it shouldn't. Why is CMake not passing the compiler stuff on?
# Which version of LLVM do we want to have (or newer)?
set(LLVM_VERSION "19.1.7")
2025-04-17 13:14:57 +02:00
2025-04-18 16:05:46 +02:00
cmake_minimum_required(VERSION 4.0 FATAL_ERROR)
2025-04-17 13:14:57 +02:00
include_guard(GLOBAL)
list(APPEND CMAKE_MESSAGE_INDENT "[LLVM] ")
2025-04-20 15:49:33 +02:00
# CMake 3.6: Force variables to be propagated to try_compile sub-processes.
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
LLVM_CLANG
LLVM_CLANGPP
LLVM_AR
LLVM_RANLIB
LLVM_NM
LLVM_READELF
LLVM_OBJCOPY
LLVM_OBJDUMP
LLVM_STRIP
LLVM_DIR
CMAKE_CXX_COMPILER
CMAKE_C_COMPILER
CMAKE_ASM_COMPILER
CMAKE_RC_COMPILER
CMAKE_LINKER
CMAKE_C_COMPILER_LINKER
CMAKE_CXX_COMPILER_LINKER
CMAKE_RC_COMPILER_LINKER
CMAKE_ASM_COMPILER_LINKER
CMAKE_NM
CMAKE_OBJDUMP
CMAKE_OBJCOPY
CMAKE_RANLIB
CMAKE_C_COMPILER_RANLIB
CMAKE_CXX_COMPILER_RANLIB
CMAKE_RC_COMPILER_RANLIB
CMAKE_ASM_COMPILER_RANLIB
CMAKE_AR
CMAKE_C_COMPILER_AR
CMAKE_CXX_COMPILER_AR
CMAKE_RC_COMPILER_AR
CMAKE_ASM_COMPILER_AR
)
set(CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES OFF)
# Macro for common stuff
macro(find_llvm)
set(LLVM_FOUND "FALSE")
# - AR
find_program(
LLVM_AR
NAMES
llvm-ar
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - Library Randomizer
find_program(
LLVM_RANLIB
NAMES
llvm-ranlib
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - Linker
if(_ARCH MATCHES "[xX]64")
find_program(
LLVM_LD
NAMES
ld64.lld
ld.lld
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
else()
find_program(
LLVM_LD
NAMES
ld.lld
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
2025-04-17 13:14:57 +02:00
endif()
2025-04-18 15:31:59 +02:00
2025-04-20 15:49:33 +02:00
# - Object Copy
find_program(
LLVM_OBJCOPY
NAMES
llvm-objcopy
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - Object Dump
find_program(
LLVM_OBJDUMP
NAMES
llvm-objdump
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - NM
find_program(
LLVM_NM
NAMES
llvm-nm
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - ReadELF
find_program(
LLVM_READELF
NAMES
llvm-readelf
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - Strip Debug Info
find_program(
LLVM_STRIP
NAMES
llvm-strip
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - C Compiler
find_program(
LLVM_CLANG
NAMES
clang
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
# - C++ Compiler
find_program(
LLVM_CLANGPP
NAMES
clang++
PATHS
"${LLVM_DIR}/bin/"
NO_CACHE
)
set(LLVM_FOUND TRUE)
foreach(_TEST IN ITEMS
"LLVM_AR"
"LLVM_LD"
"LLVM_CLANG"
"LLVM_CLANGPP")
if(NOT IS_EXECUTABLE ${${_TEST}})
set(LLVM_FOUND FALSE)
break()
else()
execute_process(
COMMAND "${${_TEST}}" --version
OUTPUT_VARIABLE ${_TEST}_VERSION
RESULT_VARIABLE _RES
)
if(NOT _RES EQUAL 0)
set(LLVM_FOUND FALSE)
break()
endif()
string(REGEX MATCH "[1-9+]?[0-9+]\.[1-9+]?[0-9+]\.[1-9+]?[0-9+]\." "${_TEST}_VERSION" "${${_TEST}_VERSION}")
string(REGEX REPLACE "[\r\n]+" "" "${_TEST}_VERSION" "${${_TEST}_VERSION}")
endif()
endforeach()
endmacro()
if(NOT CMAKE_C_COMPILER OR NOT CMAKE_CXX_COMPILER OR NOT CMAKE_LINKER OR NOT CMAKE_AR)
2025-04-18 15:31:59 +02:00
# Try and figure out what processor we need to get binaries for.
if(CMAKE_HOST_SYSTEM_NAME MATCHES "[Ww]indows")
set(_OS "windows")
string(TOLOWER "$ENV{PROCESSOR_ARCHITECTURE}" _ARCH)
if(_ARCH MATCHES "(amd64)|(AMD64)")
set(_FILE_NAME "LLVM-${LLVM_VERSION}-win64")
elseif(_ARCH MATCHES "(x86)|(X86)")
set(_FILE_NAME "LLVM-${LLVM_VERSION}-win32")
else()
set(_FILE_NAME "LLVM-${LLVM_VERSION}-woa64")
endif()
set(_FILE_EXT "exe")
#Computer\HKEY_CURRENT_USER\SOFTWARE\7-Zip\Path64
cmake_host_system_information(
RESULT 7ZIP_DIR
QUERY WINDOWS_REGISTRY "HKCU/SOFTWARE/7-Zip" VALUE "Path64"
VIEW HOST
)
find_program(7ZIP_BIN
NAMES
7z
7za
HINTS
"${7ZIP_DIR}"
"C:/Program Files/7-Zip"
"C:/Program Files (x86)/7-Zip"
)
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "[Dd]arwin")
set(_OS "macos")
2025-04-17 13:14:57 +02:00
execute_process(
COMMAND "uname -m"
OUTPUT_VARIABLE _ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _RES
)
2025-04-18 15:31:59 +02:00
if(_ARCH MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set(_FILE_NAME "LLVM-${LLVM_VERSION}-MacOS-X64")
else()
set(_FILE_NAME "LLVM-${LLVM_VERSION}-MacOS-ARM64")
endif()
set(_FILE_EXT "tar.xz")
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "[Oo]pen[Bb][Ss][Dd]")
set(_OS "openbsd")
execute_process(
COMMAND "arch"
OUTPUT_VARIABLE _ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(_FILE_EXT "tar.xz")
if(_ARCH MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set(_FILE_NAME "LLVM-${LLVM_VERSION}-Linux-X64")
else()
set(_FILE_NAME "LLVM-${LLVM_VERSION}-Linux-ARM64")
endif()
2025-04-17 13:14:57 +02:00
else()
2025-04-18 15:31:59 +02:00
set(_OS "linux")
execute_process(
COMMAND "uname -p"
OUTPUT_VARIABLE _ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _RES
)
if(_RES EQUAL 0)
execute_process(
COMMAND "uname -m"
OUTPUT_VARIABLE _ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _RES
)
endif()
set(_FILE_EXT "tar.xz")
if(_ARCH MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set(_FILE_NAME "LLVM-${LLVM_VERSION}-Linux-X64")
else()
set(_FILE_NAME "LLVM-${LLVM_VERSION}-Linux-ARM64")
endif()
2025-04-17 13:14:57 +02:00
endif()
2025-04-18 15:31:59 +02:00
set(LLVM_DIR "${CMAKE_SOURCE_DIR}/extra/llvm-${LLVM_VERSION}-${_OS}-${_ARCH}")
# Try and find an existing LLVM installation.
find_llvm()
if(LLVM_CLANG_VERSION AND LLVM_CLANG_VERSION VERSION_LESS LLVM_VERSION)
message(STATUS "Found outdated v${LLVM_CLANG_VERSION}.")
elseif(NOT LLVM_FOUND)
message(STATUS "No installed LLVM found.")
endif()
2025-04-17 13:14:57 +02:00
2025-04-20 15:49:33 +02:00
if((NOT LLVM_FOUND) OR (LLVM_CLANG_VERSION VERSION_LESS LLVM_VERSION))
2025-04-18 15:31:59 +02:00
# It isn't up to date or doesn't exist, so try to download the latest version.
if((_FILE_EXT MATCHES "exe") AND NOT 7ZIP_BIN)
message(FATAL_ERROR "7-Zip is required to continue setting up LLVM. Please provide '7z.exe' in PATH or by installing the latest version from https://www.7-zip.org/.")
endif()
# Download the ideal version.
if(NOT EXISTS "${LLVM_DIR}.${_FILE_EXT}")
message(STATUS "Downloading LLVM v${LLVM_VERSION}...")
file(DOWNLOAD
"https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${_FILE_NAME}.${_FILE_EXT}"
"${LLVM_DIR}.${_FILE_EXT}"
SHOW_PROGRESS
)
else()
message(STATUS "Skipping download as file already exists.")
endif()
# Extract it.
message(STATUS "Extracting...")
if(_FILE_EXT MATCHES "exe")
execute_process(
COMMAND ${7ZIP_BIN} x -y -aoa "-o${LLVM_DIR}/" "${LLVM_DIR}.${_FILE_EXT}"
COMMAND_ERROR_IS_FATAL ANY
OUTPUT_QUIET
ERROR_QUIET
)
else()
file(ARCHIVE_EXTRACT
INPUT "${LLVM_DIR}.${_FILE_EXT}"
DESTINATION "${LLVM_DIR}/"
)
endif()
# Delete the archive itself.
message(STATUS "Cleaning...")
2025-04-20 15:49:33 +02:00
#file(REMOVE "${LLVM_DIR}.${_FILE_EXT}")
2025-04-18 15:31:59 +02:00
# Final stuff
#message(STATUS "Testing...")
find_llvm()
endif()
2025-04-17 13:14:57 +02:00
2025-04-18 15:31:59 +02:00
if(LLVM_FOUND AND (LLVM_CLANG_VERSION VERSION_GREATER_EQUAL LLVM_VERSION))
message(STATUS "Found v${LLVM_CLANG_VERSION}.")
2025-04-20 15:49:33 +02:00
foreach(_T IN ITEMS CMAKE_AR CMAKE_C_COMPILER_AR CMAKE_CXX_COMPILER_AR CMAKE_RC_COMPILER_AR CMAKE_ASM_COMPILER_AR)
set(${_T} "${LLVM_AR}")
#set(${_T} "${LLVM_AR}" PARENT_SCOPE)
set(${_T} "${LLVM_AR}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_AR}")
endforeach()
foreach(_T IN ITEMS CMAKE_RANLIB CMAKE_C_COMPILER_RANLIB CMAKE_CXX_COMPILER_RANLIB CMAKE_RC_COMPILER_RANLIB CMAKE_ASM_COMPILER_RANLIB)
set(${_T} "${LLVM_RANLIB}")
#set(${_T} "${LLVM_RANLIB}" PARENT_SCOPE)
set(${_T} "${LLVM_RANLIB}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_RANLIB}")
endforeach()
foreach(_T IN ITEMS CMAKE_OBJCOPY)
set(${_T} "${LLVM_OBJCOPY}")
#set(${_T} "${LLVM_OBJCOPY}" PARENT_SCOPE)
set(${_T} "${LLVM_OBJCOPY}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_OBJCOPY}")
endforeach()
foreach(_T IN ITEMS CMAKE_OBJDUMP)
set(${_T} "${LLVM_OBJDUMP}")
#set(${_T} "${LLVM_OBJDUMP}" PARENT_SCOPE)
set(${_T} "${LLVM_OBJDUMP}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_OBJDUMP}")
2025-04-18 15:31:59 +02:00
endforeach()
2025-04-20 15:49:33 +02:00
foreach(_T IN ITEMS CMAKE_NM)
set(${_T} "${LLVM_NM}")
#set(${_T} "${LLVM_NM}" PARENT_SCOPE)
set(${_T} "${LLVM_NM}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_NM}")
endforeach()
foreach(_T IN ITEMS CMAKE_LINKER CMAKE_C_COMPILER_LINKER CMAKE_CXX_COMPILER_LINKER CMAKE_RC_COMPILER_LINKER CMAKE_ASM_COMPILER_LINKER)
set(${_T} "${LLVM_LD}")
#set(${_T} "${LLVM_LD}" PARENT_SCOPE)
set(${_T} "${LLVM_LD}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_LD}")
endforeach()
foreach(_T IN ITEMS CMAKE_C_COMPILER CMAKE_ASM_COMPILER CMAKE_RC_COMPILER)
set(${_T} "${LLVM_CLANG}")
#set(${_T} "${LLVM_CLANG}" PARENT_SCOPE)
set(${_T} "${LLVM_CLANG}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_CLANG}")
endforeach()
foreach(_T IN ITEMS CMAKE_CXX_COMPILER)
set(${_T} "${LLVM_CLANGPP}")
#set(${_T} "${LLVM_CLANGPP}" PARENT_SCOPE)
set(${_T} "${LLVM_CLANGPP}" CACHE STRING "" FORCE)
set(ENV{${_T}} "${LLVM_CLANGPP}")
endforeach()
foreach(_T IN ITEMS LLVM_CLANG LLVM_CLANGPP LLVM_AR LLVM_RANLIB LLVM_NM LLVM_READELF LLVM_OBJCOPY LLVM_OBJDUMP LLVM_STRIP LLVM_DIR)
set(${_T} "${${_T}}" CACHE STRING "" FORCE)
set(ENV${_T} "${${_T}}")
endforeach()
else()
2025-04-18 15:31:59 +02:00
message(FATAL_ERROR "Failed to find or provide a compatible LLVM installation.")
endif()
endif()
2025-04-17 13:14:57 +02:00
2025-04-18 15:31:59 +02:00
list(POP_BACK CMAKE_MESSAGE_INDENT)