Skip to content

Commit c5598e8

Browse files
Add compiler path to $PATH and $CRYSTAL_EXEC_PATH for subcommands (#15186)
1 parent a4e9666 commit c5598e8

File tree

5 files changed

+47
-15
lines changed

5 files changed

+47
-15
lines changed

.github/workflows/mingw-w64.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,5 @@ jobs:
148148
run: |
149149
export CRYSTAL_SPEC_COMPILER_BIN="$(which crystal.exe)"
150150
make -o .build/crystal.exe primitives_spec # we know the compiler is fresh; do not rebuild it here
151+
env:
152+
SPEC_FLAGS: --tag=~external_commands # skip exec_external_command spec because it doesn't work with this setup

bin/crystal

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ case "$(uname -s)" in
186186
;;
187187
esac
188188

189+
# CRYSTAL_EXEC_PATH determines the location of the `crystal` program for external
190+
# compiler commands.
191+
CRYSTAL_EXEC_PATH="$SCRIPT_ROOT"
192+
export CRYSTAL_EXEC_PATH
193+
189194
if [ -x "$CRYSTAL_DIR/${CRYSTAL_BIN}" ]; then
190195
__warning_msg "Using compiled compiler at ${CRYSTAL_DIR#"$PWD/"}/${CRYSTAL_BIN}"
191196
exec "$CRYSTAL_DIR/${CRYSTAL_BIN}" "$@"

spec/primitives/external_command_spec.cr

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,40 @@
33
require "../support/tempfile"
44

55
describe "Crystal::Command" do
6-
it "exec external commands", tags: %w[slow] do
7-
with_temp_executable "crystal-external" do |path|
6+
it "exec external commands", tags: %w[slow external_commands] do
7+
with_temp_executable "crystal-external" do |command_path|
8+
compiler_path = File.expand_path(ENV["CRYSTAL_SPEC_COMPILER_BIN"]? || "bin/crystal")
9+
810
with_tempfile "crystal-external.cr" do |source_file|
911
File.write source_file, <<-CRYSTAL
10-
puts ENV["CRYSTAL"]?
12+
puts Process.find_executable("crystal")
13+
puts ENV["CRYSTAL_EXEC_PATH"]?
1114
puts PROGRAM_NAME
1215
puts ARGV
1316
CRYSTAL
1417

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

18-
File.exists?(path).should be_true
21+
File.exists?(command_path).should be_true
1922

20-
process = Process.new(ENV["CRYSTAL_SPEC_COMPILER_BIN"]? || "bin/crystal",
23+
process = Process.new(compiler_path,
2124
["external", "foo", "bar"],
22-
output: :pipe,
23-
env: {"PATH" => {ENV["PATH"], File.dirname(path)}.join(Process::PATH_DELIMITER)}
25+
output: :pipe, error: :pipe,
26+
env: {"PATH" => {ENV["PATH"], File.dirname(command_path)}.join(Process::PATH_DELIMITER)}
2427
)
28+
2529
output = process.output.gets_to_end
30+
error = process.error.gets_to_end
2631
status = process.wait
27-
status.success?.should be_true
28-
lines = output.lines
29-
lines[0].should match /crystal/
30-
lines[1].should match /crystal-external/
31-
lines[2].should eq %(["foo", "bar"])
32+
status.success?.should be_true, failure_message: "Running external subcommand failed.\nstderr:\n#{error}\nstdout:\n#{output}"
33+
34+
output.lines.should eq [
35+
compiler_path,
36+
File.dirname(compiler_path),
37+
command_path,
38+
%(["foo", "bar"]),
39+
]
3240
end
3341
end
3442
end

src/compiler/crystal/command.cr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,19 @@ class Crystal::Command
132132
error "file '#{command}' does not exist"
133133
elsif external_command = Process.find_executable("crystal-#{command}")
134134
options.shift
135-
Process.exec(external_command, options, env: {"CRYSTAL" => Process.executable_path})
135+
136+
crystal_exec_path = ENV["CRYSTAL_EXEC_PATH"]?
137+
unless crystal_exec_path
138+
if executable_path = Process.executable_path
139+
crystal_exec_path = File.dirname(executable_path)
140+
end
141+
end
142+
path = [crystal_exec_path, ENV["PATH"]?].compact!.join(Process::PATH_DELIMITER)
143+
144+
Process.exec(external_command, options, env: {
145+
"PATH" => path,
146+
"CRYSTAL_EXEC_PATH" => crystal_exec_path,
147+
})
136148
else
137149
error "unknown command: #{command}"
138150
end

src/compiler/crystal/command/spec.cr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ class Crystal::Command
9595

9696
output_filename = Crystal.temp_executable "spec"
9797

98-
ENV["CRYSTAL_SPEC_COMPILER_BIN"] ||= Process.executable_path
98+
ENV["CRYSTAL_SPEC_COMPILER_BIN"] ||= if crystal_exec_path = ENV["CRYSTAL_EXEC_PATH"]?
99+
File.join(crystal_exec_path, "crystal")
100+
else
101+
Process.executable_path
102+
end
103+
99104
compiler.compile sources, output_filename
100105
report_warnings
101106
execute output_filename, options, compiler, error_on_exit: warnings_fail_on_exit?

0 commit comments

Comments
 (0)