ABI compatibility?
Using the very handy abipkgdiff I compared the ABI from a 1.9.0 build of libucs.so.0.0.0 on Leap 15 to a 1.11.1 build on the same platform. The report output was:
$ abipkgdiff libucs0-1.9.0-2.11.x86_64.rpm libucs0-1.11.1-0.x86_64.rpm
================ changes of 'libucs.so.0.0.0'===============
Functions changes summary: 0 Removed, 0 Changed, 74 Added functions
Variables changes summary: 0 Removed, 0 Changed, 5 Added variables
Function symbols changes summary: 6 Removed, 0 Added function symbols not referenced by debug info
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
74 Added functions:
[A] 'function int ini_parse(const char*, ini_handler, void*)' {ini_parse}
[A] 'function int ini_parse_file(FILE*, ini_handler, void*)' {ini_parse_file}
[A] 'function int ini_parse_stream(ini_reader, void*, ini_handler, void*)' {ini_parse_stream}
[A] 'function int ini_parse_string(const char*, ini_handler, void*)' {ini_parse_string}
[A] 'function ucs_status_t ucs_array_grow(void**, size_t*, size_t, size_t, const char*, const char*)' {ucs_array_grow}
[A] 'function int ucs_async_is_from_async(const ucs_async_context_t*)' {ucs_async_is_from_async}
[A] 'function ucs_status_t ucs_config_clone_allow_list(void*, void*, void*)' {ucs_config_clone_allow_list}
[A] 'function void ucs_config_help_allow_list(char*, size_t, void*)' {ucs_config_help_allow_list}
[A] 'function ucs_status_t ucs_config_parse_config_file(const char*, int)' {ucs_config_parse_config_file}
[A] 'function void ucs_config_parser_print_env_vars_once(const char*)' {ucs_config_parser_print_env_vars_once}
[A] 'function void ucs_config_release_allow_list(void*, void*)' {ucs_config_release_allow_list}
[A] 'function int ucs_config_sprintf_allow_list(char*, size_t, void*, void*)' {ucs_config_sprintf_allow_list}
[A] 'function int ucs_config_sprintf_ternary_auto(char*, size_t, void*, void*)' {ucs_config_sprintf_ternary_auto}
[A] 'function int ucs_config_sprintf_time_units(char*, size_t, void*, void*)' {ucs_config_sprintf_time_units}
[A] 'function int ucs_config_sscanf_allow_list(const char*, void*, void*)' {ucs_config_sscanf_allow_list}
[A] 'function int ucs_config_sscanf_ternary_auto(const char*, void*, void*)' {ucs_config_sscanf_ternary_auto}
[A] 'function int ucs_config_sscanf_time_units(const char*, void*, void*)' {ucs_config_sscanf_time_units}
[A] 'function ucs_conn_match_elem_t* ucs_conn_match_get_elem(ucs_conn_match_ctx_t*, void*, ucs_conn_sn_t, ucs_conn_match_queue_type_t, int)' {ucs_conn_match_get_elem}
[A] 'function int ucs_debug_is_handle_errors()' {ucs_debug_is_handle_errors}
[A] 'function char* ucs_dirname(char*, int)' {ucs_dirname}
[A] 'function int ucs_empty_function_return_one_int()' {ucs_empty_function_return_one_int}
[A] 'function int ucs_empty_function_return_zero_int()' {ucs_empty_function_return_zero_int}
[A] 'function size_t ucs_empty_function_return_zero_size_t()' {ucs_empty_function_return_zero_size_t}
[A] 'function uint64_t ucs_get_system_id()' {ucs_get_system_id}
[A] 'function int ucs_log_get_current_indent()' {ucs_log_get_current_indent}
[A] 'function void ucs_log_indent(int)' {ucs_log_indent}
[A] 'function void ucs_log_set_thread_name(const char*, ...)' {ucs_log_set_thread_name}
[A] 'function const char* ucs_mask_str(uint64_t, ucs_string_buffer_t*)' {ucs_mask_str}
[A] 'function void ucs_memory_info_set_host(ucs_memory_info_t*)' {ucs_memory_info_set_host}
[A] 'function const char* ucs_memunits_range_str(size_t, size_t, char*, size_t)' {ucs_memunits_range_str}
[A] 'function int ucs_posix_memalign_realloc(void**, size_t, size_t, const char*)' {ucs_posix_memalign_realloc}
[A] 'function void ucs_profile_cleanup(ucs_profile_context_t*)' {ucs_profile_cleanup}
[A] 'function ucs_status_t ucs_profile_init(unsigned int, const char*, size_t, ucs_profile_context_t**)' {ucs_profile_init}
[A] 'function int ucs_rand()' {ucs_rand}
[A] 'function ucs_status_t ucs_rand_range(int, int, int*)' {ucs_rand_range}
[A] 'function void ucs_rand_seed_init()' {ucs_rand_seed_init}
[A] 'function void ucs_rcache_region_invalidate(ucs_rcache_t*, ucs_rcache_region_t*, ucs_rcache_invalidate_comp_func_t, void*)' {ucs_rcache_region_invalidate}
[A] 'function void ucs_recursive_spinlock_destroy(ucs_recursive_spinlock_t*)' {ucs_recursive_spinlock_destroy}
[A] 'function ucs_status_t ucs_sock_ipstr_to_sockaddr(const char*, sockaddr_storage*)' {ucs_sock_ipstr_to_sockaddr}
[A] 'function ucs_status_t ucs_sockaddr_get_ifaddr(const char*, sockaddr_in*)' {ucs_sockaddr_get_ifaddr}
[A] 'function ucs_status_t ucs_sockaddr_get_ifmask(const char*, sockaddr_in*)' {ucs_sockaddr_get_ifmask}
[A] 'function ucs_status_t ucs_sockaddr_get_ip_local_port_range(ucs_range_spec_t*)' {ucs_sockaddr_get_ip_local_port_range}
[A] 'function ucs_status_t ucs_sockaddr_get_ipstr(const sockaddr*, char*, size_t)' {ucs_sockaddr_get_ipstr}
[A] 'function ucs_status_t ucs_sockaddr_inet_addr_size(sa_family_t, size_t*)' {ucs_sockaddr_inet_addr_size}
[A] 'function ucs_status_t ucs_sockaddr_inet_addr_sizeof(const sockaddr*, size_t*)' {ucs_sockaddr_inet_addr_sizeof}
[A] 'function int ucs_sockaddr_is_inaddr_loopback(const sockaddr*)' {ucs_sockaddr_is_inaddr_loopback}
[A] 'function int ucs_sockaddr_is_known_af(const sockaddr*)' {ucs_sockaddr_is_known_af}
[A] 'function ucs_status_t ucs_sockaddr_set_inet_addr(sockaddr*, void*)' {ucs_sockaddr_set_inet_addr}
[A] 'function void ucs_spinlock_destroy(ucs_spinlock_t*)' {ucs_spinlock_destroy}
[A] 'function void ucs_string_buffer_append_hex(ucs_string_buffer_t*, void*, size_t, size_t)' {ucs_string_buffer_append_hex}
[A] 'function void ucs_string_buffer_dump(const ucs_string_buffer_t*, const char*, FILE*)' {ucs_string_buffer_dump}
[A] 'function char* ucs_string_buffer_extract_mem(ucs_string_buffer_t*)' {ucs_string_buffer_extract_mem}
[A] 'function void ucs_string_buffer_init_fixed(ucs_string_buffer_t*, char*, size_t)' {ucs_string_buffer_init_fixed}
[A] 'function size_t ucs_string_buffer_length(ucs_string_buffer_t*)' {ucs_string_buffer_length}
[A] 'function size_t ucs_string_common_prefix_len(const char*, const char*)' {ucs_string_common_prefix_len}
[A] 'function size_t ucs_string_count_char(const char*, char)' {ucs_string_count_char}
[A] 'function ucs_status_t ucs_sys_get_file_time(const char*, ucs_sys_file_time_t, timespec*)' {ucs_sys_get_file_time}
[A] 'function void ucs_sys_iterate_vm(void*, size_t, ucs_sys_vma_cb_t, void*)' {ucs_sys_iterate_vm}
[A] 'function int ucs_sys_max_open_files()' {ucs_sys_max_open_files}
[A] 'function const char* ucs_topo_distance_str(const ucs_sys_dev_distance_t*, char*, size_t)' {ucs_topo_distance_str}
[A] 'function ucs_status_t ucs_topo_find_device_by_bdf_name(const char*, ucs_sys_device_t*)' {ucs_topo_find_device_by_bdf_name}
[A] 'function unsigned int ucs_topo_num_devices()' {ucs_topo_num_devices}
[A] 'function const char* ucs_topo_sys_device_bdf_name(ucs_sys_device_t, char*, size_t)' {ucs_topo_sys_device_bdf_name}
[A] 'function ucs_status_t ucs_vfs_obj_add_dir(void*, void*, const char*, ...)' {ucs_vfs_obj_add_dir}
[A] 'function ucs_status_t ucs_vfs_obj_add_ro_file(void*, ucs_vfs_file_show_cb_t, void*, uint64_t, const char*, ...)' {ucs_vfs_obj_add_ro_file}
[A] 'function void ucs_vfs_obj_remove(void*)' {ucs_vfs_obj_remove}
[A] 'function void ucs_vfs_obj_set_dirty(void*, ucs_vfs_refresh_cb_t)' {ucs_vfs_obj_set_dirty}
[A] 'function ucs_status_t ucs_vfs_path_get_info(const char*, ucs_vfs_path_info_t*)' {ucs_vfs_path_get_info}
[A] 'function ucs_status_t ucs_vfs_path_list_dir(const char*, ucs_vfs_list_dir_cb_t, void*)' {ucs_vfs_path_list_dir}
[A] 'function ucs_status_t ucs_vfs_path_read_file(const char*, ucs_string_buffer_t*)' {ucs_vfs_path_read_file}
[A] 'function void ucs_vfs_show_memory_address(void*, ucs_string_buffer_t*, void*, uint64_t)' {ucs_vfs_show_memory_address}
[A] 'function void ucs_vfs_show_memunits(void*, ucs_string_buffer_t*, void*, uint64_t)' {ucs_vfs_show_memunits}
[A] 'function void ucs_vfs_show_primitive(void*, ucs_string_buffer_t*, void*, uint64_t)' {ucs_vfs_show_primitive}
[A] 'function void ucs_vfs_show_ulunits(void*, ucs_string_buffer_t*, void*, uint64_t)' {ucs_vfs_show_ulunits}
5 Added variables:
[A] 'ucs_profile_context_t* ucs_profile_default_ctx' {ucs_profile_default_ctx}
[A] 'unsigned int ucs_rand_seed' {ucs_rand_seed}
[A] 'const char* ucs_thread_mode_names[]' {ucs_thread_mode_names}
[A] 'const ucs_sys_dev_distance_t ucs_topo_default_distance' {ucs_topo_default_distance}
[A] '__anonymous_struct__ ucs_vfs_obj_context' {ucs_vfs_obj_context}
6 Removed function symbols not referenced by debug info:
[D] ucs_config_parser_warn_unused_env_vars_once
[D] ucs_config_sprintf_ternary
[D] ucs_conn_match_retrieve
[D] ucs_init_once_mutex_unlock
[D] ucs_profile_global_cleanup
[D] ucs_profile_global_init
================ end of changes of 'libucs.so.0.0.0'===============
The 5 added variables would explain the "undefined symbol: ucs_thread_mode_names" that I got when trying to run a binary created with libucs0 1.11.1 on a system with libucs0 1.9.0.
But my understanding is that ABI versioning is supposed to prevent me from even being able to run my application as it should error out due to a not finding a library that is ABI compatible (i.e. using the SOVERSION).
Shouldn't all of those added functions and variables between 1.9.0 and 1.11.1 have resulted in the SOVERSION being incremented? Or is there something about that that I am misunderstanding?