我正在尝试为iOS应用程序制作一个动态框架。改名的是新版本,我们可以在创建一个新项目时选择一个可可触摸框架,而不再需要添加聚合目标、运行脚本等来创建一个。我在构建框架时没有问题。但是当我试图在iOS应用程序中使用它时,我会遇到一些架构问题。

ld: warning: ignoring file /Library/Frameworks/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (arm64): /Library/Frameworks/MyFramework.framework/MyFramework
Undefined symbols for architecture arm64:
  "_OBJC_CLASS_$_MyFrameworkWebService", referenced from:
      objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

ld: warning: ignoring file /Library/Frameworks/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (armv7): /Library/Frameworks/MyFramework.framework/MyFramework
Undefined symbols for architecture armv7:
  "_OBJC_CLASS_$_MyFrameworkWebService", referenced from:
      objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

嗯,我已经尝试更改框架项目和目标的设置(仅架构和构建有效架构和有效架构)。我为iOS应用程序项目做了同样的事情,但没有任何工作。我想有些事情我不明白。

例如,当我只为i386(iOS模拟器)构建框架时,请使用命令行检查 "xcrun lipo-info MyFramework",我有一个问题

劳工处:警告:忽略文件/库/框架/MyFramework。框架/MyFramework,文件是为x86_64构建的,而x86_64不是正在链接的体系结构(i386)。..

如果有人可以帮助我得到一个适用于所有iOS体系结构(包括模拟器)的框架。

有帮助吗?

解决方案 11

抱歉我让这个主题打开了这么长的时间......你们中的一些人已经正确回答了我的问题。当我写这个问题时,我没有捕获有两种切片(也称为FAT)框架(即将使用)。一个用于iOS设备,一个用于模拟器。当我发现我使用lipo命令用来融合两个切片并自动完成完整框架时。

其他提示

基于所有响应, raywenderlich .com gist chris conway 我想出了这个

执行以下步骤,我能够构建一个Cocoa触摸框架(包括Swift和Objective-C文件),其中包含模拟器和设备的所有架构:

  1. 在框架的项目中创建一个新的(聚合)目标
  2. 在“构建阶段”中选择“添加运行脚本”和复制的这个文件
  3. 选择 聚合目标 scheme 选择下降
  4. build target 聚合方案
  5. 希望它有助于:)

    更新:修复了GIST中的错误,其中步骤#3中的路径不正确。感谢 tokuriku !!

    更新在Xcode 7和8中,单击“文件”>“新建”>“目标...”,选择“其他”组以选择聚合目标

尝试以下步骤创建包含框架项目和应用程序项目的工作区。

工作区:

  • 创建一个工作区。

框架项目:

  • 在工作区内创建一个ios 可可触摸框架项目。
  • 添加一个简单的目标c class myclass (标题.h和实现文件.m),并创建一个方法 - (void)问候语
  • go project build阶段> 标题> move myclass.h project public < /强>。
  • 更改框架项目的方案,然后选择 iOS模拟器,然后构建。 (选择 iOS设备如果将此框架集成在设备上运行的应用程序。我将在此示例中继续使用模拟器)
  • 您应该没有问题构建,框架构建是在派生数据目录中找到的,您可以在 constorizer 中找到。

应用程序项目:

  • 在工作区内创建Swift单视图应用程序。
  • 拖动到iOS模拟器框架构建(在调试-iphonesimulator recelety-iphonesimulator )到您的项目中。
  • 创建桥接标题以将客观的C类方法曝光到SWIFT。
  • 导入桥接标题文件中的myclass.h。
  • 请注意,如果找不到MyClass定义,则添加框架标题标题,构建设置标题搜索路径
  • ViewController.swift 的ViewDidload中创建 myclass 的实例,然后调用问候语
  • 为目标添加框架>嵌入二进制文件
  • 将方案更改为应用程序项目,然后选择 iOS模拟器,然后构建。
  • 你应该能够看到问候留言。

请注意,上面的示例演示如何构建在模拟器中运行的应用程序。如果您需要创建在模拟器设备上运行的通用静态库,则将一般步骤为:

  • 模拟器
  • 构建库
  • 构建设备
  • 的库
  • 使用 lipo
  • 结合它们

网站上有很好的引用,这里

为框架创建通用二进制文件:导航到框架派生数据目录然后 / cant / products ,以下命令应该帮助您在产品目录中创建一个通用二进制文件:

lipo -create -output "framework-test-01-universal" "Debug-iphonesimulator/framework-test-01.framework/framework-test-01" "Debug-iphoneos/framework-test-01.framework/framework-test-01" 
.

注意, Framework-Test-01 是我的框架项目名称。

以下是创建fat(通用)框架的步骤:

  1. 套装 ONLY_ACTIVE_ARCH=NOBuild Settings 在你的项目中。

    • 为模拟器构建库
    • 为设备构建库
  2. 在控制台中打开 Products 框架的文件夹 (您可以通过打开框架文件夹和 cd .. 从那里)

enter image description here enter image description here

  1. 这个脚本Products 文件夹。它在此文件夹中创建fat框架。(或者按照下面的说明手动执行 4. 5.)

    framework_name="${$(basename $(find ./Debug-iphoneos -type d -name '*.framework' -maxdepth 1))%.*}" && \
    cp -R Debug-iphoneos/$framework_name.framework ./$framework_name.framework && \
    lipo -create -output "$framework_name.framework/$framework_name" "Debug-iphonesimulator/$framework_name.framework/$framework_name" "Debug-iphoneos/$framework_name.framework/$framework_name"
    

或:

  1. 结合这2个框架使用 利波 通过此脚本(替换 YourFrameworkName 到你的框架名称)

    lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
    
  2. 替换为现有框架中的新二进制文件:

    cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework
    mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
    

  1. 利润: ./YourFrameworkName.framework - 是现成的脂肪二进制! 您可以将其导入到您的项目中!

对于项目,不在 xcworkspace-es:

您也可以尝试使用 这个要旨 但它似乎不适用于工作区中的项目。

我的做法与 vladof 类似,但希望更简单一些。我将该框架作为应用程序项目的子项目。

框架项目

  • 创建一个新的 iOS Cocoa Touch 框架。称之为 MyLib。这将创建一个 MyLib.h
  • 添加一个简单的 Cocoa Touch Obj-C 类 MyClass (.h & .m) 并在 .m 的实现中创建一个返回字符串的方法 - (NSString *)greetings;
  • 在 MyLib.h 中,在底部附近添加 #import "MyClass.h"
  • 在目标的“构建阶段/标头”部分中,将 MyClass.h 从“项目”部分移动到“公共”部分。
  • 进行构建 (cmd-B)
  • 关闭项目

应用项目

  • 创建一个新的单视图应用程序项目,可以是 Swift,也可以是 Obj-C。称之为我的应用程序。
  • 从 Finder 中,将 MyLib 项目文件拖到 MyApp 窗口的左侧组织器部分,并确保插入行位于 MyApp 的正下方。这使得 MyLib 成为 MyApp 的子项目。(在其他项目中仍然可以同样的方式使用)
  • 单击管理器中的 MyApp,然后选择 MyApp 目标并选择构建阶段。
  • 在目标依赖项中,单击 + 号并添加 MyLib。
  • 在“与库链接”中,单击 + 号并添加 MyLib.framework。

对于 Obj-C 应用程序

  • 在ViewController.m中,添加#import
  • 在 viewDidLoad 中,添加以下行:
  • MyLib *x = [[MyLib alloc] init];
  • NSLog(@"%@", x.greetings);
  • 运行该项目,您应该在调试窗口中看到该消息。-

对于 Swift 应用程序

  • 在 ViewController.swift 中,添加 import MyLib
  • 在 viewDidLoad 中,添加以下行:
  • 变量x:我的库 = 我的库()
  • println("(x.greetings())") -

通过这种方式,应用程序依赖于框架,因此如果您对框架类进行更改,则不必更改目标来单独构建框架,它只会先编译框架,然后再编译应用程序。

我已经改变了某人的脚本有点支持所有模拟器的架构:

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"

# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator VALID_ARCHS="x86_64 i386" BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

# Step 2. Copy the framework structure to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"

# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"

# Step 4. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"

# Step 5. Delete temporary build directory in the project's directory
rm -rf "${PROJECT_DIR}/build"

# Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"
.

自从上述链接之前的旧视频不再可用。

如何使用Xcode 6创建可可触摸框架

vladof共享的方法周围的额外点,这些方法更适用于Swift基于Swift的框架

  1. 关联链路中的脚本需要修改以自Swift为ARM和I386的单独编译文件分开编译iPhoneSimulator和iPhoneOS复制所有文件
  2. 确保您只有archs=“x86_64”ocke_active_arch= no for iPhoneSimulator以避免模拟器的链接问题
  3. 确保您的界面/类扩展NSObject否则当您尝试使用swift中的代码时,您将遇到问题(它将抱怨无法使用()。

最后,我拿到了我的工作! 对不起大黄色框架,我不知道如何更好地格式化。

解决方案来自Claudio Romandi,但链接的脚本有一个小问题。我无法评论他的帖子,因为我需要50个声誉,所以我留下了很少的选择,而是为了复制他的帖子来拥有完整的解决方案..

  1. 在框架项目中创建一个新的(聚合)目标
  2. 在工作区中选择聚合并添加“新运行脚本阶段”
  3. 将以下代码放入其中:

    #!/bin/sh
    
    UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
    
    # make sure the output directory exists mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
    
    # Step 1. Build Device and Simulator versions xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION}
    -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
    
    # Step 2. Copy the framework structure (from iphoneos build) to the universal folder cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
    
    # Step 3. Copy Swift modules (from iphonesimulator build) to the copied framework directory cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
    
    # Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory lipo -create
    -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
    
    # Step 5. Convenience step to copy the framework to the project's directory cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
    
    # Step 6. Convenience step to open the project's directory in Finder open "${PROJECT_DIR}"
    
  4. 在方案选择下拉下来选择聚合

  5. build,你已经完成了!
  6. 问题是模拟器目录指向非现有目录,将“框架”更改为“$ {project_name}”在2个地方执行以下诀窍:)

想要为skywinder 这里。我遵循这些步骤,但仍然无法让我的框架在模拟器上运行,只有设备。修复:

-i进入了框架的调试 - iphonesimulator版本,在模块/ [frameworkname]中.swiftmodule,我复制了所有I386和X86文件。

-i然后进入了新创建的框架的胖版本,并导航到同一个文件夹。我粘贴在i386和x86文件中(与已经存在的arm文件一起使用),然后将我的胖框架添加到我的项目中。

voila,她工作在模拟器和真实的设备上!这是Xcode 10 / Swift 4.2 btw

这个问题已发布一段时间以前(Xcode 6),但我最近用Xcode 10遇到了同样的问题。

所以问题是:构建的框架不支持足够的体系结构。

如果一个人不知道架构代表什么,不同的iPhone设备有不同的架构,这里是一个完整的列表:

  • ARM6:iPhone 1,2,3g
  • arm7:用于最旧的iOS 7支持设备[32位]。 iphone 4, 4s
  • ARM7S:在iPhone 5和5C中使用[32位]。 iphone 5,5c
  • ARM64:在iPhone 5s中的64位臂处理器[64位]。 iPhone 5S 和上面。
  • ARM64E:用于A12芯片组。 iphone xs / xs max / xr
  • i386:对于32位模拟器
  • x86_64:用于64位模拟器

所以,如果您在模拟器上使用框架,则框架需要支持I386或X86_64;如果您在iPhone 6上运行应用程序,则框架需要支持ARM64架构。

因此,在大多数情况下,框架需要支持所有上述架构。

现在回到如何解决问题。我们需要为两个设备和模拟器构建框架。

如何构建设备:

  1. 在“常规”中,指定“部署目标”。
  2. 在“构建设置”中,将“仅构建活动架构”将“否”
  3. 在“构建设置”中,确保“有效架构”列出所有 您需要的架构。通常我们只是使用默认值 选项(ARM64,ARM64E,ARMV7,ARMV7S)。
  4. 转到“编辑方案” - >“运行” - >“构建配置”,更改“构建 配置“释放”
  5. 选择“Active Scheme”Generic IOS设备“。命中cmd + b以构建项目。
  6. 右键单击[MyFrameWorkProject] .FrameWork在Xcode项目中的“产品”文件夹下,并在“查找器”中点击“Show”。[MyFrameWorkProject] .Framework支持所有规定的架构 第2步。
  7. 拖动[myframeworkproject] .framework到需要使用的项目 这个框架。此外,将[MyFrameWorkProject]拖动到“嵌入二进制文件”。
  8. 如何构建模拟器:

    1. 步骤1至4相同。
    2. 选择任何模拟器作为活动方案。命中cmd + b构建 项目。
    3. 步骤6至7与上述相同。
    4. 如何构建用于设备和模拟器:

      有设备框架后,您需要将模拟器的框架与“Lipo”命令组合在一起。 将模拟器的框架重命名为[MyFrameWorkProject] _sim.framework并将两个框架复制到同一文件夹。在终端中运行命令(确保您在文件夹中):

      lipo -create -output [MyFrameworkProject].framework/[MyFrameworkProject] [MyFrameworkProject].framework/MyFrameworkProject [MyFrameworkProject]_sim.framework/MyFrameworkProject
      
      .

      现在[myframeworkproject] .framework是支持模拟器和设备的最终产品。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top