Symbolic links inside Xojo framework

When building an app in 2014 R1.1, the Xojo framework now includes some symbolic link files:

MyApp.app
  /Contents
     /Frameworks
      /XojoFramework.framework
        /Resources (a symlink to the Resources folder below)
        /Versions
          /A
            /Resources
...etc...

My question is : what will happen if I delver this app through a non-HFS filesystem (say, FTPing or putting it on a SMB server)? Do the symlinks die? Does the OS care? is there an easy way to re-create them on the other end?

I know an answer would be “use a DMG” or “zip the app first” but let’s say that’s not possible?

Hmm - there’s a good discussion here http://superuser.com/questions/222549/zipping-files-in-osx-want-to-resolve-symbolic-links
It looks as if there’s some magical bytes in the FSCatalogInfo’s finderInfo[16] structure.

To clarify what I’m trying to do : worst-case, I’d like to be able to zip a file on Windows or Linux, and have that file properly unzip on Mac OS, including the symbolic links.

You can safely assume that symlinks within the bundle are safe as they are using relative paths within the bundle. Mac OS X manages very well and transparently non-HFS file systems. For instance MS-DOS FAT32 very commonly used for USB keys. So essentially, as long as Mac OS X sees a disk, whether it is physical, remote or virtual, you can assume it knows how to manage it.

[quote=90270:@Michael Diehr]
My question is : what will happen if I delver this app through a non-HFS filesystem (say, FTPing or putting it on a SMB server)? Do the symlinks die? Does the OS care? is there an easy way to re-create them on the other end?

I know an answer would be “use a DMG” or “zip the app first” but let’s say that’s not possible?[/quote]

The OS doesn’t recreate them and you run the risk of them being completely borked
There’s a reason we don’t create a “bundle” on windows - it won’t work
And yes they are really rather important

Further info: it looks like there are magic flags that can be stuck inside a zip file to get it to work properly, e.g. http://www.tempel.org/RB/ZipPackage has examples of handling symlinks.

Digging through my own code I realize I’m already parsing some of these magic flags (such as for “DOS file: hidden”) and so I just need to add support for the symlink side. Shouldn’t be that hard.

I have been delivering zipped Mac apps on my site for the longest time without any issue of any kind. They where all compressed on a Mac, though. So copying a zip file on a different system (Unix on the server through FTP) and back, it comes back intact within the zip created on Mac. And the symlink inside is fine.

Up until now, I never had the strange idea of zipping a Mac app bundle under Windows. But thanks to Michael (who seems to love complexity - no offense), that made me wonder.

So I have copied one of my apps onto a Windows disk and zipped it there. Then got it back to the Mac, and decompressed it. Good news are that it still works fine. But the Resources symlink inside the XojoFramework.framework folder is broken.

The conclusion is simple : unless you are thoroughly kin to reinvent the wheel, why compress Mac OS X apps anywhere else but on a Mac ? Unless, of course, this is for pure enjoyment of taking something apart and painfully putting it back together :wink:

I accept your compliment :slight_smile:

While I do enjoy programming, this is for a real live commercial app, which is fully cross-platform (the mac version can do windows things, and the windows version can do mac things).

In prior versions of Xojo, there were no symlinks inside the mac bundles. Now, there are.

What’s interesting is that even though your test found that the symlinks were broken, you also found that your app still worked. This makes me wonder just how critical those symlinks inside frameworks are? One guesses they aren’t there for no good reason…

The documentation https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html seems to suggest that a framework could ignore all of the Resources symlinking stuff, e.g.

which suggests that it would be OK to have the Xojo framework bundle be unversioned.

Norman, Is there a reason it is?

For fun, I tried “flattening” XojoFramework (removing the symlinks) and my app refuses to launch:

Library not loaded: @executable_path/../Frameworks/XojoFramework.framework/Versions/A/XojoFramework

So it appears that the MacOS executable is hard-coded to /Versions/A/XojoFramework

However, simply removing the “Resources” and “XojoFramework” symlinks doesn’t seem to hurt the app, which is consistent with what Michel found. Curious.

I would not risk distributing an app with a broken symlink inside, when it is so easy to compress it on Mac. So the experiment was purely to satisfy my curiosity. I doubt Xojo would place a symlink there without a purpose anyway. Maybe Norman will tell ?

What I learned through that little exercise is more ominous : I use extensively symlinks on my web site to deliver archives under several version names and avoid redundancies. I always assumed that moving files between platforms insured their integrity, especially since Unix Symbolic links are after all text files. Now it appears they can be broken by archive/dearchive. I knew they where fragile, but not to that point :frowning:

Of course, they are easy to recreate, but still…

I’m not Norman, but the reason we do it the way we do is that’s how the documentation says to lay out a framework, that’s how Xcode’s template makes a framework, and that’s how every framework I’ve seen is laid out. The symlinks are a pain, but they’re less painful than worrying about MAS rejections.

What’s funny is that a million years ago, everyone complained about MacOS using non-standard Resource forks, for this same reason : they are hard to deal with on cross-platform filesystems.

Mac OS X came along and deprecated them, and now they are almost never used.

However, the reliance on symlinks puts us back in the same boat: relying on filesystem behavior that’s not universal.

The theory behind framework bundles and symlinks is interesting: it would allow one to share frameworks and even have major & minor version tracking. However, given that Xojo builds a monolithic app, there seems to be no benefit of this, and it only adds complexity.

Frameworks without certain elements included do not get code signed on OS X 10.9 Mavericks. Thats the only issue I’ve come across with broken (but still functional) framework bundles.

I can’t quite recall exactly what it was that’s missing, but I had to make a framework fixer to post process some ^&%$^**er apps. I’ve also since discovered that other third party toolkits also create functional framework bundles, that cannot be code signed until all elements are present.

A newer version of App Wrapper will automagically validate all framework bundles before it tries to code sign.

Thanks, Joe, this raises two questions:

  • if as I interpret the documentation, symlinks are optional, is there any thought to getting rid of them in future versions and just having a flat framework folder?
  • MAS approval : that’s a good point, as the rules they use are ever-changing and arbitrary. They could conceivably reject an app even it was legal according to their own documentation… it’s happened before.

[quote=90351:@Sam Rowlands]Frameworks without certain elements included do not get code signed on OS X 10.9 Mavericks. Thats the only issue I’ve come across with broken (but still functional) framework bundles.
…[/quote]

That’s another issue: even if an app runs after being transferred through a windows filesystem, the code-signature may be broken. I’d love to hear more if you can remember the details.

Fair enough. Do as you’re told and you will be safe. Given Apple’s finickyness, makes sense.

About the zipping on Windows and unzipping on Mac : the original symlink is 26 bytes long, and the extracted/broken one is 1,067 bytes long, padded with chr(&h20). It has lost its icon and appears as a dark grey exec document like an unknown Dos file.

Seems that indeed, this is a case of resource fork getting in the way. But by their very nature, symlinks are strange under Unix as well : although they are files, they cannot be opened as such.

Normally, trying to copy a symlink to disk under Unix will copy the target. In Apple case, they must have done something rather nifty to insure symlinks inside their bundles can be copied and remain intact.

The symlinks in frameworks are a holdover from NeXT when they actually did make use of it. For example, AppKit is currently on version ‘C’.

[quote=90352:@Michael Diehr]if as I interpret the documentation, symlinks are optional, is there any thought to getting rid of them in future versions and just having a flat framework folder?
[/quote]

I didn’t read the document in the same way. Until Apple explicitly says that they’re changing how frameworks are packaged, it’s extremely unlikely that Xojo will change.

This isn’t really a question.

For what it’s worth, we’ve ran into something like this before when producing a Linux/OS X app from Windows. Windows doesn’t have an executable bit, so the compiler puts the result inside of a tar file after post build scripts have ran. Inside of the tar file, the executable has the +x bit set.

We took a similar approach when dealing with symlinks. For the Windows IDE, we ship the Cocoa framework inside of a tar file. Now when we generate the built app’s tar file, we just add the contents of XojoFramework.tar in the correct places in the app’s tar file.

Yeah, I think I’m going to have to do something similar. In the past I had been able to just copy the Mac helper app inside a folder on the Windows app and it usually “just worked” when copied back to mac. But using Tar (or in my case, Zip) as the wrapper would alleviate that problem. It might also fix some other issues I’ve seen, such as bizarre permissions issues for certain customers that we could not reproduce.

Firstly if it’s code signed on the Mac, I would strongly suggest compressing it first, I don’t think any good will come from transportation of it uncompressed. It the files within the bundle get modified after code signing (and before the destination machine has verified it), the code signature gets broken and thus the app won’t work (for your average user anyway).

Python (py2app), it’s framework, doesn’t contain a plist file and only one symbolic link (Current).
Filemasher, contains zero symbolic links and no plist file either.

Neither of these can be code signed. It may be because in both of these the plist is missing.

When copying a symlink, rather than the file, you can pass a flag to CP and it will do it for you.

Oh yes, we may have finally lost resource forks (looks at Adobe engineers), but Apple’s Access Control Lists are the new nightmare. It’s another thing that I had to add to App Wrapper was resetting permissions, the ACLs can get so funky, that like you witness, the app works on one machine and not on another with no clear reason why (until you reset the permissions).