Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/mingw-w64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,5 @@ jobs:
run: |
export CRYSTAL_SPEC_COMPILER_BIN="$(which crystal.exe)"
make -o .build/crystal.exe primitives_spec # we know the compiler is fresh; do not rebuild it here
env:
SPEC_FLAGS: --tag=~external_commands # skip exec_external_command spec because it doesn't work with this setup
5 changes: 5 additions & 0 deletions bin/crystal
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ case "$(uname -s)" in
;;
esac

# CRYSTAL_EXEC_PATH determines the location of the `crystal` program for external
# compiler commands.
CRYSTAL_EXEC_PATH="$SCRIPT_ROOT"
export CRYSTAL_EXEC_PATH

if [ -x "$CRYSTAL_DIR/${CRYSTAL_BIN}" ]; then
__warning_msg "Using compiled compiler at ${CRYSTAL_DIR#"$PWD/"}/${CRYSTAL_BIN}"
exec "$CRYSTAL_DIR/${CRYSTAL_BIN}" "$@"
Expand Down
34 changes: 21 additions & 13 deletions spec/primitives/external_command_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,40 @@
require "../support/tempfile"

describe "Crystal::Command" do
it "exec external commands", tags: %w[slow] do
with_temp_executable "crystal-external" do |path|
it "exec external commands", tags: %w[slow external_commands] do
with_temp_executable "crystal-external" do |command_path|
compiler_path = File.expand_path(ENV["CRYSTAL_SPEC_COMPILER_BIN"]? || "bin/crystal")

with_tempfile "crystal-external.cr" do |source_file|
File.write source_file, <<-CRYSTAL
puts ENV["CRYSTAL"]?
puts Process.find_executable("crystal")
Comment thread
straight-shoota marked this conversation as resolved.
puts ENV["CRYSTAL_EXEC_PATH"]?
puts PROGRAM_NAME
puts ARGV
CRYSTAL

Process.run(ENV["CRYSTAL_SPEC_COMPILER_BIN"]? || "bin/crystal", ["build", source_file, "-o", path])
Process.run(compiler_path, ["build", source_file, "-o", command_path], error: :inherit)
end

File.exists?(path).should be_true
File.exists?(command_path).should be_true

process = Process.new(ENV["CRYSTAL_SPEC_COMPILER_BIN"]? || "bin/crystal",
process = Process.new(compiler_path,
["external", "foo", "bar"],
output: :pipe,
env: {"PATH" => {ENV["PATH"], File.dirname(path)}.join(Process::PATH_DELIMITER)}
output: :pipe, error: :pipe,
env: {"PATH" => {ENV["PATH"], File.dirname(command_path)}.join(Process::PATH_DELIMITER)}
)

output = process.output.gets_to_end
error = process.error.gets_to_end
status = process.wait
status.success?.should be_true
lines = output.lines
lines[0].should match /crystal/
lines[1].should match /crystal-external/
lines[2].should eq %(["foo", "bar"])
status.success?.should be_true, failure_message: "Running external subcommand failed.\nstderr:\n#{error}\nstdout:\n#{output}"

output.lines.should eq [
compiler_path,
File.dirname(compiler_path),
command_path,
%(["foo", "bar"]),
]
end
end
end
14 changes: 13 additions & 1 deletion src/compiler/crystal/command.cr
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,19 @@ class Crystal::Command
error "file '#{command}' does not exist"
elsif external_command = Process.find_executable("crystal-#{command}")
options.shift
Process.exec(external_command, options, env: {"CRYSTAL" => Process.executable_path})

crystal_exec_path = ENV["CRYSTAL_EXEC_PATH"]?
unless crystal_exec_path
if executable_path = Process.executable_path
crystal_exec_path = File.dirname(executable_path)
end
end
path = [crystal_exec_path, ENV["PATH"]?].compact!.join(Process::PATH_DELIMITER)

Process.exec(external_command, options, env: {
"PATH" => path,
"CRYSTAL_EXEC_PATH" => crystal_exec_path,
})
else
error "unknown command: #{command}"
end
Expand Down
7 changes: 6 additions & 1 deletion src/compiler/crystal/command/spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ class Crystal::Command

output_filename = Crystal.temp_executable "spec"

ENV["CRYSTAL_SPEC_COMPILER_BIN"] ||= Process.executable_path
ENV["CRYSTAL_SPEC_COMPILER_BIN"] ||= if crystal_exec_path = ENV["CRYSTAL_EXEC_PATH"]?
File.join(crystal_exec_path, "crystal")
else
Process.executable_path
end

compiler.compile sources, output_filename
report_warnings
execute output_filename, options, compiler, error_on_exit: warnings_fail_on_exit?
Expand Down