如标题, 从之前文章对 axmol 的介绍已经了解到,axmol是基于Cocos2d-x-4.0的持续维护分支,axmol的AudioEngine模块API标准继承了Cocos2d-x-3.x/4.0,但相对于官方最大区别是统一了全平台的音频后端API,全平台基于OpenAL,接下来,本文将从Cocos2d-x音频库的历史到axmol的音频库,来介绍axmol是如何把iOS平台的OpenAL换成openal-soft: https://github.com/kcat/openal-soft
openal-soft的作者github id是kcat
, 以下内容使用kcat
代替openal-soft作者
第1代音频引擎: SimpleAudioEngine,不用介绍,使用过的人都知道,是从cocos2d objc版本继承过来的,除了linux和apple平台是OpenAL, 其他平台底层是调用各操作系统API实现
第2代音频引擎: AudioEngine,linux平台基于fmod, android平台官方基于OpenSL实现了一套,其他平台基于OpenAL接口实现,第二代音频引擎带来了更加易用的接口以及单独给每个声音设置音量的支持,这也是笔者为什么将公司cocos2d-x-2.x时代的SimpleAudioEngine升级为3.x的原因,并且升级过程中也进行了如下优化及问题修复
应该说是2.5代音频引擎,因为继承了Cocos2d-x-3.x的音频接口,axmol对AudioEngine实现做了进一步的统一,linux,android,apple,win32均基于OpenAL接口规范实现,apple平台默认基于系统OpenAL.framework,其他平台基于kcat大神维护的openal-soft版本,音频格式单通道/双通道所有平台均支持的格式:
这里提下,u0u0维护的cocos2d Lua社区版本也是全平台基于openal-soft的,但接口和3.x/4.x完全不同
kcat
漫长的讨论,作者给了肯定的答案,LGPL-2.1可以以动态链接库的形式在嵌入式的iOS设备免费使用,详见: kcat/openal-soft#187以上提到的PR经历了笔者和kcat
漫长的讨论,大约10天后,最终完成并被合并至openal-soft的master
,经过这次PR的工作,笔者和kcat
至少搞清楚了如下可能是困扰部分程序员
多时的问题:
# The workaround for solve try_compile failed with code sign
# since cmake-3.18.2, not required
# everyting for cmake toolchain config before project(xxx) is better
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
"CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED"
"CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED NO)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO)
否则,用cmake生成iOS arm的xcode工程时try_compile
必然失败,进而导致生成xcode工程失败,而github上第三方 ios.toolchain.cmake默认将ENABLE_STRICT_TRY_COMPILE
设置为了FALSE
,也就是禁用了严格try_compile
,这样做只能解决生成静态arm库的xcode工程问题,而生成动态arm库的xcode工程时会导致错误的检查到平台本身没有的系统库,从而添加链接选项,最终导致动态库构建的过程中链接失败
11.0
, 否则默认DEPLOMENT_TARGET会是mac系统安装的最新版本,如iOS13
,从而导致xcode clang编译失败# Fix compile failed with armv7 deployment target >= 11.0, xcode clang will report follow error
# clang: error: invalid iOS deployment version '--target=armv7-apple-ios13.6',
# iOS 10 is the maximum deployment target for 32-bit targets
# If not defined CMAKE_OSX_DEPLOYMENT_TARGET, cmake will choose latest deployment target
if(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "iOS")
if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ".*armv7.*")
if(NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET
OR "${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_GREATER "11.0"
OR "${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_EQUAL "11.0")
message(STATUS "Sets iOS minimum deployment target to 10.0 for armv7")
# a. armv7 maximum deployment 10.x
# b. armv7 TLS require deployment 10.x
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.0" CACHE STRING "Minimum OS X deployment version")
endif()
endif()
endif()
soft_oal.framework
链接到axmol的cpp-tests并部署到iphone手机上启动候立刻闪退,闪退原因是dyld error: /Users/.../soft_oal.framework/soft_oal
加载不到动态库,明眼一看,竟然尝试去加载macbook本机的编译生成路径,经过一番搜索,笔者发现有个@rpath
的东西需要启用,大概意思就是将生成的动态framework里的路径用@rpath
代替,贴出CMake脚本# Build: Fix rpath in iOS shared libraries
# If this flag is not set, the final dylib binary ld path will be
# /User/xxx/*/soft_oal.framework/soft_oal, which can't be loaded by iOS devices.
# See also: https://github.com/libjpeg-turbo/libjpeg-turbo/commit/c80ddef7a4ce21ace9e3ca0fd190d320cc8cdaeb
if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
endif()
set_target_properties(${IMPL_TARGET} PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION C
MACOSX_FRAMEWORK_NAME "${IMPL_TARGET}"
MACOSX_FRAMEWORK_IDENTIFIER "org.openal-soft.openal"
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${LIB_VERSION}
MACOSX_FRAMEWORK_BUNDLE_VERSION ${BUNDLE_VERSION}
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
PUBLIC_HEADER "${TARGET_PUBLIC_HEADERS}"
MACOSX_RPATH TRUE)
!!!重要: 以上脚本设置CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG
和MACOSX_RPATH TRUE
是关键,少一个都不行。
git clone https://github.com/kcat/openal-soft
cd openal-soft
# build device
cmake -S . -GXcode -DCMAKE_SYSTEM_NAME=iOS -DALSOFT_OSX_FRAMEWORK=ON -B build_arm "-DCMAKE_OSX_ARCHITECTURES=armv7;arm64"
cmake --build build_arm --config Release --target OpenAL
# build simulator64
cmake -S . -GXcode -DCMAKE_SYSTEM_NAME=iOS -DALSOFT_OSX_FRAMEWORK=ON -B build_x64 -DCMAKE_OSX_SYSROOT=iphonesimulator
cmake --build build_x64 --config Release --target OpenAL
# combine device & simulator dyn libs to one flat-file
cp -r build_arm/Release-iphoneos/soft_oal.framework ./
lipo -create build_arm/Release-iphoneos/soft_oal.framework/soft_oal build_x64/Release-iphonesimulator/soft_oal.framework/soft_oal -output ./soft_oal.framework/soft_oal
# check the flat lib
lipo -info soft_oal.framework/soft_oal
虽然我们现在可以很方便的编译生成 soft_oal.framework
, 但是目前由于CMake还不支持自动将ios App连接的第三方dynamic framework自动设置为 Embedded Content
,因此需要手动拖拽到xcode工程的General/Embedded Content
属性下生成的ipa才能正常在设备上跑。
然而根据CMake官方issue#18073, cmake-3.20发布后,也许就支持了,让我们静静地期待吧。。。