Developer Connection

Member Login 登录 | 不是会员? 联系 ADC 高级搜索

Technical Note TN2012
Building QuickTime Components for Mac OS X

这个技术说明文档讨论如果连编 Mac OS X 上的 Carbon Mach-O QuickTime 构件,并演示如果对构件管理器(Component Manager)的 thing('thng')资源进行配置,以连编同时支持基于 PowerPC 和 Intel 的 Macintoshe 系统的通用二进制构件。





二进制格式

Mac OS X支持两种应用程序的二进制格式:Mach-O和CFM。

Mach-O是本地的Mac OS X对象格式,也是gcc编译器和Xcode支持的格式。

CFM(Code Fragment Manager,即代码片断管理器)是在运行传统Mac OS系统的Power Macintosh计算机上使用的老格式,一些编译器支持这种格式,比如Metrowerks CodeWarrior。

虽然Mac OS X上的Carbon构件可以连编为Mach-O或者CFM代码,但是CFM已经是不推荐使用的格式了。更为重要的是,Mach-O是唯一能够本地运行在基于Intel的Macintosh系统上的二进制格式。

如果您正在连编一个新的构件,则请从使用最新版本的Xcode(2.1或者更高版本)开始,连编一个通用的二进制构件(一种独立的构件,其二进制文件中同时包含可运行于PowerPC和基于Intel的Macintosh的代码)。如果您正在更新老版本的构件,则首先需要迁移到最新版本的Xcode上来,然后根据需要更新您的构件。请参见本文尾部的参考部分,以获得集中讨论开发者如何向Xcode迁移的文档连接。

请注意:虽然CodeWarrior能够连编Mach-O格式的二进制代码,但是不能连编可以同时本地运行于PowerPC和基于Intel的Macintosh计算机上的通用二进制代码。

返回顶部 

Mach-O构件

Mac OS X的Mach-O构件在其数据分支中包含一个动态库(dylib),并使用类似于传统的Mac OS动态库的机制进行连编,但是具有下面的区别:

  • 入口点是通过符号名称找到的,这和Windows上的机制是一样的-- 即"代码资源类型"为'dlle',而'dlle'资源中包含一个C字符串,值为输出符号的名称。请参见列表1。

  • 如果您正在为基于PowerPC的Macintosh连编构件,则平台类型应为platformPowerPCNativeEntryPoint,而不是platformPowerPC。请参见列表2。

  • 如果您正在为基于Intel的Macintosh连编构件,则平台类型应为platformIA32NativeEntryPoint。请参见列表3。

列表1:Mach-O & Windows入口点。

// Code Entry Point for PowerPC-based & Intel-based Macs and Windows
resource 'dlle' (256) {
    "MyComponentDispatch"
};

列表2:Mach-O基于PowerPC的Mac 'thng'资源。

// extended 'thng' template
#define thng_RezTemplateVersion 1

#include <Carbon/Carbon.r>
#include <QuickTime/QuickTime.r>

resource 'thng' (256) {
    kSomeComponentType, // Type
    'DEMO',             // SubType
    'DEMO',             // Manufacturer
    0,                  // use componentHasMultiplePlatforms
    0,
    0,
    0,
    'STR ',             // Name Type
    128,                // Name ID
    'STR ',             // Info Type
    129,                // Info ID
    0,                  // Icon Type
    0,                  // Icon ID
    kMyComponentVersion,  // Version
    componentHasMultiplePlatforms + // Registration Flags
    myComponentRegistrationFlags,
    0,                  // Resource ID of Icon Family
    {
      kMyComponentFlags,
      'dlle',           // Entry point found by symbol name 'dlle' resource
      256,              // ID of 'dlle' resource
      platformPowerPCNativeEntryPoint, // Architecture
    };
};

列表3:Mach-O基于Intel的Mac 'thng'资源。

// extended 'thng' template
#define thng_RezTemplateVersion 1

#include <Carbon/Carbon.r>
#include <QuickTime/QuickTime.r>

resource 'thng' (256) {
    kSomeComponentType, // Type
    'DEMO',             // SubType
    'DEMO',             // Manufacturer
    0,                  // use componentHasMultiplePlatforms
    0,
    0,
    0,
    'STR ',             // Name Type
    128,                // Name ID
    'STR ',             // Info Type
    129,                // Info ID
    0,                  // Icon Type
    0,                  // Icon ID
    kMyComponentVersion,  // Version
    componentHasMultiplePlatforms + // Registration Flags
    myComponentRegistrationFlags,
    0,                  // Resource ID of Icon Family
    {
      kMyComponentFlags,
      'dlle',           // Entry point found by symbol name 'dlle' resource
      256,              // ID of 'dlle' resource
      platformIA32NativeEntryPoint, // Architecture
    };
};

通用二进制构件

架构设置

一旦您已经将目标的架构设置设定为同时为ppci386连编,且将SDKROOT设置为连编通用二进制代码编程指南文档中描述的值,则您已经为连编一个通用二进制构件做好准备了。请看图1。

图1:Xcode架构目标设置。

Figure 1, Xcode architecture target settings.

返回顶部 

ComponentPlatformInfo

然而,构件管理器通过查看构件的'thng'资源来识别QuickTime构件支持何种架构,而不是直接检查二进制文件的架构。特别值得一提的是,构件管理器查看的是'thng'资源中的ComponentPlatformInfo数组。

由于'thng'资源中的"platform(平台)"信息是一个包含多个ComponentPlatformInfo条目的数组,因此连编支持多架构的单一构件是比较容易的。在传统的Mac OS中,68k/PPC "FAT" 构件就是以这种方式连编的,即在构件中的平台数组包含两个条目,并分别指定恰当的架构。

现在,连编一个Mach-O通用二进制构件并无区别,在ComponentPlatformInfo数组中同时指定platformPowerPCNativeEntryPointplatformIA32NativeEntryPoint架构就可以了,如列表4所示。

列表4:通用二进制构件的'thng'资源。

// File : My_Component.r

// extended 'thng' template
#define thng_RezTemplateVersion 1

#if TARGET_REZ_CARBON_MACHO
    #include <Carbon/Carbon.r>
    #include <QuickTime/QuickTime.r>
#else
    #include "ConditionalMacros.r"
    #include "MacTypes.r"
    #include "Components.r"
    #include "QuickTimeComponents.r"
    #include "ImageCompression.r"
#endif

resource 'thng' (256) {
    kSomeComponentType, // Type
    'DEMO',             // SubType
    'DEMO',             // Manufacturer
    0,                  // use componentHasMultiplePlatforms
    0,
    0,
    0,
    'STR ',             // Name Type
    128,                // Name ID
    'STR ',             // Info Type
    129,                // Info ID
    0,                  // Icon Type
    0,                  // Icon ID
    kMyComponentVersion,  // Version
    componentHasMultiplePlatforms + // Registration Flags
    myComponentRegistrationFlags,
    0,                  // Resource ID of Icon Family
    { // COMPONENT PLATFORM INFORMATION ----------------------
#if TARGET_OS_MAC
    #if TARGET_REZ_CARBON_MACHO
        #if !(TARGET_REZ_MAC_PPC || TARGET_REZ_MAC_X86)
            #error "Platform architecture not defined!"
        #endif
        #if TARGET_REZ_MAC_PPC
              kMyComponentFlags,
              'dlle',
              256,
              platformPowerPCNativeEntryPoint,  // PowerPC-based Macintosh
        #endif
        #if TARGET_REZ_MAC_X86
              kMyComponentFlags,
              'dlle',
              256,
              platformIA32NativeEntryPoint,     // Intel-based Macintosh
        #endif
    #else
        #error "TARGET_REZ_CARBON_MACHO should be defined."
    #endif
#elif TARGET_OS_WIN32
    #if TARGET_REZ_WIN32
        kMyComponentFlags,
        'dlle',
        256,
        platformWin32,
    #else
        #error "TARGET_REZ_WIN32 should be defined."
    #endif
#else
    #error "I have no idea what you're trying to do!"
#endif
    };
};

返回顶部 

资源文件定义

建立构件资源文件的一个简单方法是包含一个定义了恰当的TARGET_REZ_XXX_XXX标识的主资源(.r)文件,然后在该主资源文件中包含所有其它单独的构件资源(.r)文件,请参见图2。

列表5显示了一个可能的主资源文件。请注意该文件是如何设置恰当的定义,并在之后包含名为My_Component.r的特定构件的资源文件。

图2:增加一个单独的主资源文件

Figure 2, Adding a single master resource file.

列表5:主资源文件。

// File : My_Component_MachO.r
//
//
// Mac OS X Mach-O Component: Set TARGET_REZ_CARBON_MACHO to 1
//
// In the target settings of your Xcode project, add one or both of the
// following defines to your OTHER_REZFLAGS depending on the type of component
// you want to build:
//
//      PPC only: -d ppc_$(ppc)
//      x86 only: -d i386_$(i386)
//      Universal Binary: -d ppc_$(ppc) -d i386_$(i386)
//
// Windows Component: Set TARGET_REZ_CARBON_MACHO to 0
// ---------------------------------------------------

// Set to 1 == building Mac OS X
#define TARGET_REZ_CARBON_MACHO 1

#if TARGET_REZ_CARBON_MACHO
    #if defined(ppc_YES)
        // PPC architecture
        #define TARGET_REZ_MAC_PPC 1
    #else
        #define TARGET_REZ_MAC_PPC 0
    #endif

    #if defined(i386_YES)
        // x86 architecture
        #define TARGET_REZ_MAC_X86 1
    #else
        #define TARGET_REZ_MAC_X86 0
    #endif

    #define TARGET_REZ_WIN32 0
#else
    // Must be building on Windows
    #define TARGET_REZ_WIN32 1
#endif

// include the individual component resource files
#include "My_Component.r"

返回顶部 

其它Rez标志

My_Component_MachO.r文件依赖于ppc_YES 和/或者i386_YES的定义情况。根据您连编的目标架构的不同,在目标的Other Rez Flags(其它Rez选项)(OTHER_REZFLAGS)的Rez设置中加入一个定义,或者同时加入两个定义:

  • 如果目标架构是PPC,加入-d ppc_$(ppc)选项

  • 如果目标架构是x86,加入-d i386_$(i386)选项

  • 如果目标架构同时为PPC和x86,加入-d ppc_$(ppc) -d i386_$(i386)选项

图3:建立Rez定义。

Figure 3, Setting up defines for Rez.

返回顶部 

Resourcerer工具

Mathemaesthetics, Inc.公司提供的Resourcerer对于QuickTime构件开发者来说是一个极好的工具。您可以用它来查看和编辑资源,并快速检查'thng'资源的正确性。图4显示的是一个通用二进制配置中连编的'thng'资源,其ComponentPlatformInfo数组中包含两个条目。

图4:Resourcerer中看到的通用二进制构件的'thng'资源。

Figure 4, Universal Binary Component 'thng' viewed in Resourcerer.

返回顶部 

程序包构件

程序包是文件系统中的一个目录,它将相关资源组织为一个组放在一个位置上。Xcode允许将构件连编为程序包,或者一个单独的dylib文件。然而,QuickTime构件应该连编为Mac OS X的程序包。连编为一个单独的Mach-O构件dylib文件是不推荐的做法。

将老版本的构件配置为一个独立的二进制文件的开发者应该更新工程的目标,将产品连编为构件程序包。此外,使用老版本开发工具的开发者应该确保没有将资源连编到Mach-O二进制文件的资源分支中

要连编一个构件程序包,请在Xcode的'New Project' (新建工程)对话框中选择 'Carbon Bundle' (Carbon程序包)模板;如果要在现有的Xcode工程中加入一个目标,则在'New Target'(新建目标)对话框中选择'Loadable Bundle'(可装载程序包)模板。

返回顶部 

lipo

lipo是Xcode在通用二进制代码连编过程中使用的命令,负责创建通用二进制代码,并对其进行操作。通过指定-detailed_info选项,lipo可以取得连编到通用二进制代码文件中的架构列表,请看列表6。

请注意:如果需要更多lipo命令的信息,请在Terminal程序上键入man lipo指令。

列表6:使用lipo命令获取通用二进制代码的信息。

toronto:~ ed$ lipo -detailed_info /ElectricImageUniversal.component/Contents/MacOS/
ElectricImageUniversal
Fat header in: /ElectricImageUniversal.component/Contents/MacOS/ElectricImageUniversal fat_magic 0xcafebabe nfat_arch 2 architecture ppc cputype CPU_TYPE_POWERPC cpusubtype CPU_SUBTYPE_POWERPC_ALL offset 4096 size 128176 align 2^12 (4096) architecture i386 cputype CPU_TYPE_I386 cpusubtype CPU_SUBTYPE_I386_ALL offset 135168 size 132084 align 2^12 (4096)

返回顶部 

Rosetta

Rosetta是一个使PowerPC的二进制代码运行在基于Intel的Macintosh系统上的翻译进程。这个技术使应用程序可以以非本地二进制代码的方式运行。然而,Rosetta不支持将本地的代码和经过翻译的代码混合在一个进程中,没有提供与传统Mac OS系统上的"Mixed Mode(混合代码)" 技术相等价的技术。

只支持PowerPC的构件将不能在本地运行于采用Intel微处理器的Macintosh系统上的应用程序中被装载。这意味着构件必须连编为通用的二进制代码,否则,用户在本地应用程序上将不能使用依赖于非本地构件的功能。

反过来,在Rosetta下面运行的应用程序将总是装载通用二进制构件中的PowerPC版本。这意味着在非通用的应用程序中,媒体回放的性能将受到限制。

重要提示:苹果电脑鼓励QuickTime构件开发者将自己的构件连编为通用二进制版本。这将使用户避免在本地应用程序中执行期望的功能时碰到困难。

返回顶部 

文件扩展名和位置

构件文件的扩展名应为".component",位于/Library/QuickTime目录下。

返回顶部 

实例代码

电子图像构件实例演示了本文档概述的技术,并说明了如何连编五种QuickTime构件:图形导入器,图形导出器,电影导入器,电影导出器,以及图像解压器。这些构件协同工作,使QuickTime可以使用电子图像格式的图像文件。

返回顶部 

参考

返回顶部 

文档修订历史

日期 说明
2005-07-14 为Tiger进行更新,增加通用二进制代码的信息
2001-03-08 新文档

公布时间: 2005-07-14


Gray line