feat(fourdst): added better arch detect and pkg-config cli option

This commit is contained in:
2025-08-06 11:54:01 -04:00
parent 729ffe94ca
commit 7e92b2dd6e
9 changed files with 58 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
composition_p = subproject('libcomposition', default_options: ['pkg-config=false'])
composition_p = subproject('libcomposition', default_options: ['pkg-config=' + pkg_config_bool_str])
comp_dep = composition_p.get_variable('composition_dep')
libcomposition = composition_p.get_variable('libcomposition')
spw_dep = composition_p.get_variable('species_weight_dep')

View File

@@ -1,3 +1,3 @@
const_p = subproject('libconstants', default_options: ['pkg-config=false'])
const_p = subproject('libconstants', default_options: ['pkg-config=' + pkg_config_bool_str])
const_dep = const_p.get_variable('const_dep')
libconst = const_p.get_variable('libconst')

View File

@@ -1,4 +1,4 @@
logging_p = subproject('liblogging', default_options: ['pkg-config=false'])
logging_p = subproject('liblogging', default_options: ['pkg-config=' + pkg_config_bool_str])
liblogging = logging_p.get_variable('liblogging')
logging_dep = logging_p.get_variable('logging_dep')

View File

@@ -0,0 +1,4 @@
plugin_p = subproject('libplugin', default_options: ['pkg-config=' + pkg_config_bool_str])
libplugin = logging_p.get_variable('libplugin')
plugin_dep = logging_p.get_variable('plugin_dep')

View File

@@ -2,4 +2,5 @@ subdir('libcomposition')
subdir('libconfig')
subdir('libconstants')
subdir('liblogging')
subdir('libplugin')
subdir('pybind')

View File

@@ -18,7 +18,7 @@ except ImportError:
sys.exit(1)
from fourdst.cli.common.config import LOCAL_TRUST_STORE_PATH
from fourdst.cli.common.utils import calculate_sha256, get_platform_identifier
from fourdst.cli.common.utils import get_platform_identifier, calculate_sha256, is_abi_compatible
bundle_app = typer.Typer()
@@ -149,7 +149,7 @@ def bundle_inspect(bundle_path: Path = typer.Argument(..., help="The .fbundle fi
for b in binaries:
plat = b.get('platform', {})
is_compatible = (plat.get('triplet') == host_platform['triplet'] and
plat.get('abi_signature') == host_platform['abi_signature'])
is_abi_compatible(host_platform['abi_signature'], plat.get('abi_signature', '')))
color = typer.colors.GREEN if is_compatible else None
if is_compatible:

View File

@@ -164,7 +164,7 @@ def get_available_build_targets() -> list:
for name, image in DOCKER_BUILD_IMAGES.items():
arch = name.split(' ')[0]
targets.append({
"triplet": f"linux-{arch}",
"triplet": f"{arch}-linux",
"abi_signature": f"docker-{image}",
"is_native": False,
"cross_file": None,
@@ -325,7 +325,7 @@ def _build_plugin_in_docker(sdist_path: Path, build_dir: Path, target: dict, plu
abi_string = f"{compiler}-{stdlib}-{stdlib_version}-{abi}"
final_target = {
"triplet": f"{abi_details.get('os', 'linux')}-{arch}",
"triplet": f"{arch}-{abi_details.get('os', 'linux')}",
"abi_signature": abi_string,
"is_native": False,
"cross_file": None,
@@ -345,6 +345,45 @@ def _build_plugin_in_docker(sdist_path: Path, build_dir: Path, target: dict, plu
return local_lib_path, final_target
def is_abi_compatible(host_abi: str, binary_abi: str) -> bool:
"""
Checks if a binary's ABI is compatible with the host's ABI.
Compatibility is defined as:
1. Same compiler, stdlib, and ABI name.
2. Host's stdlib version is >= binary's stdlib version.
"""
try:
host_parts = host_abi.split('-')
bin_parts = binary_abi.split('-')
if len(host_parts) != 4 or len(bin_parts) != 4:
# Fallback to exact match for non-standard ABI strings
return host_abi == binary_abi
host_compiler, host_stdlib, host_version, host_abi_name = host_parts
bin_compiler, bin_stdlib, bin_version, bin_abi_name = bin_parts
# 1. Check for exact match on compiler, stdlib, and abi name
if not (host_compiler == bin_compiler and host_stdlib == bin_stdlib and host_abi_name == bin_abi_name):
return False
# 2. Compare stdlib versions (e.g., "2.41" vs "2.28")
# We can treat them as dot-separated integers for comparison.
host_v_parts = list(map(int, host_version.split('.')))
bin_v_parts = list(map(int, bin_version.split('.')))
# Pad shorter version with zeros for safe comparison
max_len = max(len(host_v_parts), len(bin_v_parts))
host_v_parts.extend([0] * (max_len - len(host_v_parts)))
bin_v_parts.extend([0] * (max_len - len(bin_v_parts)))
return host_v_parts >= bin_v_parts
except (ValueError, IndexError):
# If parsing fails, fall back to a simple string comparison
return host_abi == binary_abi
def calculate_sha256(file_path: Path) -> str:
"""Calculates the SHA256 checksum of a file."""
sha256_hash = hashlib.sha256()

View File

@@ -2,6 +2,12 @@ project('fourdst', 'cpp', version: 'v0.6.0', default_options: ['cpp_std=c++23'],
add_project_arguments('-fvisibility=default', language: 'cpp')
pkg_config_bool_str = 'false'
if get_option('pkg-config')
pkg_config_bool_str = 'true'
endif
# Configure vendor libraries
subdir('build-config')

1
meson_options.txt Normal file
View File

@@ -0,0 +1 @@
option('pkg-config', type: 'boolean', value: false, description: 'generate pkg-config file for all libraries and fourdst (defaults to false to allow easy pip building)')