Проблема
Основная проблема - конфликты заголовочных файлов, поскольку ncurses также предоставляется в /Applications/Xcode.app/.../MacOSX10.14.sdk/usr/include.
Обычное решение на чистом C в таких ситуациях состоит в том, чтобы просто указать пользовательские каталоги include и lib с ключом -I reverse -L, и это сработает, см. мой ответ относительно C ncurses здесь: https://stackoverflow.com/a/56623033/2331445
Этот подход не работает с менеджером пакетов Swift.Но это не значит, что это невозможно без особых усилий.
Возможное решение
Нам нужно убедиться, что заголовочные файлы ncurses, предоставляемые macOS SDK,игнорируются.Мы можем сделать это, указав параметр -Xcc -D__NCURSES_H для команды быстрой сборки.
Это работает, потому что в заголовочном файле есть такая типичная проблема:
#ifndef __NCURSES_H
#define __NCURSES_H
...
#endif
ПроблемаКонечно, это влияет на нашу пользовательскую установку ncurses с использованием Brew.Но мы можем обойти это:
- скопировать новые заголовочные файлы ncurses в наш каталог Sources / Cncurses
- заменить __NCURSES_H через что-то другое, например, __CNCURSES_H (обратите внимание на ведущий 'C')
- , затем убедитесь, что все последующие вложенные включения сначала ищутся в нашем локальном каталоге включений, заменив угловые скобки включений на кавычки, поэтому, например, вместо
#include <ncursesw/unctrl.h>
форма '#include' ncursesw / unctrl.h«» используется
На самом деле это можно сделать с помощью следующих команд командной строки:
cd Sources/Cncurses
cp -r /usr/local/Cellar/ncurses/6.1/include include
find . -name '*.h' -exec sed -i '' 's/__NCURSES_H/__CNCURSES_H/g' {} \;
find . -name '*.h' -exec sed -i '' -E -e "s/<(.*(`find . -name '*.h' -exec basename {} \; | paste -sd "|" -`))>/\"\1\"/g" {} \;
Последнее утверждение может потребовать некоторого объяснения.С помощью команды echo вы можете посмотреть на сгенерированное выражение sed, т.е. если вы выполните
echo "s/<(.*(`find . -name '*.h' -exec basename {} \; | paste -sd "|" -`))>/\"\1\"/g"
, вы получите следующий вывод:
s/<(.*(termcap.h|form.h|term.h|panel.h|ncurses.h|termcap.h|cursesp.h|cursesf.h|etip.h|form.h|cursesw.h|nc_tparm.h|unctrl.h|cursesapp.h|term.h|cursslk.h|panel.h|ncurses.h|tic.h|eti.h|ncurses_dll.h|term_entry.h|menu.h|cursesm.h|curses.h|curses.h|cncurses.h))>/"\1"/g
Как видите,он ищет и заменяет только локальные доступные включаемые файлы.
Test
Для теста нам понадобится простая программа-пример ncurses.Он должен быть собран, и мы должны убедиться, что используется правильная версия библиотеки.
module.modulemap
Мой заголовочный файл называется cncurses.h.Файл module.modulemap выглядит следующим образом:
module cncurses [system]
{
umbrella header "cncurses.h"
link "ncurses"
export *
}
cncurses.h
cncurses.h - это однострочный файл, он импортирует наш скопированный и настроенный файл ncurses.hфайл из нашей локальной папки include:
#include "include/ncurses.h"
main.swift
В папке NcursesExample у нас есть main.swift, где у нас есть простое приложение cncurses swift:
import cncurses
initscr()
curs_set(0)
move(5, 10)
addstr("NCURSES")
move(10, 10)
addstr("Hello World!")
refresh()
select(0, nil, nil, nil, nil)
Package.swift
Обратите внимание, здесь pkgConfig: "ncurses"
в системе. Цели библиотеки:
// swift-tools-version:5.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "NcursesExample",
dependencies: [
],
targets: [
.systemLibrary(name: "cncurses", pkgConfig: "ncurses"),
.target(name: "NcursesExample", dependencies: ["cncurses"]),
.testTarget(
name: "NcursesExampleTests",
dependencies: ["NcursesExample"]),
]
)
Сборка
Чтобы pkg-config правильно выполнял свою работу, мы должны сначала вызвать следующее:
export PKG_CONFIG_PATH="/usr/local/opt/ncurses/lib/pkgconfig"
Наконец, мы начинаем сборку с:
swift build -Xcc -D__NCURSES_H
ИтакСначала мы должны проверить, была ли использована правильная библиотека ncurses.Мы можем сделать это с помощью:
otool -L .build/x86_64-apple-macosx/debug/NcursesExample
Среди других строк вывод содержит следующее:
/usr/local/opt/ncurses/lib/libncursesw.6.dylib (compatibility version 6.0.0, current version 6.0.0)
, что выглядит многообещающе.
Наконец, вызов двоичного файла:
Проект Xcode
Если вы хотите создать проект Xcode, используйте следующую команду:
swift package generate-xcodeproj
Затем загрузите проект в Xcode и
- выберите узел проекта
- в настройках сборки введите Preprocessor в поле поиска в правом верхнем углу
- под Apple Clang - Макросы предварительной обработки / предварительной обработки добавляют __NCURSES_H = 1 для отладки и выпуска