Skip to content

Commit

Permalink
Make compiler aware of output extension when building programs (#13370)
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil authored May 25, 2023
1 parent 61a2c52 commit 0627b47
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 25 deletions.
8 changes: 0 additions & 8 deletions src/compiler/crystal/codegen/link.cr
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,6 @@ module Crystal
end

class Program
def object_extension
case
when has_flag?("windows") then ".obj"
when has_flag?("wasm32") then ".wasm"
else ".o"
end
end

def lib_flags
has_flag?("windows") ? lib_flags_windows : lib_flags_posix
end
Expand Down
15 changes: 15 additions & 0 deletions src/compiler/crystal/codegen/target.cr
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ class Crystal::Codegen::Target
end
end

def executable_extension
case
when windows? then ".exe"
else ""
end
end

def object_extension
case
when windows? then ".obj"
when @architecture == "wasm32" then ".wasm"
else ".o"
end
end

def macos?
@environment.starts_with?("darwin") || @environment.starts_with?("macos")
end
Expand Down
27 changes: 16 additions & 11 deletions src/compiler/crystal/command.cr
Original file line number Diff line number Diff line change
Expand Up @@ -327,14 +327,13 @@ class Crystal::Command
compiler : Compiler,
sources : Array(Compiler::Source),
output_filename : String,
original_output_filename : String,
arguments : Array(String),
specified_output : Bool,
hierarchy_exp : String?,
cursor_location : String?,
output_format : String? do
def compile(output_filename = self.output_filename)
compiler.emit_base_filename = original_output_filename
compiler.emit_base_filename = output_filename.rchop(File.extname(output_filename))
compiler.compile sources, output_filename
end

Expand Down Expand Up @@ -521,17 +520,23 @@ class Crystal::Command
if has_stdin_filename
sources << Compiler::Source.new(filenames.shift, STDIN.gets_to_end)
end
sources += gather_sources(filenames)
first_filename = sources.first.filename
first_file_ext = File.extname(first_filename)
original_output_filename = File.basename(first_filename, first_file_ext)
sources.concat gather_sources(filenames)

# Check if we'll overwrite the main source file
if first_file_ext.empty? && !output_filename && !no_codegen && !run && first_filename == File.expand_path(original_output_filename)
error "compilation will overwrite source file '#{Crystal.relative_filename(first_filename)}', either change its extension to '.cr' or specify an output file with '-o'"
output_extension = compiler.cross_compile? ? compiler.codegen_target.object_extension : compiler.codegen_target.executable_extension
if output_filename
if File.extname(output_filename).empty?
output_filename += output_extension
end
else
first_filename = sources.first.filename
output_filename = "#{::Path[first_filename].stem}#{output_extension}"

# Check if we'll overwrite the main source file
if !no_codegen && !run && first_filename == File.expand_path(output_filename)
error "compilation will overwrite source file '#{Crystal.relative_filename(first_filename)}', either change its extension to '.cr' or specify an output file with '-o'"
end
end

output_filename ||= original_output_filename
output_format ||= "text"
unless output_format.in?("text", "json")
error "You have input an invalid format, only text and JSON are supported"
Expand All @@ -543,7 +548,7 @@ class Crystal::Command
error "can't use `#{output_filename}` as output filename because it's a directory"
end

@config = CompilerConfig.new compiler, sources, output_filename, original_output_filename, arguments, specified_output, hierarchy_exp, cursor_location, output_format
@config = CompilerConfig.new compiler, sources, output_filename, arguments, specified_output, hierarchy_exp, cursor_location, output_format
end

private def gather_sources(filenames)
Expand Down
9 changes: 4 additions & 5 deletions src/compiler/crystal/compiler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module Crystal
# If `true`, doesn't generate an executable but instead
# creates a `.o` file and outputs a command line to link
# it in the target machine.
property cross_compile = false
property? cross_compile = false

# Compiler flags. These will be true when checked in macro
# code by the `flag?(...)` macro method.
Expand Down Expand Up @@ -306,17 +306,16 @@ module Crystal
private def cross_compile(program, units, output_filename)
unit = units.first
llvm_mod = unit.llvm_mod
object_name = output_filename + program.object_extension

@progress_tracker.stage("Codegen (bc+obj)") do
optimize llvm_mod if @release

unit.emit(@emit_targets, emit_base_filename || output_filename)

target_machine.emit_obj_to_file llvm_mod, object_name
target_machine.emit_obj_to_file llvm_mod, output_filename
end

_, command, args = linker_command(program, [object_name], output_filename, nil)
_, command, args = linker_command(program, [output_filename], output_filename, nil)
print_command(command, args)
end

Expand Down Expand Up @@ -708,7 +707,7 @@ module Crystal
@name = "#{@name[0..16]}-#{::Crystal::Digest::MD5.hexdigest(@name)}"
end

@object_extension = program.object_extension
@object_extension = compiler.codegen_target.object_extension
end

def compile
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/macros/macros.cr
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class Crystal::Program
# When cross-compiling, the host compiler shouldn't copy the config for
# the target compiler and use the system defaults instead.
# TODO: Add configuration overrides for host compiler to CLI.
unless compiler.cross_compile
unless compiler.cross_compile?
host_compiler.flags = compiler.flags
host_compiler.dump_ll = compiler.dump_ll?
host_compiler.link_flags = compiler.link_flags
Expand Down

0 comments on commit 0627b47

Please sign in to comment.