• Mac m1 上编译阿里 OSS c++ 供 UE 使用


    环境:

    • 操作系统:macOS 12.5
    • 芯片:Apple M1
    • Xcode:13.4.1
    • UE:5.0.3

    环境准备

    编译 openssl

    起初,我是在 M1 通过 brew 安装的 openssl。通过安装命令 $ brew install openssl 最新版本的openssl。安装后的目录为

    • /opt/homebrew/opt/openssl
    • /opt/homebrew/opt/openssl/lib
    • /opt/homebrew/opt/openssl/include/

    发现不行,需要自己编译 x86_64 版本。

    https://www.openssl.org/source/ 下载 openssl-1.1.1g.tar.gz。解压后将文件夹修改为 openssl-1.1.1g-x86_64,在此文件夹下生成 x86_64 版本的 openssl。终端进入该目录,开始编译。

    export MACOSX_DEPLOYMENT_TARGET=10.15
    cd openssl-1.1.1g-x86_64
    ./Configure darwin64-x86_64-cc shared
    make
    
    • 1
    • 2
    • 3
    • 4

    成功的话,就可以在文件夹下看到生成的动态库和静态库文件:

    • libcrypto.1.1.dylib
    • libcrypto.a
    • libcrypto.dylib
    • libssl.1.1.dylib
    • libssl.a
    • libssl.dylib

    通过生成多个架构的 openssl,可以参考:How to build openssl for M1 and for Intel?

    安装 CMake

    CMake 是一个跨平台的编译工具,可以用简单的语句来描述所有平台的编译过程。到 CMake 的下载页面,下载并安装 CMake。

    在 Mac 中自带了 CMake,可以通过命令行的方式编译阿里 OSS sdk,也可以安装 CMake,生成 Xcode 项目编译阿里 OSS sdk。

    编译 c++ SDK

    首先查看阿里文档。根据提示,下载 c++ SDK 的安装包并解压:

    在这里插入图片描述
    打开终端,进入目录aliyun-oss-cpp-sdk-master。创建 build 文件夹,并进入。

    mkdir build
    cd build
    
    • 1
    • 2

    配置 cmake:

    cmake -DOPENSSL_ROOT_DIR=/Users/...../openssl-1.1.1g-x86_64  \
          -DOPENSSL_INCLUDE_DIRS=/Users/...../openssl-1.1.1g-x86_64/include/ \
          -DCMAKE_OSX_ARCHITECTURES=x86_64 ..
    
    • 1
    • 2
    • 3

    其中:

    • DOPENSSL_ROOT_DIR、DOPENSSL_LIBRARIES、DOPENSSL_INCLUDE_DIRS:指定 openssl 的目录,此处需要修改为上面自己编译的 openssl 的目录。
    • DCMAKE_OSX_ARCHITECTURES:指定 CPU 架构。因为 UE 编译时为 x86_64 架构,所以在 M1 上编译时需要指定。如果同时编译多个架构,可以设置为 arm64;x86_64

    经过测试 DOPENSSL_LIBRARIES 并不需要指定。

    打开 build/CMakeCache.txt的文件,找到下面的内容:

    //Minimum OS X version to target for deployment (at runtime); newer
    // APIs weak linked. Set to empty string for default value.
    CMAKE_OSX_DEPLOYMENT_TARGET:STRING=
    
    • 1
    • 2
    • 3

    设置 CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.15系统版本,因为 UE 的支持的最低版本为 10.15。如果不设置的话,在之后的使用当中,会报如下的错误:

    libalibabacloud-oss-cpp-sdk.a(OssClient.cc.o)) was built for newer macOS version (12.0) than being linked (10.15)

    这个值应该怎么通过命令进行设置呢?我暂时没有找到。

    设置之后,开始编译:

    make
    
    • 1

    结果报错了

    /Users/fuyoufang/Desktop/UE_OSS/aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc:440:25: error: loop variable 'rule' creates a copy from type 'const AlibabaCloud::OSS::LifecycleRule' [-Werror,-Wrange-loop-construct]
            for (auto const rule : outcome.result().LifecycleRules()) {
                            ^
    /Users/fuyoufang/Desktop/UE_OSS/aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc:440:14: note: use reference type 'const AlibabaCloud::OSS::LifecycleRule &' to prevent copying
            for (auto const rule : outcome.result().LifecycleRules()) {
                 ^~~~~~~~~~~~~~~~~
                            &
    /Users/fuyoufang/Desktop/UE_OSS/aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc:473:29: error: loop variable 'origin' creates a copy from type 'const std::string' [-Werror,-Wrange-loop-construct]
                for (auto const origin : rule.AllowedOrigins()) {
                                ^
    /Users/fuyoufang/Desktop/UE_OSS/aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc:473:18: note: use reference type 'const std::string &' to prevent copying
                for (auto const origin : rule.AllowedOrigins()) {
                     ^~~~~~~~~~~~~~~~~~~
                                &
    /Users/fuyoufang/Desktop/UE_OSS/aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc:471:25: error: loop variable 'rule' creates a copy from type 'const AlibabaCloud::OSS::CORSRule' [-Werror,-Wrange-loop-construct]
            for (auto const rule : outcome.result().CORSRules()) {
                            ^
    /Users/fuyoufang/Desktop/UE_OSS/aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc:471:14: note: use reference type 'const AlibabaCloud::OSS::CORSRule &' to prevent copying
            for (auto const rule : outcome.result().CORSRules()) {
                 ^~~~~~~~~~~~~~~~~
                            &
    3 errors generated.
    make[2]: *** [sample/CMakeFiles/cpp-sdk-sample.dir/src/bucket/BucketSample.cc.o] Error 1
    make[1]: *** [sample/CMakeFiles/cpp-sdk-sample.dir/all] Error 2
    make: *** [all] Error 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pRBeuHl4-1660811366632)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/38d977e6b42f4b368cba368281b26644~tplv-k3u1fbpfcp-zoom-1.image)]

    应该是编辑条件比较严格,for (auto const rule : outcome.result().LifecycleRules()) { },会进行拷贝操作,应该使用引用。打开 aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc 文件,在 440,471,473 行,修一下报错的地方,修改为引用使用,即在变量前加 &。重新编译。

    make
    
    • 1

    此时,应该编译成功,就可以看到编译好的 build/lib/libalibabacloud-oss-cpp-sdk.a 文件了。

    在这里插入图片描述

    UE 中使用

    创建一个 C++ 类型的 UE 项目 TestAliOSS,来测试编译好的库文件。

    创建插件

    给 UE 项目 TestAliOSS,创建一个插件 AliOSS,用于封装阿里 OSS sdk。

    在这里插入图片描述

    此处创建一个空白的插件,命名为 AliOSS

    在这里插入图片描述

    AliOSS 的源码路径 Source 下,新建文件 OSSThirdParty文件,然后做以下操作:

    1. 复制编译好的 libalibabacloud-oss-cpp-sdk.a 文件到 OSSThirdParty/Lib 文件下;
    2. 复制阿里 SDK 源文件中的 aliyun-oss-cpp-sdk-master/sdk/include 到 OSSThirdParty/include 文件下,即阿里 OSS 相关的头文件
    3. 复制阿里 SDK 源文件中的 aliyun-oss-cpp-sdk-master/third_party/include/curl 到 OSSThirdParty/include/ 文件下,即 curl 相关的头文件( 我发现复制过来的 openssl 头文件不行)
    4. 复制 openssl-1.1.1g-x86_64/include/openssl 到 OSSThirdParty/include 文件下,即 openssl 相关的头文件;
    5. 复制 openssl-1.1.1g-x86_64 下的 libcrypto.a 和 libssl.a 文件到 ~~OSSThirdParty/lib/Mac_x86_64~~ 文件下,即 openssl 的库文件;(发现这一步可以省掉,应该使用 UE 的库文件)
    6. 将 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/lib/libcurl.tbd 拷贝一份,放到 OSSThirdParty/lib/Mac_x86_64 文件夹下

    第 6 步中的 libcurl.tbd 文件是什么?

    libcurl 是 mac 的一个库文件。我是在阿里源码中,通过 Cmake 生成的项目文件中,看到需要 link 这样一个文件。拷贝这个文件到插件当中,感觉有点奇怪,但是暂时没办通过其他方式不依赖这个文件。

    在这里插入图片描述

    现在目录结构为

    • Plugins/AliOSS/Source
      • AliOSS
      • OSSThirdParty
      • include
        • alibabacloud/oss/…
        • curl
        • openssl
      • lib
        • libalibabacloud-oss-cpp-sdk.a
        • Mac_x86_64/libcurl.4.tbd

    修改 AliOSS.Build.cs文件为下面的内容:

    // Copyright Epic Games, Inc. All Rights Reserved.
    using System;
    using System.IO;
    using UnrealBuildTool;
    
    public class AliOSS : ModuleRules
    {
        private string OSSThirdPartyPath
        {
            get
            {
                // ModuleDirectory 为插件的 项目路径/Plugins/SimpleOSS/Source/SimpleOSS/ 目录
                return Path.GetFullPath(Path.Combine(ModuleDirectory, "../OSSThirdParty/"));
            }
        }
    
        public AliOSS(ReadOnlyTargetRules Target) : base(Target)
        {
            PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
            PublicIncludePaths.AddRange(
            new string[] {
                    // ... add public include paths required here ...
                }
            );
    
            PrivateIncludePaths.AddRange(
                new string[] {
                    // ... add other private include paths required here ...
                }
            );
    
            PublicDependencyModuleNames.AddRange(
                new string[]
                {
                    "Core",
                    // ... add other public dependencies that you statically link with here ...
                }
            );
    
            PrivateDependencyModuleNames.AddRange(
                new string[]
                {
                    "CoreUObject",
                    "Engine",
                    "Slate",
                    "SlateCore",
                    // ... add private dependencies that you statically link with here ...
                }
            );
    
            DynamicallyLoadedModuleNames.AddRange(
                new string[]
                {
                    // ... add any modules that your module loads dynamically here ...
                }
            );
    
            string OssincludePath = Path.Combine(OSSThirdPartyPath, "include");
    
            PublicIncludePaths.Add(OssincludePath);
            string AlibabacloudPath = Path.Combine(OssincludePath, "alibabacloud/oss");
            PublicIncludePaths.Add(AlibabacloudPath);
    
            PublicIncludePaths.Add(Path.Combine(AlibabacloudPath, "auth"));
            PublicIncludePaths.Add(Path.Combine(AlibabacloudPath, "client"));
            PublicIncludePaths.Add(Path.Combine(AlibabacloudPath, "encryption"));
            PublicIncludePaths.Add(Path.Combine(AlibabacloudPath, "http"));
            PublicIncludePaths.Add(Path.Combine(AlibabacloudPath, "model"));
            PublicIncludePaths.Add(Path.Combine(AlibabacloudPath, "utils"));
    
            // PublicIncludePaths.Add(Path.Combine(OssincludePath, "curl"));
            PublicIncludePaths.Add(Path.Combine(OssincludePath, "openssl"));
    
            string LibPath = Path.Combine(OSSThirdPartyPath, "lib");
            PublicIncludePaths.Add(LibPath);
            PublicAdditionalLibraries.Add(Path.Combine(LibPath, "libalibabacloud-oss-cpp-sdk.a"));
    
            // 被注释掉的两个,可以使用下面的替换
            //PublicAdditionalLibraries.Add(Path.Combine(LibPath, "Mac_x86_64", "libcrypto.a"));
            //PublicAdditionalLibraries.Add(Path.Combine(LibPath, "Mac_x86_64", "libssl.a"));
            AddEngineThirdPartyPrivateStaticDependencies(Target, "libcurl");
            AddEngineThirdPartyPrivateStaticDependencies(Target, "OpenSSL");
            
            PublicAdditionalLibraries.Add(Path.Combine(LibPath, "Mac_x86_64", "libcurl.4.tbd"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    注意添加头文件:

    using System;
    using System.IO;
    
    • 1
    • 2

    在插件中添加测试程序,新建 Test.h 和 Test.cpp,创建一个 OSSTest 类,内容分别如下:

    #pragma once
    #include "CoreMinimal.h"
    
    namespace OSSTest
    {
        // 加上导出宏,否则其他模块无法使用
        // 导出宏的格式为,`插件名字的大写_API`
        ALIOSS_API int32 MainOSS();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    #include "Test.h"
    #include "alibabacloud/oss/OssClient.h"
    
    using namespace AlibabaCloud::OSS;
    
    int32 OSSTest::MainOSS()
    {
        std::string AccessKeyId = "";
        std::string AccessKeySecret = "";
        std::string Endpoint = "";
        std::string BucketName = "";
        /* 初始化网络等资源 */
        InitializeSdk();
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意,插件中的方法要在其他模块中使用时,需要加上导出宏,否则其他模块无法使用。导出宏的格式为,插件名字的大写_API。比如插件的名字为AliOSS时,导出宏为:ALIOSS_API

    UE 中测试插件

    在 UE 工程中的 TestAliOSS.Build.cs 中添加依赖 AliOSS

    PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AliOSS" });
    
    • 1

    在 ATestOSSGameModeBase 的 BeginPlay() 方法中调用测试方法 MainOSS

    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/GameModeBase.h"
    #include "TestOSSGameModeBase.generated.h"
    
    /**
     * 
     */
    UCLASS()
    class TESTOSS2_API ATestOSSGameModeBase : public AGameModeBase
    {
    GENERATED_BODY()
    public:
        virtual void BeginPlay() override;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    #include "TestOSSGameModeBase.h"
    #include "Test.h"
    
    void ATestOSSGameModeBase::BeginPlay()
    {
        Super::BeginPlay();
    
        OSSTest::MainOSS();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果编译错误:

    Declaration shadows a variable in namespace ‘AlibabaCloud::OSS’

    在这里插入图片描述

    不知道具体原始是什么,暂时直接将 URL 改成 URL1

    enumType
    {
      URL1 = 0,
      JSON
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    发现可以通过编译了。

    其他错误

    错误:UnrealEditor.app: No such file or directory

    不知道为什么在 Mac M1 下,UE5 经常遇到下面的问题:

    CodeSign /Volumes/devfang/App/UE_5.0/Engine/Binaries/Mac/UnrealEditor.app
        cd /Volumes/devfang/com/Test/TestAliOSS/Intermediate/ProjectFiles
        export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
    
    Signing Identity:     "-"
    
        /usr/bin/codesign --force --sign - --generate-entitlement-der --entitlements /Volumes/devfang/com/Test/TestAliOSS/Intermediate/ProjectFiles/build/TestAliOSS.build/Development\ Editor/TestAliOSS.build/UnrealEditor.app.xcent --timestamp=none /Volumes/devfang/App/UE_5.0/Engine/Binaries/Mac/UnrealEditor.app
    /Volumes/devfang/App/UE_5.0/Engine/Binaries/Mac/UnrealEditor.app: No such file or directory
    Command /usr/bin/codesign failed with exit code 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    解决方案为:重新校验 UE5 。

    在这里插入图片描述

  • 相关阅读:
    SpringCloud链路追踪SkyWalking-第六章-日志采集
    回顾.NET系列:Framework、Net Core、Net 过往
    SpringMVC之注解驱动的控制器
    重置Mac电脑的SMC怎么操作,重置SMC方法分享~
    java基于Spring boot+vue的点餐外卖订餐系统-商家-用户-骑手
    使用BeanShell写入内容到文件【JMeter】
    HTML进阶(5)- 其他元素
    基于JSP的小型汽车票务管理系统
    nodejs安装和环境配置-Windows
    【毕业设计】机器视觉的图像拼接算法研究与实现 - python 深度学习
  • 原文地址:https://blog.csdn.net/fuyoufang1/article/details/126408677