Xcode 4 не может найти общедоступные файлы заголовков из зависимости статической библиотеки

Альтернативные заголовки для поиска

  • Xcode не может найти заголовок
  • Отсутствует .h в Xcode
  • Файл Xcode.h не найден.
  • Файл с лексическим или препроцессорным выпуском не найден.

Я работаю над проектом приложения iOS, который появился в Xcode 3. Теперь я перешел в Xcode 4, мой проект создает несколько статических библиотек.

Эти статические библиотеки также объявляют публичные заголовки, а те заголовки используются кодом приложения. В Xcode 3.x заголовки были скопированы (как фаза сборки) в public headers directory, а затем в проект приложения public headers directory был добавлен в headers search list.

В Xcode 4 каталог сборки перемещается в ~/Library/Developer/Xcode/DerivedData/my-project.

Проблема в том, как я могу ссылаться на это новое местоположение в настройках поиска заголовков? Кажется, что:

  • public headers directory относится к каталогу DerivedData, но
  • headers search каталог относится к чему-то другому (возможно, к месту проекта)

Как настроить статическую библиотечную цель для разработки iOS в Xcode 4, которая обеспечит доступ к файлам заголовков для клиентов, которые используют статическую библиотеку при попытке скомпилировать как зависимость?

Ответ 1

Проект Xcode 4 Не удается скомпилировать статическую библиотеку

Связанный вопрос: "файл с лексической или препроцессорной проблемой не найден" в Xcode 4

Ошибки могут включать: отсутствующие файлы заголовков, "лексическая или препроцессорная проблема"

Решения:

  • Проверьте правильность "путей заголовка пользователя".
  • Установите "Всегда искать пути пользователя" к YES
  • Создайте групповой вызов "Заголовки индексирования" в вашем проекте и перетащите заголовки в эту группу, НЕ добавляйте к каким-либо объектам при появлении запроса.

Ответ 2

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

Короткий ответ

Добавьте следующий путь к пути поиска заголовка пользователя

"$ (BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts"

Почему это работает?

Во-первых, нам нужно понять проблему. При нормальных обстоятельствах, то есть при запуске, тестировании, профиле или анализе, Xcode создает проект и помещает его в каталог Build/Products/Configuration/Products, доступный через $BUILT_PRODUCTS_DIR макрос.

В большинстве руководств, касающихся статических библиотек, рекомендуется установить Путь к папке Public Headers $TARGET_NAME, что означает, что ваш файл lib станет $BUILT_PRODUCTS_DIR/libTargetName.a и ваши заголовки помещаются в $BUILT_PRODUCTS_DIR/TargetName. Пока ваше приложение включает $BUILT_PRODUCTS_DIR в пути поиска, импорт будет работать в 4 приведенных выше ситуациях. Однако при попытке архивирования это не сработает.

Архивирование работает немного иначе

При архивировании проекта Xcode использует другую папку с именем ArchiveIntermediates. В этой папке вы найдете /YourAppName/BuildProductsPath/Release -iphoneos/. Это папка, на которую указывает $BUILT_PRODUCTS_DIR, когда вы делаете архив. Если вы посмотрите там, вы увидите, что есть символическая ссылка на ваш встроенный файл статической библиотеки, но папка с заголовками отсутствует.

Чтобы найти заголовки (и файл lib), вам нужно перейти в IntermediateBuildFilesPath/UninstalledProducts/. Помните, когда вам сказали установить Пропустить установку в YES для статических библиотек? Ну, это эффект, который возникает при создании архива.

Примечание: если вы не установите его для пропустить установку, ваши заголовки будут помещены в другое место, и файл lib будет скопирован в ваш архив, что помешает вам экспортировать файл .ipa, который вы можете отправить в App Store.

После большого поиска я не смог найти какой-либо макрос, который соответствует папке UninstalledProducts, и, следовательно, нужно построить путь с помощью "$ (BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts"

Резюме

Для вашей статической библиотеки убедитесь, что вы пропустили установку и что ваши публичные заголовки помещены в $TARGET_NAME.

Для вашего приложения задайте пути поиска заголовка пользователя на "$ (BUILT_PRODUCTS_DIR)", который отлично подходит для регулярных сборок и "$ (BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts" , который работает для архивных сборок.

Ответ 3

Я столкнулся с этой проблемой при разработке моей собственной статической библиотеки, и хотя ответ Колина был очень полезен, мне пришлось немного изменить его, чтобы работать последовательно и просто, когда выполняются и архивируются проекты под Xcode 4 с использованием Workspace.

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

Мой метод выглядит следующим образом:

Создать рабочее пространство

  • В разделе Xcode 4 перейдите в File, New, Workspace.
  • Из Finder вы можете перетащить проекты .xcodeproj как для статической библиотеки, которую вы хотите использовать, так и для нового приложения, которое вы создаете, используя библиотеку. Дополнительную информацию о настройке рабочих областей см. В документах Apple: https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Workspace.html

Настройки проекта статической библиотеки

  • Убедитесь, что все заголовки статической библиотеки настроены на копирование в "Публичный". Это делается в настройках целевой статической библиотеки > Build Phases. На этапе "Копирование заголовков" убедитесь, что все ваши заголовки находятся в разделе "Публикация".
  • Далее перейдите в раздел "Настройка параметров", найдите "Путь к папке общих заголовков" и введите путь к вашей библиотеке. Я решил использовать это:

включают в себя /LibraryName

Я принял это от использования с RestKit и нашел, что он работает лучше всего со всеми моими статическими библиотеками. Это означает, что Xcode копирует все заголовки, которые мы переместили в раздел "Публичные" заголовки на шаге 1, в папку, указанную здесь, которая находится в папке "Производные данные" при создании. Как и в RestKit, мне нравится использовать единую папку "include" , чтобы содержать каждую статическую библиотеку, которую я использую в проекте.

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

  1. Найдите "Пропустить установку" и убедитесь, что для этого параметра установлено значение "YES".

Настройки для проекта с использованием статической библиотеки

  • Добавить статическую библиотеку в качестве фреймворка в разделе "Фазы построения" > "Связать двоичные файлы с библиотеками" и добавить файл libLibraryName.a для любой статической библиотеки, которую вы хотите использовать.
  • Затем убедитесь, что для проекта задано поиск путей поиска пользователей. Это делается в разделе "Настройки сборки" > "Всегда искать пользовательские пути" и убедитесь, что для него установлено значение "ДА".
  • В этой же области найдите пути поиска заголовка пользователя и добавьте:

    "$ (PROJECT_TEMP_DIR)/../UninstalledProducts/включить"

Это говорит Xcode искать статические библиотеки в промежуточной сборке, которую Xcode создает во время процесса сборки. Здесь мы имеем папку "include" , которую мы используем для наших статических мест библиотек, которые мы устанавливаем на шаге 2 для параметров проекта статической библиотеки. Это самый важный шаг в том, чтобы заставить Xcode правильно находить ваши статические библиотеки.

Настроить рабочее пространство

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

  • Убедитесь, что вы выбрали схему, которая создаст ваше приложение.
  • В раскрывающемся меню выберите "Редактировать схему".
  • Выберите "Сборка" в верхней части списка слева. Добавьте новую цель, нажав + на средней панели.
  • Вы должны увидеть, как появляется статическая библиотека для библиотеки, которую вы пытаетесь установить. Выберите статическую библиотеку iOS.
  • Нажмите "Выполнить" и "Архив". Это сообщает схеме компиляции библиотек для статической библиотеки всякий раз, когда вы создаете приложение.
  • Перетащите статическую библиотеку над целевым объектом приложения. Это заставляет статические библиотеки компилироваться до назначения вашего приложения.

Начать использование библиотеки

Теперь вы можете импортировать свою статическую библиотеку, используя

import <LibraryName/LibraryName.h>

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

Зачем это работает?

Все зависит от этого пути:

"$(PROJECT_TEMP_DIR)/../UninstalledProducts/include"

Поскольку мы настраиваем нашу статическую библиотеку на использование "Пропустить установку", скомпилированные файлы перемещаются в папку "UninstalledProjects" во временном каталоге сборки. Наш путь здесь также разрешает папку "include" , которую мы устанавливаем для нашей статической библиотеки, и используем для нашего пути поиска заголовка пользователя. Обе команды вместе позволяют Xcode знать, где найти нашу библиотеку во время процесса компиляции. Поскольку этот временный каталог сборки существует для конфигураций Debug и Release, вам нужен только один путь для Xcode для поиска статических библиотек.

Ответ 4

Это был очень полезный поток. Изучая мою собственную ситуацию, я обнаружил, что Apple имеет 12-страничный документ от сентября 2012 года под названием "Использование статических библиотек в iOS". Здесь ссылка pdf: http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf

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

Если у вашей целевой библиотеки есть фаза сборки "Копирование заголовков", вы должны удали это; фаз сборки заголовков копий не работают корректно со статическими библиотеки при выполнении действия "Архив" в Xcode.

Появятся новые цели статической библиотеки, созданные с помощью Xcode 4.4 или более поздней версии с соответствующим образом сконфигурированной фазой "Копировать файлы" для заголовков, так что вы должен проверить, есть ли у вас уже один файл перед его созданием. Если вы не хотите, нажмите "Добавить фазу сборки" в нижней части целевого редактора и выберите "Добавить файлы копирования". Раскрыть новую сборку копий файлов и установите пункт назначения в "Каталог продуктов". Установить подпуть для включения /${PRODUCT_NAME}. Это скопирует файлы в папку с именем после вашей библиотеки (взятой из настройки сборки PRODUCT_NAME), внутри папка с именем include, внутри каталога ваших встроенных продуктов. включить папку внутри каталога продуктов сборки по умолчанию путь поиска заголовков для приложений, поэтому это подходящее место для размещения файлов заголовков.

Я уверен, что во многих существующих ситуациях подход Apple может быть недостаточным. Я размещаю это здесь для всех, кто только начинает свое путешествие по старинному садовому пути библиотеки - это может быть лучшей отправной точкой для простых случаев.

Ответ 5

http://developer.apple.com/library/ios/#technotes/iOSStaticLibraries/Articles/creating.html

Документация Apple Apple:

В вашей библиотеке будет один или несколько файлов заголовков, которые должны импортировать клиенты этой библиотеки. Чтобы настроить, какие заголовки экспортированы на клиенты, выберите проект библиотеки, чтобы открыть редактор проекта, выберите цель библиотеки, чтобы открыть целевой редактор, и выберите вкладку фаз сборки. Если целевой объект библиотеки имеет фазу сборки "Копирование заголовков", вы должны удалить ее; фаз сборки заголовков копий не работают корректно с задачами статической библиотеки при выполнении действия "Архив" в Xcode.

Ответ 7

Добавьте $(OBJROOT)/UninstalledProducts/exactPathToHeaders в маршруты поиска заголовков.

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

В окне "Навигатор журнала" в Xcode (вкладка справа от навигатора точек останова) вы можете увидеть историю сборки. Если вы выберете фактический сбой сборки, вы можете развернуть его детали, чтобы увидеть setenv PATH, и убедитесь, что существует путь к вашим файлам заголовков.

Ответ 8

Добавьте следующий путь к путям поиска заголовка пользователя:

$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts

Это проверено!

Ответ 9

Рискуя показать, что такое идиот, я... Я страдал от XCode, отказавшегося найти мои файлы .h во все дни.

Тогда я понял.

Поскольку я использовал "XCode 4", я "разумно" решил поместить все мои проекты в подпапки папки " XCode 4 projects".

Эти пробелы в имени папки перепутали XCode в большое время!

Переименование этой папки на " XCode_4_Projects" принесло радость (и меньше клятвы) обратно в мою жизнь.

Напомнить мне еще раз, в каком году это?

Возможно, кто-то может сказать разработчикам Apple...

Ответ 10

Ни один из этих ответов не работал у меня. Вот что. Добавьте следующее точно (копирование и вставка, включая двойные кавычки) в настройку сборки Пользовательские пути поиска:

"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/include/"

Обратите внимание на добавление подкаталога "/include/" по сравнению с другими ответами. Как указывали другие пользователи, "рекурсивный" вариант, похоже, ничего не делает, поэтому вы можете игнорировать его.

Мой проект теперь смог успешно архивировать при импорте файлов заголовков статической библиотеки в следующем виде:

#import "LibraryName/HeaderFile.h"

Вам нужно не включить параметр Всегда искать пользовательские пути, если вы не включаете заголовки статической библиотеки с угловыми скобками (#import <LibraryName/HeaderFile.h>), но вы действительно должны Так или иначе, если это не заголовок системы/структуры.

Ответ 11

Ни один из ответов выше не работал у меня на Xcode 7, но они дали мне хорошую идею. Для парней, борющихся с Xcode 7, я получил это исправление, добавив следующие пути поиска пользователей (включая цитаты)

"$(BUILT_PRODUCTS_DIR)/usr/local/include"

Измените относительную часть URL usr/local/include в соответствии с тем, что находится в настройке статической библиотеки "Открытый заголовок папки"

Ответ 12

В моем случае у моей рабочей области было несколько статических проектов библиотеки, и у одной из них есть зависимость, включая заголовочные файлы, с другой. Вопрос был с порядком строительства. На странице "Редактировать схему" в разделе "Сборка" я отменил выбор параметра "Распараллеливать" и упорядочил порядок целей в зависимости от зависимостей и решил проблему

Ответ 13

Это связанная с этим проблема, которая привела меня к этому вопросу, поэтому я добавляю свое решение строго для документации/он может спасти еще несколько часов души потливости

Файл DropboxSDK.h не найден

После нескольких попыток получить VES для компиляции для iOS я в конечном итоге столкнулся с этой проблемой. DropboxSDK.h был определенно доступен для search headers Я даже добавил его к пути поиска framework headers, include d the .h напрямую и перешел на всевозможные большие длины, чтобы попытаться найти DropboxSDK.h.

Решение

EXPLICITY перетащите файл DropboxSDK.framework в Xcode Project Navigation и убедитесь, что отмечен Copy Files if needed. Также убедитесь, что ваша цель проверена по мере необходимости.

Внимание

Настройка явного расположения фреймов в build phases не помогла мне. Мне пришлось перетащить .framework в Xcode и убедиться, что файлы скопированы в мой проект.

# mbp2015 # xcode7 # ios9

Ответ 14

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

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

  • Каждый раз, когда вам нужно начинать новый проект с помощью своей библиотеки и архивировать его для iTunes, это аддон конфигурации.
  • Каждый раз, когда вам нужно поделиться своим проектом с вашей командой или клиентами, она может сломаться по любой причине (контекст, Версия Xcode, что угодно,..)

Мой выбор, наконец, просто использовал фреймворки - всегда - как рекомендовано Apple (WWDC Videos).

Это так проще и делает ту же работу в конце!

Другим довольно элегантным решением, которое, похоже, работает, является использование Private Cocoapods. Cocoapods выполняет всю работу по настройке, заголовок и т.д.

Рамки Rocks!

Ответ 15

Вот для меня эта проблема решена.

У меня есть приложение Target и iMessage Extension Target. Затем у меня было 2 SDK (мой собственный), к которым привязана ссылка приложения.

Проблема заключалась в том, что моя цель iMessage также использовала мои собственные SDK (отдельные проекты), но она не связывалась с ними в Build Phases → Link Binary With Libraries. Я должен был добавить свои 2 SDK в iMessage Target там, чтобы соответствовать цели моего приложения, и теперь он архивирует.

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

Ответ 16

Сохраните проблему и сделайте это = создайте новую учетную запись на своем Mac - откройте проект под новой учетной записью пользователя - все проблемы исчезнут. Сэкономьте свое время и держите свое здравомыслие. все эти болтливые ответы не помогают!

Удача