I have the anaconda python distribution installed on my mac (10.9). I'm trying to install the ffnet package and the SpacePy package, but having trouble in doing so. Library not found for -lbundle1.o when installing python packages (ffnet, spacepy) on my mac. Ask Question Asked 6 years, 1 month ago. Library not found for -lbundle1.o. Aug 04, 2016 I have a Swift 3 based project (started under Xcode 8b1). It's been working fine under betas 1 and 2, but under 3 it's crashing at launch: dyld: Library not loaded: @rpath/libswiftAVFoundation.dylib Looking at the bundle, I see the /Frameworks folder is empty.
Bundle structures can vary depending on the type of the bundle and the target platform. The following sections describe the bundle structures used most commonly in both macOS and iOS.
Note: Although bundles are one way of packaging executable code, they are not the only way that is supported. UNIX shell scripts and command-line tools do not use the bundle structure, neither do static and dynamic shared libraries.
Application Bundles
Application bundles are one of the most common types of bundle created by developers. The application bundle stores everything that the application requires for successful operation. Although the specific structure of an application bundle depends on the platform for which you are developing, the way you use the bundle is the same on both platforms. This chapter describes the structure of application bundles in both iOS and macOS.
What Files Go Into an Application Bundle?
Table 2-1 summarizes the types of files you are likely to find inside an application bundle. The exact location of these files varies from platform to platform and some resources may not be supported at all. For examples and more detailed information, see the platform-specific bundle sections in this chapter.
Although most of the resources in an application bundle are optional, this may not always be the case. For example, iOS applications typically require additional image resources for the application’s icon and default screen. And although not explicitly required, most Mac apps include a custom icon instead of the default one provided by the system.
Anatomy of an iOS Application Bundle
The project templates provided by Xcode do most of the work necessary for setting up the bundle for your iPhone or iPad application. However, understanding the bundle structure can help you decide where you should place your own custom files. The bundle structure of iOS applications is geared more toward the needs of a mobile device. It uses a relatively flat structure with few extraneous directories in an effort to save disk space and simplify access to the files.
The iOS Application Bundle Structure
A typical iOS application bundle contains the application executable and any resources used by the application (for instance, the application icon, other images, and localized content) in the top-level bundle directory. Listing 2-1 shows the structure of a simple iPhone application called
MyApp . The only files that are required to be in subdirectories are those that need to be localized; however, you could create additional subdirectories in your own applications to organize resources and other relevant files.
Listing 2-1 Bundle structure of an iOS application
Table 2-2 describes the contents of the application shown in Listing 2-1. Although the application itself is for demonstration purposes only, many of the files it contains represent specific files that iOS looks for when scanning an application bundle. Your own bundles would include some or all of these files depending on the features you support.
Note: An iOS app bundle cannot include a custom folder named “Resources.”
An iOS application should be internationalized and have a language
.lproj folder for each language it supports. In addition to providing localized versions of your application’s custom resources, you can also localize your launch images by placing files with the same name in your language-specific project directories. Even if you provide localized versions, however, you should always include a default version of these files at the top-level of your application bundle. The default version is used in situations where a specific localization is not available. For more information about localized resources, see Localized Resources in Bundles.
The Information Property List File
Every iOS application must have an information property list (
Info.plist ) file containing the application’s configuration information. When you create a new iOS application project, Xcode creates this file automatically and sets the value of some of the key properties for you. Table 2-3 lists some additional keys that you should set explicitly. (Xcode obscures actual key names by default, so the string displayed by Xcode is also listed in parenthesis where one is used. You can see the real key names for all keys by Control-clicking the Information Property List key in the editor and choosing Show Raw Keys/Values from the contextual menu that appears.)
In addition to the keys in the preceding table, Table 2-4 lists some keys that are commonly used by iOS applications. Although these keys are not required, most provide a way to adjust the configuration of your application at launch time. Providing these keys can help ensure that your application is presented appropriately by the system.
Application Icon and Launch Images
Application icons and launch images are standard graphics that must be present in every application. Every application must specify an icon to be displayed on the device’s Home screen and in the App Store. And an application may specify several different icons for use in different situations. For example, applications can provide a small version of the application icon to use when displaying search results. Launch images provide visual feedback to the user that your application launched.
The image files used to represent icons and launch images must all reside in the root level of your bundle. How you identify these images to the system can vary, but the recommended way to specify your application icons is to use the
CFBundleIconFiles key. For detailed information about how to specify the icons and launch images in your application, see the discussion of these items in Advanced App Tricks in App Programming Guide for iOS.
Note: In addition to the icons and launch image at the top level of your bundle, you can also include localized versions of launch images in your application’s language-specific project subdirectories. For more information about including localized resources in your application, see Localized Resources in Bundles.
Resources in an iOS Application
In an iOS application, nonlocalized resources are located at the top-level of the bundle directory, along with the application’s executable file and the
Info.plist file. Most iOS applications have at least a few files at this level, including the application’s icon, launch image, and one or more nib files. Although you should place most nonlocalized resources in this top-level directory, you can also create subdirectories to organize your resource files. Localized resources must be placed in one or more language-specific subdirectories, which are discussed in more detail in Localized Resources in Bundles.
Listing 2-2 shows a fictional application that includes both localized and nonlocalized resources. The nonlocalized resources include
Hand.png , MainWindow.nib , MyAppViewController.nib , and the contents of the WaterSounds directory. The localized resources include everything in the en.lproj and jp.lproj directories.
Listing 2-2 An iOS application with localized and nonlocalized resources
For information about finding resource files in your application bundle, see Accessing a Bundle's Contents. For information about how to load resource files and use them in your program, see Resource Programming Guide.
Anatomy of a macOS Application Bundle
The project templates provided by Xcode do most of the work necessary for setting up your Mac app bundle during development. However, understanding the bundle structure can help you decide where you should place your own custom files. macOS bundles use a highly organized structure to make it easier for the bundle-loading code to find resources and other important files in the bundle. The hierarchical nature also helps the system distinguish code bundles such as applications from the directory packages used by other applications to implement document types.
The Structure of a macOS Application Bundle
The basic structure of a Mac app bundle is very simple. At the top-level of the bundle is a directory named
Contents . This directory contains everything, including the resources, executable code, private frameworks, private plug-ins, and support files needed by the application. While the Contents directory might seem superfluous, it identifies the bundle as a modern-style bundle and separates it from document and legacy bundle types found in earlier versions of Mac OS.
Listing 2-3 shows the high-level structure of a typical application bundle, including the immediate files and directories you are most likely to find inside the
Contents directory. This structure represents the core of every Mac app.
Listing 2-3 The basic structure of a Mac app
Table 2-5 lists some of the directories that you might find inside the
Contents directory, along with the purpose of each one. This list is not exhaustive but merely represents the directories in common usage.
Application bundles have evolved significantly over the years but the overall goal has been the same. The bundle organization makes it easier for the application to find its resources while making it harder for users to interfere with those resources. Because the Finder treats most bundles as opaque entities, it is difficult for casual users to move or delete the resources an application might need.
The Information Property List File
For the Finder to recognize an application bundle as such, you need to include an information property list (
Info.plist ) file. This file contains XML property-list data that identifies the configuration of your bundle. For a minimal bundle, this file would contain very little information, most likely just the name and identifier of the bundle. For more complex bundles, the Info.plist file includes much more information.
Important: Bundle resources are located using a case-sensitive search. Therefore, the name of your information property list file must start with a capital “I”.
Table 2-6 lists the keys that you should always include in your
Info.plist file. Xcode provides all of these keys automatically when you create a new project. (Xcode obscures actual key names by default, so the string displayed by Xcode is also listed in parenthesis. You can see the real key names for all keys by Control-clicking the Information Property List key in the editor and choosing Show Raw Keys/Values from the contextual menu that appears.)
Table 2-7 lists the keys that you should also consider including in your
Info.plist file.
The exact information you put into your
Info.plist file is dependent on your bundle’s needs and can be localized as necessary. For more information on this file, see Runtime Configuration Guidelines.
The Resources DirectoryMac Software Bundles
The
Resources directory is where you put all of your images, sounds, nib files, string resources, icon files, data files, and configuration files among others. The contents of this directory are further subdivided into areas where you can store localized and nonlocalized resource files. Non-localized resources reside at the top level of the Resources directory itself or in a custom subdirectory that you define. Localized resources reside in separate subdirectories called language-specific project directories, which are named to coincide with the specific localization.
The best way to see how the
Resources directory is organized is to look at an example. Listing 2-4 shows a fictional application that includes both localized and nonlocalized resources. The nonlocalized resources include Hand.tiff , MyApp.icns and the contents of the WaterSounds directory. The localized resources include everything in the en.lproj and jp.lproj directories or their subdirectories.
Listing 2-4 A Mac app with localized and nonlocalized resources
Each of your language-specific project directories should contain a copy of the same set of resource files, and the name for any single resource file must be the same across all localizations. In other words, only the content for a given file should change from one localization to another. When you request a resource file in your code, you specify only the name of the file you want. The bundle-loading code uses the current language preferences of the user to decide which directories to search for the file you requested.
For information about finding resource files in your application bundle, see Accessing a Bundle's Contents. For information about how to load resource files and use them in your program, see Resource Programming Guide.
The Application Icon File
One special resource that belongs in your top-level
Resources directory is your application icon file. By convention, this file takes the name of the bundle and an extension of .icns ; the image format can be any supported type, but if no extension is specified, the system assumes .icns .
Localizing the Information Property List
Because some of the keys in an application’s
Info.plist file contain user-visible strings, macOS provides a mechanism for specifying localized versions of those strings. Inside each language-specific project directory, you can include an InfoPlist.strings file that specifies the appropriate localizations. This file is a strings file (not a property list) whose entries consist of the Info.plist key you want to localize and the appropriate translation. For example, in the TextEdit application, the German localization of this file contains the following strings:
Creating an Application Bundle
The simplest way to create an application bundle is using Xcode. All new application projects include an appropriately configured application target, which defines the rules needed to build an application bundle, including which source files to compile, which resource files to copy to the bundle, and so on. New projects also include a preconfigured
Info.plist file and typically several other files to help you get started quickly. You can add any custom files as needed using the project window and configure those files using the Info or Inspector windows. For example, you might use the Info window to specify custom locations for resource files inside your bundle.
For information on how to configure targets in Xcode, see Xcode Build System Guide.
Framework Bundles
A framework is a hierarchical directory that encapsulates a dynamic shared library and the resource files needed to support that library. Frameworks provide some advantages over the typical dynamic shared library in that they provide a single location for all of the framework’s related resources. For example, most frameworks include the header files that define the symbols exported by the framework. Grouping these files with the shared library and its resources makes it easier to install and uninstall the framework and to locate the framework’s resources.
Just like a dynamic shared library, frameworks provide a way to factor out commonly used code into a central location that can be shared by multiple applications. Only one copy of a framework’s code and resources reside in-memory at any given time, regardless of how many processes are using those resources. Applications that link against the framework then share the memory containing the framework. This behavior reduces the memory footprint of the system and helps improve performance.
Note: Only the code and read-only resources of a framework are shared. If a framework defines writable variables, each application gets its own copy of those variables to prevent it from affecting other applications.
Although you can create frameworks of your own, most developers’ experience with frameworks comes from including them in their projects. Frameworks are how macOS delivers many key features to your application. The publicly available frameworks provided by macOS are located in the
/System/Library/Frameworks directory. In iOS, the public frameworks are located in the System/Library/Frameworks directory of the appropriate iOS SDK directory. For information about adding frameworks to your Xcode projects, see Xcode Build System Guide.
Note: The creation of custom frameworks is not supported in iOS.
For more detailed information about frameworks and framework bundles, see Framework Programming Guide.
Anatomy of a Framework Bundle
The structure of framework bundles differs from that used by applications and plug-ins. The structure for frameworks is based on a bundle format that predates macOS and supports the inclusion of multiple versions of the framework’s code and resources in the framework bundle. This type of bundle is known as a versioned bundle. Supporting multiple versions of a framework allows older applications to continue running even as the framework shared library continues to evolve. The bundle’s
Versions subdirectory contains the individual framework revisions while symbolic links at the top of the bundle directory point to the latest revision.
The system identifies a framework bundle by the
.framework extension on its directory name. The system also uses the Info.plist file inside the framework’s Resources directory to gather information about the configuration of the framework. Listing 2-5 shows the basic structure of a framework bundle. The arrows (-> ) in the listing indicate symbolic links to specific files and subdirectories. These symbolic links provide convenient access to the latest version of the framework.
Listing 2-5 A simple framework bundle
Frameworks are not required to include a
Headers directory but doing so allows you to include the header files that define the framework’s exported symbols. Frameworks can store other resource files in both standard and custom directories.
Creating a Framework Bundle
If you are developing software for macOS, you can create your own custom frameworks and use them privately or make them available for other applications to use. You can create a new framework using a separate Xcode project or by adding a framework target to an existing project.
For information about how to create a framework, see Framework Programming Guide.
Mac Bundle InstallLoadable Bundles
Plug-ins and other types of loadable bundles provide a way for you to extend the behavior of an application dynamically. A loadable bundle consists of executable code and any resources needed to support that code stored in a bundle directory. You can use loadable bundles to load code lazily into your application or to allow other developers to extend the basic behavior of your application.
Note: The creation and use of loadable bundles is not supported in iOS.
Anatomy of a Loadable Bundle
Loadable bundles are based on the same structure as application bundles. At the top-level of the bundle is a single
Contents directory. Inside this directory are several subdirectories for storing executable code and resources. The Contents directory also contains the bundle’s Info.plist file with information about the bundle’s configuration.
Unlike the executable of an application, loadable bundles generally do not have a
main function as their main entry point. Instead, the application that loads the bundle is responsible for defining the expected entry point. For example, a bundle could be expected to define a function with a specific name or it could be expected to include information in its Info.plist file identifying a specific function or class to use. This choice is left to the application developer who defines the format of the loadable bundle.
Listing 2-6 shows the layout of a loadable bundle. The top-level directory of a loadable bundle can have any extension, but common extensions include
.bundle and .plugin . macOS always treats bundles with those extensions as packages, hiding their contents by default.
Listing 2-6 A simple loadable bundle
In addition to the
MacOS and Resources directories, loadable bundles may contain additional directories such as Frameworks , PlugIns , SharedFrameworks , and SharedSupport —all the features supported by full-fledged application packages.
The basic structure of a loadable bundle is the same regardless of which language that bundle uses in its implementation. For more information about the structure of loadable bundles, see Code Loading Programming Topics.
Creating a Loadable Bundle
If you are developing software for macOS, you can create your own custom loadable bundles and incorporate them into your applications. If other applications export a plug-in API, you can also develop bundles targeted at those APIs. Xcode includes template projects for implementing bundles using either C or Objective-C, depending on the intended target application.
For more information about how to design loadable bundles using Objective-C, see Code Loading Programming Topics. For information about how to design loadable bundles using the C language, see Plug-in Programming Topics.
Localized Resources in Bundles
Within the
Resources directory of a macOS bundle (or the top-level directory of an iOS application bundle), you can create one or more language-specific project subdirectories to store language- and region-specific resources. The name of each directory is based on the language and region of the desired localization followed by the .lproj extension. To specify the language and region, you use the following format:
The language portion of the directory name is a two-letter code that conforms to the ISO 639 conventions. The region portion is also a two-letter code but it conforms to the ISO 3166 conventions for designating specific regions. Although the region portion of the directory name is entirely optional, it can be a useful way to tune your localizations for specific parts of the world. For example, you could use a single
en.lproj directory to support all English speaking nations. However, providing separate localizations for Great Britain (en_GB.lproj ), Australia (en_AU.lproj ), and the United States (en_US.lproj ) lets you tailor your content for each of those countries.
Note: For backwards compatibility, the
NSBundle class and CFBundleRef functions also support human-readable directory names for several common languages, including English.lproj , German.lproj , Japanese.lproj , and others. Although the human-readable names are supported, the ISO names are preferred.
If most of your resource files are the same for all regions of a given language, you can combine a language-only resource directory with one or more region-specific directories. Providing both types of directories alleviates the need to duplicate every resource file for each region you support. Instead, you can customize only the subset of files that are needed for a particular region. When looking for resources in your bundle, the bundle-loading code looks first in any region-specific directories, followed by the language-specific directory. And if neither localized directory contains the resource, the bundle-loading code looks for an appropriate nonlocalized resource.
Important: Do not store code in your
lproj folders, because the system does not load or execute code stored in lproj folders. To learn more about where code and other types of data should be stored in your app bundle, see macOS Code Signing In Depth.
Listing 2-7 shows the potential structure of a Mac app that contains both language- and region-specific resource files. (In an iOS application, the contents of the
Resources directory would be at the top-level of the bundle directory.) Notice that the region-specific directories contain only a subset of the files in the en.lproj directory. If a region-specific version of a resource is not found, the bundle looks in the language-specific directory (in this case en.lproj ) for the resource. The language-specific directory should always contain a complete copy of any language-specific resource files.
Listing 2-7 A bundle with localized resources
For more information on language codes and the process for localizing resources, see Internationalization and Localization Guide.
Copyright © 2017 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2017-03-27
Now that you have the basic pieces in place, it is time to build your application. This section covers some of the more common issues that you may encounter in bringing your UNIX application to OS X. These issues apply largely without regard to what type of development you are doing.
Using GNU Autoconf, Automake, and Autoheader
If you are bringing a preexisting command-line utility to OS X that uses GNU
autoconf , automake , or autoheader , you will probably find that it configures itself without modification (though the resulting configuration may be insufficient). Just run configure and make as you would on any other UNIX-based system.
If running the
configure script fails because it doesn’t understand the architecture, try replacing the project’s config.sub and config.guess files with those available in /usr/share/automake-1.6 . If you are distributing applications that use autoconf, you should include an up-to-date version of config.sub and config.guess so that OS X users don’t have to do anything extra to build your project.
If that still fails, you may need to run
/usr/bin/autoconf on your project to rebuild the configure script before it works. OS X includes autoconf in the BSD tools package. Beyond these basics, if the project does not build, you may need to modify your makefile using some of the tips provided in the following sections. After you do that, more extensive refactoring may be required.
Library Not Found For Bundle Mac Download
Some programs may use autoconf macros that are not supported by the version of autoconf that shipped with OS X. Because autoconf changes periodically, you may actually need to get a new version of autoconf if you need to build the very latest sources for some projects. In general, most projects include a prebuilt
configure script with releases, so this is usually not necessary unless you are building an open source project using sources obtained from CVS or from a daily source snapshot.
However, if you find it necessary to upgrade autoconf, you can get a current version from http://www.gnu.org/software/autoconf/. Note that autoconf, by default, installs in
/usr/local/ , so you may need to modify your PATH environment variable to use the newly updated version. Do not attempt to replace the version installed in /usr/ .
For additional information about using the GNU autotoolset, see http://autotoolset.sourceforge.net/tutorial.html and the manual pages
autoconf , automake , and autoheader .
Compiling for Multiple CPU Architectures
Because the Macintosh platform includes more than one processor family, it is often important to compile software for multiple processor architectures. For example, libraries should generally be compiled as universal binaries even if you are exclusively targeting an Intel-based Macintosh computer, as your library may be used by a PowerPC binary running under Rosetta. For executables, if you plan to distribute compiled versions, you should generally create universal binaries for convenience.
When compiling programs for architectures other than your default host architecture, such as compiling for a ppc64 or Intel-based Macintosh target on a PowerPC-based build host, there are a few common problems that you may run into. Most of these problems result from one of the following mistakes:
Whenever cross-compiling occurs, extra care must be taken to ensure that the target architecture is detected correctly. This is particularly an issue when generating a binary containing object code for more than one architecture.
In many cases, binaries containing object code for more than one architecture can be generated simply by running the normal configuration script, then overriding the architecture flags at compile time.
For example, you might run
followed by
to generate a universal binary (for Intel-based and PowerPC-based Macintosh computers). To generate a 4-way universal binary that includes 64-bit versions, you would add
-arch ppc64 and -arch x86_64 to the CFLAGS and LDFLAGS .
Note: If you are using an older version of gcc and your makefile passes
LDFLAGS to gcc instead of passing them directly to ld, you may need to specify the linker flags as -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk . This tells the compiler to pass the unknown flags to the linker without interpreting them. Do not pass the LDFLAGS in this form to ld, however; ld does not currently support the -Wl syntax.
If you need to support an older version of gcc and your makefile passes
LDFLAGS to both gcc and ld, you may need to modify it to pass this argument in different forms, depending on which tool is being used. Fortunately, these cases are rare; most makefiles either pass LDFLAGS to gcc or ld, but not both. Newer versions of gcc support -syslibroot directly.
If your makefile does not explicitly pass the contents of
LDFLAGS to gcc or ld , they may still be passed to one or the other by a make rule. If you are using the standard built-in make rules, the contents of LDFLAGS are passed directly to ld . If in doubt, assume that it is passed to ld . If you get an invalid flag error, you guessed incorrectly.
If your makefile uses gcc to run the linker instead of invoking it directly, you must specify a list of target architectures to link when working with universal binary object (.o) files even if you are not using all of the architectures of the object file. If you don't, you will not create a universal binary, and you may also get a linker error. For more information about 64-bit executables, see 64-Bit Transition Guide.
However, applications that make configuration-time decisions about the size of data structures will generally fail to build correctly in such an environment (since those sizes may need to be different depending on whether the compiler is executing a
ppc pass, a ppc64 pass, or an i386 pass). When this happens, the tool must be configured and compiled for each architecture as separate executables, then glued together manually using lipo .
In rare cases, software not written with cross-compilation in mind will make configure-time decisions by executing code on the build host. In these cases, you will have to manually alter either the configuration scripts or the resulting headers to be appropriate for the actual target architecture (rather than the build architecture). In some cases, this can be solved by telling the configure script that you are cross-compiling using the
--host , --build , and --target flags. However, this may simply result in defaults for the target platform being inserted, which doesn’t really solve the problem.
The best fix is to replace configure-time detection of endianness, data type sizes, and so on with compile-time or run-time detection. For example, instead of testing the architecture for endianness to obtain consistent byte order in a file, you should do one of the following:
Similarly, instead of performing elaborate tests to determine whether to use
int or long for a 4-byte piece of data, you should simply use a standard sized type such as uint32_t .
Note: Not all script execution is incompatible with cross-compiling. A number of open source tools (GTK, for example) use script execution to determine the presence or absence of libraries, determine their versions and locations, and so on.
In those cases, you must be certain that the info script associated with the universal binary installation (or the target platform installation if you are strictly cross-compiling) is the one that executes during the configuration process, rather than the info script associated with an installation specific to your host architecture.
There are a few other caveats when working with universal binaries:
For additional information about autoconf, automake, and autoheader, you can view the autoconf documentation at http://www.gnu.org/software/autoconf/manual/index.html.
For additional information on compiler flags for Intel-based Macintosh computers, modifying code to support little-endian CPUs, and other porting concerns, you should read Universal Binary Programming Guidelines, Second Edition, available from the ADC Reference Library.
Cross-Compiling a Self-Bootstrapping Tool
Probably the most difficult situation you may experience is that of a self-bootstrapping tool—a tool that uses a (possibly stripped-down) copy of itself to either compile the final version of itself or to construct support files or libraries. Some examples include TeX, Perl, and gcc.
Ideally, you should be able to build the executable as a universal binary in a single build pass. If that is possible, everything “just works”, since the universal binary can execute on the host. However, this is not always possible. If you have to cross-compile and glue the pieces together with
lipo , this obviously will not work.
If the build system is written well, the tool will bootstrap itself by building a version compiled for the host, then use that to build the pieces for the target, and finally compile a version of the binary for the target. In that case, you should not have to do anything special for the build to succeed.
In some cases, however, it is not possible to simultaneously compile for multiple architectures and the build system wasn’t designed for cross-compiling. In those cases, the recommended solution is to pre-install a version of the tool for the host architecture, then modify the build scripts to rename the target’s intermediate copy of the tool and copy the host’s copy in place of that intermediate build product (for example,
mv miniperl miniperl-target; cp /usr/bin/perl miniperl ).
By doing this, later parts of the build script will execute the version of the tool built for the host architecture. Assuming there are no architecture dependencies in the dependent tools or support files, they should build correctly using the host’s copy of the tool. Once the dependent build is complete, you should swap back in the original target copy in the final build phase. The trick is in figuring out when to have each copy in place.
Conditional Compilation on OS X
You will sometimes find it necessary to use conditional compilation to make your code behave differently depending on whether certain functionality is available.
Older code sometimes used conditional statements like
#ifdef __MACH__ or #ifdef __APPLE__ to try to determine whether it was being compiled on OS X or not. While this seems appealing as a quick way of getting ported, it ultimately causes more work in the long run. For example, if you make the assumption that a particular function does not exist in OS X and conditionally replace it with your own version that implements the same functionality as a wrapper around a different API, your application may no longer compile or may be less efficient if Apple adds that function in a later version.
Apart from displaying or using the name of the OS for some reason (which you can more portably obtain from the
uname API), code should never behave differently on OS X merely because it is running on OS X. Code should behave differently because OS X behaves differently in some way—offering an additional feature, not offering functionality specific to another operating system, and so on. Thus, for maximum portability and maintainability, you should focus on that difference and make the conditional compilation dependent upon detecting the difference rather than dependent upon the OS itself. This not only makes it easier to maintain your code as OS X evolves, but also makes it easier to port your code to other platforms that may support different but overlapping feature sets.
The most common reasons you might want to use such conditional statements are attempts to detect differences in:
Instead it is better to figure out why your code needs to behave differently in OS X, then use conditional compilation techniques that are appropriate for the actual root cause.
The misuse of these conditionals often causes problems. For example, if you assume that certain frameworks are present if those macros are defined, you might get compile failures when building a 64-bit executable. If you instead test for the availability of the framework, you might be able to fall back on an alternative mechanism such as X11, or you might skip building the graphical portions of the application entirely.
For example, OS X provides preprocessor macros to determine the CPU architecture and byte order. These include:
In addition, using tools like
autoconf , you can create arbitrary conditional compilation on nearly any practical feature of the installation, from testing to see if a file exists to seeing if you can successfully compile a piece of code.
For example, if a portion of your project requires a particular application framework, you can compile a small test program whose
main function calls a function in that framework. If the test program compiles and links successfully, the application framework is present for the specified CPU architecture.
You can even use this technique to determine whether to include workarounds for known bugs in Apple or third-party libraries and frameworks, either by testing the versions of those frameworks or by providing a test case that reproduces the bug and checking the results.
For example, in OS X,
poll does not support device files such as /dev/tty . If you just avoid poll if your code is running on OS X, you are making two assumptions that you should not make:
A better solution is to use a configuration-time test that tries to use
poll on a device file, and if the call fails, disables the use of poll . If using poll provides some significant advantage, it may be better to perform a runtime test early in your application execution, then use poll only if that test succeeds. By testing for support at runtime, your application can use the poll API if is supported by a particular version of any operating system, falling back gracefully if it is not supported.
A good rule is to always test for the most specific thing that is guaranteed to meet your requirements. If you need a framework, test for the framework. If you need a library, test for the library. If you need a particular compiler version, test the compiler version. And so on. By doing this, you increase your chances that your application will continue to work correctly without modification in the future.
Choosing a Compiler
OS X ships two compilers and their corresponding toolchains. The default compiler is based on GCC 4.2. In addition, a compiler based on GCC 4.0 is provided. Older versions of Xcode also provide prior versions. Compiling for 64-bit PowerPC and Intel-based Macintosh computers is only supported in version 4.0 and later. Compiling 64-bit kernel extensions is only supported in version 4.2 and later.
Always try to compile your software using GCC 4 because future toolchains will be based on GCC version 4 or later. However, because GCC 4 is a relatively new toolchain, you may find bugs that prevent compiling certain programs.
Use of the legacy GCC 2.95.2-based toolchain is strongly discouraged unless you have to maintain compatibility with OS X version 10.1.
If you run into a problem that looks like a compiler bug, try using a different version of GCC. You can run a different version by setting the
CC environment variable in your Makefile. For example, CC=gcc-4.0 chooses GCC 4.0. In Xcode, you can change the compiler setting on a per-project basis or a per-file basis by selecting a different compiler version in the appropriate build settings inspector.
Setting Compiler Flags
When building your projects in OS X, simply supplying or modifying the compiler flags of a few key options is all you need to do to port most programs. These are usually specified by either the
CFLAGS or LDFLAGS variable in your makefile, depending on which part of the compiler chain interprets the flags. Unless otherwise specified, you should add these flags to CFLAGS if needed.
Note: The 64-bit toolchain in OS X v10.4 and later has additional compiler flags (and a few deprecated flags). These are described in more detail in 64-Bit Transition Guide.
Some common flags include:
Comments are closed.
|
AuthorWrite something about yourself. No need to be fancy, just an overview. Archives
December 2020
Categories |