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

Added a feature shards build #136

Closed
wants to merge 7 commits into from
Closed

Conversation

tbrand
Copy link

@tbrand tbrand commented Nov 15, 2016

Hi all,

This PR is based on crystal-lang/crystal#3538.
I added a build command for shards.

In shard.yml, we set

targets:
  default:
    main: src/main.cr
    options:
      - -o bin/main
      - --release
  sub:
    main: src/sub.cr

Then,

$ shards build # Build "default" target without specified target
Building: default

$ shards build sub # Build specified target, here it is "sub"
Building: sub

$ shards build all # Build all targets
Building: default
Building: sub

$ shards build fake # Undefined targets raise an error
Target 'fake' is not found

Thanks for your review!

@bcardiff
Copy link
Member

Related to #110

Copy link
Contributor

@ysbaddaden ysbaddaden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to work on this!

That being said, I would like the feature to be as minimal as possible, and we sadly lacked a proper design beforehand, merely a few random ideas tossed in an issue comment. So, I would like to make many changes, sorry.

  1. the target name is meant to be the name of the resulting binary, which should be installed into the bin directory; also the main must be a complete path (it could be outside the src folder); the command should thus be: ["crystal", "build", target.main, "-o", File.join("bin", target.name)].
  2. let's simplify the command, since default and all won't work as expected (it's the target binary name), so it becomes shards build [options] [target, ...] meaning that:
    • shards build will build all configured targets; erroring if none are found (no targets configured);
    • shards build one two three will build the one, then two then three targets, one after the other; erroring if a target doesn't exist (missing target foo).
  3. please drop the options Array. I don't think there is much need for it for the time being; options could be passed via the command for example (e.g. shards build --release);
  4. no need to check for the presence of the crystal binary. Let the command fail, and print it with the error message; BTW maybe we'd like to honor an ENV["CRYSTAL"] variable that would default to crystal?
  5. the build command should check the dependencies and install them before trying to build.

Last but not least, thank you for writing integration tests, and taking of your time to work on this feature!

case pull.read_scalar
when "main"
target.main = pull.read_scalar
when "options"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid options for now; they could be passed as options to the command for example:

$ shards build --release

getter spec_path : String
getter lockfile_path : String

@spec : Spec?
@locks : Array(Dependency)?

def initialize(path)
def initialize(path, @sub = nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is sub? Can we avoid it?

@options = [] of String
end

def cmd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about shell_command? Thought the model shouldn't have to deal with the invocation. Command::Build should be the one generating the command.

property options : Array(String)

def initialize(@name)
super()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed: there are no superclass.

Dir.cd(application_path) do
File.open "mock.cr", "w"
ex = assert_raises(FailedCommand) { run "shards build mock_fake" }
assert_match "\e[31mTarget\e[0m 'mock_fake' is not found\n", ex.stdout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pass --no-color to the command.

@ysbaddaden ysbaddaden added this to the v0.7.0 milestone Nov 15, 2016
@tbrand
Copy link
Author

tbrand commented Nov 16, 2016

Thanks for your review!
I believe I've implemented what you suggested :)
Please tell me if I haven't do it.

We set

targets:
  test0:
    main: src/main0.cr
  test1:
    main: src/main1.cr

Then

$ shards build # Build main0.cr and main1.cr and generate binaries onto bin/test0 and bin/test1
Building: test0
Building: test1

$ shards build test1 # Build main1.cr and generate a binary onto bin/test1
Building: test1

$ shards build test0 test1 # Same as the top case
Building: test0
Building: test1

One thing that I have to say is that it is quite difficult to know whether an argument is a "target" or "option"
For example,

shards build -aaa bbb

In this case, shards cannot decide bbb is a value of "-aaa" or a target.
If it is okay to decide the order to "shards -> build -> targets -> options", it is possible to regard the input after the arguement with "-" prefix as options.

shards build aaa bbb -ccc ddd
# => aaa and bbb are targets, ddd is a value of -ccc

I can hard code crystal build options, but it is not ideal from the view point of frexibility.

For now, I took first approach.(Regarding the input after the argument with "-" prefix as options)
Please give me comments especially for this implementation.

As a supplement, I don't understand why the test/cli.cr parses a hash manually.
Why don't it use yaml.cr?

@ysbaddaden
Copy link
Contributor

Thanks! I'll correctly review this when I have some free time.

Copy link
Member

@bcardiff bcardiff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After tbrand@58fc34f there are some unused changes i think.

@@ -5,6 +5,7 @@ require "../spec"
module Shards
abstract class Command
getter path : String
getter sub : String | Nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused?

@@ -24,8 +25,8 @@ module Shards

abstract def run

def self.run(path)
new(path).run
def self.run(path, sub = nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused change? It should be rolledback probably.

parse_args
# mkdir bin
mkdir_bin
if @targets.size == 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if @targets.empty? :)

def parse_args
is_option? = false
@@args.each do |arg|
is_option? = true if arg.starts_with?("-")
Copy link
Contributor

@Sija Sija Nov 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use Char here: '-'

@ysbaddaden ysbaddaden self-assigned this Nov 17, 2016
@ysbaddaden
Copy link
Contributor

ysbaddaden commented Nov 17, 2016

Squashed and merged as 82fef4d. Thank you!

@ysbaddaden ysbaddaden closed this Nov 17, 2016
@tbrand
Copy link
Author

tbrand commented Nov 17, 2016

You meant you keep sub?
82fef4d#diff-3d1bd35545e168a4d913eb6fb9a9f87bR8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants