From 26998893427125a507899032dee3d8dc1183b1e8 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Mon, 20 Sep 2021 22:54:54 +0200
Subject: [PATCH] python/build/cmake.py: use CMAKE_TOOLCHAIN_FILE

Let cmake know that we're cross-crompiling.
---
 android/build.py      |  1 +
 python/build/cmake.py | 51 +++++++++++++++++++++++++++++++++----------
 win32/build.py        |  1 +
 3 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/android/build.py b/android/build.py
index c3577b0b7..202453d9e 100755
--- a/android/build.py
+++ b/android/build.py
@@ -83,6 +83,7 @@ class AndroidNdkToolchain:
         install_prefix = os.path.join(arch_path, 'root')
 
         self.arch = arch
+        self.actual_arch = arch
         self.install_prefix = install_prefix
 
         llvm_path = os.path.join(ndk_path, 'toolchains', 'llvm', 'prebuilt', build_arch)
diff --git a/python/build/cmake.py b/python/build/cmake.py
index 3f08d9872..158bf6d76 100644
--- a/python/build/cmake.py
+++ b/python/build/cmake.py
@@ -1,35 +1,62 @@
+import os
 import subprocess
 
 from build.project import Project
 
-def __cmake_compiler_args(language, compiler):
+def __write_cmake_compiler(f, language, compiler):
     s = compiler.split(' ', 1)
-    result = []
     if len(s) == 2:
-        result.append(f'-DCMAKE_{language}_COMPILER_LAUNCHER={s[0]}')
+        print(f'set(CMAKE_{language}_COMPILER_LAUNCHER {s[0]})', file=f)
         compiler = s[1]
-    result.append(f'-DCMAKE_{language}_COMPILER={compiler}')
-    return result
+    print(f'set(CMAKE_{language}_COMPILER {compiler})', file=f)
+
+def __write_cmake_toolchain_file(f, toolchain):
+    if '-darwin' in toolchain.actual_arch:
+        cmake_system_name = 'Darwin'
+    elif toolchain.is_windows:
+        cmake_system_name = 'Windows'
+    else:
+        cmake_system_name = 'Linux'
+
+    f.write(f"""
+set(CMAKE_SYSTEM_NAME {cmake_system_name})
+set(CMAKE_SYSTEM_PROCESSOR {toolchain.actual_arch.split('-', 1)[0]})
+
+set(CMAKE_C_COMPILER_TARGET {toolchain.actual_arch})
+set(CMAKE_CXX_COMPILER_TARGET {toolchain.actual_arch})
+
+set(CMAKE_C_FLAGS "{toolchain.cflags} {toolchain.cppflags}")
+set(CMAKE_CXX_FLAGS "{toolchain.cxxflags} {toolchain.cppflags}")
+""")
+    __write_cmake_compiler(f, 'C', toolchain.cc)
+    __write_cmake_compiler(f, 'CXX', toolchain.cxx)
 
 def configure(toolchain, src, build, args=()):
     cross_args = []
 
     if toolchain.is_windows:
-        cross_args.append('-DCMAKE_SYSTEM_NAME=Windows')
         cross_args.append('-DCMAKE_RC_COMPILER=' + toolchain.windres)
 
+    # Several targets need a sysroot to prevent pkg-config from
+    # looking for libraries on the build host (TODO: fix this
+    # properly); but we must not do that on Android because the NDK
+    # has a sysroot already
+    if '-android' not in toolchain.actual_arch and '-darwin' not in toolchain.actual_arch:
+        cross_args.append('-DCMAKE_SYSROOT=' + toolchain.install_prefix)
+
+    os.makedirs(build, exist_ok=True)
+    cmake_toolchain_file = os.path.join(build, 'cmake_toolchain_file')
+    with open(cmake_toolchain_file, 'w') as f:
+        __write_cmake_toolchain_file(f, toolchain)
+
     configure = [
         'cmake',
         src,
 
+        '-DCMAKE_TOOLCHAIN_FILE=' + cmake_toolchain_file,
+
         '-DCMAKE_INSTALL_PREFIX=' + toolchain.install_prefix,
         '-DCMAKE_BUILD_TYPE=release',
-    ] + \
-    __cmake_compiler_args('C', toolchain.cc) + \
-    __cmake_compiler_args('CXX', toolchain.cxx) + \
-    [
-        '-DCMAKE_C_FLAGS=' + toolchain.cflags + ' ' + toolchain.cppflags,
-        '-DCMAKE_CXX_FLAGS=' + toolchain.cxxflags + ' ' + toolchain.cppflags,
 
         '-GNinja',
     ] + cross_args + args
diff --git a/win32/build.py b/win32/build.py
index 9f3011831..0e22b0675 100755
--- a/win32/build.py
+++ b/win32/build.py
@@ -38,6 +38,7 @@ class CrossGccToolchain:
     def __init__(self, toolchain_path, arch,
                  tarball_path, src_path, build_path, install_prefix):
         self.arch = arch
+        self.actual_arch = arch
         self.tarball_path = tarball_path
         self.src_path = src_path
         self.build_path = build_path