17

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

Undefined symbols for architecture x86_64:
  "_iconv", referenced from:
  "_iconv_close", referenced from:
  "_iconv_open", referenced from:

或者我得到:

Undefined symbols for architecture x86_64:
"_libiconv", referenced from:
"_libiconv_open", referenced from:
"_libiconv_close", referenced from:

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

4

4 回答 4

26

我在 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

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

发生这种情况(至少)有 3 个原因:

  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") 并且即使您没有在任何地方安装 GNU libiconv 版本的 iconv lib,您也会收到错误找不到 "_libiconv" 符号。

该怎么办:

您的工作是获取您正在运行/编译的任何内容,以便在其他人之前找到正确版本的 iconv。你可以通过几种方式做到这一点。

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

我个人的偏好是只对有问题的项目包含这些类型的更改,这样它就不会在以后对不相关的项目产生级联影响。对我来说,这意味着编辑由“configure”创建的 Makefile,并将 iconv lib 目录直接包含在 Makefile 的 LDFLAGS 条目(或类似条目)中。当你传递“配置”一个“ --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 , <absolute path to lib file with no prior -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;博士:不要这样做。

为了使您的编译工作,您可能已经添加了指向 GNU iconv 库的 DYLD_LIBRARY_PATH 或 LD_LIBRARY_PATH(在 ~/.bash_profile 或类似文件中)的新路径,以“帮助”链接器查找内容。当与您现在正在做的事情完全无关的事情正在寻找 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

于 2019-08-31T00:47:54.480 回答
3

我在尝试安装时遇到了同样的问题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)
<...>

libiconv我的解决方案不是从MacPorts禁用:

sudo port deactivate libiconv

然后安装成功。

libiconv如果您的某些Macports应用程序无法正常工作,您可能需要重新激活:

sudo port activate libiconv
于 2019-11-03T18:32:15.823 回答
0

OS/161 学生:如果您在使用 Mac OS Lion 作为主机编译 gcc-4.8 时遇到此错误,

sudo port deactivate libiconv

为我修好了。

于 2021-03-27T06:21:58.073 回答
0

避免出现此问题的方法之一是制定规则,以确保您正在构建/安装的程序的所有包/库依赖项都是常驻的并且可以立即您的系统上找到。在 MacOS [可能还有其他基于 UNIX 的系统] 上,它们都应该在/usr/local, 或带有相关符号链接的目录中。

我在尝试从 MacOS 上的源文件构建和安装 PHP 时遇到了这个问题。

这是我的配置命令:

./configure --prefix=/usr/local/_utils/php/7.3.27 --enable-fpm --with-fpm-user=myusername --with-fpm-group=mygroupname --enable-bcmath --enable-cli --enable-exif --enable-ftp --enable-mbstring --enable-sockets --enable-zip --with-libzip=/usr/local/_utils/libzip --with-libxml-dir=/usr/local/_utils/libxml2 --with-mysqli --with-pdo-mysql=mysqlnd --with-iconv=/usr/local/_utils/iconv --with-iconv-dir=/usr/local/_utils/iconv --with-openssl=/usr/local/_utils/libressl --with-openssl-dir=/usr/local/_utils/libressl --with-zlib-dir=/usr/local/_utils/zlib --with-pcre-dir=/usr/local --with-pcre-regex=/usr/local --with-sodium=/usr/local/_utils/sodium

如果您注意到所有 [除了几个]--with-pkg=选项直接引用库/包,因为它们都已安装在自定义目录中,并创建了相关的符号链接。

拿一个像 libxml2 这样的包。以下是它的安装方法:

# Create install directory
sudo mkdir -p /usr/local/_utils/libxml2

# Download and install
wget -c ftp://xmlsoft.org/libxml2/libxml2-2.9.10.tar.gz
tar -zxf libxml2-2.9.10.tar.gz
cd libxml2-2.9.10
./configure --prefix=/usr/local/_utils/libxml2
make
sudo make install

# Create symlinks for bin
sudo ln -s /usr/local/_utils/libxml2/bin/xml2-config /usr/local/bin/
sudo ln -s /usr/local/_utils/libxml2/bin/xmlcatalog /usr/local/bin/
sudo ln -s /usr/local/_utils/libxml2/bin/xmllint /usr/local/bin/

# Create symlinks for lib
sudo ln -s /usr/local/_utils/libxml2/lib/libxml2.a /usr/local/lib/
sudo ln -s /usr/local/_utils/libxml2/lib/libxml2.la /usr/local/lib/
sudo ln -s /usr/local/_utils/libxml2/lib/libxml2.dylib /usr/local/lib/

# Create symlinks for lib/pkgconfig
sudo ln -s /usr/local/_utils/libxml2/lib/pkgconfig/libxml-2.0.pc /usr/local/lib/pkgconfig/

# Create symlinks for include
sudo ln -s /usr/local/_utils/libxml2/include/libxml2 /usr/local/include/

注意:您不必使用_utils; 您可以选择您认为合适的任何目录。此外,为了避免符号链接,您可以./configure --prefix=/usr/local直接使用并安装到/usr/local,但使用自定义目录更安全。

安装包/库后,您可以直接引用它,例如./configure --with-libxml-dir=/usr/local/_utils/libxml2. 此外,由于符号链接,如果您无意中排除了该选项,将很容易找到它。

为什么这是必要的?

我注意到的是,当我还没有安装这个包 [libxml2] 并且我没有指定--with-libxml-dir时,发生了以下情况:

  1. configure操作进行了搜索以找到libxml,因为libxml是必需的。
  2. libxml在一个位置找到:/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/lib
  3. 然后它将此目录添加到特定变量下的 Makefile,特别是EXTRA_LDFLAGSEXTRA_LDFLAGS_PROGRAM. 然后,我最终得到了一个 Makefile,其相关部分如下所示:
...
EXTRA_LDFLAGS = -L/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/lib -L/usr/local/_utils/libxml2/lib -L/usr/local/_utils/zlib/lib -L/usr/local/_utils/xz/lib -L/usr/local/_utils/libressl/lib -L/usr/local/lib -L/usr/local/_utils/iconv/lib -L/usr/local/_utils/sodium/lib -L/usr/local/_utils/libzip/lib
EXTRA_LDFLAGS_PROGRAM = -L/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/lib -L/usr/local/_utils/libxml2/lib -L/usr/local/_utils/zlib/lib -L/usr/local/_utils/xz/lib -L/usr/local/_utils/libressl/lib -L/usr/local/lib -L/usr/local/_utils/iconv/lib -L/usr/local/_utils/sodium/lib -L/usr/local/_utils/libzip/lib
...
  1. make然后,当您运行命令时,将在构建包的过程中搜索上面列出的目录以查找库。

问题是在这些目录中搜索了所有库。所以,在我的例子中,你可以看到我已经iconv在 Makefile: 中有一个链接-L/usr/local/_utils/iconv/lib,但是/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/lib首先被搜索[因为它首先出现],并且在其中发现了一个不合适的版本iconv,然后使用它而不是iconvI指定的。结果是错误。

Undefined symbols for architecture x86_64:
"_libiconv", referenced from:
"_libiconv_open", referenced from:
"_libiconv_close", referenced from:

这很有趣,因为这个问题甚至不iconv相关;正是缺少libxml它导致了搜索并随后将搜索到的目录包含/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/lib到 Makefile 中。

John Q 的回答中,他建议将此引用移至列表末尾。这应该有效。但是,我会考虑编辑 Makefile 不好的做法并建议不要这样做。

要解决此问题:

  1. 确保在配置期间可以找到您正在构建/安装的实际程序的所有必需的库/包依赖项,即./configure .... 当您执行此操作时,像上面列出的 [/Library/...等] 搜索的目录将不会包含在 Makefile 中。
  2. 运行后检查 Makefile configure。如果在/usr/local带有 suffix 的任何变量下除了带有前缀的目录之外还有其他目录LDFLAGS,那么您必须缺少一些库/包。找出它是什么并安装它。
于 2021-04-21T09:35:52.867 回答