Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a 'run' command to zig? #466

Closed
marler8997 opened this issue Sep 12, 2017 · 5 comments
Closed

Add a 'run' command to zig? #466

marler8997 opened this issue Sep 12, 2017 · 5 comments
Labels
accepted This proposal is planned. enhancement Solving this issue will likely involve adding new logic or components to the codebase. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@marler8997
Copy link
Contributor

marler8997 commented Sep 12, 2017

zig run <compiler-args> dosomething.zig <runtime-args>...

this would do the same thing as the "build_exe" command, except it would save the executable to a global directory, then automatically run the executable with the given <runtime-args>.

On subsequent calls, if the <compiler-args> are the same as a previous call, the compiler can re-use the previously compiled executable. The compiler should also have a way of knowing what compiler-arguments/build settings were used to create an existing executable.

Note: we may also want an option to tell zig where to cache the executable, i.e.

zig run --cache-path . <compiler-args> dosomething.zig <runtime-args> ...

The directory where zig saves the executable should probably live relative to where the compiler is installed so that each compiler only uses executables that it has built itself. Take the following example:

<my-project-path>/hello.zig

> zig run hello.zig

The directory where zig might save this executable could be:

<zig-install-path>/zig.exe
<zig-install-path>/zig/std       (the standard library might go here)
<zig-install-path>/zig/cached    (a place to store global cached executables)
<zig-install-path>/zig/cached/<my-project-path>/hello.zig/bf6d8826c8e6a7f.exe

The last filename is the executable that was cached by zig. It's proposed that it live under <my-project-path> so that users can look in the cached directory and easily determine where projects came from, and also avoid conflicts between projects with the same name. The name of the exe file "bf6d8826c8e6a7f.exe" is a hash of all the build settings that affect the binary output of the executable. So all the compiler has to do to determine if the program has already been built is create a hash of all the build settings and check if that file exists.

@andrewrk andrewrk added the enhancement Solving this issue will likely involve adding new logic or components to the codebase. label Sep 12, 2017
@andrewrk andrewrk added this to the 0.2.0 milestone Sep 12, 2017
@andrewrk
Copy link
Member

andrewrk commented Sep 12, 2017

I like this a lot. At first I was thinking that we had to try to make it work with no subcommand, just something like:

zig program.zig --program --args

Because I thought this would be necessary for shebang lines:

#!zig

But I realized recently that shebang lines perfectly accept command line options. So run subcommand is ideal.

#!zig run

So another component to this issue is that zig should allow a shebang line.

One small improvement to the original proposal, is to have instead of the path be bf6d8826c8e6a7f.exe, it'll be /some/dir/bf6d8826c8e6a7f/program.exe where program is the name of the exe, probably derived from the root .zig filename. This will make it look nicer in task managers and things like this.

One more modification is that I think we need to allow specifying the location of cache files at build time. Posix-y systems tend to have a place like /var/ where stuff like this is supposed to go. And just like #463 we can have a fallback to a directory relative to zig.exe as you suggested.

One advanced idea, which is maybe not necessary but could be interesting, is to have it compile in Debug mode when the cache file is missing, and then launch the child process ASAP, but after the child is launched, zig performs another build, this time with ReleaseSafe. When this build completes it replaces the cache file with this improved and optimized executable.

Caching stuff is related to #330

Potentially the zig build system will take advantage of this caching system used for zig run. Both will need to be intelligent enough to detect when certain cases cause cache invalidation, such as files copied from one target to another, the zig compiler exe updating, any changes to any source files depended on by the application, C files referenced with @cImport, files referenced with @embedFile, and a few more.

@tiehuis
Copy link
Member

tiehuis commented Sep 12, 2017

I like the idea of a run command but I think the behavior should be a bit simpler, effectively a convenience wrapper around zig build.

zig run

zig build
./zig-cache/program.zig # or wherever it was placed

This would allow us to utilize whatever file caching is provided for zig build as Andrew mentioned.

zig run program.zig

zig build_exe $TEMP
$TEMP_DIR/program

I don't think this should do any caching since that would mean the compiler would need to cache all input imported files as well. I think in this case we should prefer a simple approach as more complex programs that want to be cached can just run the two commands separately.

I think go run is similar for this last case in that it just uses a temporary directory.

@marler8997
Copy link
Contributor Author

This simpler version without caching could be implemented first, and then caching added later if it is found to be worth the complexity. It does mean that every time the program is run, it has to be recompiled. I think the caching would be worth it in the end but if we implement it without caching we can get some real data on whether people believe it's needed. Then again, if people want to cache the resulting binary, they could just build/run in 2 separate steps.

I use the equivalent feature in D on a daily basis (the rdmd program) and am very happy that it automatically caches and reuses the executable for me. It makes D feel like a scripting language which allows me to write things in D that I would otherwise write in scripting/shell languages.

@andrewrk
Copy link
Member

I don't think this should do any caching since that would mean the compiler would need to cache all input imported files as well.

Can you elaborate on this?

I was thinking that it would create a hash of imported filenames and their content or maybe just mtimes. It would be pretty low overhead and zig will already have to use this mechanism to cache compiler_rt.o and builtin.o.

@tiehuis
Copy link
Member

tiehuis commented Sep 12, 2017

I was probably just overthinking the effort involved. I think you are right that it isn't much extra work involved. From an end user perspective though, I do think that it should be as good an experience as possible so regarding the run caching I think I'm more convinced.

@andrewrk andrewrk added accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. labels Sep 17, 2017
@andrewrk andrewrk modified the milestones: 0.2.0, 0.3.0 Dec 8, 2017
@andrewrk andrewrk mentioned this issue Feb 24, 2018
@andrewrk andrewrk modified the milestones: 0.3.0, 0.4.0 Feb 28, 2018
tiehuis added a commit that referenced this issue Mar 31, 2018
'zig run file.zig' builds a file and stores the artifacts in the global
cache. On successful compilation the binary is executed.

'zig run file.zig -- a b c' does the same, but passes the arguments a,
b and c as runtime arguments to the program. Everything after an '--' are
treated as runtime arguments.

On a posix system, a shebang can be used to run a zig file directly. An
example shebang would be '#!/usr/bin/zig run'. You may not be able pass
extra compile arguments currently as part of the shebang. Linux for example
treats all arguments after the first as a single argument which will result
in an 'invalid command'.

Currently there is no customisability for the cache path as a compile
argument. For a posix system you can use `TMPDIR=. zig run file.zig` to
override, in this case using the current directory for the run cache.

The input file is always recompiled, even if it has changed. This is
intended to be cached but further discussion/thought needs to go into
this.

Closes #466.
tiehuis added a commit that referenced this issue Apr 1, 2018
'zig run file.zig' builds a file and stores the artifacts in the global
cache. On successful compilation the binary is executed.

'zig run file.zig -- a b c' does the same, but passes the arguments a,
b and c as runtime arguments to the program. Everything after an '--' are
treated as runtime arguments.

On a posix system, a shebang can be used to run a zig file directly. An
example shebang would be '#!/usr/bin/zig run'. You may not be able pass
extra compile arguments currently as part of the shebang. Linux for example
treats all arguments after the first as a single argument which will result
in an 'invalid command'.

Currently there is no customisability for the cache path as a compile
argument. For a posix system you can use `TMPDIR=. zig run file.zig` to
override, in this case using the current directory for the run cache.

The input file is always recompiled, even if it has changed. This is
intended to be cached but further discussion/thought needs to go into
this.

Closes #466.
@andrewrk andrewrk modified the milestones: 0.4.0, 0.3.0 Sep 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. enhancement Solving this issue will likely involve adding new logic or components to the codebase. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

3 participants