Xcode 6 iOS создание Cocoa Touch Framework-проблемы с архитектурой

Я пытаюсь создать динамическую структуру для приложения iOS. Благодаря новой версии Xcode (6) мы можем выбрать Cocoa Touch Framework при создании нового проекта, и больше нет необходимости добавлять агрегатную цель, запускать скрипт и так далее. У меня нет проблем, когда я строю каркас. Но когда я пытаюсь использовать его внутри приложения 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)

Ну, я попытался изменить настройки проекта и цели framework (Архитектуры и построить допустимую архитектуру только & допустимые архитектуры). Я сделал то же самое для проекта приложения iOS, но ничего не работает. Кажется, я чего-то не понял.

например, когда я создаю фреймворк только для i386 (iOS Simulator), проверьте с помощью командной строки "xcrun lipo-info MyFramework", у меня есть проблема, которая

ld: предупреждение: игнорирование файла / библиотеки / фреймворков / MyFramework.рамки/MyFramework, файл был построен для x86_64, который не архитектура связывается (i386)...

Если кто-то может помочь мне получить структуру, которая работает для всех архитектур iOS, включая тренажеры.

9 ответов


на основе всех ответов post on raywenderlich.com и суть создано Крис Конвей Я придумал этой.

выполнив следующие шаги, я смог построить Cocoa Touch framework (включая файлы Swift и Objective-C), который содержит все архитектуры как для симулятора, так и для устройства:

  1. создайте новую (агрегатную) цель в проекте вашей структуры
  2. под "Этапы сборки" выберите "Добавить скрипт запуска" и скопируйте содержимое этот файл
  3. выберите the совокупный элемент на схемы выбор выпадающего
  4. построить the цель на the совокупный схемы

надеюсь, что это помогает :)

обновление: Исправлена ошибка в gist, где пути в шаге #3 были неправильными. Спасибо Tokuriku!!

обновление в Xcode 7 и 8 выберите Файл>Создать>цель... и там выберите" другую " группу, чтобы выбрать Aggregate target


выполните следующие действия, чтобы создать рабочую область, содержащую проект фреймворка и проект приложения.

рабочее место:

  • создайте рабочее пространство.

в рамках проекта:

  • создать iOS какао касания рамки проект внутри рабочей области.
  • добавить простой класс Objective C MyClass (заголовок .H и файл реализации .m), и создать метод - (пустота)приветствую.
  • Go project Собрать Фаз>заголовки > перейти MyClass.h С проект to общественные.
  • изменить схему на рамочный проект и выбрать iOS simulator, потом строить. (Выберите устройство iOS если приложение, которое интегрирует эту структуру работает на устройстве. Я буду продолжать использовать симулятор в этом примере)
  • у вас не должно быть создание проблемы, сборка фреймворка находится в вашем Данные, который вы можете найти в организатор.

проект приложения:

  • создайте приложение Swift Single View внутри рабочей области.
  • перетащите выше iOS simulator framework сборки (найдено в Debug-iphonesimulator или Release-iphonesimulator) к вашему проекту.
  • создайте заголовок моста для отображения цели C методы класса в Swift.
  • Импорт MyClass.h в файле заголовка моста.
  • обратите внимание, что если определение MyClass не найдено, добавьте framework заголовки путь для создания настроек Пути Поиска Заголовка.
  • создать экземпляр MyClass в viewDidLoad ViewController.Свифт!--20-->, тогда звоните поздравления.
  • добавить фреймворк в Target > встроенные двоичные файлы
  • изменить схема проекта приложения и выберите iOS simulator, потом строить.
  • вы должны иметь возможность видеть поздравительные сообщения.

обратите внимание, что в приведенном выше примере показано, как создать приложение, которое работает в симулятор. Если вам нужно создать универсальную статическую библиотеку, которая работает как симулятор и устройства, то общие шаги:

  • создать библиотека для симулятор
  • создать библиотека устройства
  • объединить их с помощью Липо

есть хорошие ссылки в интернете об этом!--108-->здесь например.

создайте универсальный двоичный файл для framework: перейдите в каталог производных данных framework, затем /Строительства/Продукты, следующая команда должна помочь вам создать универсальный двоичный файл в продукты каталог:

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" 

отметим, что фреймворк-тест-01 - это имя моего рамочного проекта.


вот шаги по созданию fat (universal) Framework:

  1. Set ONLY_ACTIVE_ARCH=NO на Build Settings в вашем проекте.

    • построить библиотеку для симулятора
    • построить библиотеку для устройства
  2. открыть в консоли Products папка для вашего фреймворка (вы можете открыть его с помощью папки open framework и cd .. от там)

enter image description hereenter image description here

  1. Run этот скрипт С Products папка. Он создает Fat Framework в этой папке. (или сделайте это вручную, как описано ниже в 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 фреймворка, используя Липо по этому скрипту (replace 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 - готов к использованию fat binary! вы можете импортировать его в ваш проект!

для проекта, что не в xcworkspace - es:

вы также можете попробовать использовать в этом суть но похоже, что она не работает для проектов в рабочих пространствах.


то, как я это сделал, похоже на vladof, но, надеюсь, немного проще. Я сделал фреймворк подпроектом проекта app.

в рамках проекта

  • создайте новую платформу iOS Cocoa Touch. Назовите это MyLib. Это создаст единый MyLib.h
  • добавьте простой класс Cocoa Touch Obj-C, MyClass (.ч. & м )и в осуществлении.m, создайте метод, который возвращает строку, - (NSString *)приветствия;
  • В Проекте "MyLib".h, добавьте это внизу, #импорт " MyClass.h"
  • в разделе этапы/заголовки сборки цели переместите MyClass.h из раздела проекта в раздел Public.
  • выполните сборку (cmd-B)
  • закрыть проект

проект приложения

  • создайте новый проект приложения с одним представлением, Swift или Obj-C. назовите его MyApp.
  • из Finder перетащите файл проекта MyLib в левый раздел организатора MyApp окно и убедитесь, что строка вставки находится чуть ниже MyApp. Это делает MyLib подпроектом MyApp. (Его все еще можно использовать таким же образом в других проектах)
  • нажмите MyApp в организаторе, а затем выберите цель MyApp и выберите фазы сборки.
  • в целевой зависимости, щелкните знак " + "и добавить "MyLib".
  • в ссылке с библиотеками щелкните знак + и добавьте MyLib.рамки.

для приложения Obj-C

  • In Файл ViewController.m, добавить #import
  • в viewDidLoad добавьте следующие строки:
  • MyLib * x = [[MyLib alloc] init];
  • NSLog (@ "%@ " , x.привет);
  • запустите проект и вы увидите сообщение в окне отладки. -

для быстрого приложения

  • В ViewController.Свифт, добавить "MyLib" импорт
  • в viewDidLoad добавьте следующие строки:
  • ВАР х: библиотеки MyLib = MyLib ()
  • println ("(x.привет ())") -

делая это таким образом, приложение зависит от фреймворка, поэтому, если вы внесете изменения в классы фреймворка, вам не придется менять цели для создания фреймворка отдельно, он просто скомпилирует фреймворк сначала, а затем приложение.


Я немного изменил чей-то скрипт для поддержки всех архитектур симулятора:

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}"

старое видео, которое я сделал, так как вышеуказанная ссылка ранее больше не доступна.

как создать Cocoa Touch Framework с помощью Xcode 6


несколько дополнительных моментов вокруг подхода, разделяемого vladof, которые более применимы к фреймворкам на основе swift

  1. скрипт в связанной ссылке нуждается в модификации, чтобы скопировать все файлы из iphonesimulator и iphoneos, так как swift имеет отдельные скомпилированные файлы для arm и i386
  2. убедитесь, что у вас есть ARCHS="x86_64" ONLY_ACTIVE_ARCH=нет в сборке для iphonesimulator, чтобы избежать проблем компоновщика для симулятора
  3. убедитесь, что ваш интерфейс / класс расширяет NSObject, иначе вы столкнетесь с проблемами при попытке использовать код в swift (он будет жаловаться на невозможность создания объекта с помощью ().

наконец, я получил его, чтобы работать на меня! И извините за большую желтую рамку, я понятия не имею, как отформатировать ее лучше.

решение пришло от Клаудио Романди, но связанный скрипт имеет незначительную проблему. Я не могу комментировать его сообщение, потому что мне нужна репутация 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. построить, вы сделали!

проблема заключалась в том, что каталог симулятора указывал на несуществующий каталог, изменяя "Framework" на "${PROJECT_NAME} " в 2 местах, сделал трюк :)


Извините, что я позволил этой теме открыться так долго... Некоторые из вас правильно ответили на мой вопрос. Когда я написал этот вопрос, я не поймал, что было два куска в полной (также называемой жирной) структуре (готовой к использованию). Один для устройств iOS и один для симулятора. Когда я обнаружил, что я сделал сценарий с помощью команды lipo для слияния двух срезов и автоматически получил полную структуру.