A few deficiencies with the current install

Hi.

First of all I'd like to say I'm very happy with this recent development and I'm very interested in Swift on Windows.

There are, however, a few serious problems with the current state of affairs. I wanted to discuss them first here rather than opening JIRA issues for them in the bug tracker.

The issues are, in no particular order:

  1. The installer is not properly signed. It's nice that there's a PGP signature but on Windows it's customary to use Authenticode PE signing. The self-signing by dt.compnerd.com is nice but doesn't quite cut it.
    Just like on macOS the .pkg files are signed in the native was appropriate for the platform, so it should be on Windows. I shouldn't be getting SmartScreen warnings nor should I be getting the orange UAC prompt (unsigned or unidentified signer).

  2. The default install directory is very extremely not Windows-like. Program Files would orobably be a better place, but the very least we should have we specify an custom directory. The documentation says:

    The default installation location for the toolchain on Windows is %SystemDrive%\Library\Developer\Toolchains.

    but gives no way to specify another one.
    Also, running swift-5.3-RELEASE-windows10.exe /layout just created a copy of the installer.

  3. Continuing the previous issue, it would be very nice if there would a .zip release, or any other release that supports "XCOPY deployment".

  4. Using Swift should absolutely not require us to drop files in the VS directory as currently required and documented in Support Files. The fact that it isn't persistent and requires maintenance after every VS update is just the icing on the cake.

  5. The REPL should not require python.exe in PATH.
    If you feel that locating the Python install in the Registry is not something you should do and want to require Python in PATH you should require py.exe rather than Python.

If I had to sort them by importance for me it would be: #4, #3, #2, #1 and #5.
#4 is absolutely the worst problem. #5 and #1 are "merely" annoyances and #2 and #3 may be worked around but not as easily.

Thanks and great job on your work so far!

6 Likes

Thanks for the feedback.

I think that this is desired long term. The proper way to handle this IMO is to actually support module maps outside relative to the system include paths. If that were the case, it would be possible to do something like -fmodule-map=... to load the SDK and ucrt modulemaps as it is not impossible to currently add these to the SDK as that is under Microsoft's purview. I think that if you want to take this work on, it would be amazing.

I think that this is something which could possibly be done for the future releases. I think that the issue that remains there is how to ensure the signing. I suppose that signing the zip file with PGP is a likely option. The other issue to consider is the fact that there are multiple pieces in the installer:

  • ICU
  • toolchain
  • SDK
  • devtools
  • runtime

Are you suggesting that these be individual zip files? Is there an easy way to generate the zip file from the installer? It would be rather annoying to have to re-create the structure both in the installer definition and as a separate script. I suppose that it may also require the catalog based manifest signing which I haven't been able to figure out how to do.

This is definitely something that can be improved about the installer. I would welcome help to improve the installer to make it possible to relocate the installed image. I think that using Program Files however may be a challenge as the file path would now include spaces. There may be additional work to make the various pieces of the image work with spaces in paths.

Unfortunately, getting a root signed certificate is not as easy (and it is a recurring cost AFAIK). I am happy to change that if there is a way to get the root signed certificate that I have missed.

python.exe is not required, it is actually python.dll that is required. Adding that into the path dynamically is plausible via SetDllDirectory I suppose. This would be something that would need to be discussed at llvm.org rather than here as that is not specific to Swift but rather a LLDB behaviour change which is part of the LLVM project.

As of now I have not been able to run Swift properly and I'm hardly familiar with LLVM/Swift enough to make this contribution, but after reading the clang documentation on the subject seem like -fmodule-map-file= is indeed what missing.

Some more Googling suggests that while Swift doesn't have a parameter for specifying module maps, like clang it looks for module maps in all the include dirs, so maybe adding an include dir with only those module maps would work?

I think this could still be an EXE installer with inline Authenticode signature, but with the /layout argument working as expected

From my testing it looks like running msiexec /a {msi} TARGETDIR=somedir for each for the 4 MSIs embedded inside the installer gives me the exact directory layout of C:\Library that I get from running the installer.

So if the /layout argument simply did that it would probably be enough.

I'm guessing there's not much more beyond extracting the files, and the rest could go into a PowerShell script. The only thing I noticed was creating the SDKPATH environment variable.

To make some experiments, could you note if there's anything the installer does besides extracting the 4 MSIs? Or even better, where could I find the source for the installer?

I did not intent for you to buy the Authenticode certificate and sign it using your identity.
I was thinking more of Apple signing it using their certificate, or the same "Swift Open Source" identity that signs the macOS installer (for which Apple would hopefully donate the 250$-700$ a year for the certificate).

Correct, the flag -fmodule-map-file= already exists, and its use is what I was suggesting. The flag itself is not exposed (nor should it be) by the Swift compiler. The Swift frontend would use that to add the modulemap when setting up the ClangImporter. That is very simple to do.

The problem is that although adding the modulemap itself is very easy, the modulemap must live next to the headers or reference the headers by absolute paths. Because the WinSDK versions change and the layout can change, the install locations can change, you would need to re-generate the module map dynamically at runtime (which doesn't really seem possible since it is not derived via a pattern but rather requires developer intervention) or the module map needs to reside next to the files. This is the current state.

The idea that I am proposing is to have the modulemap reside outside of the header paths, but evaluate the paths relative to the system roots (and possibly user defined include search paths). Of course this would require working with clang's upstream (llvm.org) to actually extend the functionality in Clang and possibly with the C++ standards committee for any impact on the C++ standards for module support.

I don't know how to add the additional argument processing for the installer bundle. Adding an additional command line option to use /layout is perfectly reasonable and if that solves the problem that sounds great!

The only things beyond the extraction that the installer does is setup SDKROOT and DEVELOPER_DIR environment variables. The sources for the installer are at https://github.com/compnerd/swift-build/tree/master/wix