Mac OSX 上的 _libiconv 或 _iconv 未定义符号

Joh*_*n Q 17 iconv libiconv

在 Mac OSX 上从源代码编译某些包时,出现以下 iconv 错误:

Undefined symbols for architecture x86_64:
  "_iconv", referenced from:
  "_iconv_close", referenced from:
  "_iconv_open", referenced from:
Run Code Online (Sandbox Code Playgroud)

或者我得到:

Undefined symbols for architecture x86_64:
"_libiconv", referenced from:
"_libiconv_open", referenced from:
"_libiconv_close", referenced from:
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,我该如何解决这种依赖性,或者更一般地说,弄清楚发生了什么以及如何解决它?

Joh*_*n Q 23

我在 Mac OSX 的多年/升级中遇到了这个问题。我已经通读了所有不同的答案,其中有很多。这个答案是我开始这段旅程时希望得到的答案,所以我希望它有所帮助。

发生了什么:

您安装了两个(可能是三个)版本的 iconv:

  1. 与 MacOSX 一起安装在 /usr/lib 中的一个,其函数调用名称为“iconv()”、“iconv_open()”、“iconv_close”等。
  2. 用于 *nix 系统的 GNU libiconv 版本,其函数调用名称为“libiconv”、“libiconv_open()”、“libiconv_close()”等。
  3. 可能是与 Xcode 一起安装的版本:/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib

无论您正在编译/运行什么程序,都找不到它想要的程序。

这可能出于(至少)三个原因:

  1. 您的系统上安装了多个版本的 iconv,并且库搜索路径会首先找到另一个版本。这种情况经常发生在将 *nix 包带入 MacOSX 的包管理器中(如 MacPorts、Homebrew、Fink 等)。他们不仅引入了 GNU libiconv 版本,而且通常会修改 lib 搜索路径以首先访问它们的目录(即,未找到“_iconv”,因为它所命中的第一个 lib 定义了 GNU libiconv 的“_libiconv”)。
  2. 您完全缺少代码正在寻找的 iconv 版本,通常是 GNU libiconv 版本。我在从源代码编译 PHP 时遇到过这个问题。它需要 GNU libiconv 版本(即,它调用“libiconv_open()”、“libiconv_close()”等。
  3. 您有编译器从一个版本中找到的 .h 文件,但库搜索路径首先从另一个版本中找到库。例如,如果您首先找到 GNU libiconv 的 iconv.h 文件,它会将“iconv”重新定义为“libiconv”,但链接器可能只能在 /usr/lib 中找到 Mac OSX 库(其中包含符号“_iconv”、“_iconv_open” ", "_iconv_close") 并且即使您没有在任何地方安装 iconv lib 的 GNU libiconv 版本,您也会收到找不到“_libiconv”符号的错误。

怎么办:

您的工作是获取您正在运行/编译的任何内容,以便在其他人之前找到正确版本的 iconv。您可以通过多种方式执行此操作。

编译时,您可以尝试在运行“configure”时包含“ --with-iconv=<dir>”和或“ --with-iconv-dir=<dir>”或“ --with-libiconv-prefix=<dir>”指令以指向正确的版本。如果这不起作用,您将需要采取更直接的方法,例如直接编辑 Makefile。

我个人的偏好是将这些类型的更改仅包含在有问题的项目中,以便以后不会对不相关的项目产生级联影响。对我来说,这意味着编辑由“configure”创建的 Makefile,并将 iconv lib 目录直接包含在 Makefile 的 LDFLAGS 条目(或类似条目)中。当你传递“configure”一个“ --with-iconv=”指令时,它应该这样做,但我发现它并不总是有效,因为Makefile会在你想要的目录之前包含一些其他的lib目录。

你在这里追求的是订购。您希望您的 iconv lib 目录在“cc”编译命令中的其他 lib 目录之前显示,因此在运行“make”时检查输出(详细模式)。此外,您可以将“-liconv”替换为lib文件本身的绝对路径(即“path/to/iconv/lib/libiconv.dylib”,没有-L,没有-l)。

另外,如果你在 Makefile 的 lib 路径中看到这个

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/lib

然后把它放在库路径列表的最后,并确保正确的 iconv lib 目录的路径在它之前。-I 包含路径上的这个也一样:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include

潜在地,您也可以进入不需要的 iconv lib 目录并将它们移动到另一个位置(注意:这不适用于 MacOSX 版本,因为它们受系统保护)。

如何在您的系统上调试此问题:

  • find / -name iconv.* (或 libiconv.* 并且您可能需要成为 root 才能找到所有这些)
  • 如果您的编译尚未向您显示编译/链接的每个内容的 -I 和 -L 路径,那么找出一个详细选项,以便它会(对于配置,我认为只需export V=1在命令行上运行“ ”,然后运行配置和在同一个 shell 窗口中制作)。
  • 您会认为将“ --with-iconv=<path-to-iconv-dir>”指定为 ./configure 的参数会解决这个问题,但有时不能保证生成的 Makefile 将在另一个获取其他 iconv 文件的库路径之前包含您的 iconv 路径,因此您可能需要编辑 Makefile 以真正强制它查看您希望它首先查看的位置。
  • otool -L <executable/dylib> 将显示二进制文件链接到哪些库。
  • “文件文件”将向您显示库具有用于哪些架构的符号。
  • 只需复制失败的“cc”命令(运行 Makefile 时的输出行之一),然后添加或排序参数,直到找出有效的组合(即 -I、-L、-l , <lib 文件的绝对路径,没有前面的 -l>),然后从那里向后工作以使 Makefile 做同样的事情(或者只是再次运行“make”以让它继续编译和链接其他所有内容)。
  • 注意:有时,当您使用 Homebrew、MacPorts 等安装软件包时会发生什么情况是,为解决非常具体的依赖项而引入的 iconv 库现在潜伏在您的库中并包含路径,并为依赖于正常的其他东西而拾取MacOSX 版本 - 突然之间,即使您“没有更改任何内容”,一个不相关的程序也会出现问题。
  • 注意:您会注意到 /usr/lib 中有一个 iconv 库,但 /usr/include 中没有相应的头文件。事实上,根本没有 /usr/include 目录。最新版本的 Mac OSX 将开发头文件与操作系统分开。开发头文件和库由 Xcode 处理,您可以通过运行以下命令找到它们:“ xcrun --show-sdk-path”,然后转到您将找到 /include 和 /lib 目录的目录。在这里解释:https : //developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes#3035624

DYLD_LIBRARY_PATH 和 LD_LIBRARY_PATH

tl;博士:不要这样做。

为了让您的编译正常工作,您可能已经向 DYLD_LIBRARY_PATH 或 LD_LIBRARY_PATH(在 ~/.bash_profile 或类似文件中)添加了一个指向 GNU iconv 库的新路径,以便“帮助”链接器查找内容。当与您现在正在做的事情完全无关的事情正在寻找 MacOSX iconv 库而不是拉入 GNU libiconv 库时,这将在另一个时间/一天回来咬你。因此,当涉及到 iconv 时,我不理会 DYLD_LIBRARY_PATH 和 LD_LIBRARY_PATH。对于我从源代码编译的其他项目,如 OpenSSL,是的,我确实更改了 DYLD_LIBRARY_PATH 和 LD_LIBRARY_PATH,因为到目前为止在 MacOSX 上还没有任何冲突。

最后,这里是讨论这个问题的 MacPorts 支持线程,它非常说明为什么存在这个问题:https : //trac.macports.org/ticket/57821

  • 在 macOS 10.14 上编译 PHP 7.3.9 时,我还必须编辑 Makefile 行 `INCLUDES =` 添加 `-I/path/to/libiconv-build-directory/include` 作为第二个元素。然后我就可以成功编译PHP了。 (2认同)

Art*_*kiy 16

我在尝试安装时遇到了同样的问题cargo-tree

cargo install cargo-tree
<...>
= note: Undefined symbols for architecture x86_64:
        "_iconv", referenced from:
            _git_path_iconv in liblibgit2_sys-966b1b327b8681d4.rlib(path.o)
           (maybe you meant: _git_path_iconv_clear, _git_path_iconv_init_precompose , _git_path_iconv )
        "_iconv_open", referenced from:
            _git_path_direach in liblibgit2_sys-966b1b327b8681d4.rlib(path.o)
<...>
Run Code Online (Sandbox Code Playgroud)

我的解决方案是libiconv禁用MacPorts

sudo port deactivate libiconv
Run Code Online (Sandbox Code Playgroud)

然后就安装成功了。

libiconv如果某些Macports应用程序无法运行,您可能需要重新激活:

sudo port activate libiconv
Run Code Online (Sandbox Code Playgroud)


cri*_*fan 8

同样的问题

\n

Xcode 编译在链接步骤失败:

\n
Showing All Messages\nLd /Users/crifan/Library/Developer/Xcode/DerivedData/Aweme-fswcidjoxbkibsdwekuzlsfcdqls/Build/Products/Debug-iphoneos/libAwemeDylib.dylib normal (in target \'AwemeDylib\' from project \'Aweme\')\n...\nUndefined symbols for architecture arm64:\n  "_iconv_open", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\n  "_iconvctl", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\n  "_iconv", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\n  "_iconv_close", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\nld: symbol(s) not found for architecture arm64\nclang: error: linker command failed with exit code 1 (use -v to see invocation)\n
Run Code Online (Sandbox Code Playgroud)\n

最终作品

\n
    \n
  • 使用Xcode添加引用的框架:libiconv

    \n
      \n
    • Xcode-> 选择正确的项目Targets-> Build Phases-> Link Binary With Libraries-> 单击+ -> 搜索libiconv-> 选择找到的libiconv.tbd

      \n
    • \n
    • 在此输入图像描述

      \n
    • \n
    • 在此输入图像描述

      \n
    • \n
    \n
  • \n
  • 一些内部细节

    \n
  • \n
\n

这里 Xcode 的iPhoneOS15.2SDK 包含相关的(上面搜索出的)libiconvlib:

\n
Showing All Messages\nLd /Users/crifan/Library/Developer/Xcode/DerivedData/Aweme-fswcidjoxbkibsdwekuzlsfcdqls/Build/Products/Debug-iphoneos/libAwemeDylib.dylib normal (in target \'AwemeDylib\' from project \'Aweme\')\n...\nUndefined symbols for architecture arm64:\n  "_iconv_open", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\n  "_iconvctl", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\n  "_iconv", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\n  "_iconv_close", referenced from:\n      +[CrifanLibiOS removeInvalidUtf8Nsdata:] in CrifanLibiOS.o\nld: symbol(s) not found for architecture arm64\nclang: error: linker command failed with exit code 1 (use -v to see invocation)\n
Run Code Online (Sandbox Code Playgroud)\n
\n
    \n
  • 没有10
      \n
    • 不应添加到错误的Xcode 项目的目标\n
        \n
      • 就像我之前一样:添加到错误的目标Aweme,导致仍然失败,然后在这里更改为正确的目标:AwemeDylib,然后工作。
      • \n
      \n
    • \n
    \n
  • \n
\n