|
|
(Note that Frameworks has now been broken out into its own page so it
|
|
|
can be tracked there. See
|
|
|
[CMake:MacOSX_Frameworks](CMake%3AMacOSX_Frameworks "wikilink"))
|
|
|
|
|
|
## Issue
|
|
|
|
|
|
On Mac there are several different cases of combinations of bundles,
|
|
|
frameworks, and unix tools.
|
|
|
|
|
|
- What is framework?
|
|
|
- Acording to
|
|
|
[1](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
|
|
|
[2](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".
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
- 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/>. **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:"
|
|
|
|
|
|
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
|
|
|
|
|
|
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 [CMake Bug
|
|
|
Tracker](http://www.cmake.org/Bug) as of 10/April/2006. It is [Bug
|
|
|
\#3118](http://www.cmake.org/Bug/bug.php?op=show&bugid=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:
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
/Applications/
|
|
|
appl1.app/
|
|
|
Contents/
|
|
|
Info.plist
|
|
|
MacOS/
|
|
|
appl1 -> appl1-1
|
|
|
appl1-1
|
|
|
appl1_aux1
|
|
|
appl1_aux2
|
|
|
Resources/
|
|
|
appl1_res1
|
|
|
appl1_res2
|
|
|
|
|
|
- Suggested api:
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
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
|
|
|
)
|
|
|
|
|
|
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:
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
/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
|
|
|
|
|
|
- Suggested api:
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
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)
|
|
|
|
|
|
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
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
/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
|
|
|
|
|
|
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:
|
|
|
|
|
|
Wrapper
|
|
|
Executables
|
|
|
Resources
|
|
|
Java Resources
|
|
|
Frameworks
|
|
|
Shared Frameworks
|
|
|
Shared Support
|
|
|
PlugIns
|
|
|
|
|
|
(This is from Xcode 2.2.1, the names seem to have changed slightly since
|
|
|
Panther.)
|
|
|
|
|
|
The directory mappings for an .app bundle are:
|
|
|
|
|
|
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/
|
|
|
|
|
|
The directory mappings for the following in a .framework seem to be
|
|
|
different:
|
|
|
|
|
|
Shared Support: .framework/Versions/A/Resources/
|
|
|
PlugIns: .framework/Versions/A/Resources/
|
|
|
|
|
|
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:
|
|
|
|
|
|
Absolute Path
|
|
|
Products Directory
|
|
|
|
|
|
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/.)
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
/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
|
|
|
|
|
|
### Framework + Unix tools
|
|
|
|
|
|
- Framework stuff in one directory, unix tools in typical unix
|
|
|
location
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
/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
|
|
|
|
|
|
### Bundle + Framework + Unix tools
|
|
|
|
|
|
- Framework stuff in one directory, unix tools in typical unix
|
|
|
location
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
/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
|
|
|
|
|
|
## Linking Issues
|
|
|
|
|
|
### Link a Framework
|
|
|
|
|
|
Assuming:
|
|
|
|
|
|
/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/
|
|
|
|
|
|
Regular library is linked like this:
|
|
|
|
|
|
libtool -dynamic libr3_src1.o libr3_src2.o -o libr3.dylib
|
|
|
|
|
|
Framework is linked like this:
|
|
|
|
|
|
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
|
|
|
|
|
|
You link libr2.dylib like
|
|
|
this:
|
|
|
|
|
|
libtool -dynamic libr1_src1.o libr1_src2.o -o FRlibr1.framework/Versions/ver2/Libraries/libr2.dylib
|
|
|
|
|
|
- Looks like the difference between linking framework and linking
|
|
|
shared library
|
|
|
is:
|
|
|
- Framework:
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
gcc <b>-dynamiclib</b> -o FRlibr1.framework/Versions/ver2/FRlibr1 <sources>
|
|
|
|
|
|
- - Shard library:
|
|
|
|
|
|
<!-- end list -->
|
|
|
|
|
|
gcc <b>-dynamic</b> -o libr2 <sources>
|
|
|
|
|
|
### Private Frameworks
|
|
|
|
|
|
Assuming:
|
|
|
|
|
|
/Applications/
|
|
|
appl1.app/
|
|
|
Contents/
|
|
|
Info.plist
|
|
|
MacOS/
|
|
|
appl1 -> appl1-1
|
|
|
appl1-1
|
|
|
Resources/
|
|
|
Framework/
|
|
|
libr1-ver1.dylib
|
|
|
|
|
|
You have to run:
|
|
|
|
|
|
install_name_tool \
|
|
|
-id @executable_path/../Frameworks/libr-ver1.dylib \
|
|
|
appl1.app/Contents/Frameworks/libr1-ver1.dylib
|
|
|
|
|
|
and
|
|
|
|
|
|
install_name_tool \
|
|
|
-change libr-ver1.dylib \
|
|
|
@executable_path/../Frameworks/libr-ver1.dylib \
|
|
|
appl1.app/Contents/MacOS/appl1
|
|
|
|
|
|
- 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:
|
|
|
|
|
|
<?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>
|
|
|
|
|
|
### 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:
|
|
|
|
|
|
<key>CFBundleIconFile</key>
|
|
|
<string>MyAppIcon.icns</string>
|
|
|
|
|
|
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.
|
|
|
|
|
|
----
|
|
|
This page was initially populated by conversion from its [original location](https://public.kitware.com/Wiki/CMake:Bundles_And_Frameworks) in another wiki. |