Skip to content

Problem with versioned functions (FreeBSD) #236

Open

Description

@kaj

Trying to build rust_icu_ustring on FreeBSD (after getting around #235), I get a bunch of errors like this:

error[E0425]: cannot find function `u_strFromUTF8_70` in this scope
   --> /home/kaj/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_icu_ustring-2.0.0/src/lib.rs:160:13
    |
160 |             versioned_function!(u_strFromUTF8)(
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `u_strFromUTF8`
    |
   ::: /usr/home/kaj/proj/r4s/target/debug/build/rust_icu_sys-f73623289ad55f94/out/lib.rs:3:850138
    |
3   | ..."] pub fn u_strFromUTF8 (dest : * mut UChar , destCapacity : i32 , pDestLength : * mut i32 , src : * const :: std :: os :: raw :: c_char , srcLength : i32 , pErrorCode : * mut UErrorCode) -> * mut UChar ; } ...
    |       --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- similarly named function `u_strFromUTF8` defined here
    |
    = note: this error originates in the macro `versioned_function` (in Nightly builds, run with -Z macro-backtrace for more info)

I get eleven such errors, all for different function names u_\w+_70. Checking the actual library, (with nm --dynamic --defined-only (libfile) it contains the symbols like u_strFromUTF8 but no symbols ending with _70 (or any other _number). The same command on linux (Fedora 35) shows u_strFromUTF8_69 (but no unversioned symbols).

The version number itself is correct, libicuuc.so on my FreeBSD host is a symlink to libicuuc.so.70.1. But the symbols in it are not versioned.

In rust_icu_sys/bindgen/macros.rs, it seems that versioning can be disabled by not using the renaming or the icu_version_in_env feature, but apparently at least one or those gets defined in my build even though it should not. Or should the cfg

/// This macro will be used when no function renaming is needed.
#[cfg(not(any(feature="renaming",feature="icu_version_in_env")))]
#[macro_export]
macro_rules! versioned_function {
($func_name:path) => {
$func_name
}
}

be changed to just

 #[cfg(not(feature="renaming"))] 

?

Activity

  1. kaj commented on Jan 15, 2022

    @kaj
    Author

    I believe I have up-to-date versions of the rust_icu_* crates:

    : guran%; cargo tree -i rust_icu_sys
    rust_icu_sys v2.0.0
    ├── rust_icu_common v2.0.0
    │   ├── rust_icu_ucol v2.0.0
    │   │   └── r4s v0.1.0 (/usr/home/kaj/proj/r4s)
    │   ├── rust_icu_uenum v2.0.0
    │   │   └── rust_icu_ucol v2.0.0 (*)
    │   └── rust_icu_ustring v2.0.0
    │       └── rust_icu_ucol v2.0.0 (*)
    ├── rust_icu_ucol v2.0.0 (*)
    ├── rust_icu_uenum v2.0.0 (*)
    └── rust_icu_ustring v2.0.0 (*)
    

    My rust toolchain is:

      stable-x86_64-unknown-freebsd unchanged - rustc 1.58.0 (02072b482 2022-01-11)
    
  2. filmil commented on Jan 15, 2022

    @filmil
    Contributor

    It is unexpected that only some of the symbols in the ICU library are renamed and some not.

    be changed to just

    #[cfg(not(feature="renaming"))]

    That should not be correct, as

    #[cfg(all(feature="renaming",not(feature="icu_version_in_env")))]
    is supposed to cover that feature combination.

  3. kaj commented on Jan 15, 2022

    @kaj
    Author

    @filmil huh? It seems to be line 9 and and 22 is for when renaming is enabled, so I think line 33 should cover both the cases when renaming is not enabled.

    renaming icu_version_in_env selected
    enabled enabled line 22
    enabled disabled line 9
    disabled disabled line 33
    disabled enabled ??

    But maybe icu_version_in_env is never enabled unless renaming is? It seems to me that renaming is enabled when building on FreeBSD but should not be.

  4. kaj commented on Jan 15, 2022

    @kaj
    Author

    I also tried to disable features by changing my dependency to:

    rust_icu_ucol = { version = "2.0.0", default-features = false }
    

    but then I got the message:

    error: You must use `renaming` when not using `use-bindgen`
    

    So I changed the dependency to:

    rust_icu_ucol = { version = "2.0.0", default-features = false, features = ["use-bindgen"] }
    

    ... and then I got this error:

    error: couldn't read /usr/home/kaj/proj/r4s/target/debug/build/rust_icu_sys-00ce2788a020995a/out/macros.rs: No such file or directory (os error 2)
      --> /home/kaj/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_icu_sys-2.0.0/src/lib.rs:45:1
       |
    45 | include!(concat!(env!("OUT_DIR"), "/macros.rs"));
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
       = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)
    
  5. kaj commented on Jan 16, 2022

    @kaj
    Author

    Some more info on this; checking out the rust_icu sources on my FreeBSD host, I find cargo test works fine in rust_icu_sys and rust_icu_common, but fails on versioned functions as above for other crates, such as rust_icu_ucol and rust_icu_uenum. So my present guess is that rust_icu_sys detects the unversioned symbol fine and works with them, but somehow fails to communicate this to downstream crates.

    Thoughts on that? Any suggestions for things I can try?

  6. filmil commented on Jan 16, 2022

    @filmil
    Contributor
  7. kaj commented on Jan 16, 2022

    @kaj
    Author

    It seems I was actually rather close above (#236 (comment)). If I edit the dependency like this it works:

    rust_icu_ucol = { version = "2.0.0", default-features = false, features = ["use-bindgen", "icu_config"] }

    ... but of course, like that it does not build on Linux anymore. So I really think these flags should not be cargo features to be enabled or not from the consuming package at all, but instead autodetected flags that rust_icy_sys makes availiable for all dependent packages.

  8. filmil commented on Jan 17, 2022

    @filmil
    Contributor
  9. yshui commented on Aug 21, 2022

    @yshui

    Same problem on Gentoo, icu-i18n.pc looks like this:

    # Copyright (C) 2016 and later: Unicode, Inc. and others.
    # License & terms of use: http://www.unicode.org/copyright.html
    # Copyright (C) 2010-2013, International Business Machines Corporation. All Rights Reserved.
    
    # CFLAGS contains only anything end users should set
    CFLAGS =
    # CXXFLAGS contains only anything end users should set
    CXXFLAGS =
    # DEFS only contains those UCONFIG_CPPFLAGS which are not auto-set by platform.h
    DEFS =  -DU_DISABLE_RENAMING=1
    prefix = /usr
    exec_prefix = ${prefix}
    #bindir = ${exec_prefix}/bin
    libdir = /usr/lib
    includedir = ${prefix}/include
    baselibs = -lpthread -lm
    #datarootdir = /usr/share
    #datadir = /usr/share
    #sbindir = ${exec_prefix}/sbin
    #mandir = /usr/share/man
    #sysconfdir = /etc
    UNICODE_VERSION=14.0
    ICUPREFIX=icu
    ICULIBSUFFIX=
    LIBICU=lib${ICUPREFIX}
    #SHAREDLIBCFLAGS=-fPIC
    pkglibdir=${libdir}/icu${ICULIBSUFFIX}/71.1
    #pkgdatadir=${datadir}/icu${ICULIBSUFFIX}/71.1
    ICUDATA_NAME = icudt71l
    #ICUPKGDATA_DIR=/usr/lib
    #ICUDATA_DIR=${pkgdatadir}
    ICUDESC=International Components for Unicode
    
    Version: 71.1
    Cflags: -I${includedir}
    # end of icu.pc.in
    Description: International Components for Unicode: Internationalization library
    Name: icu-i18n
    Requires: icu-uc
    Libs: -licui18n
    

    I think icu_sys only checks --cflags?

  10. kaj commented on Aug 30, 2022

    @kaj
    Author

    Here's output from a bunch of pkg-config commands on my FreeBSD host:

    :; pkg-config icu-i18n --cflags
    -I/usr/local/include 
    :; pkg-config icu-i18n --libs
    -licui18n -L/usr/local/lib -licuuc -licudata 
    :; pkg-config icu-i18n --variable=DEFS
    -DU_DISABLE_RENAMING=1
    :;
    :; pkg-config icu-i18n --print-requires
    icu-uc
    :;
    :; pkg-config icu-uc --cflags
    -I/usr/local/include 
    :; pkg-config icu-uc --libs
    -L/usr/local/lib -licuuc -licudata 
    :; pkg-config icu-uc --variable=DEFS
    -DU_DISABLE_RENAMING=1

    I guess the problem is that rust_icu doesn't find the -DU_DISABLE_RENAMING=1 flag, but I don't know if it is a bug in the FreeBSD pkgconfig data that it is not included in cflags or a bug in rust_icu that it doesn't look at --variable=DEFS.

    The FreeBSD port of icu runs configure for icu with --disable-renaming (and some other flags) and does not seem to mess with the icu-*.pc files, so it seems that those are as intended by the icu project.


    Looking some more, it seems that the omission of the U_DISABLE_RENAMING flag from --cflags is intentional. Instead, it is defined like this in unicode/uconfig.h:

    /**
     * \def U_DISABLE_RENAMING
     * Determines whether to disable renaming or not.
     * @internal
     */
    #ifndef U_DISABLE_RENAMING
    #define U_DISABLE_RENAMING 1
    #endif

    So I guess the correct way of finding if renaming is enabled or not is to build and run a little program like this:

    #include <unicode/uconfig.h>
    #include <stdio.h>
    
    int main() {
      if (U_DISABLE_RENAMING) {
        printf("Renaming disabled");
      } else {
        printf("Renaming enabled");
      }
    }

    ... then compile that with proper flags from pkg-config, run it, and look at the output.

  11. ip1981 commented on Oct 3, 2026

    @ip1981

    See #415

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions