-
-
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
Conversation
This commit allows the crystal compiler to emit correct linker commands for --cross-compile for windows machines. This allows complication of simple --prelude=empty windows executables.
@@ -18,6 +18,7 @@ module Crystal | |||
# optionally generates an executable. | |||
class Compiler | |||
CC = ENV["CC"]? || "cc" | |||
CL = "cl" |
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
and CL
to something like POSIX_LINKER
and WINDOWS_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.aspx
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.
The LINK tool prepends the options and arguments defined in the
LINK
environment variable and appends the options and arguments defined in the_LINK_
environment variable to the command line arguments before processing.
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 of cl
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 of cc
? 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.
Great work! |
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.
Great! I was hoping to do something like this and get it to master.
I think is fine for know to not include libcmt.lib in the windows as part of the lib_flags or the linker command.
A LibWindows as in your submitted example should do the work IMO.
@@ -18,6 +18,7 @@ module Crystal | |||
# optionally generates an executable. | |||
class Compiler | |||
CC = ENV["CC"]? || "cc" | |||
CL = "cl" |
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.aspx
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 comment
The reason will be displayed to describe this comment to others. Learn more.
why program has lost it's type restriction : Program
?
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.
It was superfluous and made the line longer. ASTNode
is required to distinguish the override, Program
is just repeating the information contained in the variable name program
.
I also can suggest as a temporary solution not to call cl.exe directly but call a batch file that makes necessary environment setup, for example
or put this command line in |
@txe I think that the idea is that you'd run the msvc environment setup batch (e.g. open the VS command prompt from the start menu) and then run crystal inside that prompt which already has the correct PATH and LIB env vars set up. That's certainly what I did when I was testing. I think it's the job of the user to set up their environment not the compiler. |
I thought it was a question of usability:
|
Why not just keep the build prompt open? To me that's like complaining you have to open a terminal when you want to use the crystal compiler. Sure you do, but you can just keep one open. In addition, I don't think there's going to be a way to find that batch file consistently across all systems. |
Actually, I have a script which run the compiler and link without the prompt, so I talk about this feature which will run cl.exe directly and demand the prompt. Just a small step further and the prompt is not needed :) Edit: sorry, I wrote the prompt and not the prompt, but maybe it's not clear what the difference is. Edit2: there is a way to put ./bin in PATH during crystal startup for the current executing process, so CL can be kept simple like CL="cl.bat" |
I believe this the user responsibility to set the CL env variable correctly, either through the VS console as explained above or manually. We use an env variable for a reason :) This should be documented, thought, along with an example for usual VS installs. |
It seem to be a windows tradition to set the location of |
Thanks @RX14 . Once the compiler is ready for windows the environment setup will be addressed by a wrapper script, documentation or some other artifact. For now is great to have the command to link in windows and the refactor make senses. |
This PR allows the crystal compiler to emit correct linker commands for
--cross-compile
for windows machines. This allows complication of simple--prelude=empty
windows executables. Hopefully this is the first part of a gradual merge of windows support for crystal.Using the below test case and crystal command, crystal emits a
cl
(equivalent ofcc
on windows) command to link the object file. Please test this out yourself if you have a machine with visual studio installed.One question is whether we want to emit
libcmt.lib
by default as part of every linker command: it is windows' libc implementation which calls the executables'main
function. On linux,ld
includes the equivalent of this automatically.