0

我正在编写一个可执行的 Swift 包,我需要在其中使用系统库(用 C++ 编写)。

AFAIK 我正确编写了 package.swift、module.modulemap 和伞头文件。

当我import在我的文件中添加库时,我main.swift收到一个错误'stdexcept' file not found。该错误来自#include <stdexcept>系统库的公共头文件之一。

当前运行:

  • XCode v13.2.1
  • macOS v12.2.1(蒙特雷)

我认为这个问题与 XCode 的命令行工具有关,但我不确定如何解决它。帮助!

包.swift

// swift-tools-version:5.5
import PackageDescription

let package = Package(
    name: "GeodesicApp",
    platforms: [.macOS(.v11)],
    dependencies: [
    ],
    targets: [
      .systemLibrary(name: "geographiclib",
                     pkgConfig: "geographiclib",
                     providers: [
                      .brew(["geographiclib"])
                     ]
                    ),
        .executableTarget(
            name: "GeodesicApp",
            dependencies: ["geographiclib"])
    ]
)

模块.modulemap

module geographiclib {
  umbrella header "geographiclib.h"
  export *
  link "geographiclib"
}

伞头(geographiclib.h)

#include <GeographicLib/Config.h>
#include <GeographicLib/Geodesic.hpp>

main.swift

import geographiclib     // error: 'stdexcept' file not found

...  // 

错误。 XCode 错误

4

1 回答 1

0

回答我自己的问题。我只能通过围绕系统库创建一个 C 包装程序包来获得一个可行的解决方案;然后,该 C 包装器包又被另一个 Swift 包装器包装,以公开“Swifty 风格”代码——我无法获得包含所有必需部分的单个包。

我的工作解决方案如下......

包:CGeographicLib

系统库的 C 包装器的文件夹结构是:

.
├── Package.swift
├── README.md
└── Sources
    ├── CGeographicLib
    │   ├── CGeodesic.cpp
    │   └── include
    │       └── CGeodesic.h
    └── geographiclib
        ├── geographiclib.h
        └── module.modulemap

更新Package.swift

import PackageDescription

let package = Package(
    name: "CGeographicLib",
    platforms: [.macOS(.v11)],
    products: [
      .library(name: "CGeographicLib", targets: ["CGeographicLib"])
    ],
    targets: [
      .systemLibrary(name: "geographiclib",
                     pkgConfig: "geographiclib",
                     providers: [
                      .brew(["geographiclib"])
                     ]),
      .target(name: "CGeographicLib", dependencies: ["geographiclib"])
    ],
    cxxLanguageStandard: .cxx20
)

我添加platforms: [.macOS(.v11)]的最新版本的GeographicLib系统库只支持macOS v11或更高版本。

我正在使用的系统库有一些 C++11 扩展,我添加了语言标准.cxx20,但这同样可以.cxx11,它应该仍然适用于我正在使用的系统库。

更新module.modulemap

module geographiclib [system] {
  umbrella header "geographiclib.h"
  link "geographiclib"
  export *
}

伞头,geographiclib.h不变。

对于新的 C 包装器元素 CGeodesic.h

#ifdef __cplusplus
extern "C"  {
#endif

double geoLibInverse(double lat1, double lon1, double lat2, double lon2);

#ifdef __cplusplus
}
#endif

CGeodesic.cpp

#include "include/CGeodesic.h"
#include "../../geographiclib/geographiclib.h"

double geoLibInverse(double lat1, double lon1, double lat2, double lon2) {
  
  using namespace std;
  using namespace GeographicLib;
  
  Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
  double s12;
  geod.Inverse(lat1, lon1, lat2, lon2, s12);
    
  return s12;
}

包:SwiftyGeographicLib

使用 C 包装器包的 Swift 包的文件夹结构是:

.
├── Package.swift
├── README.md
├── Sources
│   └── SwiftyGeographicLib
│       └── Geodesic.swift
└── Tests
    └── SwiftyGeographicLibTests
        └── SwiftyGeographicLibTests.swift

Package.swift

import PackageDescription

let package = Package(
    name: "SwiftyGeographicLib",
    platforms: [.macOS(.v11)],
    products: [
        .library(
            name: "SwiftyGeographicLib",
            targets: ["SwiftyGeographicLib"]),
    ],
    dependencies: [
      .package(name: "CGeographicLib",
               url: "/Users/kieran/codeProjects/z.TestProjects/SPM/CGeographicLib",
               branch: "master")
    ],
    targets: [
        .target(
            name: "SwiftyGeographicLib",
            dependencies: ["CGeographicLib"]),
        .testTarget(
            name: "SwiftyGeographicLibTests",
            dependencies: ["SwiftyGeographicLib"]),
    ]
)

这个例子中的包依赖指向一个本地包——我同样可以在 GitHub 上上传并创建一个版本标签。

Geodesic.swift

import Foundation
import CGeographicLib

public func geodesicInverse(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Double {
  
  return geoLibInverse(lat1, lon1, lat2, lon2)
}
于 2022-02-21T14:43:41.870 回答