electron/packager

Packaging darwin build on Windows results in blocked folder (access denied)

fourpixels opened this issue · 45 comments

Hi there,
I've just started using the packager, and it works pretty well. Thanks for the great work and the efforts here :)

I just have a problem with building for Mac on Windows. I use this line of code:

D:\work\www\droplet>electron-packager ./ Droplet --platform=darwin --arch=x64 -- version=0.33.9 --out=build

And the build was successful:

Packaging app for platform darwin x64 using electron v0.33.9
Wrote new app to build\Droplet-darwin-x64

But here comes the problem - I cannot archive or copy this build. When archiving with WinRAR, I get the following error:

!   D:\work\www\droplet\build\Droplet-darwin-x64.rar: Cannot open D:\work\www\droplet\build\Droplet-darwin-x64\Droplet.app\Contents\Frameworks\Electron Framework.framework\Libraries
    Access is denied.
!   D:\work\www\droplet\build\Droplet-darwin-x64.rar: Cannot open D:\work\www\droplet\build\Droplet-darwin-x64\Droplet.app\Contents\Frameworks\Electron Framework.framework\Resources
    Access is denied.

Followed by a 5 seconds wait time, and another like 10 errors for maybe all things in Frameworks folder.

I've managed to copy it through cmd, using xcopy, BUT the build was 50% larger (don't know why), and does not run on Mac: The application “Droplet.app” can’t be opened.

Do you have any ideas why this happens? Using Windows builds (on any arch) works like a charm! Any ideas will be appreciated!

+1. We ran into this issue a few weeks back and have been packaging OS X builds from an OS X build machine as a workaround. Access is denied seems to indicate an access or authorization issue but I suspect the root cause here is file/archive corruption caused by cross-building assets.

I don't think any of the current active contributors have a Windows-based development environment, so a community contribution would be most appreciated.

I would love to do something about it, but I'll need some help as I don't know where to start from :) Any ideas or recommendations?

@fourpixels See if you can get the test suite to run on your Windows machine, just run npm test. If that works, maybe write a test that fails on windows?

From what I recall when I tested this (I run Windows 8 and tested on a win7 VM), you normally cannot even run electron-packager targeting darwin without admin privileges due to symlinks (which electron-packager detects and skips), and if you do run with admin privileges, yes, I've found it impossible to archive correctly without running into errors. I'm not sure if there's a way around it besides packaging for OS X on OS X or Linux.

To be clear, electron-packager itself shouldn't be resulting in an error AFAIK.

the links created arent real sym-links though (just shortcuts), so even if you pack the resulting folder with admin privileges it doesnt work on osx then.

It also seems to be the case that the fs.symlink calls are setup incorrectly. e.g when dumping the calls i get the following args:

[ 'c:\\Development\\Test\\electron\\Versions\\Current\\Mantle\\',
  'c:\\Development\\Test\\electron\\Giftnotruf-darwin-x64\\Giftnotruf.app\\Contents\\Frameworks\\Mantle.framework\\Mantle',
  [Function] ]
[ 'c:\\Development\\Test\\electron\\A\\',
  'c:\\Development\\Test\\electron\\Giftnotruf-darwin-x64\\Giftnotruf.app\\Contents\\Frameworks\\ReactiveCocoa.framework\\Versions\\Current',
  [Function] ]

where c:\\Development\\Test is my current working directory. The first parameter is the path to target to link to but those target folders dont exist. Even when i inject 'junction' into the parameters now (as would be helpful for windows (see https://nodejs.org/docs/latest/api/fs.html#fs_fs_symlink_destination_path_type_callback) it wont help obviously.

Where are these target folders supposed to be ? e.g Versions\Current\Mantle

this would seem to be related to #117

@matthiasg I am confused as to how it works on mac - the code used to unzip is extract-zip, which is JS only and therefore should be running the same on mac as on windows?

I don't know much about symlinking, so I experimented with some changes to extract-zip, but didn't get anywhere constructive..

  • you are right about junction - because isDir is always false for the symlinks and one of them is a file and the other are directories
  • One of the problems appears to me to be the paths - the link path is relative to the zip, but no opts.dir is joined on to it, so I don't see how link will ever be right
  • Another problem is that the directories the symlinks are created in do not exist, so it needs to make those directories

I get this output:

creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Electron Framework.framework\Electron Framework" to "C:\test\build\macos\Versions\Current\Electron Framework"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Electron Framework.framework\Libraries" to "C:\test\build\macos\Versions\Current\Libraries"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Electron Framework.framework\Resources" to "C:\test\build\macos\Versions\Current\Resources"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Electron Framework.framework\Versions\Current" to "C:\test\build\macos\A"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Mantle.framework\Headers" to "C:\test\build\macos\Versions\Current\Headers"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Mantle.framework\Mantle" to "C:\test\build\macos\Versions\Current\Mantle"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Mantle.framework\Modules" to "C:\test\build\macos\Versions\Current\Modules"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Mantle.framework\Resources" to "C:\test\build\macos\Versions\Current\Resources"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Mantle.framework\Versions\Current" to "C:\test\build\macos\A"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\ReactiveCocoa.framework\Headers" to "C:\test\build\macos\Versions\Current\Headers"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\ReactiveCocoa.framework\Modules" to "C:\test\build\macos\Versions\Current\Modules"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\ReactiveCocoa.framework\ReactiveCocoa" to "C:\test\build\macos\Versions\Current\ReactiveCocoa"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\ReactiveCocoa.framework\Resources" to "C:\test\build\macos\Versions\Current\Resources"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\ReactiveCocoa.framework\Versions\Current" to "C:\test\build\macos\A"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Squirrel.framework\Headers" to "C:\test\build\macos\Versions\Current\Headers"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Squirrel.framework\Modules" to "C:\test\build\macos\Versions\Current\Modules"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Squirrel.framework\Resources" to "C:\test\build\macos\Versions\Current\Resources"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Squirrel.framework\Squirrel" to "C:\test\build\macos\Versions\Current\Squirrel"
creating symlink - "C:\test\build\macos\Electron.app\Contents\Frameworks\Squirrel.framework\Versions\Current" to "C:\test\build\macos\A"

from the following code changes

            // AFAICT the content of the symlink file itself is the symlink target filename string
            function writeSymlink () {
              readStream.pipe(concat(function (data) {
                var link = data.toString()
                link = path.resolve('C:\\test', path.join(opts.dir, link));
                dest = path.resolve('C:\\test', dest);
                var destDir = path.dirname(link);
                mkdirp(destDir, function() {
                    debug('creating symlink - "' + dest + '" to "' + link + '"')
                    fs.symlink(link, dest, 'junction', function (err) {
                      if (err) {
                          debug(err);
                          cancelled = true
                      }
                      done(err)
                    })
                });
              }))
            }
          })

the arguments to fs.symlink are destination, path
it seems that the 2nd argument e.g. path is the symlink location and the 1st argument is the one that it points to.

so to pick one example
"C:\test\build\macos\Electron.app\Contents\Frameworks\Squirrel.framework\Resources" should be a symlink to "C:\test\build\macos\Versions\Current\Resources"

which makes sense because multiple things link to Versions\Current\Resources.

I assume that the only way it could work is when I write a file to the symlink folder, mac creates the destination path if it doesn't exist.

My code doesn't work, not sure yet why.

Looking at the very first entry, it writes the file and then creates a symlink in the location the file is at.. preusmably mac must copy the file to the symlinked location and then link to it.

I think all this symlinking quirks would have to be handled for us to get a mac distrib and even after we have done it, there is no guarentee that packaging up the windows symlinks will create an archive with the right format for mac :(

anyone else have any input or thoughts?

I'm running into the same problem too,the output folder cann't be zipped and not work on OS X

Any news on this? I'm also stuck not able to get my app out for OSX? Is there any workaround?

Normal zip packaging turns symlinked files into duplicates, which both makes the app larger and breaks code-signing.

The /usr/bin/zip that comes installed on MacOS has a --symlinks argument which preserves links. If that's available, use it.

If not, try packaging the Mac app as a DMG file. That format preserves symlinks as well.

Basically, the workaround is to build packages targeted for OS X on non-Windows host platforms.

Building OS X app on windows has very limited scope. Because you cannot sign it (and unsigned app is forbidden by default) and cannot build DMG.

Anyway — I think this issue is out of electron-packager scope. Do not archive resulting directory using regular non-aware system tool — even on OS X it requires knowledge about --symlinks. If you need to get zipped artifact — use electron-builder. Currently, electron-builder creates zip for squirrel.mac (using 7za — compression is better, but it is still standard zip) and it supported only on OS X (because dmg is supported only on OS X), but if this issue is still actual for you — file issue to electron-builder (in any case in the future it will be added (zip, sfx, 7z, xz targets)).

I'm curious if this is related to the output of electron-packager creating folders on OSX that you can't move as Sudo?

Could this be changed to work?

@johnroper100 Per the "help wanted" label, we're looking for someone from the community to try to fix this problem. Otherwise, the workaround mentioned above is your best bet.

I would like to hear from anyone who managed to build darwin on win. I failed on win xp 32 win 8.1 64bit and on win 10. This is not that way as it seems from the first glance. If you follow all the issues from electron userland you will get the answer to your question. There are lots of ambitions out there fighting there, and you as a dev get just some of it what has been promised. As an example - electron-builder is a complete misunderstanding. Just dont use it, and you will save time. When you build an app that is to be compatible between browsers and electron and nwjs and adobe phonegap you will see what it costs. So every time I read an issue about building darwin, I know the answer would be. Just dont take the answers of the devs of electron to close. Test it on your own.

Basically, the workaround is to build packages targeted for OS X on non-Windows host platforms.

Why should they.

Ok, thanks. Trying on Linux now. It would just be so much easier on me.

Has anyone found a way to build a darwin version on Windows?

I haven't found a solution, but I've found a way to make my life a bit easier:
Build a package using Mac. For your next releases you can use WinRAR or similar to update the source/asar.

If you really need to pack mac not on mac machine and you don't care of code signing — and if you don't want to use Linux machine or VM, you can use Docker for Windows (only Docker for Windows, Docker Toolbox doesn't work) and electron-builder docker image to build (set mac.target to zip or tar.gz or dir or to any other of supported targets (except pkg and dmg). Please see https://github.com/electron-userland/electron-builder/wiki/Docker

@jhovgaard Thanks, that's a good suggestion. I have now created a mac build, using a borrowed mac, I'll try and update it this way.

I don't know whether this might help, but this is what I did.

Using Node 6.9.2, Electron 1.4.10, electron-packager 8.3.0.

Working on Ubuntu 16.04. Used electron-packager to package my app for Linux, Windows and Mac. The app works perfectly on Linux and Windows. I tried the app on a MacBook with OS X 10.9 and it crashes.

So I built it on that MacBook, using the same versions for all, and it works.

@marckris Could you please describe in more detail what you mean by "crash"? I personally have not had any problems building an OS X app on a Linux host platform, so I would like to know the circumstances under which you built the packaged app. In particular:

  • Console output when you run electron-packager with the environment variable DEBUG=electron-packager.

  • If there is a stacktrace when you run the packaged app (if that's what you meant by "crashes"), please paste it here.

  • What command line arguments are you passing? Alternatively, if you are using the API, what
    parameters are you passing to the packager() function?

  • A failing minimal testcase (with code) or detailed steps would be very helpful in order to reproduce your problem. Using electron-quick-start is a good starting point.

Sorry, I have to hide the name of my app as xxxxx.
Please note that I am not a Mac user so I have a bare minimum knowledge.

On Linux
---------
1. Run from terminal
	electron-packager ./ xxxxx --app-version=2.0 --platform=darwin --version=1.4.10 --arch=x64 --build-version=20 --asar --icon=icon.icns --out=/xxxxx/package --overwrite

2. Console ouput (after set DEBUG=electron-packager)
	Packaging app for platform darwin x64 using electron v1.4.10
	Wrote new app to /xxxxx/package/xxxxx-darwin-x64

3. Copy /xxxxx/package/xxxxx-darwin-x64 to my NTFS drive

On MacBook
----------
1. Open my NTFS drive on MacBook
2. Run xxxxx.app by double-clicking

Stacktrace:
I don't know how to do this.
This is the only output I got (in a dialog window).


xxxxx can not be opened because of a problem.

Check with the developer to make sure xxxxx works with this version of OS X. You may need to reinstall the application. Be sure to install any available
updates for the application and OS X.

This report will be sent to Apple automatically.

Problem Details and System Configuration

Process:         xxxxx [47158]
Path:            /Volumes/VOLUME/*/xxxxx.app/Contents/MacOS/xxxxx
Identifier:      com.electron.xxxxx
Version:         ???
Code Type:       X86-64 (Native)
Parent Process:  launchd [134]
Responsible:     xxxxx [47158]
User ID:         501

Date/Time:       2016-12-07 14:29:25.804 +0700
OS Version:      Mac OS X 10.9.5 (13F34)
Report Version:  11
Anonymous UUID:  B253151A-0A5E-70A8-BDEB-C69DBE24302D

Sleep/Wake UUID: 939C3E08-AE67-48A3-B1B6-0B7489D2DAAF

Crashed Thread:  0

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000002, 0x0000000000000000

Application Specific Information:
dyld: launch, loading dependent libraries

Dyld Error Message:
  Library not loaded: @rpath/Electron Framework.framework/Electron Framework
  Referenced from: /Volumes/VOLUME/*/xxxxx.app/Contents/MacOS/xxxxx
  Reason: no suitable image found.  Did find:
	/Volumes/MarcNTFS/xxxxx-darwin-x64/xxxxx.app/Contents/MacOS/../Frameworks/Electron Framework.framework/Electron Framework: file too short

Binary Images:
    0x7fff643a4000 -     0x7fff643d7817  dyld (239.4) <7AD43B9B-5CEA-3C7E-9836-A06909F9CA56> /usr/lib/dyld

Model: MacBook6,1, BootROM MB61.00C8.B00, 2 processors, Intel Core 2 Duo, 2.26 GHz, 4 GB, SMC 1.51f53

One more question: have you tried copying the app off of the NTFS drive, then running it? Or using another method other than an NTFS drive to copy it to the Macbook? It's a long shot, but maybe the app's files lose certain metadata when it's moved to an NTFS-formatted partition.

They only way I know how to do this on Linux is use diff.

diff --no-ignore-file-name-case --text --recursive /home/xxxxx-darwin-x64/ /media/marc/MyNTFS/xxxxx-darwin-x64/

diff reports no difference. I also tried a number of different flags, just in case I miss something, but the result is the same.

I have done this kind of thing on many occasions although never for an Electron app, but it should work fine, I think.

On MacBook I simply double clicked the app directly from the NTFS drive.
I also tried to copy the whole directory from the NTFS drive to a local working directory with Finder copy/paste, then use that directory instead. Result is the same.

Side note: I use https://github.com/thefanclub/ntfs-write/tree/master/DMG if I have to write to an NTFS drive but in this case I didn't use it.

I don't remember if file metadata changes show up using diff. (They do with git diff, at least permission changes.)

At any rate, this is a bit offtopic for a Windows host issue.

I think you are right. If I copy the package result from MacBook to my NTFS and compare it with the package result on Linux, symbolic links are not correctly copied. I suspect the other way around was also true.

Yes, not Windows, but at least I have learned not to just copy the result from Linux to Mac unless you have a bulletproof NTFS software that give you the exact same copy.

BTW I also tried it via a burn to a CD with K3b with the same result. Now I have to figure out how to burn the damn thing properly because this is suppose to be an app distributed on a CD. Damn those symlinks!

Well, at any rate. My bad. I should have known this.

Just my closing note for anyone who encounters the same "issue". The problem was definitely because symbolic links were not copied properly. I just finished burning a CD with the appropriate settings and use a proper NTFS software and now everything works perfectly. Thus confirming that you can use electron-packager on Linux to package your app for Windows, Mac and, of course, Linux itself. Thank you all and especially those who created this great app! You practically saved my neck :)

@marckris What "proper NTFS software" are you using?

I've had luck in simply not copying symlinks at all for the darwin version of my test project, but this tends to approximately double the size of the resulting copy on disk. I'm writing the project from a VirtualBox with Ubuntu 16.04 installed in an ext3/ext4 file system, to a USB drive. The USB drive is currently formatted to exFAT, but I suspect that FAT32 would work as well. NTFS proved to be problematic on our test Mac.

I use "cp -rL source/ dest/". This dereferences the symlinks. The packaged project size goes from 112.9 MB to 340.3 MB, and this is for a very basic test app that only includes index.js, index.html, and package.json files. I just discovered the --deref-symlinks option, but this appears to not have worked as I expected, and still created symlinks that "cp -r source/ dest/" alone tripped over when attempting to copy.

So my crude beginner's process for packaging is as follows:
russ@russ-VirtualBox: ~/Desktop/electron$ ll
total 20
drwxrwxr-x 2 russ russ 4096 Jan 17 09:50 ./
drwxr-xr-x 4 russ russ 4096 Jan 17 10:05 ../
-rwxrwxrwx 1 russ russ 340 Jan 17 10:14 index.html*
-rwxrwxrwx 1 russ russ 1717 Jan 17 09:20 index.js*
-rwxrwxrwx 1 russ russ 267 Jan 17 09:20 package.json*
russ@russ-VirtualBox: ~/Desktop/electron$ electron-packager . --platform=darwin --electron-version=1.4.14 --out=/home/russ/Desktop/electron-mac
russ@russ-VirtualBox: ~/Desktop/electron$ cp -rL /home/russ/Desktop/electron-mac/electron-test1-darwin-x64 /media/russ/exFAT/electron-test1-darwin-x64

  • Only relevant lines were reproduced in the above.

So it is possible to package for Mac on Linux, but it took some interesting contortions to get there. Now I just need to actually build my app! :-)

deref-symlinks only works on symlinks inside the app code, not the files from the prebuilt Electron zip. This is by design.

I'm beginning to think that we should just recommend packaging where the target platform is the same as the host platform. It's really difficult to debug the various FS-related issues otherwise.

#561 has been created to address ambiguities in the deref-symlinks docs.

Has anyone figured out how to delete the blocked folder that this issue was originally about? (Besides the obvious use of a Linux live CD or similar, which I don't think is even an option for me because I'm using Bitlocker.)

I've come to the conclusion that it will be a bit less painful for Electron app developers if the host and target platforms are the same. That is, build Windows bundles on Windows, macOS bundles on Macs, and Linux bundles on Linux. (Which is actually how Electron Forge, an Electron build tool that uses Packager, is designed.)

@malept But this is the only case where it doesn't work, right? I might agree with you if we didn't have something that already mostly works.

I'm fine with recommending doing things that way, but I think the project should continue to support cross OS packaging as well as possible.

@NoahAndrews Regarding reported bugs, there's #357 (building Windows targeted bundles on non-Windows host platforms), other problems with symlinks on Windows (another problem with building Mac targeted builds on Windows host platforms), and #115 (problems with permissions when building Linux targeted bundles on Windows).

And then there's the problem of building DMGs on non-Mac host platforms (it's non-trivial on Linux and I don't think it's possible on Windows), you can't create builds for the Mac App Store on non-macOS host platforms, you can't create appx (Windows Store) builds on non-Windows host platforms, you can't create flatpak (Linux packaging format) on non-Linux host platforms... I could go on.

I think maybe I misunderstood the point you were trying to make. I took your original comment as implying you wanted to stop supporting cross OS packaging in electron-packager, as opposed to just suggesting that I and others build on the target platform. I certainly agree that doing things that way is best, if you're able to.

The things in your second paragraph are true of course, but I really like that electron-packager doesn't try to do them, and as a result we get (some) cross OS packaging support. We have electron-forge and electron-builder to do the more complicated things that require a particular host OS.

As an aside, I'd still like to know how to delete the mac folder :)

My point was that there are a lot of cross-operating-system packaging bugs, so my default stance is to suggest to people that they don't use it unless they can't build on multiple OSes, and they're willing to deal with bugs such as this one, because I can't debug them and no one in the community with this problem has gone into a deep dive to figure out the root cause. (I do appreciate it a lot when community members do this, for example what has transpired in the past week regarding #544.)

For me, I just fix the problem by compressing it to a 7Zip archive (.7zip) and then uncompress it somewhere else.
Note that compressing in a zip archive (.zip) with 7zip doesn't work (same access problem).

@Bobavince I can't believe that actually works. Thank you.

Just bumping this to say that i'm able to build for darwin on windows 10
I'm coming here because someone using my project came across the same error as OP (app success but cannot zip due to access denied) so I was looking for a fix
Why does it work for me ?
Though, I haven't tested my zip-successfull file on mac since I have none

I am having the exact same issue on Windows 10 with 7Zip, 7Zip as admin, and the base Windows Zip feature in file explorer.
Running 20H2 (OS Build 19042.1288) Enterprise.
Node v16.13.0
Npm v8.1.2