|
|
(One intermediate revision by one other user not shown) |
Line 1: |
Line 1: |
| (Note that Frameworks has now been broken out into its own page so it can be tracked there. See [[CMake:MacOSX_Frameworks]])
| | {{CMake/Template/Moved}} |
| ==Issue==
| |
|
| |
|
| On Mac there are several different cases of combinations of bundles, frameworks, and unix tools.
| | This page has moved [https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/platform_dependent_issues/Bundles-And-Frameworks here]. |
| | |
| * What is framework?
| |
| ** Acording to [http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachOTopics/Articles/building_files.html#//apple_ref/doc/uid/TP40001828-97030-TPXREF106] Frameworks are shared libraries that are packaged with associated resources, such as graphics files, developer documentation, and programming interfaces. See "Using Shared Libraries and Frameworks" in “Loading Code at Runtime” for more information.
| |
| * What is bundle?
| |
| ** Acording to [http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachOTopics/Articles/building_files.html#//apple_ref/doc/uid/TP40001828-97030-TPXREF106] Bundles are executable files that your program can load at runtime using dynamic linking functions. Bundles implement plug-in functionality, such as file format importers for a word processor. The term “bundle” has two related meanings in Mac OS X:
| |
| *** The actual object file containing the executable code
| |
| *** A directory containing the object file and associated resources. A bundle need not contain an object file. For more information on bundles, see Bundle Programming Guide.
| |
| ** The latter usage is the more common. However, unless otherwise specified, this document refers to the former.
| |
| ** The .lproj "Data Bundles" are not currently supported. You must create and manage them outside of Xcode. The string to look for in a pbxproj file is "PBXVariantGroup".
| |
| | |
| * ADD_LIBRARY and ADD_EXCUTABLE as they exist now do not provide enough functionality
| |
| * The problem is that CMAKE_INSTALL_PREFIX is not enough. Also, when creating bundles and frameworks, auxilary files should be in the proper subdirectory structure.
| |
| * FIND_PROGRAM may also need support to find programs within application or framework bundles. Not sure yet if this should only be the main program in the application bundle or if it needs to also find arbitrary programs located within an application or framework bundles.
| |
| | |
| ==Current Status==
| |
| | |
| 24/Oct/2006 - I have very, very preliminary support for creating frameworks with CMake at [http://wtl.wayfarer.org/cmake/ http://wtl.wayfarer.org/cmake/]. '''Note that this is in no way ready to be merged and probably won't even work for you!''' But, it does create a framework bundle for me. Unfortunately, even though the bundle will link, it won't run as the full path to the framework library isn't set correctly. It's set as TARGET_INSTALLNAME_DIRframeworkname. It also doesn't support header files in the framework yet. It is just meant to be a starting place from which to move forward. To ask questions about it or comment on it, please e-mail me (Tanner Lovelace) at clubjuggler at gmail dot com.
| |
| | |
| Currently (March 2006) ADD_EXECUTABLE supports creating an application bundle and setting various options. From the CMake documentation for ADD_EXECUTABLE:
| |
| | |
| "MACOSX_BUNDLE indicates that when build on Mac OSX, executable should be in the bundle form. The MACOSX_BUNDLE also allows several variables to be specified:"
| |
| | |
| <pre>
| |
| MACOSX_BUNDLE_INFO_STRING
| |
| MACOSX_BUNDLE_ICON_FILE
| |
| MACOSX_BUNDLE_GUI_IDENTIFIER
| |
| MACOSX_BUNDLE_LONG_VERSION_STRING
| |
| MACOSX_BUNDLE_BUNDLE_NAME
| |
| MACOSX_BUNDLE_SHORT_VERSION_STRING
| |
| MACOSX_BUNDLE_BUNDLE_VERSION
| |
| MACOSX_BUNDLE_COPYRIGHT
| |
| </pre>
| |
| | |
| It does not, however, allow any specification of where resource or other files should go within the bundle.
| |
| <hr/>
| |
| A patch adding support for application bundles to the FIND_PROGRAM command has been uploaded to the [http://www.cmake.org/Bug CMake Bug Tracker] as of 10/April/2006. It is [http://www.cmake.org/Bug/bug.php?op=show&bugid=3118 Bug #3118]. See the bug for more details.
| |
| | |
| ==Notation==
| |
| | |
| * In all examples, the applications are named appl1, appl2, ...
| |
| * libraries are named libr1, libr2, ...
| |
| * header files are named appl1_header1, appl2_header2, libr1_header1, ...
| |
| * there are auxilary files associated with application and library appl1_aux1, appl2_aux2, libr1_aux1, ...
| |
| * and some resource files associated with application and library appl1_res1, appl2_res2, libr1_res1, ...
| |
| * All versions are ver1, ver2, ...
| |
| * All libraries have lib in their name, while frameworks do not. To differentiate, all frameworks will have names FRlibr1, FRlibr2, ...
| |
| | |
| ==Cases==
| |
| | |
| ===Unix tools only===
| |
| * No issues (just like any other unix)
| |
| | |
| ===Bundle only===
| |
| * Everything in a same directory:
| |
| | |
| <pre>
| |
| /Applications/
| |
| appl1.app/
| |
| Contents/
| |
| Info.plist
| |
| MacOS/
| |
| appl1 -> appl1-1
| |
| appl1-1
| |
| appl1_aux1
| |
| appl1_aux2
| |
| Resources/
| |
| appl1_res1
| |
| appl1_res2
| |
| </pre>
| |
| | |
| * Suggested api:
| |
| | |
| <pre>
| |
| ADD_EXECUTABLE(
| |
| appl1
| |
| MACOSX_BUNDLE
| |
| appl1_src1.cxx
| |
| appl1_src2.cxx
| |
| ...
| |
| apple1_aux1
| |
| apple1_aux2
| |
| apple1_res1
| |
| apple1_res2
| |
| )
| |
| | |
| SET_SOURCE_FILES_PROPERTIES(
| |
| apple1_aux1
| |
| apple1_aux2
| |
| PROPERTIES
| |
| MACOSX_PACKAGE_LOCATION MacOSX
| |
| )
| |
| SET_SOURCE_FILES_PROPERTIES(
| |
| apple1_res1
| |
| apple1_res2
| |
| PROPERTIES
| |
| MACOSX_PACKAGE_LOCATION Resources
| |
| )
| |
| </pre>
| |
| | |
| Comment: (submitted by david.cole)
| |
| I like the suggested api. One thing to keep in mind, however, is that some of the file system entities Mac programmers perceive as files are actually bundles themselves... For example, the resource files produced by Interface Builder (the *.nib "files") are actually bundles/directories themselves. As a Mac programmer, I think of the *.nib "file" as just another source file... In reality it's a directory with contents, which is supposed to be recursively copied into the correct location of the target bundle at build time. I would expect to be able to add either ''a file or a directory'' as a MACOSX_BUNDLE_CONTENT element in the ADD_EXECUTABLE/ADD_LIBRARY commands. If it's a file it gets copied into the target bundle at the specified location. If it's a directory, same thing, but recursively. This is '''mandatory''' in my opinion because Apple could decide to add, remove or completely reorganize elements within the *.nib file format with their next version of Xcode. I definitely don't want to mirror the hierarchical structure of a *.nib file in my CMakeLists.txt files. I also definitely don't want to be forced into using FILE(GLOB_RECURSE ...) in order to do things on a file by file basis. As a Mac programmer, I don't necessarily know whether one of these things is a file or directory - I can't tell CMake what I don't know, so CMake should definitely be able to handle either. CMake needs to support copying directories verbatim as bundle elements to make this feature worthwhile.
| |
| | |
| Maybe this concept could be generalized to "any file/directory that needs to be copied from source or binary tree into a location relative to the build exe/dll/lib" on '''any platform'''. Perhaps naming the features AUXILIARY_CONTENT_FILE and AUXILIARY_CONTENT_LOCATION would be more useful. I could see wanting to have different configuration files copied to where the exe is as part of the build step on Windows or Linux also. It's sort of an easier way of guaranteeing that a file is part of the build tree. Rather than explicit CONFIGURE_FILE or cmake -E copy/copy_directory commands, you could just add a source file as an AUXILIARY_CONTENT_FILE and cmake would make sure it gets copied/configured at build time.
| |
| | |
| ===Framework only===
| |
| * Everything in a same directory:
| |
| | |
| <pre>
| |
| /Library/
| |
| Frameworks/
| |
| FRlibr1.framework/
| |
| FRlibr1 -> Versions/Current/FRlibr1
| |
| Resources -> Versions/Current/Resources
| |
| Libraries -> Versions/Current/Libraries
| |
| Headers -> Versions/Current/Headers
| |
| Versions/
| |
| Current -> ver2
| |
| ver2/
| |
| FRlibr1
| |
| Resources/
| |
| Info.plist
| |
| version.plist
| |
| Libraries/
| |
| libr2.dylib
| |
| libr3.dylib
| |
| Headers/
| |
| FRlibr1_header1.h
| |
| FRlibr1_header2.h
| |
| FRlibr1_header3.h
| |
| </pre>
| |
| | |
| | |
| * Suggested api:
| |
| | |
| <pre>
| |
| ADD_LIBRARY(
| |
| FRlibr1
| |
| SHARED MACOSX_FRAMEWORK
| |
| appl1_src1.cxx
| |
| appl1_src2.cxx
| |
| FRlibr1_header4.h
| |
| FRlibr1_header5.h
| |
| FRlibr1_header6.h
| |
| ...
| |
| MACOSX_FRAMEWORK_HEADERS
| |
| FRlibr1_header1.h
| |
| FRlibr1_header2.h
| |
| FRlibr1_header3.h
| |
| )
| |
| | |
| SET_TARGET_PROPERTIES(FRlibr1
| |
| PROPERTIES
| |
| VERSION ver2
| |
| )
| |
| | |
| TARGET_LINL_LIBRARIES(
| |
| FRlibr1
| |
| libr2 libr3)
| |
| </pre>
| |
| | |
| Comment: (submitted by Tanner Lovelace) We need to have both the means of versioning frameworks and creating frameworks that aren't versioned. If a framework doesn't have a version, it should be placed at the top level of the framework directory structure (or, alternatively, we could decide that all frameworks must have a version and either silently default to something like "A" (not recommended!) or cause an error). If it does have a version, then it should be placed in the appropriate version directory and symlinks created to point to it. The version may be any arbitrary string. Apple itself generally uses capital letters (A, B, C, etc...) but the major version works just as well. I believe it is suggested that anything below major version number not be used since libraries should be compatible within major version numbers.
| |
| | |
| ===Bundle + Framework===
| |
| * Bundle stuff in one directory, framework stuff in another one
| |
| | |
| <pre>
| |
| /Applications/
| |
| appl1.app/
| |
| Contents/
| |
| Info.plist
| |
| MacOS/
| |
| appl1 -> appl1-ver1
| |
| appl1-ver2
| |
| appl1_aux1
| |
| appl1_aux2
| |
| Resources/
| |
| appl1_res1
| |
| appl1_res2
| |
| /Library/
| |
| Frameworks/
| |
| FRlibr1.framework/
| |
| FRlibr1 -> Versions/Current/FRlibr1
| |
| Resources -> Versions/Current/Resources
| |
| Libraries -> Versions/Current/Libraries
| |
| Headers -> Versions/Current/Headers
| |
| Versions/
| |
| Current -> ver2
| |
| ver2/
| |
| FRlibr1
| |
| Resources/
| |
| Info.plist
| |
| Version.plist
| |
| Libraries/
| |
| libr2.dylib
| |
| libr3.dylib
| |
| Headers/
| |
| FRlibr1_header1.h
| |
| FRlibr1_header2.h
| |
| FRlibr1_header3.h
| |
| </pre>
| |
| | |
| Comment: (submitted by Eric Wing) I would like to point out that having a Libraries directory is not a default. (Some examples of more default like frameworks might be CoreData, CoreAudio, and GLUT.) Don't allow people to be misled into thinking that "Libraries" is an official path, and that frameworks place the actual dynamic library executable code here and it follows the lib*.dylib format. This convention is typically done for frameworks that have a (non-NeXT) Unix heritage and try to make libraries available for easy access to traditional Unix tools by placing a second copy of libraries in the bundle for this purpose. However, notice that the Libraries convention is not entirely consistent even between Unix heritage stuff. If you look at the frameworks for Python, JavaVM, Tcl, and OpenGL, you will see many different things.
| |
| | |
| Xcode however will has some of the pre-coined locations accessible through different features. For example, if you add a "New Build Phase->New Copy Files Build Phase" to your target, there are pre-coined options for:
| |
| <pre>
| |
| Wrapper
| |
| Executables
| |
| Resources
| |
| Java Resources
| |
| Frameworks
| |
| Shared Frameworks
| |
| Shared Support
| |
| PlugIns
| |
| </pre>
| |
| (This is from Xcode 2.2.1, the names seem to have changed slightly since Panther.)
| |
| | |
| The directory mappings for an .app bundle are:
| |
| <pre>
| |
| Wrapper: .app/
| |
| Executables: .app/Versions/A/MacOS/
| |
| Resources: .app/Versions/A/Resources/
| |
| Java Resources: .app/Versions/A/Resources/Java/
| |
| Frameworks:.app/Versions/A/Frameworks/
| |
| Shared Frameworks: .app/Versions/A/SharedFrameworks/
| |
| Shared Support: .app/Versions/A/SharedSupport/
| |
| PlugIns: .app/Versions/A/PlugIns/
| |
| </pre>
| |
| | |
| The directory mappings for the following in a .framework seem to be different:
| |
| <pre>
| |
| Shared Support: .framework/Versions/A/Resources/
| |
| PlugIns: .framework/Versions/A/Resources/
| |
| </pre>
| |
| | |
| I'm not sure if this is intentional or a bug. I will file a bug report and see if I can find out.
| |
| | |
| I have not experimented with .bundle bundles for loadable modules.
| |
| | |
| There are also two options for:
| |
| <pre>
| |
| Absolute Path
| |
| Products Directory
| |
| </pre>
| |
| which allow you to place files anywhere you choose (usable for non-standard custom things like "Libraries").
| |
| | |
| It might be worth considering leveraging this feature of Xcode as to insulate CMake from any future changes Apple might adopt as to where things get placed or named or to capture the behavioral differences between frameworks and applications if the above differences are by design.
| |
| | |
| Also, Xcode has a mechanism for marking "public", "private", and "project" headers for frameworks. Public headers are copied to
| |
| .framework/Versions/A/Headers/
| |
| and Private Headers are copied to
| |
| .framework/Versions/A/PrivateHeaders/
| |
| | |
| ===Bundle + Unix tools===
| |
| * Bundle stuff in one directory, unix tools in typical unix location (Note: (submitted by Tanner Lovelace) Some darwinports ports are done this way. gpsbabel, I know, has a standard unix executable placed in <prefix>/bin and a mac application bundle placed in /Applications/DarwinPorts/.)
| |
| | |
| <pre>
| |
| /Applications/
| |
| appl1.app/
| |
| Contents/
| |
| Info.plist
| |
| MacOS/
| |
| appl1 -> appl1-ver1
| |
| appl1-ver2
| |
| appl1_aux1
| |
| appl1_aux2
| |
| Resources/
| |
| appl1_res1
| |
| appl1_res2
| |
| | |
| /usr/
| |
| bin/
| |
| appl2
| |
| share/
| |
| appl2-version/
| |
| appl2_aux1
| |
| appl2_aux2
| |
| </pre>
| |
| | |
| ===Framework + Unix tools===
| |
| * Framework stuff in one directory, unix tools in typical unix location
| |
| | |
| <pre>
| |
| /Library/
| |
| Frameworks/
| |
| FRlibr1.framework/
| |
| FRlibr1 -> Versions/Current/FRlibr1
| |
| Resources -> Versions/Current/Resources
| |
| Libraries -> Versions/Current/Libraries
| |
| Headers -> Versions/Current/Headers
| |
| Commands -> Versions/Current/Commands
| |
| Versions/
| |
| Current -> ver2
| |
| ver2/
| |
| FRlibr1
| |
| Resources/
| |
| Info.plist
| |
| version.plist
| |
| Libraries/
| |
| libr2.dylib
| |
| libr3.dylib
| |
| Headers/
| |
| FRlibr1_header1.h
| |
| FRlibr1_header2.h
| |
| FRlibr1_header3.h
| |
| Commands/
| |
| appl2
| |
| bin/
| |
| appl3
| |
| /usr/
| |
| bin/
| |
| appl1
| |
| appl2 -> /Library/Frameworks/FRlibr1.framework/Commands/appl2
| |
| appl3 -> /Library/Frameworks/FRlibr1.framework/Version/ver1/bin/appl3
| |
| share/
| |
| appl1-version/
| |
| appl1_aux1
| |
| appl1_aux2
| |
| </pre>
| |
| | |
| ===Bundle + Framework + Unix tools===
| |
| * Framework stuff in one directory, unix tools in typical unix location
| |
| | |
| <pre>
| |
| /Applications/
| |
| appl1.app/
| |
| Contents/
| |
| Info.plist
| |
| MacOS/
| |
| appl1 -> appl1-ver1
| |
| appl1-ver2
| |
| appl1_aux1
| |
| appl1_aux2
| |
| Resources/
| |
| appl1_res1
| |
| appl1_res2
| |
| /Library/
| |
| Frameworks/
| |
| FRlibr1.framework/
| |
| FRlibr1 -> Versions/Current/FRlibr1
| |
| Resources -> Versions/Current/Resources
| |
| Libraries -> Versions/Current/Libraries
| |
| Headers -> Versions/Current/Headers
| |
| Commands -> Versions/Current/Commands
| |
| Versions/
| |
| Current -> ver2
| |
| ver2/
| |
| FRlibr1
| |
| Resources/
| |
| Info.plist
| |
| version.plist
| |
| Libraries/
| |
| libr2.dylib
| |
| libr3.dylib
| |
| Headers/
| |
| FRlibr1_header1.h
| |
| FRlibr1_header2.h
| |
| FRlibr1_header3.h
| |
| Commands/
| |
| appl2
| |
| bin/
| |
| appl3
| |
| /usr/
| |
| bin/
| |
| appl1
| |
| appl2 -> /Library/Frameworks/FRlibr1.framework/Commands/appl2
| |
| appl3 -> /Library/Frameworks/FRlibr1.framework/Version/ver1/bin/appl3
| |
| share/
| |
| appl1-version/
| |
| appl1_aux1
| |
| appl1_aux2
| |
| </pre>
| |
| | |
| ==Linking Issues==
| |
| | |
| ===Link a Framework===
| |
| | |
| Assuming:
| |
| <pre>
| |
| /usr/
| |
| lib/
| |
| libr3.dylib
| |
| /Library/
| |
| Frameworks/
| |
| FRlibr1.framework/
| |
| FRlibr1 -> Versions/Current/FRlibr1
| |
| Resources -> Versions/Current/Resources
| |
| Libraries -> Versions/Current/Libraries
| |
| Headers -> Versions/Current/Headers
| |
| Versions/
| |
| Current -> ver2
| |
| ver2/
| |
| FRlibr1
| |
| Resources/
| |
| Libraries/
| |
| libr2.dylib
| |
| Headers/
| |
| </pre>
| |
| | |
| Regular library is linked like this:
| |
| | |
| <pre>
| |
| libtool -dynamic libr3_src1.o libr3_src2.o -o libr3.dylib
| |
| </pre>
| |
| | |
| Framework is linked like this:
| |
| | |
| <pre>
| |
| mkdir -p FRlibr1.framework/Versions/ver2
| |
| gcc -dynamiclib -o FRlibr1.framework/Versions/ver2/FRlibr1 FRlibr1_src1.o FRlibr1_src2.o
| |
| cd ./FRlibr1.framework/Versions && ln -sf ver2 Current
| |
| cd ./FRlibr1.framework && ln -sf Versions/Current/FRlibr1 FRlibr1
| |
| </pre>
| |
| | |
| You link libr2.dylib like this:
| |
| | |
| <pre>
| |
| libtool -dynamic libr1_src1.o libr1_src2.o -o FRlibr1.framework/Versions/ver2/Libraries/libr2.dylib
| |
| </pre>
| |
| | |
| * Looks like the difference between linking framework and linking shared library is:
| |
| ** Framework:
| |
| <pre>
| |
| gcc <b>-dynamiclib</b> -o FRlibr1.framework/Versions/ver2/FRlibr1 <sources>
| |
| </pre>
| |
| ** Shard library:
| |
| <pre>
| |
| gcc <b>-dynamic</b> -o libr2 <sources>
| |
| </pre>
| |
| | |
| ===Private Frameworks===
| |
| Assuming:
| |
| | |
| <pre>
| |
| /Applications/
| |
| appl1.app/
| |
| Contents/
| |
| Info.plist
| |
| MacOS/
| |
| appl1 -> appl1-1
| |
| appl1-1
| |
| Resources/
| |
| Framework/
| |
| libr1-ver1.dylib
| |
| </pre>
| |
| | |
| You have to run:
| |
| | |
| <pre>
| |
| install_name_tool \
| |
| -id @executable_path/../Frameworks/libr-ver1.dylib \
| |
| appl1.app/Contents/Frameworks/libr1-ver1.dylib
| |
| </pre>
| |
| | |
| and
| |
| | |
| <pre>
| |
| install_name_tool \
| |
| -change libr-ver1.dylib \
| |
| @executable_path/../Frameworks/libr-ver1.dylib \
| |
| appl1.app/Contents/MacOS/appl1
| |
| </pre>
| |
| | |
| * It seems that the private frameworks can have a dylib extension and lib prefix or not.
| |
| | |
| Comment: (submitted by seanmcbride) The more common situation is that in appl1.app/Contents/Frameworks/ one will find not just a 'naked' dylib but an entire .framework bundle. But sometimes there are also .bundle files in there (ex iTunes), or indeed naked dylibs.
| |
| | |
| Comment: (submitted by rangerrick) Also keep in mind, in some cases install_name_tool won't work because there won't be enough room in the binary to change it to a longer path (by default, I think it will only work if the name is *shorter* than what's being replaced). This can be mitigated by adding the -headerpad_max_install_names flag when linking.
| |
| | |
| Comment: (submitted by Eric Wing) Private framework might not be the proper or best term here. "Private Framework" is often used to denote frameworks that you shouldn't use because their API is unsupported and may change (or be removed). The most notable example of this are Apple's frameworks in /System/Library/PrivateFrameworks.
| |
| | |
| A better term for this might be "Embedded Frameworks" (or "Embeddable Frameworks"). The intention of what you describe is not so much to make a framework "private" to prevent users from using it, but to make an application (a .app bundle) a completely self-contained entity that can be relocated to anywhere on a system (including .dmg's) and still be run-able. Mac OS intends for applications to be drag-and-dropped for installation (and for moving around or deletion). End-users don't know a bundle is a directory structure with stuff inside. They just see a single icon. Bundling a frameworks (and resources) with an application allows the application to always find the stuff it needs to run.
| |
| | |
| Also, you have confused several different things here:
| |
| | |
| First the install_name is the required (link) mechanism that lets you specify where a dynamic library (.dylib or framework) gets installed to. You are generally required to set this value at compile/linking time (with limited ability to change it later using install_name_tool). install_name is somewhat analogous to rpath found on ELF systems. But with install_name, you can only list one path, and it must be an absolute path except when using special built-in markers like @executable_path. When you build the framework, the install_name you give it is not really intended to be changed. However, install_name_tool will let you change this, but it can only be a path of equal or shorter string length. As rangerrick points out, you can mitigate this with the correct flag (or set a path with the max length at link time), but it would be good if you just pass the -install_name flag at build (link) time and set it once to the correct value the first time around.
| |
| | |
| Second embedded (or private) frameworks have nothing to do with whether a framework has a .dylib extension or not. Pretty much all standard frameworks never use .dylib, but I presume they could be coerced to do so, regardless of whether they are embedded or not. Typically the cases that embed .dylibs are done by people who build .dylibs the traditional Unix way, but still want/need to embed the dynamic library to achieve the self-contained properties described above. This is not the norm as already pointed out.
| |
| | |
| My advice is don't do this, i.e. don't mix and match .dylibs and frameworks. If you are building frameworks, you should never need to acknowledge the existence of the .dylib, particularly within CMake. Add .dylibs to a framework is a non-standard exercise that should be left to end users (most likely through the SET_SOURCE_FILES_PROPERTIES). Don't try to create a .dylib and then coerce it into a framework. You'll confuse the heck out of everybody and you are asking for trouble, potentially breaking something like using -framework foo or running debug or profile version when building unified release/debug/profile frameworks.
| |
| | |
| ==Useful Tools==
| |
| (From http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachOTopics/index.html)
| |
| | |
| Tools for analyzing Mach-O files include the following:
| |
| * The <i>/usr/bin/lipo</i> tool allows you to create and analyze binaries that contain images for more than one architecture. An example of such a binary is a universal binary. Universal binaries can be used in PowerPC-based and Intel-based Macintosh computers. Another example is a PPC/PPC64 binary, which can be used in 32-bit PowerPC–based and 64-bit PowerPC–based Macintosh computers.
| |
| * The file-type displaying tool, <i>/usr/bin/file</i>, shows the type of a file. For multi-architecture files, it shows the type of each of the images that make up the archive.
| |
| * The object-file displaying tool, <i>/usr/bin/otool</i>, lists the contents of specific sections and segments within a Mach-O file. It includes symbolic disassemblers for each supported architecture and it knows how to format the contents of many common section types.
| |
| * The page-analysis tool, <i>/usr/bin/pagestuff</i>, displays information on each logical page that compose the image, including the names of the sections and symbols contained in each page. This tool doesn’t work on binaries containing images for more than one architecture.
| |
| * The symbol table display tool, <i>/usr/bin/nm</i>, allows you to view the contents of an object file’s symbol table.
| |
| | |
| ==Related Work==
| |
| | |
| * On mailing list: http://public.kitware.com/pipermail/cmake/2005-December/007725.html
| |
| * From apple:
| |
| ** http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachOTopics/index.html
| |
| ** http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachOTopics/Articles/loading_code.html#//apple_ref/doc/uid/TP40001830
| |
| ** http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFBundles/index.html
| |
| ** http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/index.html
| |
| * From Trolltech: http://doc.trolltech.com/qq/qq09-mac-deployment.html
| |
| * Here is a good tutorial (via Quicktime movie) on how to create Embedded frameworks: http://rentzsch.com/cocoa/embeddedFrameworks
| |
| | |
| ==Real life example==
| |
| The following project contains a typical MacOSX bundle:
| |
| http://www.rogue-research.com/vtk/SimpleCocoaVTK.html
| |
| | |
| The Info.plist looks like:
| |
| | |
| <pre>
| |
| <?xml version="1.0" encoding="UTF-8"?>
| |
| <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
| |
| <plist version="1.0">
| |
| <dict>
| |
| <key>CFBundleDevelopmentRegion</key>
| |
| <string>English</string>
| |
| <key>CFBundleDocumentTypes</key>
| |
| <array>
| |
| ...
| |
| <key>NSMainNibFile</key>
| |
| <string>MainMenu</string>
| |
| <key>NSPrincipalClass</key>
| |
| <string>NSApplication</string>
| |
| </dict>
| |
| </plist>
| |
| </pre>
| |
| | |
| ===From CMake 2.0 and PackageMaker===
| |
| | |
| So, here is a short description on how I got installation package on mac osx.
| |
| | |
| 1. '''Build package'''.
| |
| | |
| 2. '''Copy package and related files''' to the following directory structure:
| |
| | |
| ./Package_Root/Applications/MyApp.app/Contents/Info.plist
| |
| ./Package_Root/Applications/MyApp.app/Contents/MacOS
| |
| ./Package_Root/Applications/MyApp.app/Contents/MacOS/MyAppExec
| |
| ./Package_Root/Applications/MyApp.app/Contents/PkgInfo
| |
| ./Package_Root/Applications/MyApp.app/Contents/Resources/MyAppIcon.icns
| |
| ./Package_Root/Applications/MyApp.app/Contents/Resources/MyAppResources.rsrc
| |
| ./Package_Root/usr/share/somedata
| |
| ./Package_Root/usr/bin/some_utility
| |
| ./Resources/License.txt
| |
| ./Resources/ReadMe.txt
| |
| ./Resources/Welcome.txt
| |
| | |
| The file PkgInfo contains "APPL????" The file Info.plist contains
| |
| package instructions. I would suggest looking at Info.plist.in in
| |
| wxWindows and modify it by putting your info in. MyAppIcon.icns is an
| |
| icon created by IconComposer in /Developmer/Applications.
| |
| MyAppResources.rsrc is a compiled resources file. I used the one from
| |
| wxWindows and it seems to be working fine. Some mac person could
| |
| explain this. Make sure that Info.plist contains:
| |
| | |
| <pre>
| |
| <key>CFBundleIconFile</key>
| |
| <string>MyAppIcon.icns</string>
| |
| </pre>
| |
| | |
| This will tell it which icon to use.
| |
| | |
| The ./Package_Root/usr/share/somedata and
| |
| ./Package_Root/usr/bin/some_utility are some extra data that your
| |
| application is using. For example they can be a command line version
| |
| of the application and some common files.
| |
| | |
| The ./Resources directory contains resources used during
| |
| installation. The names of files describe what should go in. They can
| |
| be rtf, txt...
| |
| | |
| 3. '''Create package using PackageMaker'''.
| |
| | |
| Fire up PackageMaker from /Developmer/Applications. Fill all the
| |
| entries. Most of them are straight forward. Package root is
| |
| ./Package_Root. Resources directory is ./Resources. If your
| |
| application needs to write to /usr (or to some other place beside
| |
| /Applications, then make sure to enable authentication. After you fill
| |
| all the entries, create package. This will create a directory on your
| |
| disk containing a whole lot of junk. Now you need to package this
| |
| directory.
| |
| | |
| 4. '''Create a disk image'''.
| |
| | |
| Run Disk Copy from /Applications/Utilities. The easiest way of
| |
| creating disk image is to first create empty folder, copy all the
| |
| files in and then tell Disk Copy to create disk image from folder. So,
| |
| create folder MyApp, copy in MyApp.pkg and create package.
| |
| | |
| Now you are done. This will create one file, which you can copy around.
| |
| | |
| So, what is missing is how to make application icon show in the
| |
| finder. I can make it show when running application, but not when I am
| |
| looking at application. Even if I ask for preview.
| |
| | |
| I guess somebody else will have to answer this.
| |
| | |
| | |
| {{CMake/Template/Footer}}
| |