> On 25 Mar 2017, at 4:26 AM, Ankit Aggarwal via swift-evolution
> <swift-evolution@swift.org> wrote:
>
> Hi,
>
> We would love to get some feedback on a draft proposal for defining custom
> target layouts in the Package Manager. This proposal allows overriding the
> target layout rules set by the Package Manager and simplifies some complex
> "magic" behaviours.
>
> You can find the proposal at the link below. The text is also included in the
> email.
>
> https://github.com/aciidb0mb3r/swift-evolution/blob/custom-targets-layout/proposals/NNNN-package-manager-custom-targets-layout.md
>
> <https://github.com/aciidb0mb3r/swift-evolution/blob/custom-targets-layout/proposals/NNNN-package-manager-custom-targets-layout.md>
>
> Thanks,
> Ankit
>
> --
>
> Package Manager Custom Targets Layout
> Proposal: SE-NNNN
> <file:///Users/ankit/NNNN-package-manager-custom-targets-layout.md>
> Author: Ankit Aggarwal <https://github.com/aciidb0mb3r>
> Review Manager: TBD
> Status: Discussion
> Bug: SR-29 <https://bugs.swift.org/browse/SR-29>
> Introduction
> This proposal enhances the Package.swift manifest APIs to support custom
> target layouts, and removes a convention which allowed omission of targets
> from the manifest.
>
> Motivation
> The Package Manager uses a convention system to infer targets structure from
> disk layout. This works well for most packages, which can easily adopt the
> conventions, and frees users from needing to update their Package.swift file
> every time they add or remove sources. Adopting the conventions is more
> difficult for some packages, however – especially existing C libraries or
> large projects, which would be difficult to reorganize. We intend to give
> users a way to make such projects into packages without needing to conform to
> our conventions.
>
> The current convention rules make it very convenient to add new targets and
> source files by inferring them automatically from disk, but they also can be
> confusing, overly-implicit, and difficult to debug; for example, if the user
> does not follow the conventions correctly which determine their targets, they
> may wind up with targets they don't expect, or not having targets they did
> expect, and either way their clients can't easily see which targets are
> available by looking at the Package.swift manifest. We want to retain
> convenience where it really matters, such as easy addition of new source
> files, but require explicit declarations where being explicit adds
> significant value. We also want to make sure that the implicit conventions we
> keep are straightforward and easy to remember.
>
> Proposed solution
> We propose to stop inferring targets from disk. They must be explicitly
> declared in the manifest file. The inference was not very useful, as targets
> eventually need to be declared in order to use common features such as
> product and target dependencies, or build settings (which are planned for
> Swift 4). Explicit target declarations make a package easier to understand by
> clients, and allow us to provide good diagnostics when the layout on disk
> does not match the declarations.
>
> We propose to remove the requirement that name of a test target must have
> suffix "Tests". Instead, test targets will be explicitly declared as such in
> the manifest file.
>
> We propose a list of pre-defined search paths for declared targets.
>
> When a target does not declare an explicit path, these directories will be
> used to search for the target. The name of the directory must match the name
> of the target. The search will be done in order and will be case-sensitive.
>
> Regular targets: package root, Sources, Source, src, srcs. Test targets:
> Tests, package root, Sources, Source, src, srcs.
>
> It is an error if a target is found in more than one of these paths. In such
> cases, the path should be explicitly declared using the path property
> proposed below.
>
> We propose to add a factory method testTarget to the Target class, to define
> test targets.
>
> .testTarget(name: "FooTests", dependencies: ["Foo"])
> We propose to add three properties to the Target class: path, sources
> andexclude.
>
> path: This property defines the path to the top-level directory containing
> the target's sources, relative to the package root. It is not legal for this
> path to escape the package root, i.e., values like "../Foo", "/Foo" are
> invalid. The default value of this property will be nil, which means the
> target will be searched for in the pre-defined paths. The empty string ("")
> or dot (".") implies that the target's sources are directly inside the
> package root.
>
> sources: This property defines the source files to be included in the target,
> relative to the target path. The default value of this property will be an
> empty array, which means all valid source files found in the target's path
> will be included. This can contain directories and individual source files.
> Directories will be searched recursively for valid source files. Paths
> specified are relative to the target path.
>
> Each source file will be represented by String type. In future, we will
> consider upgrading this to its own type to allow per-file build settings. The
> new type would conform to CustomStringConvertible, so existing declarations
> would continue to work (except where the strings were constructed
> programatically).
>
>
Is the default not recursively searching for source files? If not, it would be
great to have ways that achieve that, e.g. `*.swift`.
> exclude: This property can be used to exclude certain files and directories
> from being picked up as sources. Exclude paths are relative to the target
> path. This property has more precedence than sources property.
>
> Note: We plan to support globbing in future, but to keep this proposal short
> we are not proposing it right now.
>
> It is an error if the paths of two targets overlap (unless resolved with
> exclude).
>
> // This is an error:
> .target(name: "Bar", path: "Sources/Bar"),
> .testTarget(name: "BarTests", dependencies: ["Bar"], path:
> "Sources/Bar/Tests"),
>
> // This works:
> .target(name: "Bar", path: "Sources/Bar", exclude: ["Tests"]),
> .testTarget(name: "BarTests", dependencies: ["Bar"], path:
> "Sources/Bar/Tests"),
> For C family library targets, we propose to add a publicHeadersPath property.
>
> This property defines the path to the directory containing public headers of
> a C target. This path is relative to the target path and default value of
> this property is include. This mechanism should be further improved in the
> future, but there are several behaviors, such as modulemap generation, which
> currently depend of having only one public headers directory. We will address
> those issues separately in a future proposal.
>
> All existing rules related to custom and automatic modulemap remain intact.
>
> Remove exclude from Package class.
>
> This property is no longer required because of the above proposed per-target
> exclude property.
>
> The templates provided by the swift package init subcommand will be updated
> according to the above rules, so that users do not need to manually add their
> first target to the manifest.
>
> Examples:
> Dummy manifest containing all Swift code.
> let package = Package(
> name: "SwiftyJSON",
> targets: [
> .target(
> name: "Utility",
> path: "Sources/BasicCode"
> ),
>
> .target(
> name: "SwiftyJSON",
> dependencies: ["Utility"],
> path: "SJ",
> sources: ["SwiftyJSON.swift"]
> ),
>
> .testTarget(
> name: "AllTests",
> dependencies: ["Utility", "SwiftyJSON"],
> path: "Tests",
> exclude: ["Fixtures"]
> ),
> ]
> )
> LibYAML
> let packages = Package(
> name: "LibYAML",
> targets: [
> .target(
> name: "libyaml",
> sources: ["src"]
> )
> ]
> )
> Node.js http-parser
> let packages = Package(
> name: "http-parser",
> targets: [
> .target(
> name: "http-parser",
> publicHeaders: ".",
> sources: ["http_parser.c"]
> )
> ]
> )
> swift-build-tool
> let packages = Package(
> name: "llbuild",
> targets: [
> .target(
> name: "swift-build-tool",
> path: ".",
> sources: [
> "lib/Basic",
> "lib/llvm/Support",
> "lib/Core",
> "lib/BuildSystem",
> "products/swift-build-tool/swift-build-tool.cpp",
> ]
> )
> ]
> )
> Impact on existing code
> These enhancements will be added to the version 4 manifest API, which will
> release with Swift 4. There will be no impact on packages using the version 3
> manifest API. When packages update their minimum tools version to 4.0, they
> will need to update the manifest according to the changes in this proposal.
>
> There are two flat layouts supported in Swift 3:
>
> Source files directly in the package root.
> Source files directly inside a Sources/ directory.
> If packages want to continue using either of these flat layouts, they will
> need to explicitly set a target path to the flat directory; otherwise, a
> directory named after the target is expected. For example, if a package Foo
> has following layout:
>
> Package.swift
> Sources/main.swift
> Sources/foo.swift
> The updated manifest will look like this:
>
> // swift-tools-version:4.0
> import PackageDescription
>
> let package = Package(
> name: "Foo",
> targets: [
> .target(name: "Foo", path: "Sources"),
> ]
> )
> Alternatives considered
> We considered making a more minimal change which disabled the flat layouts by
> default, and provided a top-level property to allow opting back in to them.
> This would allow us to discourage these layouts – which we would like to do
> before the package ecosystem grows – without needing to add a fully
> customizable API. However, we think the fuller API we've proposed here is
> fairly straightforward and provides the ability to make a number of existing
> projects into packages, so we think this is worth doing at this time.
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
Regards,
Anders
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution