Yeah you can - the point is that multiple physical packages can be treated as one logical package.
Let's imagine something like Clang and LLVM (as an example of a monorepo with various subsystems). Let's imagine they are two separate SwiftPM packages. Clang depends on LLVM, and it has a choice:
-
It can say that its code and LLVM's code are separate logical packages. That means they might be distributed and versioned separately, and it will need to account for future cases in enums from LLVM using
@unknown defaults. -
It can say that its code and LLVM's code are part of the same logical package. That means they are distributed together and are version-locked. It won't need to account for future cases in enums from LLVM, but they will cause build failures if not handled exhaustively.
You can think of it as taking LLVM's targets and products and merging them in to your own SwiftPM package. And this is all a separate consideration to where the actual source files are located, in which git repositories - maybe the same, maybe different.
If you are going for the version locking option, you probably want to more carefully manage when your dependencies get updated - it will be more difficult to do, potentially preventing you from quickly incorporating important bug fixes and security updates (which is why version locking should not be the default).
In Clang/LLVM's case, they can go for version locking because the projects are so tightly connected that changes to LLVM would test that Clang was updated as part of CI (which I believe is currently the case). If you have that kind of relationship with the developers of your dependencies, you can do that.
The Swift project itself could do that as well for its various libraries (string processing, swift-syntax, swift-driver, etc). Some clients of these libraries will want the first style of dependency, but the compiler itself could use the latter (version-locked) dependency.