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
成功的话,就可以在文件夹下看到生成的动态库和静态库文件:
- 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
配置 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 ..
其中:
- 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=
设置 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
结果报错了
/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 copyingfor (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 copyingfor (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 copyingfor (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
应该是编辑条件比较严格,for (auto const rule : outcome.result().LifecycleRules()) { }
,会进行拷贝操作,应该使用引用。打开 aliyun-oss-cpp-sdk-master/sample/src/bucket/BucketSample.cc 文件,在 440,471,473 行,修一下报错的地方,修改为引用
使用,即在变量前加 &
。重新编译。
make
此时,应该编译成功,就可以看到编译好的 build/lib/libalibabacloud-oss-cpp-sdk.a
文件了。
UE 中使用
创建一个 C++ 类型的 UE 项目 TestAliOSS
,来测试编译好的库文件。
创建插件
给 UE 项目 TestAliOSS
,创建一个插件 AliOSS
,用于封装阿里 OSS sdk。
此处创建一个空白的插件,命名为 AliOSS
。
在 AliOSS
的源码路径 Source
下,新建文件 OSSThirdParty
文件,然后做以下操作:
- 复制编译好的 libalibabacloud-oss-cpp-sdk.a 文件到
OSSThirdParty/Lib
文件下; - 复制阿里 SDK 源文件中的 aliyun-oss-cpp-sdk-master/sdk/include 到
OSSThirdParty/include
文件下,即阿里 OSS 相关的头文件 - 复制阿里 SDK 源文件中的 aliyun-oss-cpp-sdk-master/third_party/include/curl 到
OSSThirdParty/include/
文件下,即 curl 相关的头文件( 我发现复制过来的 openssl 头文件不行) - 复制 openssl-1.1.1g-x86_64/include/openssl 到
OSSThirdParty/include
文件下,即 openssl 相关的头文件; - 复制 openssl-1.1.1g-x86_64 下的 libcrypto.a 和 libssl.a 文件到
~~OSSThirdParty/lib/Mac_x86_64~~
文件下,即 openssl 的库文件;(发现这一步可以省掉,应该使用 UE 的库文件) - 将 /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"));}
}
注意添加头文件:
using System;
using System.IO;
在插件中添加测试程序,新建 Test.h 和 Test.cpp,创建一个 OSSTest 类,内容分别如下:
#pragma once
#include "CoreMinimal.h"namespace OSSTest
{// 加上导出宏,否则其他模块无法使用// 导出宏的格式为,`插件名字的大写_API`ALIOSS_API int32 MainOSS();
}
#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;
}
注意,插件中的方法要在其他模块中使用时,需要加上导出宏,否则其他模块无法使用。导出宏的格式为,插件名字的大写_API
。比如插件的名字为AliOSS
时,导出宏为:ALIOSS_API
。
UE 中测试插件
在 UE 工程中的 TestAliOSS.Build.cs 中添加依赖 AliOSS
。
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AliOSS" });
在 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;
};
#include "TestOSSGameModeBase.h"
#include "Test.h"void ATestOSSGameModeBase::BeginPlay()
{Super::BeginPlay();OSSTest::MainOSS();
}
结果编译错误:
Declaration shadows a variable in namespace ‘AlibabaCloud::OSS’
不知道具体原始是什么,暂时直接将 URL 改成 URL1
。
enumType
{URL1 = 0,JSON
};
发现可以通过编译了。
其他错误
错误:UnrealEditor.app: No such file or directory
不知道为什么在 Mac M1 下,UE5 经常遇到下面的问题:
CodeSign /Volumes/devfang/App/UE_5.0/Engine/Binaries/Mac/UnrealEditor.appcd /Volumes/devfang/com/Test/TestAliOSS/Intermediate/ProjectFilesexport CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocateSigning 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
解决方案为:重新校验 UE5 。
Mac m1 上编译阿里 OSS c++ 供 UE 使用相关推荐
- Java实现文件上传阿里OSS
前言简介 这边博文实际上想要展现的是一个文件上传阿里OSS的工具类,但是过程是完全实现一个公司根据业务需求去开发实现上传的一个业务需求,综合比较其他博文,这篇博文可能比较罗嗦点.所以根据自身需求来 ...
- 关于 mac m1 xcode12 编译报错 this target. for architecture arm64等问题解决方案
最近换了 mac m1 开发,xcode12在运行旧项目报错 的问题 xxxx building for iOS Simulator, but linking in object file built ...
- vue上传阿里oss
近期相中上传图片利用后端传递到阿里云服务器会慢一点,让后想着前端直接上传阿里云来提高带宽.记录一下 首先下载 npm install ali-oss //下载插件ali-oss 我利用的element ...
- mac m1下编译spring框架
首先安装好jdk8以上的版本,下载azul的,已经适配m1: 去官网上下载gradle压缩包.zip即可: https://gradle.org/releases/ 我这里下的最新版7.2(二进制bi ...
- Mac m1上使用docker搭建C++开发调试环境
说明 因为mac上虚拟机都不太好用,有些还收费,故使用docker来搭建虚拟机.况且我的Mac是m1芯片,用的是arm架构,虚拟机更是少. 搭建本机与虚拟机互通 mac上docker与linux不同, ...
- mac m1上系统内录方法BlackHole代替soundflower录音(附安装包)
文章目录 安装BlackHole 确认邮件 没有vpn可以直接用我下好的3个.pkg安装包 配置"音频MIDI设置" 配置声音 如果已经安装好blackhole但是内录不成功 在i ...
- mac M1上的效率工具——Alfred(附M1配置workflows)
前沿 在mac里,有很多第三方的软件可以极大的提高我们的Mac使用效率,可能你的职业涉及程序员,设计师,人事等等--相信我,使用了Alfred,或多或少会对你当前的工作产生一些便利,提高工作效率. 首 ...
- mac m1上运行jenkins
首先在docker官网上下载好支持m1版本的desktop客户端,随后打开jenkins.io查看安装命令: docker run \-u root \--rm \ -d \ -p 8080:8080 ...
- Mac/Ubuntu 上编译、搭建 WebRtc/licode 服务器
1.下代码 git clone https://github.com/ging/licode.git cd licode 2.安装依赖 2.1 配置ubuntu开发环境: 2.1.1 安装C/C++开 ...
最新文章
- 第九次作业-测试报告和用户使用手册
- python读取excelsheet-python实现读取excel文件中所有sheet操作示例
- python小案例随机点名_python用tkinter实现一个简易能进行随机点名的界面
- (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
- webpack指定第三方模块的查找路径
- C#读取XML文件的基类实现
- Ubuntu linux下的录屏
- svn回退后如何再还原_设计师如何管理自己的文档
- 参数嗅探_SQL Server 2016参数嗅探
- [HNOI2015]开店(树剖+主席树+标记永久化)
- XNA 三维入门讲解
- 探讨SQL Server 2005的评价函数
- ARP协议报文格式及ARP表简述
- 编译ionic应用时遇到“To run dex in process, the Gradle daemon needs a larger heap.”
- 一小时建立数据分析平台
- 这些雷达书籍,你需要收藏~(终极大汇总)
- JeeSite (三)前端
- 计算机正确的按键手法游戏,lol正确的按键手法图解
- 计算机教师专业发展规划,教师个人专业发展三年规划(2020-2023)
- carbondate mysql_CarbonData集成Hive、Spark
热门文章
- lintcode_167. 链表求和
- Expect 手册中文版
- 招商银行一卡通通过支付宝对广发信用卡进行还款
- android studio播放视频权限,Android Studio实现本地视频播放
- C#net6实现Linux系统下修改IP地址、修改系统时间、获取内存信息、获取磁盘信息、重启系统
- ipv4地址怎么设置 手机_如何设置手机的IP地址?方法很简单赶快试试吧!
- WinKawaks如何载入游戏
- 为你的PyCharm画眉
- uibot在子程序执行js失败_使用BotUI搭建js机器人
- java 判断 nan_关于java:如何测试double是否等于NaN?