I have an OSX application, and in the bundle's MacOS directory, I have an executable and a bunch of dylibs. The executable is, of course, pointed to by the Info.plist's CFBundleExecutable entry. When I try to sign it, codesign complains (as of 10.9) that my dylibs aren't signed, which makes sense. So I sign all of the dylibs, which I would think would let me sign the main executable now.
The problem is that I actually have a couple of data files in my MacOS dir, as well. The application is a cross-platform Qt application and the data files are localizations files that are found with respect to the main executable. codesign complains that it doesn't want to sign my main executable until the data files are signed.
Is this just a fundamentally wrong thing to be doing - putting anything that isn't mach-o into MacOS? Is signing those data files even a reasonable thing to do - ie like a .cat file on Windows? Clearly I wouldn't want codesign haphazardly slapping a digest hash on to the end of my data files.
Yes those data files should go into the Resources folder.
From the Bundle Programming Guide
MacOS (Required)
Contains the application’s standalone executable code. Typically, this directory contains only one binary file with
your application’s main entry point and statically linked code.
However, you may put other standalone executables (such as
command-line tools) in this directory as well.
Resources
Contains all of the application’s resource files. This contents of this directory are further organized to distinguish
between localized and nonlocalized resources. For more information
about the structure of this directory, see “The Resources Directory”
Codesigning the data files won't change them; they are simply recorded in the _CodeSignature/CodeResources file.
Related
I am not a Mac owner and am putting myself through a crash course to get up to speed (e.g., reading "Switching to the Mac"), to give you an indication of my current level of understanding. The access I have to a physical Mac is limited, so I am trying to connect as many dots as possible before my next session with my friend's computer.
I have: a file folder containing all resources needed for a self-contained application written with Java (OpenJDK 11, JavaFX 11). The JLINK tool was successfully used to create this file folder, and it holds all necessary Java libraries as well as the code I wrote for the application. The executable resides in a subfolder: /bin. The program runs perfectly well on the Mac when the executable is run.
I want: something that is easy to download, install and run.
I'm unclear about what needs to be done to get this. The road map seems to have two main steps:
the file folder needs to be converted into something that responds as if it were an application (e.g., a Bundle? or an .app?)
the resulting folder-as-executable can be shipped via either .dmg or .pkg
For the second part, I've researched and found tools such as Packages or create-dmg. It seems to me these tools are pretty straightforward and shouldn't be too difficult to learn to use. (Just have to pick one or the other or something similar.)
For the first part, I'm on shaky conceptual ground. I've found info about Bundles, but no tutorials, walk-throughs or examples. It looks like a key step is understanding how to make a proper Info.plist file, but doing this properly looks tricky. Also, I'm not clear on how the resulting Bundle will become an .app file or if it needs to, or if there is another, more direct way to make my file folder be viewed by the OS as an application.
Some hand-holding or references to tutorials or even assurance that I am on the right track (if that is the case) would be much appreciated. Thanks!
The Java Deployment guide from Oracle relies heavily on ANT, but doesn't cover the case of a self-contained, customized JVM via JLINK well enough for me to decipher. So, I've taken the approach of trying to learn/understand the necessary steps using command-line commands.
While creating a Bundle is certainly an option, there is an easier way.
Step one is to make an .app manually. An answer to this question: "How to make a Mac OS X .app with a shell script?" goes over the basic steps. The Java file system that results from jlinking has a folder /bin in which there is a bash file that runs the program. This file should be moved to the outermost folder, and it should be named the desired name of the application. The bash file itself will have to be edited and "/bin" added to the address in last command so that the executable will be found. In addition, the folder itself will have to be renamed to be the same as the bash file, but with .app added as an extension.
The next thing I wanted to have was a custom icon. The question "Include icon in manually created app bundle" shows how to do this.
For the next step I made use of the program "Packages". I'm a bit confused about where I downloaded this from (there seem to be multiple sites), but here is a link to the manual. This tool allowed me to create a .pkg file that, when executed, installs my .app in the Applications folder. Then I compressing the .pkg file (to .zip) and made it available at a URL for downloading.
I've had a friend do a test download and install, and the program works!
This isn't meant to be a complete tutorial, and there are a few steps more that I want to figure out pertaining to sandboxing and sealing, but I believe this is a reasonable roadmap that can be used for simpler jlinked Java applications for Mac distribution.
I need to create symlinks in frameworks inside an app on OSX (vers 10.10.1). I am outside of XCode as the app is developed in Qt. It provides the frameworks, but they need some retouches to work on the new codesigning rules.
I call "ln -s path_origin path_target_link" and apparently it works, the links are created and they resolve to the right place.
But when I codesign the app, I get an error "unsealed contents present in the root directory of an embedded framework"
(In order to verify my procedure, I copied a framework from another package downloaded that validates codesigning and I could sign it successfully, when I create a symlink my way codesign starts to give the error so I'm assuming the problem is my symlink creation)
I tried other methods with the same result so I must be missing something. Any ideas?
For the case it's useful to anyone. In my case the problem was that I was creating the links with absoulte paths. Obviously they should be relative: You move to the directory where the link should go and create the link relative to the current location.
Version 1 code sign recorded only files in the Resources directory and ignored the rest. But version 2 records substantially all files by default. So we have to sign each and every frameworks bundle's versions and app binaries.
Ensure your framework bundle structure is meet the requirement of apple.
According to Apple's documentation, framework bundles don't have a 'Contents' folder. Instead, each version folder gets a 'Resources' folder which contains the Info.plist file, and which is also symbolic linked at the top-level framework folder. Qt5 frameworks have incorrect layout after SDK build, so this isn't just a problem with macdeployqt, but whole framework assembly part.
so confirm, there is no faulty layout in your app bundle.
If you have a *.prl in your Qt framework bundle (i.e.QtCore.framework/QtCore.prl). *.prl file may cause trouble for you as codesign just bails out with "unsealed content presents in the root directory of an embedded framework" without telling exactly what's going on. Strip if you have any prl files.
It is necessary for the Info.plist to have the correct CFBundleExecutable field. At the moment it doesn't. The debug version of Info.plist would overwrite the release version, and it also happens to contain invalid data. In particular, CFBundleExecutable would contain the _debug suffixed library name, which it shouldn't. If you have this problem then modify the incorrect info.plist.
The last step is you have to codesign all the frameworks before you sign the entire app bundle.
For anyone confused about this issue, you can refer to Apple's documentation https://developer.apple.com/documentation/bundleresources/placing_content_in_a_bundle
It contains all the details for macOS/iOS/MacCatalyst/watchOS/tvOS...
This may sound like I'm just looking for a .exe file, but I'm not all that familiar with windows. I have been using pyinstaller to turn my apps into binaries. My app relies on a lot data directories and third party binaries that I package within the same directory as the executable binary. For Mac, this makes things easy because the user only has to click on MyApp.app inside the applications directory which is like a link to MyApp.app/Contents/MacOs/MyApp. This way MyApp never has to be touched and is all bundled together with the data directories (also loaded inside of MyApp.app/Contents/MacOs/).
However, I can't really find a windows equivalent. While Pyinstaller can create a directory with my data directories and executable inside of it, if the user ever moves the .exe file inside the directory, the app will never work (because it loses its relative location to the data directories). Is there such a thing that can package this directory like on MacOS so the user just has to click on a single .exe file that links to the .exe inside the directory packaged within it? That way we can just pass around one directory. Like a Mac.app?
Win32 apps store data within the executable file as resources, which allows the single file solution, but they can't be accessed using normal file APIs, there are a separate set of functions for resource handling. (This implies that resources aren't so useful for things that absolutely have to be files, like images of helper executables.)
Win32 also has alternate data streams, which are more similar to what you're used to with .app packages, separating a local identifier from the actual filename by $DATA:. But those only work on NTFS, get lost by many file management applications, never have been very popular, and are now effectively deprecated by Microsoft (by preventing access from Windows Store apps).
Can one get access to the application source files on mac? In Applications folder any .app file can be explored and there get access to the header files, is it all or can the class files be accessed too?
Unless a Mac application includes private frameworks (in the application bundle), which includes their headers (rare), no.
Most of the time, a Mac application will just contain the application's binary, as well as resources (icons, images, L10N, etc.).
You may disassemble the binary, if you know how to deal with assembly language.
If the application was built with Objective-C, you can use specific tools to produce a header file from the binary, with all the Objective-C interfaces.
Take a look at ClassDump, for instance.
You may also use the nm command, on the application's binary, to get a list of the symbols it contains.
i have an executable for my cocoa application as xyz.app file. But when i copy this on windows, it is showing this as a directory with all the resource files and stuff. Is there any way to create a single file executable on mac also (like .exe file on windows) so as to disable the user from seeing the resource files and other files?
Thanks
You talking about a Bundle, which is a folder that is given an extension and the OS treats it as if it is a single file, while in reality it is a folder with resources in it. The NIB files are stored in this bundle as well as your executable and the info.plist file. This is just the way apps work in Cocoa.
The only way around it would be to write your app in a different language, but i'm not sure which, if any, will give you a single file executable.
What are you storing in your app directory that you don't want people to have access to?
There are ridiculously complicated ways to do that, sure. For example, you could gzip all your resource files and decompress them at runtime. But there's no good reason to do so — all it does is make more work for you, introduce additional complexity and make your app slow. Adobe doesn't do this, Microsoft doesn't do this, micro-ISVs don't do this — it's just not advisable.