文章目录

ubuntu20.04默认9.4.0,openEuler默认7.3.0
问:我在ubuntu20.04上编译的程序,拷贝到openEuler20.03上无法运行,但是在openEuler20.03上编译的程序拷贝到ubuntu20.04上可以运行,是什么原因?
这是我在ubuntu20.04上的gcc和g++:
root@ky:~# gcc --version
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
root@ky:~# g++ --version
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
root@ky:~#
这是我在openEuler20.03上的:
[root@localhost Python-3.8.10]# gcc --version
gcc (GCC) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[root@localhost Python-3.8.10]# g++ --version
g++ (GCC) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我在ubuntu20.04上编译的程序,拷贝到openEuler20.03上无法运行,但是在openEuler20.03上编译的程序拷贝到ubuntu20.04上可以运行,是什么原因?
答
当你在 Ubuntu 20.04 上编译的程序在 openEuler 20.03 上无法运行,而反之则可以运行,这主要可能是由于以下几个原因:
-
不同的 GCC 版本:你在 Ubuntu 20.04 上使用的 GCC 版本是 9.4.0,而在 openEuler 20.03 上使用的是 7.3.0。较新的 GCC 版本可能在编译时使用了较新的优化技术和特性,这些可能不兼容于较老版本的 GCC 编译的系统环境。
-
不同的 C++ 标准库 ABI(Application Binary Interface):GCC 5.1 及之后的版本改变了 C++ 标准库的 ABI。如果你在 Ubuntu 20.04 上使用的是 GCC 9.4.0 编译,它默认使用新的 ABI。而 openEuler 20.03 使用的 GCC 7.3.0 可能默认使用的是老的 ABI,从而导致 ABI 不兼容。
-
系统库和依赖的不同:Ubuntu 和 openEuler 可能使用了不同版本的系统库,如 glibc(GNU C Library)。程序在运行时会依赖这些库,如果库的版本不兼容或者缺失必要的函数,程序就无法运行。
-
动态链接库(Shared Libraries)的不同:如果你的程序依赖于特定版本的动态链接库,这些库在不同操作系统或操作系统版本间可能有差异,特别是库的路径和可用的库版本。
为了解决这些问题,你可以尝试以下方法:
-
静态链接:在编译程序时,使用静态链接的方式(通过
-static
标志),这样程序就会包含所有需要的库,不再依赖于系统的动态链接库。这样可以提高程序的可移植性,但可能会增大程序的大小。 -
目标系统编译:为了确保最大兼容性,你可以在目标操作系统(如 openEuler 20.03)上直接编译程序。这样可以确保程序适配该系统的库和环境。
-
降级 GCC 版本:在 Ubuntu 20.04 上使用与 openEuler 20.03 相同或相近的 GCC 版本编译程序,尽量减少由于编译器版本差异带来的问题。
通过上述方法,你应该能解决跨系统移植程序时遇到的兼容性问题。
问:我可以在ubuntu上安装另一个低版本的gcc吗,编译的时候选择低版本的gcc?但是我担心我代码不兼容,因为我的代码是在高版本gcc上开发的
答
在 Ubuntu 上安装多个版本的 GCC 并在编译时选择特定版本的 GCC 是完全可行的,这通常是为了确保代码的兼容性或者测试代码在不同编译器版本下的表现。以下是你可以采取的步骤:
1. 安装低版本的 GCC
你可以使用 Ubuntu 的包管理器 apt
来安装特定版本的 GCC。Ubuntu 仓库中通常包含多个版本的 GCC。首先,你可以查找可用的 GCC 版本:
apt-cache search gcc | grep gcc-
这将列出所有可用的 GCC 版本。例如,要安装 GCC 7,你可以使用:
sudo apt install gcc-7 g++-7
2. 在编译时选择 GCC 版本
安装完毕后,你可以在编译命令中指定编译器。例如,如果你想使用 GCC 7 编译,可以这样做:
gcc-7 -o myprogram myprogram.c
或者对于 C++ 程序:
g++-7 -o myprogram myprogram.cpp
3. 确保代码兼容性
如果你担心代码在不同版本的 GCC 下的兼容性,最好的办法是在两个版本中都进行测试。有些新版本的 GCC 引入的特性在旧版本中可能不可用,也可能有细微的行为差异。进行测试可以帮助你发现潜在的问题。
-
使用条件编译:在代码中可以使用预处理指令来处理不同版本的 GCC 可能存在的差异。
-
编译器警告:通过增加编译器警告选项(如
-Wall -Wextra
),可以帮助你发现潜在的问题。
4. 其他注意事项
-
链接时问题:确保你在链接时也使用相同版本的链接器。GCC 的不同版本可能会要求不同版本的二进制支持库。
-
自动化构建工具:如果你的项目较大,使用像 CMake 或者 Makefile 这样的自动化构建工具可以帮助你更灵活地管理不同的编译器和编译选项。
通过以上步骤,你可以在 Ubuntu 上灵活地使用多个版本的 GCC,以确保你的代码在不同环境下都能正确编译和运行。如果你遇到具体的兼容性问题或者编译错误,需要具体问题具体分析。
可以在昇腾ubuntu服务器上弄个openEuler的容器来编译
问:我想在ubuntu20.04系统上弄一个跟openEuler20.03默认环境相同的容器来编译我的c++程序,然后我要把这个程序拷贝到真实的openEuler20.03服务器上去运行,我至少需要同步哪些环境信息?
答
为了在 Ubuntu 20.04 系统上创建一个与 openEuler 20.03 默认环境相同的容器环境,并确保您的 C++ 程序能够在真实的 openEuler 20.03 服务器上顺利运行,您需要考虑以下几个关键环境同步点:
-
基础镜像:使用与 openEuler 20.03 相同或相兼容的容器基础镜像。您可以在 Docker Hub 或 openEuler 的官方资源中寻找 openEuler 的 Docker 镜像。
-
编译器版本:确保容器中的 C++ 编译器(如 g++)与 openEuler 20.03 服务器上的版本一致。版本不一致可能会导致编译后的程序在目标服务器上运行时出现兼容性问题。
-
依赖库和工具:确保所有程序依赖的库(如 STL、Boost、Qt 等)版本在容器和服务器上一致。此外,还应考虑程序可能依赖的任何第三方工具或库。
-
环境变量和配置:复制 openEuler 20.03 的环境变量设置到容器中。这包括路径设置、区域设置、网络配置等。
-
系统架构和平台:如果您的服务器和开发环境的硬件架构(如 x86_64、ARM 等)不同,这也需要注意。虽然大多数情况下您可能都在使用 x86_64,但最好确认一下。
-
链接选项和编译标志:确保编译选项和链接选项在两个环境中保持一致,以避免因优化级别或特定硬件指令集的差异导致的问题。
具体操作步骤:
-
查找 openEuler 容器镜像:访问 Docker Hub 或 openEuler 官方网站,找到 openEuler 20.03 的官方容器镜像。
-
创建 Dockerfile:
- 使用 openEuler 镜像作为基础镜像。
- 安装必要的编译工具和依赖库。
- 配置环境变量和其他必要的系统设置。
例如:
FROM openeuler/openeuler:20.03 RUN yum update -y && \ yum install -y gcc-c++ make libstdc++-devel # 设置环境变量 ENV LANG C.UTF-8
-
构建和使用 Docker 容器:
- 构建 Docker 镜像:
docker build -t my-openeuler-dev .
- 运行容器并挂载您的项目目录:
docker run -it --name my-dev -v $(pwd):/project my-openeuler-dev
- 构建 Docker 镜像:
-
编译和测试:在容器环境中编译您的 C++ 程序,并进行充分的测试以确保功能正常。
-
部署到服务器:将编译好的程序文件拷贝到 openEuler 20.03 服务器上,并再次测试以确保在服务器环境中运行无误。
通过以上步骤,您可以在 Ubuntu 20.04 上创建一个尽可能接近 openEuler 20.03 的开发环境,从而提高程序在真实服务器上的兼容性和稳定性。
问:帮我生成获取基础环境信息的命令
答
为了获取您的 Linux 系统(在本例中为 openEuler 20.03)的基础环境信息,您可以使用以下命令集合来收集不同类别的信息。这些命令涵盖了操作系统版本、内核版本、已安装的软件包、环境变量、系统架构等方面,可以在终端执行:
1. 操作系统和版本信息:
cat /etc/os-release
[root@localhost tmp]# cat /etc/os-release
NAME="openEuler"
VERSION="20.03 (LTS-SP4)"
ID="openEuler"
VERSION_ID="20.03"
PRETTY_NAME="openEuler 20.03 (LTS-SP4)"
ANSI_COLOR="0;31"
[root@localhost tmp]#
2. 内核版本:
uname -r
[root@localhost tmp]# uname -r
4.19.90-2312.1.0.0255.oe2003sp4.aarch64
[root@localhost tmp]#
3. 已安装的软件包列表(针对基于 RPM 的系统,如 openEuler):
rpm -qa
参考文章:密链:openEuler20.03已安装的软件包列表
4. 环境变量:
env
[root@localhost tmp]# env
SHELL=/bin/bash
HISTCONTROL=ignoredups
HISTSIZE=1000
HOSTNAME=localhost.localdomain
PWD=/userdata/tmp
LOGNAME=root
XDG_SESSION_TYPE=tty
MOTD_SHOWN=pam
HOME=/root
LANG=en_US.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
SSH_CONNECTION=192.168.1.155 5369 192.168.1.123 22
TOOLCHAIN_HOME=/usr/local/Ascend/ascend-toolkit/latest/toolkit
ASCEND_TOOLKIT_HOME=/usr/local/Ascend/ascend-toolkit/latest
XDG_SESSION_CLASS=user
SELINUX_ROLE_REQUESTED=
PYTHONPATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:/usr/local/Ascend/ascend-toolkit/latest/opp/built-in/op_impl/ai_core/tbe:
TERM=xterm
USER=root
SELINUX_USE_CURRENT_RANGE=
SHLVL=1
XDG_SESSION_ID=1
ASCEND_OPP_PATH=/usr/local/Ascend/ascend-toolkit/latest/opp
LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:/usr/local/Ascend/ascend-toolkit/latest/lib64/plugin/opskernel:/usr/local/Ascend/ascend-toolkit/latest/lib64/plugin/nnengine:/usr/local/Ascend/ascend-toolkit/latest/opp/built-in/op_impl/ai_core/tbe/op_tiling/lib/linux/aarch64:/usr/local/Ascend/driver/lib64:/usr/local/Ascend/driver/lib64/common:/usr/local/Ascend/driver/lib64/driver:
ASCEND_AICPU_PATH=/usr/local/Ascend/ascend-toolkit/latest
XDG_RUNTIME_DIR=/run/user/0
SSH_CLIENT=192.168.1.155 5369 22
PATH=/usr/local/Ascend/ascend-toolkit/latest/bin:/usr/local/Ascend/ascend-toolkit/latest/compiler/ccec_compiler/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
SELINUX_LEVEL_REQUESTED=
ASCEND_HOME_PATH=/usr/local/Ascend/ascend-toolkit/latest
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
MAIL=/var/spool/mail/root
SSH_TTY=/dev/pts/0
_=/usr/bin/env
OLDPWD=/userdata/tmp
[root@localhost tmp]#
5. 系统架构:
uname -m
[root@localhost tmp]# uname -m
aarch64
[root@localhost tmp]#
6. 编译器版本(例如,获取 GCC 版本):
gcc --version
[root@localhost tmp]# gcc --version
gcc (GCC) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[root@localhost tmp]#
7. C++ 标准库安装情况(可以通过检查特定库的安装情况来了解):
rpm -q libstdc++-devel
[root@localhost tmp]# rpm -q libstdc++-devel
libstdc++-devel-7.3.0-2020033101.58.oe2003sp4.aarch64
[root@localhost tmp]#
8. 系统使用的默认 shell:
echo $SHELL
[root@localhost tmp]#
[root@localhost tmp]# echo $SHELL
/bin/bash
[root@localhost tmp]#
您可以将这些命令集成到一个脚本中,以便在新环境中运行和比较输出,确保您的开发和生产环境尽可能一致。这将有助于识别可能需要手动配置或同步的环境差异。
欧拉容器编译环境构建
Dockerfile
里面的RUN安装的东西是从欧拉服务器openEuler20.03部署文档拷贝过来的。
# 使用 openEuler 20.03 LTS SP3 作为基础镜像
FROM openeuler/openeuler:20.03-lts-sp3
# FROM centos:7
# 设置工作目录
WORKDIR /userdata/testKYAI
# 安装编译工具
RUN dnf install -y gcc gcc-c++ make cmake unzip zlib-devel bzip2-devel libffi-devel openssl-devel pciutils net-tools sqlite-devel lapack-devel gcc-gfortran python3-devel
# 设置环境变量
ENV LANG C.UTF-8
# 设置一个默认命令或者行为,例如保持容器运行
CMD ["tail", "-f", "/dev/null"]
build_docker_image.sh
#!/bin/bash
# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u
# 设置变量
IMAGE_NAME="compiler_arm_openeuler20.03"
IMAGE_TAG="20.03-lts-sp3_20240429"
# 检查依赖
if ! [ -x "$(command -v docker)" ]; then
echo 'Error: Docker is not installed.' >&2
exit 1
fi
# 构建 Docker 镜像
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" .
# 查看 Docker 镜像
docker images
docker_tar.sh
#!/bin/bash
# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u
REPOSITORY="compiler_arm_openeuler20.03"
REP_TAG="20.03-lts-sp3_20240429"
DOCKER_TAR="${REPOSITORY}-${REP_TAG}.tar"
USER=root
################################################################################
WHO=$(whoami | grep "${USER}$")
if [ -z ${WHO} ]; then
echo
echo "Please change to \"${USER}\" user mode first!"
echo
exit 1
fi
echo "REPOSITORY: ${REPOSITORY}"
echo "REP_TAG: ${REP_TAG}"
echo "docker save -o ${DOCKER_TAR}..."
docker save -o ${DOCKER_TAR} ${REPOSITORY}:${REP_TAG}
chmod 777 $DOCKER_TAR
run容器
install.sh
#!/bin/bash
# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u
USER=root
# USER_HOME=/root
# --------------------------------------------------------------------------
REPOSITORY="compiler_arm_openeuler20.03"
REP_TAG="20.03-lts-sp3_20240429"
CONTAINER_NAME="compiler_arm_openeuler20.03"
DOCKER_TAR=${REPOSITORY}-${REP_TAG}.tar
# --------------------------------------------------------------------------
# Check user: only support root
WHO=$(whoami | grep "${USER}$")
if [ -z ${WHO} ]; then
echo
echo "Please change to \"${USER}\" user mode first!"
echo
exit 1
fi
# --------------------------------------------------------------------------
# Check diretory
DEPLOY_PATH=$(
cd "$(dirname $0)" || {
echo "cd Failure"
exit 1
}
pwd
)
chmod 777 ${DEPLOY_PATH} -R
# --------------------------------------------------------------------------
# REP_STR=$(docker images | awk '{print $1":"$2}' | grep "^${REPOSITORY}:${REP_TAG}$")
# if [ -z ${REP_STR} ]; then
if ! docker images | awk '{print $1":"$2}' | grep -q "^${REPOSITORY}:${REP_TAG}$"; then
# 判断镜像是否已导入
# 判断镜像tar包是否存在
DOCKER_TAR_PATH=${DEPLOY_PATH}/../${DOCKER_TAR}
if [ -e $DOCKER_TAR_PATH ]; then
echo "docker load ${DOCKER_TAR}..."
docker load -i $DOCKER_TAR_PATH
if [ $? -ne 0 ]; then
echo "docker load error!"
exit 1
fi
else
# arnold modified 20230624
echo "${DEPLOY_PATH}/${DOCKER_TAR} does not exist!"
exit 1
# echo "docker pull ${REPOSITORY}:${REP_TAG}..."
# docker pull ${REPOSITORY}:${REP_TAG}
# if [ $? -ne 0 ]; then
# echo "docker pull error!"
# exit 1
# fi
fi
else
echo "image already exist."
fi
# --------------------------------------------------------------------------
# arnold add 20230326
# 判断docker容器是否已存在,若存在,提示是否删除
# Check if container exists
# if [[ "$(docker ps -aqf name=$CONTAINER_NAME)" ]]; then
if [[ "$(docker ps -aqf "name=^$CONTAINER_NAME$")" ]]; then
echo "Container $CONTAINER_NAME already exists."
read -p "Do you want to delete it? (y/n)" answer
# Check user's response
case ${answer:0:1} in
y | Y)
# Stop and remove container
docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME
# Check command result
if [ $? -eq 0 ]; then
echo "Container $CONTAINER_NAME stopped and removed successfully."
else
echo "Failed to stop or remove container $CONTAINER_NAME."
exit 1
fi
;;
*)
# Exit script
exit 0
;;
esac
fi
# --------------------------------------------------------------------------
docker run -itd --ipc=host --restart=always \
-v /ky:/ky \
-v /userdata:/userdata \
-v /etc/localtime:/etc/localtime:ro \
--name $CONTAINER_NAME \
$REPOSITORY:$REP_TAG
if [ $? -ne 0 ]; then
echo "docker run error!"
exit 1
fi
echo "docker run successfully."
echo
echo "Container deploy successfully"
echo
echo "使用下面命令进入容器:"
echo
echo "docker exec -it $CONTAINER_NAME /bin/bash"
echo
尝试了,是可以编译成功的
通过这个命令进入容器:
docker exec -it $CONTAINER_NAME /bin/bash
在104华为昇腾服务器(ubuntu)上,执行:
docker exec -it compiler_arm_openeuler20.03_LTS_SP3 /bin/bash
进入到欧拉编译容器。
然后切换目录:
cd /userdata/testKYAI/kyai/
执行命令编译:
./build.sh
测试是可以编译成功,拷贝到openEuler20.03系统上也能能够成功运行的。