398 lines
20 KiB
CMake
398 lines
20 KiB
CMake
# =============================================================================
|
|
# toolchains/_common.cmake
|
|
#
|
|
# Helpers shared by the per-DIST_TARGET toolchain files next to this one
|
|
# (linux-x64-gcc.cmake, windows-arm64-clang-cl.cmake, ...). This is not a
|
|
# toolchain file itself -- nothing should point CMAKE_TOOLCHAIN_FILE here.
|
|
#
|
|
# Why toolchain files at all
|
|
# --------------------------
|
|
# A toolchain file is CMake's own mechanism for "build with THIS compiler
|
|
# for THIS target". CMake reads it before project() detects anything, so
|
|
# the compiler and target are settled first instead of being discovered
|
|
# and then cross-checked after the fact. Every CMakePresets.json preset
|
|
# points at the toolchain file with its own name (see the "base" preset),
|
|
# and each file does three things:
|
|
#
|
|
# 1. Declares which DIST_TARGET it is for (PMN_TOOLCHAIN_DIST_TARGET), so
|
|
# Configuration.cmake no longer has to guess from the compiler and
|
|
# can't be handed a mislabeled build -- the label and the compiler
|
|
# travel together.
|
|
# 2. Picks the compiler (and, for clang-cl, the --target triple).
|
|
# 3. Where the target isn't the machine running CMake, sets up a real
|
|
# cross-compile: CMAKE_SYSTEM_NAME / CMAKE_SYSTEM_PROCESSOR, restricts
|
|
# find_package/find_library to the target's sysroot (so a host-arch
|
|
# library is never linked into a foreign-arch binary), and registers
|
|
# an emulator (qemu-user / wine) if one is installed, so ctest can run
|
|
# what it just built.
|
|
#
|
|
# Two behaviors worth knowing, both verified rather than assumed:
|
|
#
|
|
# * CMAKE_SYSTEM_NAME is only set when the build really is a cross build.
|
|
# Setting it -- even to the value the host already has -- flips
|
|
# CMAKE_CROSSCOMPILING to TRUE, which changes how try_run and
|
|
# several third-party CMakeLists behave. Native builds leave it alone.
|
|
#
|
|
# * A compiler chosen here never overrides an explicit
|
|
# -DCMAKE_CXX_COMPILER=... on the command line (an unguarded set()
|
|
# in a toolchain file silently would). The toolchain DOES beat a stray
|
|
# CXX environment variable, since a target called "linux-x64-gcc"
|
|
# shouldn't be built with whatever CXX=clang++ happens to be exported.
|
|
#
|
|
# * macOS is deliberately not a "cross build" even when the architecture
|
|
# differs from the machine's (an x86_64 build on an Apple Silicon Mac):
|
|
# Apple's clang is one multi-architecture compiler, so that is a
|
|
# different -arch flag, not a different compiler. pmn_macos_toolchain()
|
|
# leaves CMAKE_SYSTEM_NAME alone and pins CMAKE_OSX_ARCHITECTURES.
|
|
#
|
|
# Toolchain files are read more than once per configure (CMake re-reads
|
|
# them for every try_compile), so everything here must stay cheap and
|
|
# idempotent.
|
|
# =============================================================================
|
|
|
|
include_guard(GLOBAL)
|
|
|
|
include("${CMAKE_CURRENT_LIST_DIR}/../HostArch.cmake")
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_toolchain_target(<DIST_TARGET>)
|
|
#
|
|
# Declares which DIST_TARGET the calling toolchain file is for.
|
|
# Configuration.cmake reads PMN_TOOLCHAIN_DIST_TARGET and uses it as
|
|
# DIST_TARGET (an explicit, different -DDIST_TARGET is a FATAL_ERROR).
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_toolchain_target _pmn_tc_dist_target)
|
|
set(PMN_TOOLCHAIN_DIST_TARGET "${_pmn_tc_dist_target}")
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_use_compilers(<cxx-program> <c-program> "<install hint>")
|
|
#
|
|
# Selects the C++ (and C) compiler by program name, resolved on PATH to an
|
|
# absolute path so it's identical in every try_compile. Skipped for
|
|
# whichever of CMAKE_CXX_COMPILER / CMAKE_C_COMPILER the user already
|
|
# chose explicitly.
|
|
#
|
|
# A missing C++ compiler is a FATAL_ERROR here, with the install hint,
|
|
# rather than CMake's generic "compiler ... is not a full path and was not
|
|
# found in the PATH". The C compiler is set too even though the project
|
|
# is C++-only: if someone later adds a C source or a C dependency, CMake
|
|
# must not silently auto-detect the HOST's cc for a cross build and emit
|
|
# wrong-architecture objects. If the C compiler can't be found, its bare
|
|
# name is set anyway so that mistake fails loudly.
|
|
#
|
|
# A function (not a macro) on purpose: the hint is free text that a macro
|
|
# would evaluate twice, and its temporaries stay out of the caller's scope.
|
|
# PARENT_SCOPE lands in the toolchain file's own scope because the macros
|
|
# below, which call this, don't create one.
|
|
# -----------------------------------------------------------------------
|
|
function(pmn_use_compilers CXX_PROGRAM C_PROGRAM HINT)
|
|
if(NOT CMAKE_CXX_COMPILER)
|
|
find_program(_pmn_tc_cxx_path NAMES "${CXX_PROGRAM}" NO_CACHE)
|
|
if(NOT _pmn_tc_cxx_path)
|
|
message(FATAL_ERROR
|
|
"The '${PMN_TOOLCHAIN_DIST_TARGET}' toolchain needs the C++ compiler "
|
|
"'${CXX_PROGRAM}', but it isn't on PATH.\n${HINT}\n"
|
|
"(Or name a different compiler explicitly: -DCMAKE_CXX_COMPILER=<path>)")
|
|
endif()
|
|
set(CMAKE_CXX_COMPILER "${_pmn_tc_cxx_path}" PARENT_SCOPE)
|
|
endif()
|
|
if(NOT CMAKE_C_COMPILER)
|
|
find_program(_pmn_tc_c_path NAMES "${C_PROGRAM}" NO_CACHE)
|
|
if(_pmn_tc_c_path)
|
|
set(CMAKE_C_COMPILER "${_pmn_tc_c_path}" PARENT_SCOPE)
|
|
else()
|
|
set(CMAKE_C_COMPILER "${C_PROGRAM}" PARENT_SCOPE)
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_cross_target(<system-name> <system-processor> <find-root>)
|
|
#
|
|
# Turns this into a cross build. <find-root> is the target's sysroot-like
|
|
# prefix (Debian/Ubuntu put a cross toolchain's target headers and
|
|
# libraries under /usr/<triplet>); an explicit -DCMAKE_SYSROOT=... and
|
|
# -DCMAKE_FIND_ROOT_PATH=... from the user are kept and extended, not
|
|
# replaced.
|
|
#
|
|
# The four MODE settings are the standard cross-compile split: programs
|
|
# (Doxygen, a pinned ninja, ...) come from the HOST; libraries, headers
|
|
# and CMake packages only from the target's root. That last one is what
|
|
# makes FetchContent's find_package(fmt) miss the host's libfmt -- which
|
|
# would link, then fail at load time as the wrong architecture -- and fall
|
|
# through to fetching and building fmt for the target.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_cross_target _pmn_tc_system _pmn_tc_processor _pmn_tc_root)
|
|
set(CMAKE_SYSTEM_NAME "${_pmn_tc_system}")
|
|
set(CMAKE_SYSTEM_PROCESSOR "${_pmn_tc_processor}")
|
|
list(APPEND CMAKE_FIND_ROOT_PATH "${_pmn_tc_root}")
|
|
list(REMOVE_DUPLICATES CMAKE_FIND_ROOT_PATH)
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_cross_emulator(<program>|"<program>;<program>" [<args>...])
|
|
#
|
|
# Registers the first of the given program names that is installed
|
|
# (qemu-aarch64, or "wine;wine64", ...) as CMAKE_CROSSCOMPILING_EMULATOR,
|
|
# so ctest and add_custom_command(COMMAND <target>) can run a
|
|
# foreign-architecture binary, and so can scripts/run.sh. Silent if none is
|
|
# installed -- the build itself doesn't need one. An emulator the user set
|
|
# explicitly is left alone.
|
|
#
|
|
# It's a cache entry rather than a plain variable so that scripts/run.sh,
|
|
# which runs long after configure, can read it back out of CMakeCache.txt.
|
|
# CMake treats a cached CMAKE_CROSSCOMPILING_EMULATOR exactly like a
|
|
# variable set here (it's also what -DCMAKE_CROSSCOMPILING_EMULATOR=...
|
|
# creates). Only set once found, so installing qemu later still gets
|
|
# picked up on the next configure.
|
|
# -----------------------------------------------------------------------
|
|
function(pmn_cross_emulator PROGRAM)
|
|
if(NOT CMAKE_CROSSCOMPILING_EMULATOR)
|
|
find_program(_pmn_tc_emulator_path NAMES ${PROGRAM} NO_CACHE)
|
|
if(_pmn_tc_emulator_path)
|
|
set(CMAKE_CROSSCOMPILING_EMULATOR "${_pmn_tc_emulator_path}" ${ARGN}
|
|
CACHE STRING "Emulator used to run cross-compiled executables (ctest, scripts/run.sh)")
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_linux_toolchain(<x64|arm64|arm32> <gcc|clang>)
|
|
#
|
|
# One implementation behind all six linux-* toolchain files.
|
|
#
|
|
# Native or cross is decided by comparing the requested architecture with
|
|
# the machine CMake is running on (`uname -m`, via HostArch.cmake): the same
|
|
# linux-arm64-gcc preset builds natively on ARM64 hardware with the ordinary
|
|
# g++, and cross-builds from an x64 machine with aarch64-linux-gnu-g++.
|
|
#
|
|
# GCC cross: <triplet>-g++ (Debian/Ubuntu: apt install g++-<triplet>)
|
|
# Clang cross: clang++ --target=<triplet>, which additionally needs the
|
|
# target's libstdc++/libc: the GCC cross package above
|
|
# provides them under /usr/<triplet>, or pass
|
|
# -DCMAKE_SYSROOT=<sysroot>.
|
|
#
|
|
# One unusual case falls outside this: a 32-bit userland running on a
|
|
# 64-bit ARM kernel reports aarch64 from `uname -m` while its ordinary g++
|
|
# already builds 32-bit code. For that, pass -DCMAKE_CXX_COMPILER=g++ (the
|
|
# build is then labeled arm32, correctly, but is treated as a cross build).
|
|
#
|
|
# NOTE for anyone editing the macros in this file: a macro's parameters
|
|
# are textual substitutions, so every use inside if() is quoted --
|
|
# unquoted, `if(x64 STREQUAL ...)` would treat "x64" as a variable name.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_linux_toolchain _pmn_tc_arch _pmn_tc_family)
|
|
if("${_pmn_tc_arch}" STREQUAL "x64")
|
|
set(_pmn_tc_processor "x86_64")
|
|
set(_pmn_tc_triplet "x86_64-linux-gnu")
|
|
set(_pmn_tc_gcc_pkg "g++-x86-64-linux-gnu")
|
|
set(_pmn_tc_qemu "qemu-x86_64")
|
|
elseif("${_pmn_tc_arch}" STREQUAL "arm64")
|
|
set(_pmn_tc_processor "aarch64")
|
|
set(_pmn_tc_triplet "aarch64-linux-gnu")
|
|
set(_pmn_tc_gcc_pkg "g++-aarch64-linux-gnu")
|
|
set(_pmn_tc_qemu "qemu-aarch64")
|
|
elseif("${_pmn_tc_arch}" STREQUAL "arm32")
|
|
set(_pmn_tc_processor "arm")
|
|
set(_pmn_tc_triplet "arm-linux-gnueabihf")
|
|
set(_pmn_tc_gcc_pkg "g++-arm-linux-gnueabihf")
|
|
set(_pmn_tc_qemu "qemu-arm")
|
|
else()
|
|
message(FATAL_ERROR "pmn_linux_toolchain: unknown architecture '${_pmn_tc_arch}'")
|
|
endif()
|
|
|
|
pmn_host_arch(_pmn_tc_host_arch)
|
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND "${_pmn_tc_host_arch}" STREQUAL "${_pmn_tc_arch}")
|
|
# Native: this machine already IS the target.
|
|
if("${_pmn_tc_family}" STREQUAL "gcc")
|
|
pmn_use_compilers(g++ gcc "Install GCC, e.g.: sudo apt install g++")
|
|
else()
|
|
pmn_use_compilers(clang++ clang "Install Clang, e.g.: sudo apt install clang")
|
|
endif()
|
|
else()
|
|
# Cross.
|
|
pmn_cross_target(Linux "${_pmn_tc_processor}" "/usr/${_pmn_tc_triplet}")
|
|
if("${_pmn_tc_family}" STREQUAL "gcc")
|
|
pmn_use_compilers("${_pmn_tc_triplet}-g++" "${_pmn_tc_triplet}-gcc"
|
|
"Install the cross compiler, e.g.: sudo apt install ${_pmn_tc_gcc_pkg}")
|
|
else()
|
|
pmn_use_compilers(clang++ clang
|
|
"Install Clang plus the GCC cross package that provides the target's libraries, e.g.: sudo apt install clang ${_pmn_tc_gcc_pkg}")
|
|
set(CMAKE_CXX_COMPILER_TARGET "${_pmn_tc_triplet}")
|
|
set(CMAKE_C_COMPILER_TARGET "${_pmn_tc_triplet}")
|
|
endif()
|
|
pmn_cross_emulator("${_pmn_tc_qemu}" -L "/usr/${_pmn_tc_triplet}")
|
|
endif()
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_mingw_toolchain(<x64|x86>)
|
|
#
|
|
# Behind windows-x64-mingw64 and windows-x86-mingw32. On a Windows host
|
|
# (an MSYS2 MINGW64/MINGW32 shell, or a standalone MinGW-w64) this only
|
|
# picks the compiler by its triplet-prefixed name. On a Linux host it is a
|
|
# real cross build using Debian/Ubuntu's mingw-w64 packages, with wine as
|
|
# the emulator if installed.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_mingw_toolchain _pmn_tc_arch)
|
|
if("${_pmn_tc_arch}" STREQUAL "x64")
|
|
set(_pmn_tc_processor "x86_64")
|
|
set(_pmn_tc_triplet "x86_64-w64-mingw32")
|
|
set(_pmn_tc_pkg "g++-mingw-w64-x86-64")
|
|
elseif("${_pmn_tc_arch}" STREQUAL "x86")
|
|
set(_pmn_tc_processor "i686")
|
|
set(_pmn_tc_triplet "i686-w64-mingw32")
|
|
set(_pmn_tc_pkg "g++-mingw-w64-i686")
|
|
else()
|
|
message(FATAL_ERROR "pmn_mingw_toolchain: unknown architecture '${_pmn_tc_arch}'")
|
|
endif()
|
|
|
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
|
pmn_use_compilers("${_pmn_tc_triplet}-g++" "${_pmn_tc_triplet}-gcc"
|
|
"Install MinGW-w64 (e.g. MSYS2's mingw-w64 packages) and put its bin directory on PATH.")
|
|
else()
|
|
pmn_cross_target(Windows "${_pmn_tc_processor}" "/usr/${_pmn_tc_triplet}")
|
|
pmn_use_compilers("${_pmn_tc_triplet}-g++" "${_pmn_tc_triplet}-gcc"
|
|
"Install the cross compiler, e.g.: sudo apt install ${_pmn_tc_pkg}")
|
|
# Some distributions ship only a wine64 binary, others a wine one.
|
|
pmn_cross_emulator("wine;wine64")
|
|
endif()
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_msvc_toolchain(<x64|arm64>)
|
|
#
|
|
# Behind windows-x64-msvc and windows-arm64-msvc. cl.exe has no --target:
|
|
# which architecture it produces is decided by WHICH cl.exe comes first on
|
|
# PATH, i.e. by the Visual Studio developer environment the shell was
|
|
# started from. A toolchain file therefore can't switch architectures for
|
|
# MSVC. What it can do is pick cl instead of letting CMake fall through to
|
|
# whatever other compiler is on PATH, and fail early with the instruction
|
|
# that fixes the usual cause. Whether the cl.exe it found really targets
|
|
# the architecture in the DIST_TARGET is then verified by
|
|
# Configuration.cmake, from CMAKE_CXX_COMPILER_ARCHITECTURE_ID.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_msvc_toolchain _pmn_tc_arch)
|
|
if("${_pmn_tc_arch}" STREQUAL "x64")
|
|
pmn_use_compilers(cl cl
|
|
"Open an \"x64 Native Tools Command Prompt for VS\" (or a Developer PowerShell for VS defaulted to x64) and run this again.")
|
|
else()
|
|
pmn_use_compilers(cl cl
|
|
"Open a Visual Studio developer prompt configured for ARM64 -- an \"ARM64 Native Tools Command Prompt for VS\", or on an x64 machine an \"x64_arm64 Cross Tools Command Prompt for VS\" (vcvarsall.bat x64_arm64) -- and run this again.")
|
|
endif()
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_clang_cl_toolchain(<x64|arm64>)
|
|
#
|
|
# Behind windows-x64-clang-cl and windows-arm64-clang-cl: LLVM's clang-cl,
|
|
# the cl.exe-compatible driver, targeting the MSVC ABI. Unlike cl.exe,
|
|
# clang-cl takes --target, so the architecture is pinned here
|
|
# (CMAKE_CXX_COMPILER_TARGET -> --target=<triple> on every compile and
|
|
# link line, and while CMake identifies the compiler) instead of depending
|
|
# on whatever the environment or the machine's own architecture defaults
|
|
# to. That is what lets windows-x64-clang-cl mean x64 on an ARM64 Windows
|
|
# machine too.
|
|
#
|
|
# The MSVC STL headers and the Windows SDK libraries still come from a
|
|
# Visual Studio / Build Tools install, as they do for any clang-cl build.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_clang_cl_toolchain _pmn_tc_arch)
|
|
if("${_pmn_tc_arch}" STREQUAL "x64")
|
|
set(_pmn_tc_triple "x86_64-pc-windows-msvc")
|
|
elseif("${_pmn_tc_arch}" STREQUAL "arm64")
|
|
set(_pmn_tc_triple "aarch64-pc-windows-msvc")
|
|
else()
|
|
message(FATAL_ERROR "pmn_clang_cl_toolchain: unknown architecture '${_pmn_tc_arch}'")
|
|
endif()
|
|
pmn_use_compilers(clang-cl clang-cl
|
|
"Install LLVM (e.g.: winget install LLVM.LLVM) or Visual Studio's \"C++ Clang tools for Windows\" component, and make sure clang-cl's directory is on PATH.")
|
|
set(CMAKE_CXX_COMPILER_TARGET "${_pmn_tc_triple}")
|
|
set(CMAKE_C_COMPILER_TARGET "${_pmn_tc_triple}")
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_msys_clang_toolchain()
|
|
#
|
|
# Behind windows-x64-clang and windows-arm64-clang: Clang with its own
|
|
# GNU-style driver (clang++), as in an MSYS2 CLANG64 / CLANGARM64 shell
|
|
# -- distinct from clang-cl. Which architecture that clang++ targets is
|
|
# the shell environment's default, so nothing is pinned here; the
|
|
# environment is what makes clang++ a mingw-ABI compiler for the right
|
|
# machine.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_msys_clang_toolchain)
|
|
pmn_use_compilers(clang++ clang
|
|
"Open an MSYS2 CLANG64 (x64) or CLANGARM64 (ARM64) shell, whose clang++ targets the matching mingw ABI by default.")
|
|
endmacro()
|
|
|
|
# -----------------------------------------------------------------------
|
|
# pmn_macos_toolchain(<arm64|x64>)
|
|
#
|
|
# Behind macos-arm64-clang and macos-x64-clang. Apple's clang is ONE
|
|
# multi-architecture compiler: which architecture it emits is a flag
|
|
# (-arch), not a different program. So unlike the Linux cross builds there
|
|
# is no cross compiler to find, no sysroot to restrict lookups to and no
|
|
# emulator to register (an x86_64 binary runs on an Apple Silicon Mac
|
|
# through Rosetta 2, and try_run works as usual) -- and CMAKE_CROSSCOMPILING
|
|
# correctly stays FALSE. What this pins instead:
|
|
#
|
|
# CMAKE_OSX_ARCHITECTURES the ONE architecture, always -- even when
|
|
# it is the machine's own. That is the only reliable statement of what
|
|
# gets built: without it the compiler follows the process that
|
|
# launched it, so a cmake running under Rosetta 2 on an Apple Silicon
|
|
# Mac would quietly produce x86_64 for a target that says arm64.
|
|
# CMAKE_OSX_DEPLOYMENT_TARGET the oldest macOS the result runs on:
|
|
# 11.0, the first release that runs on Apple Silicon. Left unset it
|
|
# defaults to the SDK's own version, and everything built then
|
|
# refuses to start on any macOS older than the build machine's.
|
|
#
|
|
# Both only take effect if set BEFORE the first project(), which is
|
|
# exactly when a toolchain file runs, and both yield to an explicit
|
|
# -DCMAKE_OSX_...= on the command line (the label check in
|
|
# Configuration.cmake then catches an architecture that no longer matches
|
|
# the target). Homebrew's LLVM clang instead of Apple's works the same
|
|
# way: -DCMAKE_CXX_COMPILER=$(brew --prefix llvm)/bin/clang++.
|
|
# -----------------------------------------------------------------------
|
|
macro(pmn_macos_toolchain _pmn_tc_arch)
|
|
if("${_pmn_tc_arch}" STREQUAL "arm64")
|
|
set(_pmn_tc_osx_arch "arm64")
|
|
elseif("${_pmn_tc_arch}" STREQUAL "x64")
|
|
set(_pmn_tc_osx_arch "x86_64")
|
|
else()
|
|
message(FATAL_ERROR "pmn_macos_toolchain: unknown architecture '${_pmn_tc_arch}'")
|
|
endif()
|
|
|
|
if(NOT CMAKE_OSX_ARCHITECTURES)
|
|
set(CMAKE_OSX_ARCHITECTURES "${_pmn_tc_osx_arch}")
|
|
endif()
|
|
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
|
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
|
|
endif()
|
|
|
|
# /usr/bin/clang++ exists on every Mac, as a stub that only works once
|
|
# the Command Line Tools (or Xcode) are installed -- without them CMake
|
|
# would fail inside its own compiler check with "xcrun: error: invalid
|
|
# active developer path". Say what's actually wrong instead.
|
|
if(CMAKE_HOST_APPLE)
|
|
execute_process(COMMAND xcode-select -p
|
|
RESULT_VARIABLE _pmn_tc_xcode_rc
|
|
OUTPUT_QUIET ERROR_QUIET)
|
|
if(NOT _pmn_tc_xcode_rc EQUAL 0)
|
|
message(FATAL_ERROR
|
|
"The '${PMN_TOOLCHAIN_DIST_TARGET}' toolchain needs Apple's compiler, but no "
|
|
"developer directory is set (xcode-select -p failed).\n"
|
|
"Install the Xcode Command Line Tools: xcode-select --install\n"
|
|
"(scripts/setup.sh offers to do this for you.)")
|
|
endif()
|
|
endif()
|
|
|
|
pmn_use_compilers(clang++ clang
|
|
"Install the Xcode Command Line Tools: xcode-select --install")
|
|
endmacro()
|