Allowing further module organization


(Max Howell) #1

SwiftPM is a pioneer for SwiftPM, and thus we have many modules. For some of these modules I’d like to split them out even more eg:

- Sources
    - Build

Build is a module, but really I’d like:

- Sources
    - Build
        - BuildNode
        - BuildDescription

If I do this currently I still will end up with one module: `Build`, this is how the module layout rules that SwiftPM uses work. But instead I’d like Build to be purely an organizational folder and to get two modules *BuildNode* and *BuildDescription*.

I’d like to propose some method to allow further organization, but without ruining our existing rules.

I’d also like to propose tightening up our rules a little.

···

—————————

One clear way to accomplish the first goal is to extend the rules and say empty folders are not considered modules.

I am unhappy with this however, already there are easy ways to completely transform the build of a package, and the rules we have are somewhat confusing, one can see this in newcomer questions on StackOverflow.

For example:

- Foo
    - Sources
        - Bar
            - main.swift

Will build a single executable called `Bar`. However if one accidentally creates a new swift file:

- Foo
    - Sources
        - baz.swift
        - Bar
            - main.swift

Then you will get a single executable called baz, or more likely a compile error. Diagnosing this is currently an exercise in frustration (though we could improve this with better diagnostics when compiles fail, eg. we could output the modules structure we inferred).

To prevent these transformations we could just tighten up our rules.

If one browses swift packages online there is a clear preference towards a root `Sources` directory.

Thus I propose we only allow

A Sources directory with sub folders for modules
A Sources directory with sources directly in the Sources directory and NO sub folders

Any other options become errors.

If we then extend the same rules to modules then there will be no surprising behavior. At first I resisted this idea as folders are for organization, however in the new world of SwiftPM *modules* are for organization.

Modules have internal accessibility modifiers that allow powerful architectural designs. Modules have a defined public interface that maps onto folder organizational practices better than

However this prohibits eg:

- NetEngine/
    - CommonCode.swift
    - HTTP/
        - foo.swift
    - HTTPS/
        - bar.swift

And perhaps thus is overly restrictive. Though my argument is that HTTP and HTTPS would be better off being their own modules: it would encourage true encapsulation and a better code architecture.

I am unsure and thus am opening a discussion here. Certainly there are other ways to accomplish the goals here so please let us know what you think a better solution (or not) would be. Thanks for your time.

Max


(Daniel Dunbar) #2

Just to make sure I understand, the idea here is that

- Sources
- Sources/A
- Sources/A/B
- Sources/A/C

produces two modules, B & C, because A has no sources in it directly (following the convention for Sources/ itself)?

Following the SwiftPM example, why do you want BuildNode and BuildDescription to be separate modules?

The biggest problem I see here is that modules may mean different things to different people, and they have significant semantic meaning (since they change visibility). If I compare to LLVM, for example, the individual equivalent of a "module" is typically quite large. That leads to occasionally wanting to subdivide the sources of the module into subfolders without changing which module they contribute to, which I think this proposal would require?

- Daniel

···

On Apr 19, 2016, at 12:42 PM, Max Howell via swift-build-dev <swift-build-dev@swift.org> wrote:

SwiftPM is a pioneer for SwiftPM, and thus we have many modules. For some of these modules I’d like to split them out even more eg:

- Sources
    - Build

Build is a module, but really I’d like:

- Sources
    - Build
        - BuildNode
        - BuildDescription

If I do this currently I still will end up with one module: `Build`, this is how the module layout rules that SwiftPM uses work. But instead I’d like Build to be purely an organizational folder and to get two modules *BuildNode* and *BuildDescription*.

I’d like to propose some method to allow further organization, but without ruining our existing rules.

I’d also like to propose tightening up our rules a little.

—————————

One clear way to accomplish the first goal is to extend the rules and say empty folders are not considered modules.

I am unhappy with this however, already there are easy ways to completely transform the build of a package, and the rules we have are somewhat confusing, one can see this in newcomer questions on StackOverflow.

For example:

- Foo
    - Sources
        - Bar
            - main.swift

Will build a single executable called `Bar`. However if one accidentally creates a new swift file:

- Foo
    - Sources
        - baz.swift
        - Bar
            - main.swift

Then you will get a single executable called baz, or more likely a compile error. Diagnosing this is currently an exercise in frustration (though we could improve this with better diagnostics when compiles fail, eg. we could output the modules structure we inferred).

To prevent these transformations we could just tighten up our rules.

If one browses swift packages online there is a clear preference towards a root `Sources` directory.

Thus I propose we only allow

A Sources directory with sub folders for modules
A Sources directory with sources directly in the Sources directory and NO sub folders

Any other options become errors.

If we then extend the same rules to modules then there will be no surprising behavior. At first I resisted this idea as folders are for organization, however in the new world of SwiftPM *modules* are for organization.

Modules have internal accessibility modifiers that allow powerful architectural designs. Modules have a defined public interface that maps onto folder organizational practices better than

However this prohibits eg:

- NetEngine/
    - CommonCode.swift
    - HTTP/
        - foo.swift
    - HTTPS/
        - bar.swift

And perhaps thus is overly restrictive. Though my argument is that HTTP and HTTPS would be better off being their own modules: it would encourage true encapsulation and a better code architecture.

I am unsure and thus am opening a discussion here. Certainly there are other ways to accomplish the goals here so please let us know what you think a better solution (or not) would be. Thanks for your time.

Max
_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-build-dev


(Drew Crawford) #3

I hate to be "that guy", but I believe the problem under study is a special case of a much more general paradox.

Swift presently lacks any concept of "module encapsulation". A module's members are either available everywhere, or available nowhere. I refer to the following diagram:

- Sources
    - Country
         Venezuela.swift
       - United_States
           Rhode_island.swift
          - Texas
             Austin.swift

Consider the symbol Austin.SXSW. Either Austin.SXSW is public, in which case it is accessible to Texas, Rhode Island, United_States, etc, or it is private/internal, in which case it is only accessible to Austin. In no case it is accessible to Texas and not further, in no case is it "encapsulated" somehow by the Texas module. It is either invisible or global, Swift does not have another option. The namespace is flat. [0]

Meanwhile, Swift does have a concept of dependencies. We must compile *some* module first, and that module cannot depend on another module which is not yet compiled. Here, Austin has no dependencies and so it is compiled first. As a consequence it cannot depend on United States, and therefore it cannot access Rhode Island. However that has nothing to do with encapsulation, it has to do with a limitation of the Swift compiler model. A limitation which by the way, does not exist in other SwiftPM languages such as C. But in Swift, modules form a dependency tree [1].

The paradox is that, traditionally, a filesystem connotes both [0] and [1], while from a language point of view, we mean only one or the other. For example, in Unix, /usr/bin/git is an encapsulated path; if you try to run /usr/bin/git we first check that you are allowed to traverse /usr/, then /usr/bin/, and only finally /usr/bin/git. Whereas in Swift, to access Sources/Country/United_States/Texas/Austin.SXSW, we only check Austin; because Swift modules are not encapsulated. So a filesystem that promised meaning [0] did not deliver.

On the other hand, a folder depends on its contents; if you ask Unix to copy a folder you expect not just an empty folder, but a folder of the same contents, e.g. an identical folder. But if you copy a C module, you do not get all its dependencies, because there exists such a keyword as `extern`. So a filesystem that promised meaning [1] did not deliver it either.

If we then extend the same rules to modules then there will be no surprising behavior.

I suppose "surprise" is subjective, but I don't believe there is a solution to the paradox that is not surprising. We could resolve the problem in the first diagram by reorganizing to solve [0], requiring

- Sources
    - Country
       Venezuela.swift
    - United_States
       Rhode_island.swift
    - Texas
       Austin.swift

which I think is one of your proposals. But now we are wrong on [1]. That is, as a matter of compile-order, Rhode_island.Providence is not available in Austin while Austin.SXSW is available in Rhode_island, and this result is surprising given the flat filesystem layout shown.

Perhaps this sheds some light on my opposition to filesystem-defined build systems. The paradox above is not accidentally complex, that we could resolve it by "tightening the rules" to mandate some particular filesystem layout. It is essentially complex, because no filesystem layout can describe Swift's actual behavior.

We could of course redefine Swift to mean both [0] and [1], while that would break... pretty much all existing code, I would support it. However that does nothing to resolve the problem for C, so unless we plan to ban the extern keyword (which would no longer be C) that is no way out of the paradox.

···

On Apr 19, 2016, at 2:42 PM, Max Howell via swift-build-dev <swift-build-dev@swift.org> wrote:

SwiftPM is a pioneer for SwiftPM, and thus we have many modules. For some of these modules I’d like to split them out even more eg:

- Sources
    - Build

Build is a module, but really I’d like:

- Sources
    - Build
        - BuildNode
        - BuildDescription

If I do this currently I still will end up with one module: `Build`, this is how the module layout rules that SwiftPM uses work. But instead I’d like Build to be purely an organizational folder and to get two modules *BuildNode* and *BuildDescription*.

I’d like to propose some method to allow further organization, but without ruining our existing rules.

I’d also like to propose tightening up our rules a little.

—————————

One clear way to accomplish the first goal is to extend the rules and say empty folders are not considered modules.

I am unhappy with this however, already there are easy ways to completely transform the build of a package, and the rules we have are somewhat confusing, one can see this in newcomer questions on StackOverflow.

For example:

- Foo
    - Sources
        - Bar
            - main.swift

Will build a single executable called `Bar`. However if one accidentally creates a new swift file:

- Foo
    - Sources
        - baz.swift
        - Bar
            - main.swift

Then you will get a single executable called baz, or more likely a compile error. Diagnosing this is currently an exercise in frustration (though we could improve this with better diagnostics when compiles fail, eg. we could output the modules structure we inferred).

To prevent these transformations we could just tighten up our rules.

If one browses swift packages online there is a clear preference towards a root `Sources` directory.

Thus I propose we only allow

A Sources directory with sub folders for modules
A Sources directory with sources directly in the Sources directory and NO sub folders

Any other options become errors.

If we then extend the same rules to modules then there will be no surprising behavior. At first I resisted this idea as folders are for organization, however in the new world of SwiftPM *modules* are for organization.

Modules have internal accessibility modifiers that allow powerful architectural designs. Modules have a defined public interface that maps onto folder organizational practices better than

However this prohibits eg:

- NetEngine/
    - CommonCode.swift
    - HTTP/
        - foo.swift
    - HTTPS/
        - bar.swift

And perhaps thus is overly restrictive. Though my argument is that HTTP and HTTPS would be better off being their own modules: it would encourage true encapsulation and a better code architecture.

I am unsure and thus am opening a discussion here. Certainly there are other ways to accomplish the goals here so please let us know what you think a better solution (or not) would be. Thanks for your time.

Max
_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-build-dev


(Max Howell) #4

Just to make sure I understand, the idea here is that

- Sources
- Sources/A
- Sources/A/B
- Sources/A/C

produces two modules, B & C, because A has no sources in it directly (following the convention for Sources/ itself)?

Yes.

Following the SwiftPM example, why do you want BuildNode and BuildDescription to be separate modules?

I have enjoyed splitting code out into more encapsulated units. This is one example of that.

The biggest problem I see here is that modules may mean different things to different people, and they have significant semantic meaning (since they change visibility). If I compare to LLVM, for example, the individual equivalent of a "module" is typically quite large. That leads to occasionally wanting to subdivide the sources of the module into subfolders without changing which module they contribute to, which I think this proposal would require?

Indeed, my proposal is basically saying: modules should be small. But maybe this is too much.

There seems to be three options:

1. Leave it as is, subfolders of Sources are modules, subfolders of module folders are organizational.
2. What I propose, where empty folders in Sources indicate organizational folders, you can’t have subfolders to make our rules less “surprising”
3. What I propose, where empty folders indicate organizational folders, but you can have subfolders with source files in modules, this could be “surprising” where adding sources to empty folders completely changes the outputs of a build
4. Some setting in Package.swift that can mark folders as organizational

4 seems more like what you think should be done and that would be fine with me if people don’t think saying: modules should be small is acceptable.

Max


(Tony Allevato) #5

+1 to Daniel's last comment. My biggest issue with SwiftPM usability right
now is the lack of two related things:

(1) Pure Swift submodules
(2) Inability to organize source files in any way other than module
membership

I'm working on a library that is more of a suite of
related-but-also-separable feature sets. In a hypothetical pure Swift
submodule world, I could make each feature a submodule of the main library:
MyLibrary.Feature1, MyLibrary.Feature2, etc., and express any dependencies
between them (maybe ML.Feature3 depends on ML.Feature2). Without that, the
closest thing I can achieve is to make each one its own module, using
underscore delimited names like MyLibrary_Feature1, which is unappealing.

So, to avoid those issues, I resigned to making the entire library one
module, but then I have to merge all of the source files across all
features into a single folder. Xcode groups make this manageable in the
IDE, but my flattened source control view is much harder to manage.

In my particular use case, I believe pure Swift submodules would be a
better answer, but I imagine that there are others who would rather be able
to use folders for file organization only within the same module and
providing a choice to users to make both possible would increase the
complexity of the manifest and the PM implementation.

···

On Tue, Apr 19, 2016 at 12:53 PM Daniel Dunbar via swift-build-dev < swift-build-dev@swift.org> wrote:

Just to make sure I understand, the idea here is that

- Sources
- Sources/A
- Sources/A/B
- Sources/A/C

produces two modules, B & C, because A has no sources in it directly
(following the convention for Sources/ itself)?

Following the SwiftPM example, why do you want BuildNode and
BuildDescription to be separate modules?

The biggest problem I see here is that modules may mean different things
to different people, and they have significant semantic meaning (since they
change visibility). If I compare to LLVM, for example, the individual
equivalent of a "module" is typically quite large. That leads to
occasionally wanting to subdivide the sources of the module into subfolders
without changing which module they contribute to, which I think this
proposal would require?

- Daniel

On Apr 19, 2016, at 12:42 PM, Max Howell via swift-build-dev < > swift-build-dev@swift.org> wrote:

SwiftPM is a pioneer for SwiftPM, and thus we have many modules. For some
of these modules I’d like to split them out even more eg:

- Sources
    - Build

Build is a module, but really I’d like:

- Sources
    - Build
        - BuildNode
        - BuildDescription

If I do this currently I still will end up with one module: `Build`, this
is how the module layout rules that SwiftPM uses work. But instead I’d like
Build to be purely an organizational folder and to get two modules
*BuildNode* and *BuildDescription*.

I’d like to propose some method to allow further organization, but without
ruining our existing rules.

I’d also like to propose tightening up our rules a little.

—————————

One clear way to accomplish the first goal is to extend the rules and say
empty folders are not considered modules.

I am unhappy with this however, already there are easy ways to completely
transform the build of a package, and the rules we have are somewhat
confusing, one can see this in newcomer questions on StackOverflow.

For example:

- Foo
    - Sources
        - Bar
            - main.swift

Will build a single executable called `Bar`. However if one accidentally
creates a new swift file:

- Foo
    - Sources
        - baz.swift
        - Bar
            - main.swift

Then you will get a single executable called baz, or more likely a compile
error. Diagnosing this is currently an exercise in frustration (though we
could improve this with better diagnostics when compiles fail, eg. we could
output the modules structure we inferred).

To prevent these transformations we could just tighten up our rules.

If one browses swift packages online there is a clear preference towards a
root `Sources` directory.

Thus I propose we only allow

   - A Sources directory with sub folders for modules
   - A Sources directory with sources directly in the Sources directory
   and NO sub folders

Any other options become errors.

If we then extend the same rules to modules then there will be no
surprising behavior. At first I resisted this idea as folders are for
organization, however in the new world of SwiftPM *modules* are for
organization.

Modules have internal accessibility modifiers that allow powerful
architectural designs. Modules have a defined public interface that maps
onto folder organizational practices better than

However this prohibits eg:

- NetEngine/
    - CommonCode.swift
    - HTTP/
        - foo.swift
    - HTTPS/
        - bar.swift

And perhaps thus is overly restrictive. Though my argument is that HTTP
and HTTPS would be better off being their own modules: it would encourage
true encapsulation and a better code architecture.

I am unsure and thus am opening a discussion here. Certainly there are
other ways to accomplish the goals here so please let us know what you
think a better solution (or not) would be. Thanks for your time.

Max
_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-build-dev

_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-build-dev


(Max Howell) #6

+1 to Daniel's last comment. My biggest issue with SwiftPM usability right now is the lack of two related things:

(1) Pure Swift submodules

I would like this too, (could be implemented as some sort of module namespacing instead since with Swift modules the final binary can be composed of multiple modules so that part is separate), needs buy in from Swift core.

(2) Inability to organize source files in any way other than module membership
I'm working on a library that is more of a suite of related-but-also-separable feature sets. In a hypothetical pure Swift submodule world, I could make each feature a submodule of the main library: MyLibrary.Feature1, MyLibrary.Feature2, etc., and express any dependencies between them (maybe ML.Feature3 depends on ML.Feature2). Without that, the closest thing I can achieve is to make each one its own module, using underscore delimited names like MyLibrary_Feature1, which is unappealing.

Seems like ML is its own package? It’s just you would like a namespace feature. I certainly relate to the ugliness of a naming prefix. Especially with an underscore.

So, to avoid those issues, I resigned to making the entire library one module, but then I have to merge all of the source files across all features into a single folder. Xcode groups make this manageable in the IDE, but my flattened source control view is much harder to manage.

You can organize code in modules with subfolders currently:

    Sources/MyLibrary/A/a.swift
    Sources/MyLibrary/B/b.swift
    Sources/MyLibrary/c.swift

Will give you one `MyLibrary` module composed of a, b and c.swift.

Or do I misunderstand?

In my particular use case, I believe pure Swift submodules would be a better answer, but I imagine that there are others who would rather be able to use folders for file organization only within the same module and providing a choice to users to make both possible would increase the complexity of the manifest and the PM implementation.

Long term we need namespaces or submodules I agree.


(Tony Allevato) #7

> +1 to Daniel's last comment. My biggest issue with SwiftPM usability
right now is the lack of two related things:
>
> (1) Pure Swift submodules

I would like this too, (could be implemented as some sort of module
namespacing instead since with Swift modules the final binary can be
composed of multiple modules so that part is separate), needs buy in from
Swift core.

> (2) Inability to organize source files in any way other than module
membership
> I'm working on a library that is more of a suite of
related-but-also-separable feature sets. In a hypothetical pure Swift
submodule world, I could make each feature a submodule of the main library:
MyLibrary.Feature1, MyLibrary.Feature2, etc., and express any dependencies
between them (maybe ML.Feature3 depends on ML.Feature2). Without that, the
closest thing I can achieve is to make each one its own module, using
underscore delimited names like MyLibrary_Feature1, which is unappealing.

Seems like ML is its own package? It’s just you would like a namespace
feature. I certainly relate to the ugliness of a naming prefix. Especially
with an underscore.

Yes, namespaces would solve a lot of problems here that I've currently been
looking to submodules for. Especially if those namespaces had visibility
specifiers and could be easily imported separately into code that depends
on them (i.e., import MyLibrary.Feature2 in a source file without making
all of MyLibrary visible there).

There may still be some details to work out there—if the user only uses one
small feature from the library, would they have to bring along the entire
framework? As opposed to having each feature in its own module, where they
would only bring along that feature's framework (and any of its
dependencies).

> So, to avoid those issues, I resigned to making the entire library one
module, but then I have to merge all of the source files across all
features into a single folder. Xcode groups make this manageable in the
IDE, but my flattened source control view is much harder to manage.

You can organize code in modules with subfolders currently:

    Sources/MyLibrary/A/a.swift
    Sources/MyLibrary/B/b.swift
    Sources/MyLibrary/c.swift

Will give you one `MyLibrary` module composed of a, b and c.swift.

Or do I misunderstand?

I'll have to try that again. The last time I tried organizing things that
way, I ended up with A and B as separate modules; it may have been an early
version of SwiftPM that didn't support it, or it may have been an error on
my part.

···

On Tue, Apr 19, 2016 at 1:53 PM Max Howell <max.howell@apple.com> wrote:

In my particular use case, I believe pure Swift submodules would be a
better answer, but I imagine that there are others who would rather be able
to use folders for file organization only within the same module and
providing a choice to users to make both possible would increase the
complexity of the manifest and the PM implementation.

Long term we need namespaces or submodules I agree.


(Daniel Dunbar) #8

Just to make sure I understand, the idea here is that

- Sources
- Sources/A
- Sources/A/B
- Sources/A/C

produces two modules, B & C, because A has no sources in it directly (following the convention for Sources/ itself)?

Yes.

Following the SwiftPM example, why do you want BuildNode and BuildDescription to be separate modules?

I have enjoyed splitting code out into more encapsulated units. This is one example of that.

The biggest problem I see here is that modules may mean different things to different people, and they have significant semantic meaning (since they change visibility). If I compare to LLVM, for example, the individual equivalent of a "module" is typically quite large. That leads to occasionally wanting to subdivide the sources of the module into subfolders without changing which module they contribute to, which I think this proposal would require?

Indeed, my proposal is basically saying: modules should be small. But maybe this is too much.

I don't think I am comfortable with that assumption, currently.

In particular, module subdivision and visibility have substantial impact on performance (e.g., whole-module optimization), and performance sensitive clients are likely to want to put critical functionality in the same module even if it may be conceptually encapsulated. Modules are also very important for the Swift ABI resiliency model, which will encourage the same behavior.

Right now, for better or worse, modules are very similar to traditional libraries or frameworks, and not just because that is how we typically build them. It makes sense for a large project to subdivide code into modules along the same boundaries that would be done for those, which is typically fairly large.

There seems to be three options:

1. Leave it as is, subfolders of Sources are modules, subfolders of module folders are organizational.

One benefit of this is that it is very clear exactly what modules a package produces just from the Sources subdirectory structure. I tend to think this is an actively good thing. I agree it doesn't scale up.

2. What I propose, where empty folders in Sources indicate organizational folders, you can’t have subfolders to make our rules less “surprising”
3. What I propose, where empty folders indicate organizational folders, but you can have subfolders with source files in modules, this could be “surprising” where adding sources to empty folders completely changes the outputs of a build
4. Some setting in Package.swift that can mark folders as organizational

4 seems more like what you think should be done and that would be fine with me if people don’t think saying: modules should be small is acceptable.

I'm not sure about overrides for this specifically. I think we need a general purpose override mechanism, and think maybe the capability should fall out of that?

Here is an alternative proposal along a different line:

We have outstanding requests for better support for having multiple packages within a single repository. This is useful both for people who are building "monorepo" style projects, as well as for large projects which want to impose more organization. I have a design in my head sketched out, but not written up yet. If we had this support, one way to accomplish what you want without needing to change the existing conventions would be to use that support and subdivide the project into sub packages.

What do you think of the idea of using that feature to solve this problem?

- Daniel

···

On Apr 19, 2016, at 1:47 PM, Max Howell <max.howell@apple.com> wrote:

Max


(David Owens II) #9

I read this proposal as an official way to push micro-frameworks into Swift. I don't know if that's the intention, but if so, I'm strongly against that. Daniel laid out some of the reasons why above.

In general though, I'd like to see proposals for SwiftPM moving towards the direction to allow people to structure their code how they want to or how they need instead of trying to come up with a convention to solve everyone's use cases.

For example, some of us layout our code like this:

src/
  component/
    subcomponent/
      win32/
      linux/
      droid/
      ios/
      macos/
   ...

For some projects, I only want to ship a single module for `component`. For other projects, I may want to actually ship both `component` and `subcomponent` as separate modules. Just provide me with the tools to tell you what to build.

-David

···

On Apr 20, 2016, at 8:52 AM, Daniel Dunbar via swift-build-dev <swift-build-dev@swift.org> wrote:

Indeed, my proposal is basically saying: modules should be small. But maybe this is too much.

I don't think I am comfortable with that assumption, currently.

In particular, module subdivision and visibility have substantial impact on performance (e.g., whole-module optimization), and performance sensitive clients are likely to want to put critical functionality in the same module even if it may be conceptually encapsulated. Modules are also very important for the Swift ABI resiliency model, which will encourage the same behavior.

Right now, for better or worse, modules are very similar to traditional libraries or frameworks, and not just because that is how we typically build them. It makes sense for a large project to subdivide code into modules along the same boundaries that would be done for those, which is typically fairly large.


(Drew Crawford) #10

In general though, I'd like to see proposals for SwiftPM moving towards the direction to allow people to structure their code how they want to or how they need instead of trying to come up with a convention to solve everyone's use cases.

To follow up on this point, I currently have a library that lives in a *git* submodule. Since git, it must live in its own folder.

Now, you may say: obviously, this should be a separate swift module! After all I call it a "library", store it in a separate folder, and even track it in its own repository. Making it a module would promote good architecture, strong organizational principles, separation of concerns, [insert your favorite code hygiene argument here], case closed, right?

Plot twist: it's a copy protection library. It is a hard requirement that the library be as tightly integrated with the code it is protecting as is possible (e.g. linked into the same target). A dylib where somebody can swap it out defeats the purpose.

None of this is presently contemplated by SwiftPM's filesystem-based builds. Is this problem a corner case? Maybe? But it is a "corner case" that affects probably half the closed projects I work on. So half the closed codebases I work on can never be packaged with SwiftPM, by design.

I empathize with the desire to "tighten the rules" in response to complexity. But realistically, I'm not going to look at SwiftPM's rules and decide, shrug, I guess I don't need copy protection anymore. I will decide I don't need SwiftPM instead.

That really worries me.