我正在尝试在 Ubuntu 上编译一个二进制文件,以便在 CentOS 7 上运行(均为 64 位,一台主机,另一台虚拟机)。
到目前为止,我已经复制了包含所有共享库的二进制文件。我不再收到缺少库的错误,而是收到一个很好的 ld SIGSEGV
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5d67681 in ?? ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64
(gdb) where
#0 0x00007ffff5d67681 in ?? ()
#1 0x00007fffffffe3f0 in ?? ()
#2 0x00007ffff7decdd4 in _dl_check_map_versions () from /lib64/ld-linux-x86-64.so.2
#3 0x00007ffff7de08a3 in dl_main () from /lib64/ld-linux-x86-64.so.2
#4 0x00007ffff7df2aee in _dl_sysdep_start () from /lib64/ld-linux-x86-64.so.2
#5 0x00007ffff7dde4a4 in _dl_start () from /lib64/ld-linux-x86-64.so.2
#6 0x00007ffff7dddb08 in _start () from /lib64/ld-linux-x86-64.so.2
#7 0x0000000000000001 in ?? ()
#8 0x00007fffffffe8bb in ?? ()
#9 0x0000000000000000 in ?? ()
我有源代码,但我几乎无法在 ubuntu 上编译和测试,因为它依赖于一些从源代码构建的库,在 centOS 上尝试过,但 g++ 版本较旧,不支持 c++11。安装 devtools 版本后,现在我收到其他错误,但我猜这是一个不同的问题。
那么我可以做些什么来克服这个错误吗?最终会这样运行吗?将某些东西从 Ubuntu 移植到 CentOS 最简单的方法是什么?
答案1
我建议不要这样做。通常,在发行版的包构建过程中为不同发行版构建二进制文件更容易。在 CentOS 上,这将利用rpmbuild
.
由于您正在处理 VM,因此设置 CentOS 7 VM + 构建工具然后在那里进行包构建会更加简单。
来自基于源的发行版的用户的观察
我通常不会跟风编辑其他人的答案,但我发现自己在这里慢慢但肯定地赢得了声誉,通过帮助人们认识到基于源的发行版之间的区别,其中有 3 个主要发行版:
以及基于二进制的发行版,其中有两个主要发行版:
截至目前,只有 1 个主要的混合发行版(源代码和二进制文件之间的交叉):
无论 Linux 用户是否喜欢,所有其他 Linux 发行版都是这 6 个父版本之一的子版本。话虽如此,我们继续讨论下一点:
不可能将基于源的发行版中的软件与二进制发行版中的软件混合在一起
知道这一点也意味着,除非您知道自己在做什么,否则不应在二进制发行版上从源代码编译单个包。此规则也有例外:
- 您需要的包不存在于您的发行版存储库/树/等中(这是OP提出问题的原因)。
- 你找不到一个存储库/树/等中所需包的较新版本 - 请参阅第 9 条。
为什么 OP 有问题
从技术上讲,对于最终的包来说,使用包和从源代码构建没有区别,即,如果您可以成功构建包并且它可以工作,那么没有人会因为这样做而责备您。但您必须记住,当您执行此操作时,用于在一个基于二进制的发行版上构建应用程序的工具比另一二进制发行版中可用的工具版本更高。 OP 看到的是新旧软件包之间的增量或变化。增量或更改是由每个操作系统的软件包和操作系统维护者引起的,无论是上述 6 个操作系统之一,还是子操作系统,选择他们将为其操作系统标记为稳定的软件包。一旦在二进制发行版中选择了一个包,大多数情况下它会被冻结直到下一个版本,除非严重错误被发现了。
另一方面,基于源的发行版可以选择在新源可用时立即更新项目,从而即时修复错误。
这就是OP出现问题的原因
Ubuntu的发布时间表和更新周期选择采用新版本构建工具链,在 CentOS 采用它们之前。由于 CentOS 建立在稳定性之上,因此构建工具链可能要等到下一个版本才会更新主要版本。因此OP遇到了一个问题与此类似,因为 Ubuntu 的构建工具链支持 C++11,而 CentOS 的构建工具链直到所有版本不匹配都修复后才支持,并且稍后会遇到使用多个包管理器的问题。
OP 应该做什么
- 确定了包所在系统可用的构建工具。在本例中,这就是 CentOS。这里有一个有关如何正确安装它们的页面。根据上一个链接中的列表,该编译器支持 C++11。作为一个非常有经验的预感,OP的版本不匹配发生在或者
binutils
Binutilslibtool
依赖于glibc,而libtool依赖于binutils,因此libtool
间接依赖于glibc
我不会解释为什么几乎任何系统上的每个包都间接依赖于glibc
只是知道它确实如此。 - 如果正确安装后的构建工具链不支持 C++11,OP 将被迫使用 C++98 来缓解他现在面临的问题。
- 在上面的步骤 1 中更新了构建工具链后,OP 现在应该在 CentOS VM 中编译其源代码,并根据需要进行修复/修复。如果OP需要一个包,他应该使用rpmbuild,正如这篇文章所建议的,因为这是包所在的VM的本机包管理器。 Yum 不是包管理器。 Yum 是一个依赖解析器
参考
答案2
OP解决方案及结论
根据之前的答案,这是我最终所做的解决方案。
1.复制源码
将源代码复制到虚拟机或其他计算机。我用过:
scp -R /host/path/to/src/ user@remoteHost:/remote/build/path/
这就像一场公路旅行,所以打包好,收集编译所需的所有源代码,减去共享库和您可以在另一台计算机上找到的其他资源。
2.安装依赖项(库/构建工具)
将虚拟机恢复为基本安装(centOS7 分钟),并根据试验和错误更新了用于构建我的应用程序的工具(yum 搜索、安装、尝试构建命令)
yum -y update
yum -y install boost-* #probably could have used only boost-devel
yum -y install glibc-utils
yum -y install gcc-c++
yum -y install git
yum -y install libtool
yum -y install zlib-devel
yum -y install ncurses-devel
yum -y install make
yum -y install cmake
yum -y install openssl-devel
yum -y install libssh2-devel
...
如果您的项目依赖于操作系统存储库中不可用的(较新)库,请从源安装:
例如,我需要使用 c-ares 构建的curl 以及更新的mysql 客户端库。
#mysqlclient
if [[ -z $(ldconfig -p | grep libmysqlclient) ]]
then
mkdir -p "${INSTALL_PREQ_PATH}/lib/mysql/";
cd "${INSTALL_PREQ_PATH}lib/mysql/"
wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
yum -y localinstall mysql-community-release-el7-5.noarch.rpm
sudo yum install mysql-community-client
sudo yum install mysql-community-devel
fi
#c-ares
if [[ -z $(ldconfig -p | grep libcares) ]]
then
mkdir -p "${INSTALL_PREQ_PATH}lib/libcares/"
cd "${INSTALL_PREQ_PATH}lib/libcares/"
git clone git://github.com/bagder/c-ares.git
cd c-ares
./buildconf
./configure
make
sudo make install
ldconfig
fi
#libcurl
if [[ -z $(ldconfig -p | grep libcares) ]]
then
mkdir -p "${INSTALL_PREQ_PATH}lib/libcurl/"
cd "${INSTALL_PREQ_PATH}lib/libcurl/"
wget http://curl.haxx.se/download/curl-7.39.0.tar.gz
tar -xvzf curl-7.39.0.tar.gz
cd curl-7.39.0
./configure --enable-ares --with-libidn --with-zlib --disable-ipv6
make
sudo make install
ldconfig
fi
观察: 每个构建都有它自己的依赖项,并添加到上面的步骤中。
3.安装了Foreach依赖项,验证它是否正常工作并检查是否破坏了任何东西
检查系统是否加载了库:
ldconfig # update library cache
ldconfig -p | grep libcurl # check for library
在我的例子中,库安装在 /usr/local/lib/ 文件夹中,默认情况下,该文件夹不包含在链接生成器搜索路径中。要解决此问题:
echo "/usr/local/lib/">/etc/ld.so.conf.d/local.conf #add lib search path
ldconfig #reload library cache
还要检查使用该共享库的其他程序是否仍在工作。在我的例子中,curl 安装破坏了 yum,因为它缺少 ssh 和 ssl,请修复:
rm /etc/ld.so.conf.d/local.conf #remove the new libs search path
ldconfig #reload
yum install openssl-devel #install ssl dependency
yum install libssh2-devel #install ssh dependency
cd "${INSTALL_PREQ_PATH}lib/libcurl/" #go to libcurl source path
./configure --enable-ares --with-libidn --with-zlib --disable-ipv6 --with-ssl --with-libssh2 # configure build with ssl and ssh
make #compile
sudo make install #install binary, libs and headers
echo "/usr/local/lib/">/etc/ld.so.conf.d/local.conf #add lib search path
ldconfig #reload library cache
4. 构建你的程序
就我而言,我使用了与 ubuntu 相同的编译器,gcc-c++ (g++)。如果它不起作用:
- 查看是否缺少任何依赖项,阅读警告和错误
- 检查两台机器上的编译器版本,检查对您的代码和编译器标志的支持是否存在差异,使用互联网寻找针对您的操作系统更新编译器的方法
其他注意事项:
- 写下您的步骤,最好是在 bash 脚本中,以便您可以在另一台计算机上重试或(重新)安装。
- 对于生产机器来说这不是一个好建议,请在其他地方进行试验。
- 如果您使用的是虚拟机,请拍摄快照,否则进行备份,并始终做好失败的准备
- 不要接受我的建议,这对我有用,它可能不适用于所有人,并且对于其他情况可能是一个糟糕的选择。我不是专家,只是写来帮助像我这样的菜鸟:)