【Vapor】”error: could not find target(s)”というエラーを解決する


この記事は NIFTY Advent Calendar 2017 の9日目の記事です。

8日目は@dev_foodsさんの「開発が捗る便利なRubyライブラリ」でした。


最近、Swift書きたいな〜けどiOSじゃなくてWEBが書きたいな〜ということで、
Vaporというフレームワークを使って、サーバーサイドSwiftを書いております。

この記事では自分がVaporで作ったWEBアプリを紹介する予定だったのですが、
とあるエラーでかなり長いことハマってしまい、完成までに至りませんでした。なかなか情報がなく苦戦したので、ここに残しておこうと思います。

そのエラーとは・・・この後すぐ!

環境 バージョン
MacOS HighSierra
Xcode 9
Swift 4
Vapor Toolbox 3.1.2
Vapor Framework 2.3.0

error: could not find target(s): App; use the 'path' property in the Swift 4 manifest to set a custom target path

PackageにMySQLProviderを追加し、Modelを組みこみ、いったんvapor buildしてみよう、という矢先の出来事です。突然ビルドができなくなりました。

エラーメッセージを見ると、Command: build --enable-prefetchingと書いてあるので、そのオプションをつけてもう一度buildしてみます。

Building Project [Failed]

Command:
build --enable-prefetching --enable-prefetching=true

Error (1):
error: could not find target(s): App; use the 'path' property in the Swift 4 manifest to set a custom target path

同様のメッセージで怒られてしまいます。
直訳すると、「Swift4のマニフェストでは、カスタムターゲットパスを設定する際、targetのAppはpathのプロパティを使え」と言っています。詳しく調べてみましょう。

Package.swiftの記法をSwift4に対応する

https://github.com/apple/swift-evolution/blob/master/proposals/0162-package-manager-custom-target-layouts.md#impact-on-existing-code
によれば、Package.swiftの記法を4にアップデートせよと書いています。以前、Package.swiftで悩んだ際にそれは対応したと思っていたのですが・・・

Package.swift
// swift-tools-version:4.0

import PackageDescription

let package = Package(
    name: "project",
    products: [
        .library(name: "App", targets: ["App"]),
        .executable(name: "Run", targets: ["Run"])
    ],
    dependencies: [
        .package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "2.2.0")),
        .package(url: "https://github.com/vapor/leaf-provider.git", .upToNextMajor(from: "1.1.0")),
        .package(url: "https://github.com/vapor/mysql-provider.git", .upToNextMajor(from: "2.0.0")),
        .package(url: "https://github.com/vapor/auth-provider.git", .upToNextMajor(from: "1.0.0"))
    ],
    targets: [
        .target(
            name: "App",
            dependencies: ["Vapor", "LeafProvider","MySQLProvider"],
            exclude: [
                "Config",
                "Database",
                "Public",
                "Resources",
               ]
        ),
        .target(name: "Run", dependencies: ["App"]),
        .testTarget(name: "AppTests", dependencies: ["App", "Testing"])
    ]
)

たしかに、targetの"App"のところでpathのプロパティが記述されていません。
path:"Sources"を追記してみます。

怒られた

Error (1):
error: manifest parse error(s):
/Users/ys/blogUI/project/Package.swift:21:13: error: argument 'dependencies' must precede argument 'path'
dependencies: ["Vapor", "LeafProvider","MySQLProvider"],
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ほー、じゃあpathをdependenciesの後に書けばいけそう!修正してみます。
```

また怒られた

Error (1):error: target 'Run' has sources overlapping sources: /Users/ys/blogUI/project/Sources/Run/main.swift

Runとソースが重複していると怒られました。package.swiftを触って解決できる問題ではなさそうです。
別の方向から攻めます。

classをPublicにしてみる

新しいclassを作成して以降発生した問題なので、こちらの記事を参考にclassをpublicにしてみます。→Vaporで新規ファイルを追加したら

結果:直らない。

新規追加したclassを全てコメントアウトするなどしたのですが、最初のエラーが発生し続けます。
問題は別のところにありそうですが、全然検討がつきません。手詰まりです。

勇気を振り絞ってSlackで質問してみる

エラーメッセージには必ず

Help:
Join our Slack where hundreds of contributors
are waiting to help: http://vapor.team

といったことが最後に書いてあるので、思い切って以上のことを質問してみます。


「テンプレートからプロジェクトを始めた?? /Sourcesや/Tests以下のファイルとかrenameやremoveとかしてないですか?」とのことです。記憶にはありませんが、なんだかrenameはやってそうな雰囲気です。

さらに、Xcodeのファイル名の右に記されている「R」、これは何かしら悪いことが怒っていることを示唆しているらしい。これは間違いなくやらかしています。

・・・ということで、表題のエラーの解決策は、
1.フォルダ構成を正しいプロジェクトを真似しながら元の状態に戻す
2.一から作る
のどちらかになります。追加したコード量が少ない場合は2を選んだほうが楽です。どっちにしろめんどくさいですが、、、

エラーの原因を見つけるのも、解決するのも、思った以上に苦戦してしまいました。
Vaporのプロジェクトは気軽な気持ちでrenameしたりフォルダ構成を変えたりしてはいけません!!
気をつけましょう!

最後になりますが、VaporのSlackはかなり活発にやりとりが行われており、困った時のレスポンスも速く、他のやりとりも勉強になるなと感じました。
Vaporを始める際はぜひ参加してみましょうhttp://vapor.team

明日の記事は@kazuyaseoさんです。よろしくお願いします!