-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support windows linker #4491
Support windows linker #4491
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ module Crystal | |
# optionally generates an executable. | ||
class Compiler | ||
CC = ENV["CC"]? || "cc" | ||
CL = "cl" | ||
|
||
# A source to the compiler: it's filename and source code. | ||
record Source, | ||
|
@@ -225,9 +226,7 @@ module Crystal | |
bc_flags_changed | ||
end | ||
|
||
private def codegen(program : Program, node, sources, output_filename) | ||
@link_flags = "#{@link_flags} -rdynamic" | ||
|
||
private def codegen(program, node : ASTNode, sources, output_filename) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why program has lost it's type restriction There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was superfluous and made the line longer. |
||
llvm_modules = @progress_tracker.stage("Codegen (crystal)") do | ||
program.codegen node, debug: debug, single_module: @single_module || @release || @cross_compile || @emit, expose_crystal_main: false | ||
end | ||
|
@@ -247,20 +246,18 @@ module Crystal | |
CompilationUnit.new(self, type_name, llvm_mod, output_dir, bc_flags_changed) | ||
end | ||
|
||
lib_flags = program.lib_flags | ||
|
||
if @cross_compile | ||
cross_compile program, units, lib_flags, output_filename | ||
cross_compile program, units, output_filename | ||
else | ||
result = codegen program, units, lib_flags, output_filename, output_dir | ||
result = codegen program, units, output_filename, output_dir | ||
end | ||
|
||
CacheDir.instance.cleanup if @cleanup | ||
|
||
result | ||
end | ||
|
||
private def cross_compile(program, units, lib_flags, output_filename) | ||
private def cross_compile(program, units, output_filename) | ||
llvm_mod = units.first.llvm_mod | ||
object_name = "#{output_filename}.o" | ||
|
||
|
@@ -269,10 +266,34 @@ module Crystal | |
|
||
target_machine.emit_obj_to_file llvm_mod, object_name | ||
|
||
stdout.puts "#{CC} #{object_name} -o #{output_filename} #{@link_flags} #{lib_flags}" | ||
stdout.puts linker_command(program, object_name, output_filename) | ||
end | ||
|
||
private def linker_command(program : Program, object_name, output_filename) | ||
if program.has_flag? "windows" | ||
if object_name | ||
object_name = %("#{object_name}") | ||
else | ||
object_name = %(%*) | ||
end | ||
|
||
if (link_flags = @link_flags) && !link_flags.empty? | ||
link_flags = "/link #{link_flags}" | ||
end | ||
|
||
%(#{CL} #{object_name} "/Fe#{output_filename}" #{program.lib_flags} #{link_flags}) | ||
else | ||
if object_name | ||
object_name = %('#{object_name}') | ||
else | ||
object_name = %("${@}") | ||
end | ||
|
||
%(#{CC} #{object_name} -o '#{output_filename}' #{@link_flags} -rdynamic #{program.lib_flags}) | ||
end | ||
end | ||
|
||
private def codegen(program, units : Array(CompilationUnit), lib_flags, output_filename, output_dir) | ||
private def codegen(program, units : Array(CompilationUnit), output_filename, output_dir) | ||
object_names = units.map &.object_filename | ||
|
||
target_triple = target_machine.triple | ||
|
@@ -303,7 +324,7 @@ module Crystal | |
|
||
@progress_tracker.stage("Codegen (linking)") do | ||
Dir.cd(output_dir) do | ||
system %(#{CC} -o "#{output_filename}" "${@}" #{@link_flags} #{lib_flags}), object_names | ||
system(linker_command(program, nil, output_filename), object_names) | ||
end | ||
end | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest renaming
CC
andCL
to something likePOSIX_LINKER
andWINDOWS_LINKER
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, keeping the same name as ENV variables makes it easier to deal with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's a good idea. I want to work out an env var or commandline flag to set the linker, like CC on posix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't just use
LINK
https://msdn.microsoft.com/en-us/library/hx5b050y.aspxThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From this wording, it appears to me that the
LINK
env var is used to prepend options to the link command, not contain the path to the executable.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the
link
command instead ofcl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use
ld
instead ofcc
? I don't know, but I think it'd beyond the scope of this PR. If we change to use the linker directly instead of the compiler directly we should do that on all platforms simultaneously.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bcardiff Because, just like on Unix, calling the linker directly would require you to manually pass the correct C/base libraries to link. On Windows, it's more complicated than Unix; in addition to
kernel32.lib
, you need to link in the proper C library using its full path, depending on the architecture and debug vs release mode.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kirbyfan64 you certainly don't need to pass the full path.