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

Linker issues on Windows #146

Closed
tishin opened this issue Oct 1, 2023 · 20 comments
Closed

Linker issues on Windows #146

tishin opened this issue Oct 1, 2023 · 20 comments

Comments

@tishin
Copy link
Contributor

tishin commented Oct 1, 2023

1. Linker flag -undefined dynamic_lookup is macOS specific

Linking SwiftGodot product on Windows fails with

Building for debugging...
lld-link: warning: ignoring unknown argument '-undefined'
lld-link: error: could not open 'dynamic_lookup': no such file or directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[81/84] Linking C:\Projects\SwiftGodot\.build\x86_64-unknown-windows-msvc\debug\SwiftGodot.dll

It works fine on Linux, but I don't think the flag does anything there.

2. After removing the flags Windows linking fails with

lld-link: error: undefined symbol: $s10SwiftGodot7VariantC5GTypeO8rawValueSivg
lld-link: error: undefined symbol: $s10SwiftGodot12PropertyHintO8rawValueSivg
lld-link: error: undefined symbol: $s10SwiftGodot7VariantC5GTypeON

and so on for every generated symbol eventually hitting

lld-link: error: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)

This only happens on the first build, the next build after the initial one does not have those errors anymore.

3. Finally, Windows linking fails with

Building for debugging...
lld-link: error: too many exported symbols (got 125050, max 65535)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[23/24] Linking C:\Projects\SwiftGodot\.build\x86_64-unknown-windows-msvc\debug\SwiftGodot.dll

Not sure what can be done here other than separating generated codebase into different modules.

P.S. Since macros aren't yet supported on Windows, you have to specifically build SwiftGodot product to even get to linking. Building the whole package will throw macro-related compilation errors.

@tishin
Copy link
Contributor Author

tishin commented Oct 2, 2023

I managed to build the dll successfully by limiting generation with okList. So that's one way around it I guess.

@lorenalexm
Copy link
Contributor

@tishin Could I get a bit more elaboration on the okList work around? I am running into the same issue with the exported symbols error. Thanks!

@migueldeicaza
Copy link
Owner

Wow, this is really painful.

It looks like Windows only allows 64k exported symbols, so that is the hard limit we are facing.

@lorenalexm the binding generator has a built-in list of types that it can generate code for, I sometimes use that to iterate more quickly, so rather than compiling all the files, it compiles a handful of them.

Looking at the list of exported symbols, there might be some candidates to trim this down, for example, consider this property which I do not know why it gets exposed as it is not flagged as public:

0000000000650ba8 T static SwiftGodot.CSGTorus3D.method_get_material.modify : Swift.UnsafeRawPointer
0000000000650ab4 T SwiftGodot.CSGTorus3D.method_get_material.unsafeMutableAddressor : Swift.UnsafeRawPointer
0000000000650b08 T static SwiftGodot.CSGTorus3D.method_get_material.getter : Swift.UnsafeRawPointer
0000000000650b58 T static SwiftGodot.CSGTorus3D.method_get_material.setter : Swift.UnsafeRawPointer

Those are four symbols for an internal property, and these account for 80,000 of the symbols.

@migueldeicaza
Copy link
Owner

Ok, I have a patch committed.

This went from 95,721 symbols to 48,736 symbols, so that should unblock Windows for now, now that we know this, it might be worth looking at other savings like this.

@migueldeicaza
Copy link
Owner

Ok, my patch only addresses #3 - still need to look at #1 and #2

@migueldeicaza
Copy link
Owner

Another 6,600 fewer symbols. We are now at 42,801

@lorenalexm
Copy link
Contributor

@migueldeicaza Thank you! Both for the explanation, and your immediate work cutting down on the symbols.

Though now, it's funny, I am no longer receiving the linker error but instead receiving a myriad of locally defined symbol imported warnings to be followed with a handful of macros are not supported in this compiler errors; never allowing it to reach the linker. The logs can be found here. I am not sure what has changed since updating the package, but it seems to be a step backwards in my case. The compilation is being done via GitHub actions, as can be seen by the aforementioned log file.

@tishin
Copy link
Contributor Author

tishin commented Oct 7, 2023

@lorenalexm your log url is expired, so I can't say for sure, but:

-macros are not supported in this compiler errors shouldn't be an issue in the current main branch, as macros aren't included in Windows builds anymore. Try doing swift package clean before building.
-locally defined symbol imported log entries are warnings, and in my case they were all related to generator executable. And source generation was somewhat successful, so I didn't pay too much attention to them. I've got a successful dll build with those warnings present.

@lorenalexm
Copy link
Contributor

@tishin I have edited my GitHub build scripts to clean before building, and ran swift package update to set the latest version of SwiftGodot. This had me make changes like removing the SwiftGodotMacros package and imports.

After these changes and the update, my macOS and Linux builds are working without a hitch, though I am still hitting blocking errors with the Windows build. I am now experiencing this build error never actually making it to linking now:

SpinningCube.swift:10:2: error: unknown attribute 'Godot'

Do I need to completely forsake the macros and attributes to build properly on Windows, or am I managing to find issue where there shouldn't be any?

@tishin
Copy link
Contributor Author

tishin commented Oct 9, 2023

@lorenalexm Unfortunately macros aren't supported on Windows yet. You can track the progress at swiftlang/swift#68272
The way I see it the options are:

  • Have Windows support by not using macros
  • Use macros anyway. Maybe there'll be a new version of Swift with macro support on Windows by the time you actually need a Windows build. Worst case scenario you'll need to write a script that "expands" all macros in the project replacing macros with their implementations.

@lorenalexm
Copy link
Contributor

With some tinkering to the Package file and a bit of verbosity, I am now successfully compiling on Windows. @tishin @migueldeicaza I cannot express how grateful I am to the both of you in your guidance through my missteps. Thank you!

I will find some time and submit a PR with docs stepping someone through the Windows build process; hopefully alleviating some of the pain points.

@migueldeicaza
Copy link
Owner

Oh that would be a great contribution!

@compnerd
Copy link

The release of 5.9.1 should include the macro support. Hopefully we can get newer snapshots with macros soon.

@migueldeicaza
Copy link
Owner

This is music to my ears @compnerd !

@lorenalexm
Copy link
Contributor

I have just successfully built and linked the GitHub README sample with macros on Windows (via GitHub actions) using the 5.9.1 toolchain. I can try to get a PR to you in the next few days. It just required removing the compiler directives, and went without a hitch afterwards.

@migueldeicaza
Copy link
Owner

Great news!

@tishin
Copy link
Contributor Author

tishin commented Jan 5, 2024

Closing this since Windows build is included in CI checks and succeeds.

@tishin tishin closed this as completed Jan 5, 2024
@gmurray81
Copy link

@migueldeicaza sorry to comment on a closed issue, but I'm running into the same limitation for a different Swift library and was wondering if you could provide any more detail as to how to work around this? Is it just a maximum of swift symbols that can exist in a package period? Or just ones that need to be accessible externally?

@migueldeicaza
Copy link
Owner

The ones that are available externally. So if you can reduce your public surface app, you get those slots back

@gmurray81
Copy link

Oddly, I think it made no difference to debug, but helped with the release config... Maybe there's something I need to do to make it not export all symbols in debug mode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants