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

Make compiler aware of output extension when building programs #13370

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 @@ -693,7 +692,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