///////////////////////////////////////////////////////////////////////////////
// Name:        wx/private/elfversion.h
// Purpose:     Helper macro for assigning ELF version to a symbol.
// Author:      Vadim Zeitlin
// Created:     2025-04-14
// Copyright:   (c) 2025 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence:     wxWindows licence
///////////////////////////////////////////////////////////////////////////////

#ifndef _WX_PRIVATE_ELFVERSION_H_
#define _WX_PRIVATE_ELFVERSION_H_

// This symbol is defined by configure if .symver directive is supported.
#ifdef wxHAVE_ELF_SYMVER
    // Prefer to use the attribute if it is available, as it works with LTO,
    // unlike the assembler directive.
    #ifdef __has_attribute
        #if __has_attribute(__symver__)
            #define wxELF_SYMVER(sym, symver) __attribute__((__symver__(symver)))
        #endif
    #endif

    #ifndef wxELF_SYMVER
        #define wxELF_SYMVER(sym, symver) __asm__(".symver " sym "," symver);
    #endif

    // Using multiple versions for the same symbols may be not supported, in
    // which case we omit it: this results in generating 2 default versions for
    // the same symbol, which looks wrong, but doesn't seem to cause any
    // problems.
    #ifdef wxHAVE_ELF_SYMVER_MULTIPLE
        #define wxELF_SYMVER_NON_DEFAULT(sym, ver) wxELF_SYMVER(sym, ver)
    #else
        #define wxELF_SYMVER_NON_DEFAULT(sym, ver)
    #endif

    // Our version tag depends on whether we're using Unicode or not.
    #if wxUSE_UNICODE
        #define wxMAKE_ELF_VERSION_TAG(ver) "WXU_" ver
    #else
        #define wxMAKE_ELF_VERSION_TAG(ver) "WX_" ver
    #endif

    // This macro is used to repair ABI compatibility problems with the symbols
    // versions if any symbols are added with the wrong "3.4" version tag
    // because their definitions in the version script were erroneous.
    //
    // It allows to define both the old, compatible version ("3.4") and the new
    // ("3.4.N") one for the given symbol to restore ABI compatibility with the
    // previous releases without breaking it with the release containing the
    // corrected version.
    //
    // The parameters are the mangled symbol name (the simplest way to get is
    // probably to use nm or readelf on the object file or library) and the
    // part of the version after "WX[U]_", i.e. the version number itself.
    //
    // Note that this macro takes strings, not symbols, and that it includes
    // the trailing semicolon for consistency with the empty version below.
    #define wxELF_VERSION_COMPAT(sym, ver) \
        wxELF_SYMVER_NON_DEFAULT(sym, sym "@" wxMAKE_ELF_VERSION_TAG("3.4")) \
        wxELF_SYMVER(sym, sym "@@" wxMAKE_ELF_VERSION_TAG(ver))
#else
    #define wxELF_VERSION_COMPAT(sym, ver)
#endif

#endif // _WX_PRIVATE_ELFVERSION_H_
