本文介绍如何为 Raspberry Pi 4 构建运行 Catapult 节点(Symbol)的 DockerImage。

相关文章:

*对于那些阅读本文作为必备知识并理解其含义的人。

提前准备

克隆符号存储库

git clone https://github.com/symbol/symbol.git
cd symbol
git checkout -b 1.0.3.4  refs/client/catapult/v1.0.3.4

创建要在创建中间映像时使用的配置

vi jenkins/catapult/configurations/gcc-12-aarch64.yaml

compiler: ../compilers/gcc-latest.yaml
architecture: armv8-a

步骤1

创建 Dcoekr 镜像作为构建基础

vi jenkins/catapult/compilers/ubuntu-gcc/Dockerfile-ubuntu-gcc-12

FROM arm64v8/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update >/dev/null && 
    apt-get install -y 
    apt-utils 
    build-essential 
    gnupg2 
    curl 
    xz-utils 
    wget 
    >/dev/null 
	
# Use the latest gcc version.
ARG COMPILER_VERSION=12
RUN apt-get update >/dev/null && 
    apt-get install -y 
    gcc-${COMPILER_VERSION} g++-${COMPILER_VERSION} >/dev/null && 
    update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${COMPILER_VERSION} 100 && 
    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${COMPILER_VERSION} 100 && 
    update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 100 && 
    update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 100 && 
    update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-${COMPILER_VERSION} 100 && 
    update-alternatives --install /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-${COMPILER_VERSION} 100 && 
    update-alternatives --install /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-${COMPILER_VERSION} 100 && 
    rm -rf /var/lib/apt/lists/*

创建 Docker 映像

docker build -f jenkins/catapult/compilers/ubuntu-gcc/Dockerfile-ubuntu-gcc-12 -t ishidad2/symbol-server-compiler:ubuntu-gcc-12 .

第2步

每个文件都更正了,但是由于ver1.0.3.4中的添加,需要更正的行数发生了变化。因此,请找到适当的措辞进行更正,然后进行更正。

修复 runDockerBuild.py

第 3 步

修改环境.py

第4步

创建包含 cmake 和各种系统包的第一个中间映像

python3 ./jenkins/catapult/baseImageDockerfileGenerator.py 
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml 
    --operating-system ubuntu 
    --versions ./jenkins/catapult/versions.properties 
    --layer os

输出结果:

FROM symbolplatform/symbol-server-compiler:ubuntu-gcc-10
ARG DEBIAN_FRONTEND=noninteractive
MAINTAINER Catapult Development Team
RUN apt-get -y update 
    && apt-get install -y autoconf ca-certificates ccache curl gdb git libatomic-ops-dev libgflags-dev libsnappy-dev libtool libunwind-dev make ninja-build pkg-config python3 python3-ply xz-utils 
    && rm -rf /var/lib/apt/lists/* 
    && curl -o cmake-3.20.1-Linux-x86_64.sh -SL "https://github.com/Kitware/CMake/releases/download/v3.20.1/cmake-3.20.1-Linux-x86_64.sh" 
    && chmod +x cmake-3.20.1-Linux-x86_64.sh 
    && ./cmake-3.20.1-Linux-x86_64.sh --skip-license --prefix=/usr 
    && rm -rf cmake-3.20.1-Linux-x86_64.sh

更改 FROM 和 cmake 版本等并保存为 Dockerfile-preimage1

FROM ishidad2/symbol-server-compiler:ubuntu-gcc-12
ARG DEBIAN_FRONTEND=noninteractive
MAINTAINER Catapult Development Team
RUN apt-get -y update 
    && apt-get install -y autoconf ca-certificates ccache curl gdb git libatomic-ops-dev libgflags-dev libsnappy-dev libtool libunwind-dev make ninja-build pkg-config python3 python3-ply xz-utils 
    && rm -rf /var/lib/apt/lists/* 
    && curl -o cmake-3.23.2-linux-aarch64.sh -SL "https://github.com/Kitware/CMake/releases/download/v3.23.2/cmake-3.23.2-linux-aarch64.sh" 
    && chmod +x cmake-3.23.2-linux-aarch64.sh 
    && ./cmake-3.23.2-linux-aarch64.sh --skip-license --prefix=/usr 
    && rm -rf cmake-3.23.2-linux-aarch64.sh

执行以下命令

docker build -f Dockerfile-preimage1 -t ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage1 .

第 5 步

创建包含 boost build 的第二个中间映像

python3 ./jenkins/catapult/baseImageDockerfileGenerator.py 
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml 
    --operating-system ubuntu 
    --versions ./jenkins/catapult/versions.properties 
    --layer boost

输出结果:

FROM symbolplatform/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage1
RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.14/gosu-$(dpkg --print-architecture)" 
    && chmod +x /usr/local/bin/gosu
RUN curl -o boost_1_80_0.tar.gz -SL https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_1_80_0.tar.gz 
    && tar -xzf boost_1_80_0.tar.gz 
    && mkdir /mybuild 
    && cd boost_1_80_0 
    && ./bootstrap.sh  --prefix=/mybuild 
    && ./b2 address-model=64 runtime-link=shared threading=multi link=shared --layout=system variant=release cxxflags='-march=armv8-a' --prefix=/mybuild --without-context --without-contract --without-coroutine --without-fiber --without-graph --without-graph_parallel --without-headers --without-iostreams --without-json --without-mpi --without-nowide --without-python --without-serialization --without-stacktrace --without-test --without-timer --without-type_erasure --without-wave -j 8 stage release 
    && ./b2 address-model=64 runtime-link=shared threading=multi link=shared --layout=system variant=release cxxflags='-march=armv8-a' --without-context --without-contract --without-coroutine --without-fiber --without-graph --without-graph_parallel --without-headers --without-iostreams --without-json --without-mpi --without-nowide --without-python --without-serialization --without-stacktrace --without-test --without-timer --without-type_erasure --without-wave install

更改 FROM 并保存为 Dockerfile-preimage2

FROM ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage1
RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.14/gosu-$(dpkg --print-architecture)" 
    && chmod +x /usr/local/bin/gosu
RUN curl -o boost_1_80_0.tar.gz -SL https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_1_80_0.tar.gz 
    && tar -xzf boost_1_80_0.tar.gz 
    && mkdir /mybuild 
    && cd boost_1_80_0 
    && ./bootstrap.sh  --prefix=/mybuild 
    && ./b2 address-model=64 runtime-link=shared threading=multi link=shared --layout=system variant=release cxxflags='-march=armv8-a' --prefix=/mybuild --without-context --without-contract --without-coroutine --without-fiber --without-graph --without-graph_parallel --without-headers --without-iostreams --without-json --without-mpi --without-nowide --without-python --without-serialization --without-stacktrace --without-test --without-timer --without-type_erasure --without-wave -j 8 stage release 
    && ./b2 address-model=64 runtime-link=shared threading=multi link=shared --layout=system variant=release cxxflags='-march=armv8-a' --without-context --without-contract --without-coroutine --without-fiber --without-graph --without-graph_parallel --without-headers --without-iostreams --without-json --without-mpi --without-nowide --without-python --without-serialization --without-stacktrace --without-test --without-timer --without-type_erasure --without-wave install

执行以下命令

docker build -f Dockerfile-preimage2 -t ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage2 .

第 6 步

创建包含所有其他相关工具(mongo + mongo-cxx、libzmq + cppzmq、rocksdb)的第三个中间映像

python3 ./jenkins/catapult/baseImageDockerfileGenerator.py 
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml 
    --operating-system ubuntu 
    --versions ./jenkins/catapult/versions.properties 
    --layer deps

输出结果:

FROM symbolplatform/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage2
RUN git clone https://github.com/openssl/openssl.git -b OpenSSL_1_1_1q 
    && cd openssl 
    && CFLAGS='-march=armv8-a' perl ./Configure linux-x86_64  --prefix=/usr/local --openssldir=/usr/local 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf openssl
RUN git clone https://github.com/mongodb/mongo-c-driver.git -b 1.22.0 
    && cd mongo-c-driver 
    && mkdir _build 
    && cd _build 
    && cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGODB_AWS_AUTH=OFF -DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_SASL=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf mongo-c-driver 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/mongodb/mongo-cxx-driver.git -b r3.6.7 
    && cd mongo-cxx-driver 
    && mkdir _build 
    && cd _build 
    && cmake -DCMAKE_CXX_STANDARD=17 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf mongo-cxx-driver 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/zeromq/libzmq.git -b v4.3.4 
    && cd libzmq 
    && mkdir _build 
    && cd _build 
    && cmake -DWITH_TLS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf libzmq 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/zeromq/cppzmq.git -b v4.8.1 
    && cd cppzmq 
    && mkdir _build 
    && cd _build 
    && cmake -DCPPZMQ_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf cppzmq 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/facebook/rocksdb.git -b v7.4.3 
    && cd rocksdb 
    && mkdir _build 
    && cd _build 
    && cmake -DPORTABLE=1 -DWITH_TESTS=OFF -DWITH_TOOLS=OFF -DWITH_BENCHMARK_TOOLS=OFF -DWITH_CORE_TOOLS=OFF -DWITH_GFLAGS=OFF -DUSE_RTTI=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-Wno-error=maybe-uninitialized -march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf rocksdb 
    && echo "force rebuild revision 1"

更改 FROM 和 openssl 配置为 aarch64 并保存为 Dockerfile-preimage3

FROM ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage2
RUN git clone https://github.com/openssl/openssl.git -b OpenSSL_1_1_1q 
    && cd openssl 
    && CFLAGS='-march=armv8-a' perl ./Configure linux-aarch64  --prefix=/usr/local --openssldir=/usr/local 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf openssl
RUN git clone https://github.com/mongodb/mongo-c-driver.git -b 1.22.0 
    && cd mongo-c-driver 
    && mkdir _build 
    && cd _build 
    && cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGODB_AWS_AUTH=OFF -DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_SASL=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf mongo-c-driver 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/mongodb/mongo-cxx-driver.git -b r3.6.7 
    && cd mongo-cxx-driver 
    && mkdir _build 
    && cd _build 
    && cmake -DCMAKE_CXX_STANDARD=17 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf mongo-cxx-driver 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/zeromq/libzmq.git -b v4.3.4 
    && cd libzmq 
    && mkdir _build 
    && cd _build 
    && cmake -DWITH_TLS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf libzmq 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/zeromq/cppzmq.git -b v4.8.1 
    && cd cppzmq 
    && mkdir _build 
    && cd _build 
    && cmake -DCPPZMQ_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf cppzmq 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/facebook/rocksdb.git -b v7.4.3 
    && cd rocksdb 
    && mkdir _build 
    && cd _build 
    && cmake -DPORTABLE=1 -DWITH_TESTS=OFF -DWITH_TOOLS=OFF -DWITH_BENCHMARK_TOOLS=OFF -DWITH_CORE_TOOLS=OFF -DWITH_GFLAGS=OFF -DUSE_RTTI=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-Wno-error=maybe-uninitialized -march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf rocksdb 
    && echo "force rebuild revision 1"

执行以下命令

docker build -f Dockerfile-preimage3 -t ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage3 . --memory-swap -1

第 7 步

最终层创建

python3 ./jenkins/catapult/baseImageDockerfileGenerator.py 
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml 
    --operating-system ubuntu 
    --versions ./jenkins/catapult/versions.properties 
    --layer test

输出结果:

FROM symbolplatform/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage3
RUN git clone https://github.com/google/googletest.git -b release-1.12.1 
    && cd googletest 
    && mkdir _build 
    && cd _build 
    && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_GMOCK=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf googletest 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/google/benchmark.git -b v1.7.0 
    && cd benchmark 
    && mkdir _build 
    && cd _build 
    && cmake -DBENCHMARK_ENABLE_GTEST_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf benchmark 
    && echo "force rebuild revision 1"
RUN apt-get -y update 
    && apt-get remove -y --purge pylint 
    && apt-get install -y python3-pip lcov libssl-dev 
    && python3 -m pip install -U pycodestyle pylint pyyaml
RUN git clone https://github.com/openssl/openssl.git -b OpenSSL_1_1_1q 
    && cd openssl 
    && CFLAGS='-march=armv8-a' perl ./Configure linux-x86_64  --prefix=/usr/local --openssldir=/usr/local 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf openssl
RUN echo "docker image build $BUILD_NUMBER"
CMD ["/bin/bash"]

更改 FROM 和 openssl 配置为 aarch64 并保存为 Dockerfile-preimage4

FROM ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage3
RUN git clone https://github.com/google/googletest.git -b release-1.12.1 
    && cd googletest 
    && mkdir _build 
    && cd _build 
    && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_GMOCK=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf googletest 
    && echo "force rebuild revision 1"
RUN git clone https://github.com/google/benchmark.git -b v1.7.0 
    && cd benchmark 
    && mkdir _build 
    && cd _build 
    && cmake -DBENCHMARK_ENABLE_GTEST_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_FLAGS='-march=armv8-a' .. 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf benchmark 
    && echo "force rebuild revision 1"
RUN apt-get -y update 
    && apt-get remove -y --purge pylint 
    && apt-get install -y python3-pip lcov libssl-dev 
    && python3 -m pip install -U pycodestyle pylint pyyaml
RUN git clone https://github.com/openssl/openssl.git -b OpenSSL_1_1_1q 
    && cd openssl 
    && CFLAGS='-march=armv8-a' perl ./Configure linux-aarch64  --prefix=/usr/local --openssldir=/usr/local 
    && make -j 8 
    && make install 
    && cd .. 
    && rm -rf openssl
RUN echo "docker image build $BUILD_NUMBER"
CMD ["/bin/bash"]

执行以下命令以创建最终图像。

docker build -f Dockerfile-preimage4 -t ishidad2/symbol-server-build-base:ubuntu-gcc-12-armv8-a .

第 8 步

创建符号服务器测试基础图像

将以下内容另存为 Docker-test-preimage

FROM arm64v8/ubuntu:20.04

CMD ["/bin/bash"]
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get -y update 
    && apt-get install -y bison gdb git flex python3 python3-ply python3-pip shellcheck inotify-tools libdw-dev libelf-dev libiberty-dev libslang2-dev 
    && rm -rf /var/lib/apt/lists/* 
    && pip3 install -U colorama cryptography gitpython pycodestyle pylint pylint-quotes PyYAML 
    && git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux.git 
    && cd linux.git/tools/perf 
    && make 
    && cp perf /usr/bin 
    && cd ../../.. 
    && rm -rf linux.git

docker build -f Docker-test-preimage -t ishidad2/symbol-server-test-base:ubuntu .

完成此操作后,您就可以编译客户端了。

第 9 步

编译客户端

使用目前创建的 Docker 镜像执行以下命令进行编译

python3 jenkins/catapult/runDockerBuild.py 
--compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml 
--build-configuration jenkins/catapult/configurations/release-private.yaml 
--operating-system ubuntu 
--user "$(id -u):$(id -g)" 
--source-path client 
--destination-image-label gcc-10-armv8-a-main-9273d6c5

关于错误

权限错误

PermissionError: [Errno 13] Permission denied: 'binaries’

如果出现权限错误,请检查输出文件夹的权限。

sudo chown -R ubuntu:ubuntu output

构建 DockerImage 的 rest(v2.4.2)

从 git 签出 rest v2.4.2 的标签

git checkout -b rest/v2.4.2 refs/tags/rest/v2.4.2

移动到 rest 文件夹并创建 Docker-rest-preimage

rest 包含的 Dockerfile 指定 node:lts 和最新版本,但是截至 2022-10-31,如果插入 nodejs 的 tls 版本,会包含 v18 并且执行 rest 时会出错,所以显式指定 16

FROM node:16

WORKDIR /app
COPY . .
RUN npm uninstall . && rm -rf node_modules && npm install
RUN node --version && npm --version
EXPOSE 3000

使用以下命令创建一个 REST 映像

docker build -f Dockerfile -t ishidad2/symbol-rest:2.4.2 .

如果一切顺利,它应该看起来像这样:

(虽然构建过程并不顺利,垃圾仍然存在)

Catapultノード ラズパイ用DockerImageビルド(v1.0.3.4)

*ishidad2/symbol-server:gcc-1.0.3.4 只是更改 isidad2/symbol-server:gcc-10-armv8-a-main-9273d6c5 的图像标签

这是创建弹射器服务器 v1.0.3.4 和休息 v2.4.2 的 Docker 映像的方法。

如何使用用 Raspberry Pi 创建的图像

创建 mypreset.yml

例子)

nodes:
    -
        host: #自身のホスト名
        friendlyName: #好きな名前を適当に

symbolServerImage: ishidad2/symbol-server:gcc-1.0.3.4  #先程作成したイメージ名
symbolRestImage: ishidad2/symbol-rest:2.4.2            #先程作成したイメージ名

如果在symbolServerImagesymbolRestImage中输入之前创建的镜像名称并执行symbol-bootstrap就可以了。

参考:

如何在 Docker 中更改图像名称和标签名称

https://sleepless-se.net/2019/04/14/change-docker-image-and-tag-name/

码头工人形象

ishidad2/符号服务器:gcc-1.0.3.4

ishidad2/符号休息:2.4.2


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308632303.html

相关文章:

  • 2021-11-14
  • 2021-11-15
  • 2021-07-29
  • 2021-06-13
  • 2022-12-23
  • 2021-04-28
  • 2021-12-17
  • 2021-11-16
猜你喜欢
  • 2022-01-04
  • 2022-12-23
  • 2021-12-04
  • 2022-12-23
  • 2021-04-13
  • 2021-07-09
  • 2021-11-08
相关资源
相似解决方案