When you create or update a dynamic library, you should carefully consider how it may be used by developers in their products. It’s also important to give these developers flexibility by allowing their products to work with earlier or later versions of the library without them having to update their products.
1) I open Library Loader, and from within that utility I select 'Open ECAD Model' at the top left. This then brings up a file dialogue to browse to and select the zip file you downloaded from mouser or wherever (this then finds the.EPW file from inside the zip folder, or if you already extracted the zip file, just point directly to the.EPW file).
This article demonstrates how to write a dynamic library so that it’s easy to use by developers who want to take advantage of it in their own development. This article also describes how to update existing libraries and manage their version information to maximize client compatibility.
When creating a dynamic library, you should perform these tasks:
Define the library’s purpose: This information provides the focus required to define the library’s public interface.
Define the library’s interface (header files): This is the interface through which the library’s clients access its functionality.
Implement the library (implementation files): This is where you define the public functions that the library’s clients use. You may also need to define private variables and functions needed to implement the interface but not required by clients.
Set the library’s version information: The library’s version information is divided in three parts: major, minor, and compatibility. You specify all the parts of the library’s version information when you create the .dylib
file. See Managing Client Compatibility With Dependent Libraries for details.
Test the library: At the very least, you should define a test for each of the public functions your library exposes, to ensure that they perform the correct action given particular test inputs or after performing a specific set of operations.
The following sections provide an example of the process taken to develop a simple dynamic library, called Ratings. The files mentioned in the following sections are included in Ratings/1.0
in this document’s companion-file package.
The purpose of the Ratings library is to provide a ratings analyzer to its clients. Ratings are strings made up of asterisks (*) that represent levels of satisfaction for a particular item. For example, in Apple’s iTunes app, you can specify whether you like a particular song a lot with a five-star rating (*****) or not at all with a one-star rating (*).
The initial release of the library provides a way for clients to add ratings, get a count of the ratings they have added, get the mean rating, and clear the rating set.
Before you implement the library, you must define the interface the library’s clients use to interact with it. You should carefully specify each function’s semantics. A clear definition benefits you because it makes clear the purpose of each public function. It also benefits developers who use your library because it tells them exactly what to expect when they call each function in their code.
This is an example of a list of interface functions with each function’s semantic meaning:
void addRating(char *rating)
: Adds a rating value to the set kept by the library. The rating argument is a string; it must not be NULL. Each character in the string represents one rating point. For example, an empty string ('
) is equivalent to a rating of 0, '*'
means 1, '**'
means 2, and so on. The actual characters used in the string are immaterial. Therefore, ' '
means 1 and '3456'
means 4. Each call to this function increments the value returned by the ratings function.
int ratings(void)
: Returns the number of rating values in the set. This function has no side effects.
char *meanRatings(void)
: Returns the mean rating in the rating set as a string, using one asterisk per rating point. This function has no side effects.
clearRatings(void)
: Clears the rating set. After calling this function (with no subsequent calls to addRating
), the ratings
function returns 0
.
Listing 1 shows the header file that the Ratings library’s clients include to access its interface.
Listing 1 Interface to Ratings 1.0
The interface declared in Defining the Library’s Interface is implemented in Ratings.c
, shown in Listing 2.
Listing 2 Implementation of Ratings 1.0
The following list describes the tagged lines.
This comment is only to remind the library’s developers to compile this file with the compiler -fvisibility=hidden
option, so that only the symbols with the visibility('default')
attribute are exported.
This initializer is defined only to show at which point of a client’s execution the library’s initializers are called by the dynamic loader.
This finalizer is defined only to show at which point of client’s execution the library’s finalizers are called by the dynamic loader.
The _add
function is an example of an internal function. Clients don’t need to know about it and, therefore, it’s not exported. Also, because internal calls are trusted, no validation is performed. However, there’s no requirement that internal-use functions lack validation.
The addRating
function is an example of an exported function. To ensure that only correct ratings are added, the function’s input parameter is validated.
When you compile the library’s source files into a .dylib
file, you set version information that specifies whether clients can use versions of the library earlier or later than the version they were linked with. When the client is loaded into a process, the dynamic loader looks for the .dylib
file in the library search paths and, if it finds it, compares the version information of the .dylib
file with the version information recorded in the client image. If the client is not compatible with the .dylib
file, the dynamic loader doesn’t load the client into the process. In effect, the client’s load process is aborted because the dynamic loader was unable to locate a compatible dependent library.
Listing 3 shows the command used to generate version 1.0 of the Ratings library.
Listing 3 Generating version 1.0 of the Ratings dynamic library
This list indicates where the major version, minor version, and compatibility version are specified:
The major version number is specified in the library’s filename as “A” in -o libRatings.A.dylib
.
The minor version number is specified in -current_version 1.0
.
The compatibility version number is specified in -compatibility_version 1.0
.
Note: You can use libtool
to create a dynamic library from a set of object files.
Before publishing a dynamic library, you should test its public interface to ensure that it performs as you specified in the interface’s documentation (see Defining the Library’s Interface. To provide maximum flexibility to clients, you should make sure that your library can be used as a dependent library (clients link with it, and the library is loaded when the client is loaded) or as a runtime-loaded library (clients don’t link with it and use dlopen(3) OS X Developer Tools Manual Page
to load it).
Listing 4 shows an example of a test client that uses the Ratings library as a dependent library.
Listing 4 Testing Ratings 1.0 as a dependent library
The following command generates the Dependent
client program. Note that libRatings.A.dylib
is included in the compile line.
The Dependent
program produces output that shows whether calling each of the library’s exported functions produces the expected results. In addition, the initializer
and finalizer
functions defined in the library produce output lines that indicate when they are invoked in relation to the program’s normal process. This output is shown in Listing 5.
Listing 5 Test results for Ratings 1.0 as a dependent library
Notice that initializer
is called before the main
function. The finalizer function, on the other hand, is called after exiting the main
function.
Testing the Ratings library as a runtime-loaded library requires another test program, Runtime. Listing 6 shows its source file.
Listing 6 Testing Ratings 1.0 as a runtime-loaded library
The Runtime
program is very similar to the Dependent
program. However, Runtime must load libRuntime.A.dylib
using the dlopen(3) OS X Developer Tools Manual Page
function. After that, it must get the address of each function exported by the library using dlsym(3) OS X Developer Tools Manual Page
before using it.
The following command generates the Runtime
client program.
Listing 7 shows the output produced by Runtime.
Listing 7 Test results for Ratings 1.0 as a runtime-loaded library
Note that the Ratings library’s initializer function is called within the main
function execution before the call to dlopen
returns, which differs from its execution point in the Dependent
program Listing 5. The finalizer
function, however, is called after main
has exited, the same point at which it’s called in Dependent’s execution. You should consider this when writing dynamic library initializers and finalizers.
Making revisions to a previously published dynamic library is a delicate task. If you want existing clients to be able to use the library (that is, load the new version of the .dylib
file without recompilation), you must ensure that the API those clients know about is unchanged, including its semantic meaning.
When you can guarantee that the API of the new version of the library is compatible with the API that clients linked with earlier versions know about, you can deem the new version a minor revision. When you want to publish a minor revision of a dynamic library to users of the library’s clients (for example, the users of a program that uses your library) the only version information item you need to change is the library’s current version. The major version (filename) and compatibility version of the library must remain the same. When end users replace the early version of the library with the new version in their computers, the library’s clients use the new version without any problems. Managing Client Compatibility With Dependent Libraries.
From the point of view of a client image, there are two sides to compatibility with the dynamic libraries it uses: compatibility with versions of a library later than the one the client knows about, known as forward compatibility, and compatibility with versions of a library earlier than the one the client is familiar with, known as backward compatibility. You maintain forward compatibility by ensuring that the library’s API remains compatible across revisions. You facilitate backward compatibility by exporting new functions as weak references. In turn, your library’s clients must ensure that weakly imported functions actually exist before using them.
The Ratings library, introduced in Creating Libraries, has a second version, 1.1. Listing 8 shows the updated header for the Ratings library.
Listing 8 Interface to Ratings 1.1
The tagged lines declare the new functions. Notice that both declarations include the weak_import
attribute, informing client developers that the function is weakly linked. Therefore, clients must make sure the function exists before calling it.
Listing 9 shows the library’s new implementation file.
Listing 9 Implementation of Ratings 1.1
Listing 10 shows the updated source code for the Runtime program that tests the Ratings 1.1 library.
Listing 10 Testing Ratings 1.1 as a runtime-loaded library
Listing 11 shows the command used to generate version 1.1 of the Ratings library.
Listing 11 Generating version 1.1 of the Ratings dynamic library
Notice that this time the library’s current version is set to 1.1 but its compatibility version remains 1.0. When a client is linked against version 1.1 of this library, the compatibility version is encoded in the client image. Therefore, the dynamic loader loads the client image whether it finds version 1.1 or 1.0 of libRatings.A.dylib
. That is, the client is backwards compatible with version 1.0 of the library. For details on why /usr/local/lib/libAverages.dylib
was added to the compile line, see Using Dependent Libraries.
Note: Weak references are a feature of OS X v10.2 and later. Therefore, when using weak references, your library can be used only by programs running in OS X v10.2 or later.
Similar to creating initial versions of a library, updating libraries require thorough testing. You should at least add tests for each function you added to your test programs. If you used weak references, your test programs should ensure the existence of the new functions before calling them.
The Ratings/1.1
directory in this document’s companion-file package contains the source files for the Ratings 1.1 library. Listing 12 shows an updated version of the Dependent
program. The tagged lines show how to check for the presence of a function before using it.
Listing 12 Testing Ratings 1.1 as a dependent library
Ratings 1.1 depends on Averages 1.1. Therefore, to build the library as well as the test programs, libAverages.A.dylib
must be installed in ~/lib
. To accomplish this, run this command after opening this document’s companion-file package:
These are commands needed to compile the library and the test programs from the Ratings/1.1
directory:
The output the program produces is shown in Listing 13.
Listing 13 Test results for Ratings 1.1 used as a dependent library
Programs that use dlopen
to load your library should not fail if they are unable to obtain an address for your weakly exported functions with dlsym
. Therefore, the program that tests your library as a runtime-loaded library, should allow for the absence of weakly imported functions.
Listing 14 shows an updated version of the Runtime
program. Notice that it uses dlsym to try get the addresses of the new functions but doesn’t exit with an error if they are unavailable. However, just before the program uses the new functions, it determines whether they actually exists. If they don’t exist, it doesn’t perform the test.
Listing 14 Testing Ratings 1.1 as a runtime-loaded library
Listing 15 shows the output produced by Runtime.
Listing 15 Test results for Ratings 1.1 used as a runtime-loaded library
To ensure that clients linked with version 1.0 of libRatings.A.dylib
can use version 1.1 of the library, you can copy Ratings/1.1/libRatings.A.dylib
to Ratings/1.0
. When you run the first Dependent
program, its output is the identical to the output it produced when it used version 1.0 of the library. The first Dependent
program knows nothing about the functions introduced in version 1.1 of the Ratings library; therefore, it doesn’t call them.
A more interesting test, however, is making sure that clients linked with version 1.1 of the Ratings library can run when their copy of the library is replaced with version 1.0. To test this, execute the following commands in Terminal:
Listing 16 shows the output produced by the second version of Dependent
, linked with Ratings 1.1, when it loads Ratings 1.0 instead of Ratings 1.1. The highlighted lines show where the client program did not find a particular function at runtime because the function does not exist in the version of the Ratings library that it’s using.
Listing 16 Test results for Ratings 1.0 used as a dependent library by a client linked against Ratings 1.1
The second version of the Runtime
test program produces similar output when using Ratings 1.0, as shown in Listing 17.
Listing 17 Test results for Ratings 1.0 used as a runtime-loaded library by a client liked with Ratings 1.1 when using Ratings 1.0
Copyright © 2012 Apple Inc. All Rights Reserved. Terms of Use Privacy Policy Updated: 2012-07-23
The Library Menu item is hidden by default on Macs, to prevent the possibility of inexperienced users deleting important files in the Library Folder. In this article, you will find different methods to reveal the hidden Library Menu and access the Library Folder on your Mac.
The Library Folder on your Mac contains Preference Files, Caches, and Application Support Data.
While regular Mac users may not find the need to access the Hidden Library Folder, advanced Mac users will at times come across the need to access files inside the Library Folder for troubleshooting and other purposes.
One example of the need to access the Library Folder on Mac would be to rebuild the Database Files in the Library Folder, in order to fix Launchpad related issues like Apps Missing From Launchpad or deleted Apps showing up in the Launchpad.
Before going ahead with the steps to Access the Hidden Library Folder on your Mac, you need to be aware that ~/Library Folder contains important Data and Files related to Mac User Accounts.
Hence, make sure that you are accessing the Library Folder for a good reason and you do know as to what you are trying to achieve.
Follow the steps below to access the Hidden Library Menu option on your Mac.
1. Left-click your mouse anywhere on the screen of your Mac. This will reveal the Go Option in the top menu bar of your Mac. You can also click on the Finder Icon in the Dock of your Mac to activate the Go Option.
2. Next, click on the Go option in the top menu-bar of your Mac.
3. While you are still on the Go option, press and hold the Option key on your Mac and then click on the Library option that appears when you press down the Option Key.
Note: Press the Alt Key in case you are using a Windows keyboard with your Mac.
4. Clicking on the Library Menu option will take you straight to the Library Folder on your Mac.
Another way to access the Library Folder on your Mac is by using the Folder Option on your Mac.
1. Left-click your mouse anywhere on the screen of your Mac to reveal the Go Option in the top menu bar. You can also click on the Finder Icon in the Dock of your Mac to activate the Go option.
2. Next, click on the Go option from the top menu-bar on your Mac and then click on Go to Folder… option in the drop-down menu (See image below).
3. In the search window that appears, type ~/Library, and click on the Go button.
This will immediately take you to the Library Folder on your Mac.
You can permanently unhide the Library Menu Option in the top-menu bar on your Mac by using the Terminal Command. The process is reversible and you can easily go back to the default hidden Library Menu Setting by using the Terminal command once again.
1. Click on the Finder icon in the dock of your Mac to activate the Go option in the top Menu bar of your Mac.
2. Next, click on the Go option in the top menu-bar and then click on the Utilities option in the drop-down menu.
3. On the Utilities window, open the Terminal App by clicking on it.
4. Next, type chflags nohidden ~/Library/ and Press the Enter key to submit your command for execution.
Once the command is executed, you will see the Library Option clearly visible and permanently unhidden in the top menu-bar of your Mac.
As mentioned above, you can always go back to the default hidden Library option on your Mac by executing a simple command in the Command Prompt Window.
1. To hide the Library option, type chflags hidden ~/Library/ in the Command prompt window (See image below)
2. After typing the Command, hit the Enter key on the Keyboard of your Mac to execute this Command.
Once the Command is executed, you will see the Library Menu option becoming hidden.