Зависимость пакета Swift с небезопасными флагами сборки: ошибка целостности цели

TL;DR

Я получаю следующую ошибку для локальной зависимости пакета Swift при попытке использовать его в проекте iOS в Xcode:

The package product 'DlibWrapper' cannot be used as a dependency of this target because it uses unsafe build flags.

(Я использую небезопасные флаги, чтобы указать расположение статической библиотеки)

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

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

Проблема возникает как в Swift 5.2.4 (Xcode 11.6), так и в 5.3 (Xcode 12 beta 3).

Любые подсказки, в чем может быть проблема?


Подробности

Я пытаюсь создать пакет Swift, содержащий библиотеку dlib, и использовать его в приложении для iOS. Из-за платформы я не могу использовать цель .systemLibrary для связывания dlib. Поэтому я предварительно скомпилировал его в статическую библиотеку и упаковал вместе с кодом оболочки следующим образом:

DlibWrapper/
  Libraries/
    dlib/
      include/
          ...
      lib/
        arm64/
          libdlib.a

  Sources/
    CWrapper/
      include/
        module.modulemap
        cwrapper.h
      cwrapper.cpp

    SwiftWrapper/
      SwiftWrapper.swift

  Package.swift

Упрощенное содержание DlibWrapper/Package.swift:

// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "DlibWrapper",
    platforms: [
        .iOS(.v13)
    ],
    products: [
        .library(
            name: "DlibWrapper",
            targets: ["CWrapper", "SwiftWrapper"])
    ],
    dependencies: [],
    targets: [
        .target(
            name: "SwiftWrapper",
            dependencies: ["CWrapper"]
        ),
        .target(
            name: "CWrapper",

            cxxSettings: [.headerSearchPath("../../Libraries/dlib/include")],

            linkerSettings: [
                .linkedLibrary("dlib"),
                .linkedFramework("Accelerate", .when(platforms: [.iOS])),

                // The error is caused by this line
                .unsafeFlags(["-LLibraries/dlib/lib/arm64"], .when(platforms: [.iOS])),
            ]
        ),
    ],
    cxxLanguageStandard: .cxx1z
)

Я пытался использовать свойство link внутри module.modulemap, но компилятор, похоже, его игнорирует. Кроме того, указание абсолютного пути к библиотеке в .linkedLibrary() в целевом манифесте не помогает, компоновщик жалуется, что не может найти библиотеку.

Есть идеи обходных путей? (В крайнем случае я бы, наверное, все упаковал в фреймворк)

Был бы признателен за любую помощь.

Спасибо


person Boris    schedule 23.07.2020    source источник
comment
Я тоже только что столкнулся с этим. Мое решение - прекратить попытки создавать Swift Packages из сторонних библиотек. Вместо этого я попытаюсь создать для них проекты Xcode.   -  person Rick    schedule 19.04.2021


Ответы (1)


Обновлять

Оказывается, приведенный ниже метод на самом деле не работает. Swift полностью игнорирует .linkedLibrary, когда пакет компилируется как статическая библиотека (проверьте с swift build --verbose). Этот параметр используется только с динамическими библиотеками. Тем не менее синтаксис : в последнем случае ничего не делает - библиотеку все равно не найти.

(Ответ ниже сохранен по историческим причинам, возможно, это поможет кому-то найти решение)


Старый ответ

Обходной путь - использовать синтаксис двоеточия clang / gcc в параметрах компоновщика, то есть -l: (минус-эль-двоеточие). Дополнительные сведения см. В этом ответе.

Вот соответствующий фрагмент из манифеста пакета:

// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "DlibWrapper",
    //...
    targets: [
        //...
        .target(
            name: "CWrapper",

            cxxSettings: [.headerSearchPath("../../Libraries/dlib/include")],

            linkerSettings: [
                // Note the `:` in front of the relative path
                .linkedLibrary(":Libraries/dlib/lib/arm64/libdlib.a", .when(platforms: [.iOS])),
                //...
            ]
        ),
    ],
    //...
)

Объяснение

Необходимая настройка .linkedLibrary компоновщика предоставляет компоновщику флаг -l. Итак, все, что вы указали в качестве параметра, будет преобразовано во что-то вроде этого

swift build -Xlinker -l<your-linkedLibrary-string>

Синтаксис : позволяет указать библиотеку с неканоническим именем, то есть с фактическим именем файла. Наконец, поскольку рабочий каталог компоновщика настроен на корневой каталог пакета, мы можем указать ему относительный путь к библиотеке.

Я по-прежнему считаю это обходным решением, потому что правильным способом было бы иметь что-то вроде librarySearchPath, то есть -L вариант компоновщика, аналогичный headerSearchPath в cxxSettings.

person Boris    schedule 24.07.2020