Feature request: Scripting support for Swift


(Maxim Veksler) #1

Hi,

Ayaka Nonaka gave a talk[1] about basic scripting[2] support in Swift.

The gist of the idea is to use #!/usr/bin/env xcrun swift

Therefor it seems the basic building blocks for allowing a swift file to
"execute itself" are always laid out and proved to be applicable.

What's missing IMHO is a better support for dependencies, the suggested
solutions in the talk are using the -F for including frameworks that were
built using Carthage or CocoaPods. That's not idle because a script I think
should be self contained, meaning that you can "just run it" and it works.

So, I'm wondering what if it was possible to include the dependencies
inside the swift file itself? Probably using the same format as the
Package.swift syntax. The the swift binary would "detect" that it's a self
contained file, it could make this distinction because import
PackageDescription is defined by the user.

Then it would follow a 3 step process:
1. It should download and build the dependencies
2. then compile the code inside the file
3. and then run it.

Having everything happening behind the scenes, so the "script user" simply
calls ./MyScript.swift or swift MyScript.swift and it "just works".

Wondering what the community thinks.

[1] https://realm.io/news/swift-scripting/
[2] https://github.com/ayanonagon/talks/tree/master/2015-swiftsummit/2


(orta) #2

This does exist right now BTW: https://github.com/RubyNative/Diamond

ยทยทยท

--
[ยท/ ] Orta Therox

w/ Artsy <http://artsy.net/>
CocoaPods <http://cocoapods.org/> / CocoaDocs <http://cocoadocs.org/>
@orta / orta.github.com

On Sat, Feb 18, 2017 at 7:26 PM, Maxim Veksler via swift-build-dev < swift-build-dev@swift.org> wrote:

Hi,

Ayaka Nonaka gave a talk[1] about basic scripting[2] support in Swift.

The gist of the idea is to use #!/usr/bin/env xcrun swift

Therefor it seems the basic building blocks for allowing a swift file to
"execute itself" are always laid out and proved to be applicable.

What's missing IMHO is a better support for dependencies, the suggested
solutions in the talk are using the -F for including frameworks that were
built using Carthage or CocoaPods. That's not idle because a script I think
should be self contained, meaning that you can "just run it" and it works.

So, I'm wondering what if it was possible to include the dependencies
inside the swift file itself? Probably using the same format as the
Package.swift syntax. The the swift binary would "detect" that it's a self
contained file, it could make this distinction because import
PackageDescription is defined by the user.

Then it would follow a 3 step process:
1. It should download and build the dependencies
2. then compile the code inside the file
3. and then run it.

Having everything happening behind the scenes, so the "script user" simply
calls ./MyScript.swift or swift MyScript.swift and it "just works".

Wondering what the community thinks.

[1] https://realm.io/news/swift-scripting/
[2] https://github.com/ayanonagon/talks/tree/master/2015-swiftsummit/2

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


(Jason Dusek) #3

One issue with compiling the dependencies is that script startup would be
slow. Maybe there should be a per-user or system level cache? System level
is better from a disk usage perspective but some thought must be given to
security.

With Ruby and Python, it is not expected that a script's dependencies are
installed when it is run but rather they have already been installed via
the package manager, although it does seem useful for single files to
contain all the relevant information.

Here is another idea: a Swift script can be run from a project directory
with Sources/, Packages/, &c. In that environment, build products are
already cached. If the script is symlinked into /usr/local/bin/ it will be
on the path but xcrun will still be able to find the project. It is kind of
like a source-level .app bundle.

Maxim Veksler via swift-build-dev <swift-build-dev@swift.org> schrieb am
Sa. 18. Feb. 2017 um 11:28:

ยทยทยท

Hi,

Ayaka Nonaka gave a talk[1] about basic scripting[2] support in Swift.

The gist of the idea is to use #!/usr/bin/env xcrun swift

Therefor it seems the basic building blocks for allowing a swift file to
"execute itself" are always laid out and proved to be applicable.

What's missing IMHO is a better support for dependencies, the suggested
solutions in the talk are using the -F for including frameworks that were
built using Carthage or CocoaPods. That's not idle because a script I think
should be self contained, meaning that you can "just run it" and it works.

So, I'm wondering what if it was possible to include the dependencies
inside the swift file itself? Probably using the same format as the
Package.swift syntax. The the swift binary would "detect" that it's a self
contained file, it could make this distinction because import
PackageDescription is defined by the user.

Then it would follow a 3 step process:
1. It should download and build the dependencies
2. then compile the code inside the file
3. and then run it.

Having everything happening behind the scenes, so the "script user" simply
calls ./MyScript.swift or swift MyScript.swift and it "just works".

Wondering what the community thinks.

[1] https://realm.io/news/swift-scripting/
[2] https://github.com/ayanonagon/talks/tree/master/2015-swiftsummit/2
_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-build-dev


(Daniel Dunbar) #4

I have a crazy idea about how this could work by integrating with SwiftPM -- would love to see someone mock up a prototype...

1. Define a special syntax for describing a script's dependencies inline in the script source
2. Create a mode for the Swift package manager where it analyzes the input script, extracts the package dependencies, and creates a custom Swift package just for that script.
3. Identify the created Swift package by hash, and stash it somewhere in the user's home directory, so that it would be cached
4. Automatically build and run the package

The cool thing about this model is it would seamlessly integrate command line scripting and the Swift package ecosystem, and it would provide a seamless user experience that avoids needing to worry about building anything to get good script performance. As the package manager got smarter about being able to share build artifacts it would transparently get faster, but user's wouldn't need to worry about managing the dependencies.

Strawman:

ยทยทยท

--
#!/usr/bin/env swift run --script

// Uses: SuperCoolCommandLine: 1.x
// Uses: AreYouFeelingANSI: 1.3.x

import SuperCoolCommandLine
import AreYouFeelingANSI

...
--

`swift` will already happily look for binaries like `swift-run` today (like git), so there is nothing blocking someone from hacking this up as a quick and dirty script to see how it works...

Cheers,
- Daniel

On Feb 18, 2017, at 11:26 AM, Maxim Veksler via swift-build-dev <swift-build-dev@swift.org> wrote:

Hi,

Ayaka Nonaka gave a talk[1] about basic scripting[2] support in Swift.

The gist of the idea is to use #!/usr/bin/env xcrun swift

Therefor it seems the basic building blocks for allowing a swift file to "execute itself" are always laid out and proved to be applicable.

What's missing IMHO is a better support for dependencies, the suggested solutions in the talk are using the -F for including frameworks that were built using Carthage or CocoaPods. That's not idle because a script I think should be self contained, meaning that you can "just run it" and it works.

So, I'm wondering what if it was possible to include the dependencies inside the swift file itself? Probably using the same format as the Package.swift syntax. The the swift binary would "detect" that it's a self contained file, it could make this distinction because import PackageDescription is defined by the user.

Then it would follow a 3 step process:
1. It should download and build the dependencies
2. then compile the code inside the file
3. and then run it.

Having everything happening behind the scenes, so the "script user" simply calls ./MyScript.swift or swift MyScript.swift and it "just works".

Wondering what the community thinks.

[1] https://realm.io/news/swift-scripting/
[2] https://github.com/ayanonagon/talks/tree/master/2015-swiftsummit/2_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-build-dev


(Keith Smiley) #5

A related issue that's worth mentioning is the overhead of running a
Swift script in general. Here's the simplest of examples of Swift vs
Python:

$ cat helloworld
print("Hello World")

Cold:

$ time swift helloworld
Hello World
swift helloworld  0.06s user 0.44s system 67% cpu 0.746 total
$ time python helloworld
Hello World
python helloworld  0.01s user 0.01s system 22% cpu 0.095 total

Warm:

$ time swift helloworld
Hello World
swift helloworld  0.04s user 0.01s system 22% cpu 0.212 total
$ time python helloworld
Hello World
python helloworld  0.02s user 0.01s system 84% cpu 0.035 total

While we're thinking about this for scripting, I think it's tangentially
related that the repl has a similar difference in overhead:

$ time swift <<< ":quit"
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance.
swift <<< ":quit"  1.88s user 0.23s system 86% cpu 2.459 total

$ time python <<< "quit()"
python <<< "quit()"  0.01s user 0.01s system 81% cpu 0.030 total
ยทยทยท

--
Keith Smiley

On 02/19, Jason Dusek via swift-build-dev wrote:

One issue with compiling the dependencies is that script startup would be
slow. Maybe there should be a per-user or system level cache? System level
is better from a disk usage perspective but some thought must be given to
security.

With Ruby and Python, it is not expected that a script's dependencies are
installed when it is run but rather they have already been installed via
the package manager, although it does seem useful for single files to
contain all the relevant information.

Here is another idea: a Swift script can be run from a project directory
with Sources/, Packages/, &c. In that environment, build products are
already cached. If the script is symlinked into /usr/local/bin/ it will be
on the path but xcrun will still be able to find the project. It is kind of
like a source-level .app bundle.

Maxim Veksler via swift-build-dev <swift-build-dev@swift.org> schrieb am
Sa. 18. Feb. 2017 um 11:28:

> Hi,
>
> Ayaka Nonaka gave a talk[1] about basic scripting[2] support in Swift.
>
> The gist of the idea is to use #!/usr/bin/env xcrun swift
>
> Therefor it seems the basic building blocks for allowing a swift file to
> "execute itself" are always laid out and proved to be applicable.
>
> What's missing IMHO is a better support for dependencies, the suggested
> solutions in the talk are using the -F for including frameworks that were
> built using Carthage or CocoaPods. That's not idle because a script I think
> should be self contained, meaning that you can "just run it" and it works.
>
> So, I'm wondering what if it was possible to include the dependencies
> inside the swift file itself? Probably using the same format as the
> Package.swift syntax. The the swift binary would "detect" that it's a self
> contained file, it could make this distinction because import
> PackageDescription is defined by the user.
>
> Then it would follow a 3 step process:
> 1. It should download and build the dependencies
> 2. then compile the code inside the file
> 3. and then run it.
>
> Having everything happening behind the scenes, so the "script user" simply
> calls ./MyScript.swift or swift MyScript.swift and it "just works".
>
> Wondering what the community thinks.
>
> [1] https://realm.io/news/swift-scripting/
> [2] https://github.com/ayanonagon/talks/tree/master/2015-swiftsummit/2
> _______________________________________________
> 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


(Jason Dusek) #6

For the interpreter, it's acceptable since it's got the debugger in there;
but for the scripting mode it's a real obstruction.

ยทยทยท

Keith Smiley <k@keith.so> schrieb am Mo. 20. Feb. 2017 um 11:25: > A related issue that's worth mentioning is the overhead of running a > Swift script in general. Here's the simplest of examples of Swift vs > Python:

$ cat helloworld
print("Hello World")

Cold:

$ time swift helloworld
Hello World
swift helloworld  0.06s user 0.44s system 67% cpu 0.746 total
$ time python helloworld
Hello World
python helloworld  0.01s user 0.01s system 22% cpu 0.095 total

Warm:

$ time swift helloworld
Hello World
swift helloworld  0.04s user 0.01s system 22% cpu 0.212 total
$ time python helloworld
Hello World
python helloworld  0.02s user 0.01s system 84% cpu 0.035 total

While we're thinking about this for scripting, I think it's tangentially
related that the repl has a similar difference in overhead:

$ time swift <<< ":quit"
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63
clang-800.0.42.1). Type :help for assistance.
swift <<< ":quit"  1.88s user 0.23s system 86% cpu 2.459 total

$ time python <<< "quit()"
python <<< "quit()"  0.01s user 0.01s system 81% cpu 0.030 total

--
Keith Smiley

On 02/19, Jason Dusek via swift-build-dev wrote:
> One issue with compiling the dependencies is that script startup would be
> slow. Maybe there should be a per-user or system level cache? System
level
> is better from a disk usage perspective but some thought must be given to
> security.
>
> With Ruby and Python, it is not expected that a script's dependencies are
> installed when it is run but rather they have already been installed via
> the package manager, although it does seem useful for single files to
> contain all the relevant information.
>
> Here is another idea: a Swift script can be run from a project directory
> with Sources/, Packages/, &c. In that environment, build products are
> already cached. If the script is symlinked into /usr/local/bin/ it will
be
> on the path but xcrun will still be able to find the project. It is kind
of
> like a source-level .app bundle.
>
> Maxim Veksler via swift-build-dev <swift-build-dev@swift.org> schrieb am
> Sa. 18. Feb. 2017 um 11:28:
>
> > Hi,
> >
> > Ayaka Nonaka gave a talk[1] about basic scripting[2] support in Swift.
> >
> > The gist of the idea is to use #!/usr/bin/env xcrun swift
> >
> > Therefor it seems the basic building blocks for allowing a swift file
to
> > "execute itself" are always laid out and proved to be applicable.
> >
> > What's missing IMHO is a better support for dependencies, the suggested
> > solutions in the talk are using the -F for including frameworks that
were
> > built using Carthage or CocoaPods. That's not idle because a script I
think
> > should be self contained, meaning that you can "just run it" and it
works.
> >
> > So, I'm wondering what if it was possible to include the dependencies
> > inside the swift file itself? Probably using the same format as the
> > Package.swift syntax. The the swift binary would "detect" that it's a
self
> > contained file, it could make this distinction because import
> > PackageDescription is defined by the user.
> >
> > Then it would follow a 3 step process:
> > 1. It should download and build the dependencies
> > 2. then compile the code inside the file
> > 3. and then run it.
> >
> > Having everything happening behind the scenes, so the "script user"
simply
> > calls ./MyScript.swift or swift MyScript.swift and it "just works".
> >
> > Wondering what the community thinks.
> >
> > [1] https://realm.io/news/swift-scripting/
> > [2] https://github.com/ayanonagon/talks/tree/master/2015-swiftsummit/2
> > _______________________________________________
> > 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