What is the equivalent of .deb and .rpm in Mac OS X?
I am trying to create a package in Mac OS X which will include necessary libraries and scripts.
There are several approaches for Mac installation.
Simplest: self-contained application (Foo.app). You put everything in a directory (in a particular hierarchy), give the directory the .app extension, and ask the user to copy it into /Applications. All necessary libraries and scripts should be included inside the directory. It is commonly distributed inside a .dmg file, which is a disk image.
Installer: Uses a .pkg archive, which will be opened by Apple's Installer. It has capability to install libraries in root-restricted areas (after asking the user for the password).
Homebrew/Fink/MacPorts - open-source projects that provide functionality ranging from that of Debian's Aptitude to that of BSD's Ports. Authors write down recipes that the installer executes, which resolve dependencies and install necessary related packages. I believe Homebrew is now the most popular of these, with recipes being written in a Ruby DSL.
Related
I'm working to correctly distribute a software bundle for Mac ARMS (M1, M2...) which consists in a zip containing a bunch of command line utilities and dynamic libraries built using the command line tools (cc, c++ etc).
So far I've been able to sign all my executable files and my dynamic libraries with codesign using my company Developer ID certificate and to successfully notarize the zip.
Unfortunately when I download the zip using the browser my command line tools show a strange behavior: if I double click on of them from finder I get an error message saying that the identity of the developer can't be confirmed but if I run from the terminal most of the utilities work. I've noticed that if I download the last jdk as .tar.gz the behavior with the java executable is the same so I'm wondering if it's the expected behavior for command line utilities.
Still one of the utilities is not working because it is supposed to load the dynamic libraries I get an error saying that relative paths are not allowed in hardened programs.
My questions are:
Is the behavior described above for command line executable files expected?
Is there a way to allow my program that loads dynamic library to work by loading dynamic libraries as it used to do with our unsigned bundles for Intel Macs?
Does anyone knows if it's possible to notarize and distribute such a bundle in .tar.gz format rather than zip?
Thanks!
For macOS notarized software that means the executable is going to have the hard-coded path to the library and won’t work with a relative path. Usually that means setting RPATH to the hardpath
/Applications/myapp.app/Contents/Frameworks/
and aliasing your binaries from
/Applications/myapp.app/Contents/MacOS
But that is just the most common arrangement.
The hard-coded path is part of the “hardened runtime” which is a requirement to pass apple notary, an anti-malware scanner. Changing the assigned RPATH with otool is possible but invalidates the code signature, blocking execution on machines with default security without code signing at least ad hoc.
See
https://wiki.lazarus.freepascal.org/Code_Signing_for_macOS
Launching the executable directly from terminal does not run thru launchservices the way it does when you launch in finder. Launchservices begins by checking the signature against the ticket and checking the ticket, so a bare executable will be missing that info.
Thanks to the suggestions of Richard Barber I've finally understood how to correctly code-sing, notarize and deploy our bundles on Mac with hardened runtimes.
I'm leaving the steps I've taken below for future reference.
Here are the steps I needed to run:
Made sure all the dynamic executable files and libraries have referenced their dependencies without using relative paths. The relative paths may be substituted with macros like #rpath using install_name_tool
Code-singed all executable files and all the dynamic libraries suing the codesign tool with a valid Apple Distribution certificate and developer/organization key
Once signed put everything in a ZIP and sent for notarization using xcrun notarytool submit command
If the notarization succeeds the contents of the ZIP can be extracted and put in a .tar.gz without losing the validity
Once the tar.gz is downloaded on a testing machine our command line tools can be correctly used by the terminal. As suggested by Richard Barber they can't be run from Finder, but even the JDK in tar.gz format shows the same behavior, so happy with that.
This may well have been asked before I just couldn't figure out the right term to search.
I'm writing a client-server application to run on an OSX desktop which will talk to a MySQL server on the local network. It seems long-winded to implement a web-services API when basically a bunch of SQL statements will be perfect internally.
I've wrestled with the install procedure for MySQL server on my development machine, ad had to resort to symlinking libmysqlclient.18.dylib into /usr/lib even though i'd put the include path in header search paths.
What I need to know is how do I create a .app file I can send to other machines that will have access to the libmysqlclient.18.dylib file?
I'm used to Windows having installers to do this and a bit new to OSX programming although i've been doing Obj-c for iDevices for 2 years.
Is there a setting which allows the library to be copied into the .app file or do I need to install the mysql connector on each machine - if so, how do I get around the symlink issue, ideally I need it to work from the stock folders.
If this has been answered somewhere else, please point me in the right direction.
At build time the static linker on OS X, ld, writes the shared library identifier of each library that your application links against in to the application binary. At run time the dynamic linker, dyld, attempts to load each shared library from the paths specified in the application binary. You can see this information using otool -L YourApp.app/Contents/MacOS/YourApp.
The fact you needed to symlink libmysqlclient.18.dylib in to /usr/lib suggests that the shared library identifier of libmysqlclient.18.dylib is something like /usr/lib/libmysqlclient.18.dylib. To include the library in your .app bundle in a way that your application will use it rather than looking in /usr/lib you need to:
Change the shared library identifier of libmysqlclient.18.dylib so that dyld will look for the binary relative to your application binary. This is typically done by running install_name_tool -id #executable_path/../Frameworks/libmysqlclient.18.dylib libmysqlclient.18.dylib.
Copy the modified libmysqlclient.18.dylib in to the Frameworks subdirectroy in your application bundle. This is typically done using a Copy Files build phase in your Xcode project.
You should then be able to verify that the install name written in to your application binary is #executable_path/../Frameworks/libmysqlclient.18.dylib rather than /usr/lib/libmysqlclient.18.dylib (using otool -L YourApp.app/Contents/MacOS/YourApp again). If the install name isn't correct then you'll need to ensure that your linker search path is set up to find your modified version of libmysqlclient.18.dylib ahead of any other versions you may have.
How can I build a novice-usable (clickable download) installer for a Mac OS X command-line tool, and where should the binary be installed so that a novice user with no knowledge of shell paths can just open the Terminal app and type "foo" to run the freshly installed foo tool?
Can the installer also install documentation so that the user can type "man foo"?
Are there any other options that should be considered to make the use of a pure command-line (stdin, stdout) tool accessible to a novice Mac user?
What's the minimum version of OS X you're targeting? 10.6 (and IIRC 10.5) include /usr/local/bin in the default PATH, but 10.4 did not. As long as you don't need to support 10.4, you should just put the executable in /usr/local/bin and the man page in /usr/local/share/man/man1 (or whatever the appropriate chapter number is).
For building the installer itself, you can use Apple's PackageMaker utility (part of Xcode). Create a prototype local folder with bin and share/man/man1 subfolders and populate them with your files. Create a package project in PackageMaker, and choose your organization name and minimum target OS. Drag the prototype folder into the project's Contents sidebar. Set the Destination to /usr/local. Switch to the Contents tab and edit the ownership and permissions the files should be installed with (the owner/group should probably all be root/admin, with rwxrwxr-x perms on the folders and executable, rw-rw-r-- on the man page). If any irrelevant files (e.g. .DS_Store) snuck in, exclude them. Look around for any other settings you want to change, then save the project and build the installer. Then test it, to make sure it does what you expect.
I have a project whose artifacts are two dynamic libraries, let's say libX.dylib and libY.dylib (or .so for linux distributions). There are no executables.
Now I would like to distribute these libraries. Since I already use CMake to compile it, I looked at CPack and successfully generated .tgz and .deb packages for Linux. However, for Mac OSX I have no idea and the CPack Wiki about its generators did not help me much. I managed to generate a PackageMaker package, but as clearly stated at this packagemaker howto, there is no uninstall option when using this util. I then read a bit about Bundles, but I feel lost specially since I have no executable.
Question: What is the correct way to generate a package for Mac OSX using CPack?
My ideal scenario would be either something that installs as easily as a bundle or as a deb file in debian/ubuntu.
Thanks for your help
Edit
One more detail: the code to one of these libraries is not open, so I can't expect the users to do a cmake; make; make install
That's why I want a .deb, .tar.gz, bundle or whatsoever.
It depends on whether you want to install it the UNIX-y way (which is totally an ok thing to do, and actually my own preference as a Mac user) or if you want to install it as a Mac OS X Framework.
To install the libraries the UNIX-y way, you can use:
INSTALL(TARGETS target1 target2 DESTINATION lib)
In the above, replace target1 and target2 with the names of the targets that resulted in libX.dylib and libY.dylib being generated (i.e. whatever you used in ADD_LIBRARY). You can use the variable CMAKE_INSTALL_PREFIX in order to determine where the library ultimately ends up... with the above, if you set CMAKE_INSTALL_PREFIX to /usr/local, then it will install the libraries in /usr/local/lib
Edit
Based on your update, you may find Component Install with CPack and CPack Mac OS X PackageMaker Generator to be of interest. Since you will be installing libraries into the system, the PackageMaker generator is the one you should use. If you were merely distributing an application, then creating a ".app" bundle and distributing it in a ".dmg" would be the proper thing to do. PackageMaker is installed on Mac OS X when you install the Xcode Developer Tools. To package a ".app" bundle in a ".dmg", you can use the Mac OS X disk utility application or its associated commandline tools.
I'm packing the Cherokee Web Server, a very very fast webserver with a nice web-based GUI for configuration written by the spanish hacker Alvaro Lopez Herrera and available from http://www.cherokee-project.com.
So far, I've managed to create a .pkg installer using Apple's PackageMaker.app that comes with Xcode but i'm installing everything under /opt/cherokee.
I guess I'd like to have the binaries go to a dir that is already in the path and the same for the manpages and other stuff.
I looks like installing everything with prefix=/usr could work nicely, except for the config files that should go to /etc/cherokee and the document root with could go to /var/www but i'm not sure.
Would that work or should I use some directory structure under /Library? like /Library/Cherokee/VERSION/ ???
Apple's bundled Apache seems to be instaling with prefix=/usr but config files in /etc/apache2 and CGIs and the manual to /Library/WebServer with the document root in /Library/WebServer/Documents.
Maybe my docroot should be /Library/Cherokee/Documents or something like that...
For reference, Cherokee's default layout is like this: (only dirs)
http://pastebin.com/f57bc2d21
Thanks for the help in advance! :)
Do not install it directly in /usr. That's Apple's domain. Though /opt might be okay, it will not be in the default path and is not commonly used as a default installation location for third-party Unix software in Mac OS X.
My advice is to install everything under /usr/local. Apple will not touch this area (e.g., during system updates, etc.), /usr/local/bin should be in the default path for users, and I have observed many other Mac OS X server software packages using this location.
Most Mac OS X packages I've used (and most software I've built from source on Mac OS X) will create a /usr/local/whatever/... containing directory, however. So, for example, all of MySQL would be under /usr/local/mysql/... That means the MySQL binaries are in /usr/local/mysql/bin/... which is not in the default path for users. But I think the improved isolation of that extra level of directory structure is worth this sacrifice. (Another option is to install everything under /usr/local/whatever/... but then add symlinks to your most important executable(s) under /usr/local/bin)