`skip init` should create `Package.swift` in a subdirectory
Apropos #448, the Xcode workspace structure for a generated project is (still) extremely strange.
skip init creates an Xcode project .xcodeproj in the ./Darwin folder, and creates a ./Package.swift file in the generated root folder.
To make the generated library visible in the project, the root ./ folder is added to the .xcodeproj by reference, and the library name e.g. ModuleName is added as a dependency of the app project. A few file references are tossed in to the project, too, including README.md, Skip.env, and Localizable.xcstrings.
I think the normal way to have an app project that references a Swift library is to have the library appear in a ModuleName subdirectory next to the Darwin directory. Instead of:
Project.xcworkspace
Darwin/ModuleName.xcodeproj
Package.swift
Sources/ModuleName/ModuleNameApp.swift
It would look like this:
Project.xcworkspace
Darwin/ModuleName.xcodeproj
ModuleName/Package.swift
ModuleName/Sources/ModuleNameApp.swift
This would make the project structure much less confusing, IMO.
skip init and skip create can generate either a library or an app project. The latter option is just an expansion of the first, but with additional Darwin/ and Android/ folders that house the platform-specific app build files. In both cases, the project's structure is dominated by the fact that it is a pure SwiftPM project, which requires that the Package.swift file be in the top directory if other packages are to be able to use it as a dependency.
The current arrangement is admittedly non-standard compared to a traditional Xcode-oriented project setup, but it provides consistency between library and application projects.
The point of my bug is that the current layout makes skip application projects and library projects inconsistent inside a workspace.
Today, when skip create creates a basic app, it's creating three things:
- A Skip-enabled SwiftPM project rooted at the top level,
project-name/Package.swiftwhich includesproject-name/Sources/ModuleName/ModuleNameApp.swift - A workspace, also rooted at the top level,
project-name/Project.xcworkspace - The app's
project-name/Darwin/ModuleName.xcodeproj, which isn't (and can't be) a pure SwiftPM project.
When skip create creates a library package, it only does #1.
But if you're working on multiple top-level library packages inside one workspace (e.g. if you're hacking on skip-ui), you then have to create your own workspace and stop using the auto-generated workspace.
[Example A: Hacking on skip-ui in today's status quo]
ManuallyCreated.xcworkspace
project-name/Project.xcworkspace <-- now you must stop using this
project-name/Darwin/ModuleName.xcodeproj
project-name/Package.swift
project-name/Sources/ModuleName/ModuleNameApp.swift
skip-ui/Package.swift
It would be more consistent for the App's SwiftPM project to live in a subdirectory of the workspace folder, just like skip-ui.
[Example B: Hacking on skip-ui in my proposed layout]
Project.xcworkspace
Darwin/ModuleName.xcodeproj
project-name/Package.swift
project-name/Sources/ModuleNameApp.swift
skip-ui/Package.swift
Then, users who wanted to add a new Skip SwiftPM package to their workspace could run skip create in the workspace folder, creating a new sibling to the core app's package.
But if you're working on multiple top-level library packages inside one workspace (e.g. if you're hacking on skip-ui), you then have to create your own workspace and stop using the auto-generated workspace.
What makes you think that? One of the reasons we now create a Project.xcworkspace is to facilitate exactly that scenario. E.g., here is Showcases's Project.xcworkspace with a local SkipUI checkout developed alongside it.