diff --git a/build-config/libcomposition/meson.build b/build-config/libcomposition/meson.build index b72f1b8..fca7e8c 100644 --- a/build-config/libcomposition/meson.build +++ b/build-config/libcomposition/meson.build @@ -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') diff --git a/build-config/libconstants/meson.build b/build-config/libconstants/meson.build index 24138d8..d9ed5da 100644 --- a/build-config/libconstants/meson.build +++ b/build-config/libconstants/meson.build @@ -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') diff --git a/build-config/liblogging/meson.build b/build-config/liblogging/meson.build index ba288ab..ab23f9c 100644 --- a/build-config/liblogging/meson.build +++ b/build-config/liblogging/meson.build @@ -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') diff --git a/build-config/libplugin/meson.build b/build-config/libplugin/meson.build new file mode 100644 index 0000000..c5a7634 --- /dev/null +++ b/build-config/libplugin/meson.build @@ -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') diff --git a/build-config/meson.build b/build-config/meson.build index 222d743..e2f2e28 100644 --- a/build-config/meson.build +++ b/build-config/meson.build @@ -2,4 +2,5 @@ subdir('libcomposition') subdir('libconfig') subdir('libconstants') subdir('liblogging') +subdir('libplugin') subdir('pybind') diff --git a/fourdst/cli/bundle/inspect.py b/fourdst/cli/bundle/inspect.py index ba62d0c..664ec5d 100644 --- a/fourdst/cli/bundle/inspect.py +++ b/fourdst/cli/bundle/inspect.py @@ -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: diff --git a/fourdst/cli/common/utils.py b/fourdst/cli/common/utils.py index e0205e0..30cff8d 100644 --- a/fourdst/cli/common/utils.py +++ b/fourdst/cli/common/utils.py @@ -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() diff --git a/meson.build b/meson.build index f3e0091..77a8fd1 100644 --- a/meson.build +++ b/meson.build @@ -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') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..c54b2d0 --- /dev/null +++ b/meson_options.txt @@ -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)')