aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Fält <simo.falt@qt.io>2021-11-25 16:08:21 +0200
committerSimo Fält <simo.falt@qt.io>2022-04-11 17:49:05 +0300
commit4187f1d7bfba5b519cfa0880fce6f793c0ffb6f1 (patch)
tree1f51bd82b9175a94b41b21514b353e08fc4db533
parented759eaa5665d3c9f134ffd75d41edc3fc22a462 (diff)
Build macOS universal binary
Collection of bits and pieces to enable MacOS universal wheel creation in Qt CI. Change-Id: I0a889258ec4f89ca3a26c8bf2ee76f0d5c676a7a Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--build_scripts/utils.py16
-rw-r--r--coin/instructions/common_environment.yaml30
-rw-r--r--coin/instructions/execute_build_instructions.yaml29
-rw-r--r--coin/instructions/execute_test_instructions.yaml30
-rw-r--r--coin/module_config.yaml12
-rw-r--r--coin_build_instructions.py40
-rw-r--r--coin_test_instructions.py32
7 files changed, 157 insertions, 32 deletions
diff --git a/build_scripts/utils.py b/build_scripts/utils.py
index 5d62d4307..49839e2de 100644
--- a/build_scripts/utils.py
+++ b/build_scripts/utils.py
@@ -47,6 +47,7 @@ import subprocess
import fnmatch
import itertools
import glob
+from os.path import expanduser
# There is no urllib.request in Python2
try:
@@ -1157,7 +1158,7 @@ def install_pip_dependencies(env_pip, packages, upgrade=True):
def get_qtci_virtualEnv(python_ver, host, hostArch, targetArch):
- _pExe = "python"
+ _pExe = "python2"
_env = "env{}".format(str(python_ver))
env_python = _env + "/bin/python"
env_pip = _env + "/bin/pip"
@@ -1229,3 +1230,16 @@ def get_ci_qmake_path(ci_install_dir, ci_host_os):
return qmake_path + "\\bin\\qmake.exe"
else:
return qmake_path + "/bin/qmake"
+
+
+def provisioning():
+ home = expanduser("~")
+ file = "https://download.qt.io/development_releases/prebuilt/libclang/libclang-release_100-based-dyn-mac-universal.7z"
+ target = os.path.join(home, "libclang-dynlibs-10.0-universal")
+ try:
+ download_and_extract_7z(file, target)
+ except RuntimeError as e:
+ print("debug: Exception error: {}".format(e))
+ file = file.replace("s://download","://master")
+ print("New url: {}".format(file))
+ download_and_extract_7z(file, target) \ No newline at end of file
diff --git a/coin/instructions/common_environment.yaml b/coin/instructions/common_environment.yaml
index 41ab0059c..cf391324e 100644
--- a/coin/instructions/common_environment.yaml
+++ b/coin/instructions/common_environment.yaml
@@ -119,6 +119,32 @@ instructions:
variableName: LLVM_INSTALL_DIR
variableValue: "{{.Env.LLVM_DYNAMIC_LIBS_100}}"
disable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64-ARM64 # When target arch is universal binary, we can use the default libclang
+ - condition: property
+ property: host.os
+ equals_value: MacOS
+ - type: EnvironmentVariable
+ variableName: LLVM_INSTALL_DIR
+ variableValue: "/Users/qt/libclang-dynlibs-10.0-universal/libclang-dynlibs-10.0"
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64-ARM64 # When target arch is universal binary, we can use the default libclang
+ - condition: property
+ property: host.os
+ equals_value: MacOS
+ - type: PrependToEnvironmentVariable
+ variableName: PATH
+ variableValue: "/Library/Frameworks/Python.framework/Versions/3.9/bin:"
+ enable_if:
condition: property
- property: host.osVersion
- equals_value: openSUSE_15_1
+ property: host.os
+ equals_value: MacOS
+
+
diff --git a/coin/instructions/execute_build_instructions.yaml b/coin/instructions/execute_build_instructions.yaml
index e940e9250..ffd1ad5cc 100644
--- a/coin/instructions/execute_build_instructions.yaml
+++ b/coin/instructions/execute_build_instructions.yaml
@@ -1,13 +1,34 @@
type: Group
instructions:
- type: ExecuteCommand
- command: "python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}} --phase=ALL"
+ command: "python -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch={{.Env.HOS_ARCH_COIN}} --targetArch={{.Env.TARGET_ARCH_COIN}} --phase=ALL"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 1200
enable_if:
- condition: property
- property: host.os
- equals_value: MacOS
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64
+ - condition: property
+ property: host.os
+ equals_value: MacOS
+ userMessageOnFailure: >
+ Failed to execute build instructions on osx
+
+ - type: ExecuteCommand
+ command: "python3 -u coin_build_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} {{.Env.CI_USE_SCCACHE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=={{.Env.HOST_ARCH_COIN}} --targetArch=X86_64-ARM64 --phase=ALL"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 1200
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64-ARM64
+ - condition: property
+ property: host.os
+ equals_value: MacOS
userMessageOnFailure: >
Failed to execute build instructions on osx
- type: ExecuteCommand
diff --git a/coin/instructions/execute_test_instructions.yaml b/coin/instructions/execute_test_instructions.yaml
index f5dd7aa50..b30ec2b92 100644
--- a/coin/instructions/execute_test_instructions.yaml
+++ b/coin/instructions/execute_test_instructions.yaml
@@ -8,15 +8,35 @@ instructions:
variableName: QTEST_ENVIRONMENT
variableValue: "ci"
- type: ExecuteCommand
- command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
+ command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.TARGET_ARCH_COIN}}"
maxTimeInSeconds: 14400
maxTimeBetweenOutput: 1200
enable_if:
- condition: property
- property: host.os
- equals_value: MacOS
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64
+ - condition: property
+ property: host.os
+ equals_value: MacOS
+ userMessageOnFailure: >
+ Failed to execute test instructions on osx
+ - type: ExecuteCommand
+ command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/Users/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch=X86_64-ARM64"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 1200
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: target.arch
+ equals_value: X86_64-ARM64
+ - condition: property
+ property: host.os
+ equals_value: MacOS
userMessageOnFailure: >
- Failed to execute test instructions on osx
+ Failed to execute test instructions on osx
- type: ExecuteCommand
command: "python -u coin_test_instructions.py --os={{.Env.CI_OS}} {{.Env.CI_PACKAGING_FEATURE}} --instdir=/home/qt/work/install --targetOs={{.Env.CI_OS}} --hostArch=X86_64 --targetArch={{.Env.CI_TARGET_ARCHITECTURE}}"
maxTimeInSeconds: 14400
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index d736b2355..ce6b58a7d 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -18,10 +18,20 @@ accept_configuration:
not_contains_value: -no-gui
- condition: property # Following configs are not supported
property: target.osVersion
- not_in_values: [OPENSUSE_13_01, QEMU, WebAssembly, Ubuntu_18_04, SLES_12, SLES_15, MacOS_10_15, MacOS_11_00]
+ not_in_values: [openSUSE_15_1, OPENSUSE_13_01, QEMU, WebAssembly, Ubuntu_18_04, SLES_12, SLES_15, MacOS_10_15, MacOS_11_00, Windows_11_21H2]
- condition: property # MibnGW and msvc2015 are not supported
property: target.compiler
not_in_values: [Mingw, MSVC2015]
+
+ - condition: and
+ conditions:
+ - condition: property
+ property: target.osVersion
+ equals_value: Windows_11_21H2
+ - condition: property
+ property: features
+ contains_value: Packaging
+
- condition: and
conditions:
- condition: property
diff --git a/coin_build_instructions.py b/coin_build_instructions.py
index 6a4d5dfd7..663633bf0 100644
--- a/coin_build_instructions.py
+++ b/coin_build_instructions.py
@@ -44,6 +44,7 @@ from build_scripts.utils import run_instruction
from build_scripts.utils import rmtree
from build_scripts.utils import get_python_dict
from build_scripts.utils import get_ci_qmake_path
+from build_scripts.utils import provisioning
import os
import datetime
import calendar
@@ -125,10 +126,18 @@ def call_setup(python_ver, phase):
v_env = "virtualenv"
run_instruction([v_env, "-p", _pExe, _env], "Failed to create virtualenv")
# When the 'python_ver' variable is empty, we are using Python 2
- # Pip is always upgraded when CI template is provisioned, upgrading it in later phase may cause perm issue
+ try:
+ print("Upgrade pip")
+ run_instruction([env_python, "--m", "pip", "install", "--upgrade", "pip"])
+ except Exception as e:
+ print("Failed to upgrade pip")
+ pass
+
run_instruction([env_pip, "install", "-r", "requirements.txt"], "Failed to install dependencies")
if sys.platform == "win32":
run_instruction([env_pip, "install", "numpy==1.19.3"], "Failed to install numpy 1.19.3")
+ elif os.environ.get("HOST_OSVERSION_COIN") == "macos_10_13" and python_ver == "3":
+ run_instruction([env_pip, "install", "numpy==1.19.4"], "Failed to install numpy")
else:
run_instruction([env_pip, "install", "numpy"], "Failed to install numpy")
@@ -141,6 +150,12 @@ def call_setup(python_ver, phase):
cmd += ["--build-tests",
"--parallel=4",
"--verbose-build"]
+
+ if CI_TARGET_ARCH == "X86_64-ARM64":
+ cmd += ["--macos-arch='x86_64;arm64'"]
+ if CI_HOST_ARCH != "arm64":
+ cmd += ["--macos-deployment-target=10.14"]
+
if python_ver == "3":
cmd += ["--limited-api=yes"]
else:
@@ -165,19 +180,28 @@ def call_setup(python_ver, phase):
def run_build_instructions(phase):
- # Uses default python, hopefully we have python2 installed on all hosts
- # Skip building using Python 2 on Windows, because of different MSVC C runtimes (VS2008 vs VS2015+)
- if CI_HOST_OS != "Windows":
- call_setup("", phase)
- # In case of packaging build, we have to build also python3 wheel
-
- if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]:
+ if CI_TARGET_ARCH == "X86_64-ARM64":
+ # For universal wheels there will be only python3 wheel
call_setup("3", phase)
+ else:
+ # Uses default python, hopefully we have python2 installed on all hosts
+ # Skip building using Python 2 on Windows, because of different MSVC C runtimes (VS2008 vs VS2015+)
+ if CI_HOST_OS != "Windows":
+ call_setup("2", phase)
+ # In case of packaging build, we have to build also python3 wheel
+
+ if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]:
+ call_setup("3", phase)
+
if __name__ == "__main__":
# Remove some environment variables that impact cmake
arch = '32' if CI_TARGET_ARCH and CI_TARGET_ARCH == 'X86' else '64'
+ # With 5.15.9 we are missing correct libclang so we need to install it for mac
+ # to create universal binaries.
+ if CI_HOST_OS == "MacOS" and CI_TARGET_ARCH == "X86_64-ARM64":
+ provisioning()
expand_clang_variables(arch)
for env_var in ['CC', 'CXX']:
if os.environ.get(env_var):
diff --git a/coin_test_instructions.py b/coin_test_instructions.py
index 4ba5ac9ff..abb465223 100644
--- a/coin_test_instructions.py
+++ b/coin_test_instructions.py
@@ -43,6 +43,8 @@ from build_scripts.utils import get_qtci_virtualEnv
from build_scripts.utils import run_instruction
from build_scripts.utils import rmtree
from build_scripts.utils import get_ci_qmake_path
+from build_scripts.utils import provisioning
+
import os
import site
import sys
@@ -85,6 +87,8 @@ def call_testrunner(python_ver, buildnro):
run_instruction([env_pip, "install", "-r", "requirements.txt"], "Failed to install dependencies")
if sys.platform == "win32":
run_instruction([env_pip, "install", "numpy==1.19.3"], "Failed to install numpy 1.19.3")
+ elif os.environ.get("HOST_OSVERSION_COIN") == "macos_10_13" and python_ver == "3":
+ run_instruction([env_pip, "install", "numpy==1.19.4"], "Failed to install numpy")
else:
run_instruction([env_pip, "install", "numpy"], "Failed to install numpy")
@@ -96,7 +100,7 @@ def call_testrunner(python_ver, buildnro):
qmake_path = get_ci_qmake_path(CI_ENV_INSTALL_DIR, CI_HOST_OS)
# Try to install built wheels, and build some buildable examples.
- if CI_RELEASE_CONF:
+ if CI_RELEASE_CONF and CI_HOST_OS != "MacOS":
wheel_tester_path = os.path.join("testing", "wheel_tester.py")
cmd = [env_python, wheel_tester_path, qmake_path]
run_instruction(cmd, "Error while running wheel_tester.py")
@@ -104,6 +108,12 @@ def call_testrunner(python_ver, buildnro):
def run_test_instructions():
# Remove some environment variables that impact cmake
arch = '32' if CI_TARGET_ARCH and CI_TARGET_ARCH == 'X86' else '64'
+
+ if CI_TARGET_ARCH == "X86_64-ARM64":
+ print("Install Libclang supporting universal binary")
+ provisioning()
+ else:
+ print("Using preinstalled libclang. While target arch was:" + str(CI_TARGET_ARCH))
expand_clang_variables(arch)
for env_var in ['CC', 'CXX']:
if os.environ.get(env_var):
@@ -111,18 +121,18 @@ def run_test_instructions():
os.chdir(CI_ENV_AGENT_DIR)
testRun = 0
- # We didn't build for Python 2 in win
- if CI_HOST_OS != "Windows":
+ # In win machines, there are additional python versions to test with
+ if CI_HOST_OS == "Windows":
+ call_testrunner("3.6.1", str(testRun))
+ call_testrunner("3.8.1", str(testRun))
+ elif CI_HOST_OS == "MacOS" and CI_TARGET_ARCH=="X86_64-ARM64":
+ call_testrunner("3", str(testRun))
+ else:
call_testrunner("", str(testRun))
testRun =+ 1
- # We know that second build was with python3
- if CI_RELEASE_CONF:
- # In win machines, there are additional python versions to test with
- if CI_HOST_OS == "Windows":
- call_testrunner("3.6.1", str(testRun))
- call_testrunner("3.8.1", str(testRun))
- else:
- call_testrunner("3", str(testRun))
+ call_testrunner("3", str(testRun))
if __name__ == "__main__":
+ print("HOST OS " + str(CI_HOST_OS))
+ print("TARGET ARCH " + str(CI_TARGET_ARCH))
run_test_instructions()