MacOSX APP使用x264动态库

作者:罗上文,微信:Loken1,公众号:FFmpeg弦外之音

在MacOSX上使用x264是非常简单的,本文以Objective-C为例。

在编译 x264 代码之前,我们需要设置一下汇编器(AS)、编译器(CC)的环境变量,如下:

export PATH="$PATH:/Users/loken/Documents/x264/tools/"
export AS="gas-preprocessor.pl -arch powerpc -- xcrun -sdk macosx clang"
export CC="xcrun -sdk macosx clang"

gas-preprocessor.pl 是 x264 项目的 tools 目录下的一个 Perl 脚本,如下:

1-3

这个脚本已经有10年的历史了,早期他应该是为了扩展苹果的 gas 命令的,也就是用 perl 在 gas 上包了一层,使用起来更加方便。

然后现在已经是2024年了,苹果系统的 gas 命令应该是被删除了,目前用来编译汇编代码,把汇编代码转成机器码的是 clang 命令。

所以 clang 命令,它即是 汇编器,也是 编译器


gas-preprocessor.pl -arch powerpc -- xcrun -sdk macosx clang

上面这条命令是比较复杂的,我们需要仔细研究它的具体的用法,需要弄清楚以下几个问题。

1,-arch 参数

-arch 顾名思义是指定计算机架构,也是确定生成的机器码是什么CPU架构的,我的是旧版 Mac Mini,采用的是 intel i5 芯片,所以 arch 肯定是 powerpc。

如果是别的CPU芯片呢?gas-preprocessor.pl 一共支持几种架构,如何查看?

答:需要翻 gas-preprocessor.pl 的源代码,如下:

my %canonical_arch = ("aarch64" => "aarch64", "arm64" => "aarch64",
                      "arm"     => "arm",
                      "powerpc" => "powerpc", "ppc"   => "powerpc");

可以看到,它一共支持 3 种架构,aarch64、arm、powerpc。


2,-- 参数

-- 参数其实是它这个 perl 脚本自己实现的功能,-- 后面必须接汇编器的命令。作者的注释如下:

Options for this program needs to be separated with ' -- ' from the assembler
command. Following options are currently supported:

3,xcrun 命令

xcrun 其实是 MacOSX 系统的命令,全称是 Xcode Run。简单来说,它相当于 python 的虚拟环境 anaconda。

xcrun -sdk macosx clang

上面的命令其实是分为两个部分的,如下:

1-1

你可以这样理解上面这条命令,xcrun 会设置编译环境为 macosx,什么是编译环境?

就是编译的时候需要引入一些头文件,链接一些系统库等等。-sdk macosx 的作用就是告诉 clang 命令,需要的头文件、系统库、命令工具、等等都去 macosx sdk 的环境拿。

macosx sdk 的环境是什么呢?实际上它就是一个路径,如下:

xcrun -sdk macosx --show-sdk-path

上面的命令会打印出来 macosx 环境的路径

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk

xcrun 一共支持几种 SDK 环境呢?如下:

  • iphoneos,手机SDK
  • iphonesimulator,手机模拟器SDK
  • macosx,PC-SDK
  • watchos,手表SDK
  • watchtv,苹果电视SDK

配置完 汇编器编译器 的环境变量,我们就可以编译 x264 的代码了,命令如下:

./configure \
--enable-static \
--disable-asm \
--enable-pic \
--enable-shared \
--enable-debug \
--host=x86_64-apple-darwin \
--extra-cflags="-arch x86_64 -mmacosx-version-min=12.0" \
--extra-asflags="-arch x86_64 -mmacosx-version-min=12.0" \
--extra-ldflags="-arch x86_64 -mmacosx-version-min=12.0" \
--prefix="/Users/loken/Documents/x264/thin/x86_64"

make -j4
make install

--prefix 一定要设置成绝对路径,如果设置成相对目录,你运行的时候可能会遇到下面的报错。

--prefix="./thin/x86_64"
dyld[23683]: Library not loaded: ./thin/x86_64/lib/libx264.157.dylib
  Referenced from: /Users/loken/Library/Developer/Xcode/DerivedData/test-gvcajfcsyrvpwxapjscewdhnqemd/Build/Products/Debug/test
  Reason: tried: '/Users/loken/Library/Developer/Xcode/DerivedData/test-gvcajfcsyrvpwxapjscewdhnqemd/Build/Products/Debug/libx264.157.dylib' (no such file), '/usr/lib/system/introspection/libx264.157.dylib' (no such file), './thin/x86_64/lib/libx264.157.dylib' (no such file), '/usr/local/lib/libx264.157.dylib' (no such file), '/usr/lib/libx264.157.dylib' (no such file)
Program ended with exit code: 9

这个错误其实也可以设置 RunPath Search Path 来解决,但是有点麻烦。


-arch x86_64 这个参数也比较重要,这个其实就是 clang 命令的参数,那 clang 支持多少种架构呢?我们可以通过下面的命令查看

clang -print-targets

编译完成之后,就能在 ./thin/x86_64 目录下看到 x264 的动态库与静态库了,如下:

1-2


下面介绍一下如何在 Objective-C 里面调用 x264 的动态库。

其实在 Xcode 里面引入动态库 跟在 VS2019 里引入动态库是非常类似的,无非就是指定头文件的搜索路径、指定动态库的搜索路径、指定链接器要去链接哪些动态库、等等。如下:

1-4

然后我们在 Build Phases 里面添加一下 libx264.157.dylib 动态库到项目里,如下:

1-6


现在我们就可以修改 main.m 的代码,使用 libx264 动态库里面的函数了,如下:

#import <Foundation/Foundation.h>
#include "x264_config.h"
#include "x264.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        x264_param_t xp;
        x264_param_default(&xp);
    }
    return 0;
}

上面的代码很简单,我就设置了一个 xp 变量,然后给他赋予默认值。读者可以自行断点调试,如下:

1-5

因为我编译的时候开启了 --enable-debug,所以是可以跳进去 x264_param_default 函数的源代码的。


扩展知识:

我们可以打开 Xcode 的编译构建日志,可以看到,我们设置的 x264 路径以及库名称已经传递给了 clang 命令了,如下:

1-6

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c 省略 -I/Users/loken/Documents/x264/thin/x86_64/include -c /Users/loken/Documents/test/test/main.m 省略
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -target x86_64-apple-macos12.3 省略 -fobjc-link-runtime -lx264.157 -Xlinker -no_adhoc_codesign -Xlinker -dependency_info -Xlinker /Users/loken/Library/Developer/Xcode/DerivedData/test-gvcajfcsyrvpwxapjscewdhnqemd/Build/Intermediates.noindex/test.build/Debug/test.build/Objects-normal/x86_64/test_dependency_info.dat -o /Users/loken/Library/Developer/Xcode/DerivedData/test-gvcajfcsyrvpwxapjscewdhnqemd/Build/Products/Debug/test

参考资料:

  1. xcrun 使用说明
  2. What is the correct flag for "*"-version-min
  3. What are the differences between .so and .dylib on macOS?
  4. How to list supported target architectures in clang?
  5. Xcode linking against static and dynamic library

版权所属 xianwanzhiyin.net 罗上文 2024 all right reserved,powered by Gitbook该文件修订时间: 2024-05-16 16:29:27

results matching ""

    No results matching ""