July 24th, 2015
A recent (and even more recently reverted) change to Homebrew highlighted an interesting (read: maddening) quirk of clang on OS X. Here’s the background.
Gcc Header Search Path
PATHSUFFIXES specifies additional subdirectories to check below each search path. If NODEFAULTPATH is specified, then no additional paths are added to the search. If NODEFAULTPATH is not specified, the search process is as follows: Search paths specified in cmake-specific cache variables. How do I set the static library path in OS X Lion? Ask Question. The normal command line is to use the -L option to add the path to the library search.
The search paths for libraries come from three sources: the environment variable LDLIBRARYPATH (if set), any rpath encoded in the binary (more on this later), and the system default search paths. They're searched in this order, and the first matching library found is used. LDLIBRARYPATH is broken and should not be used if at all possible.
When you compile something using clang on OS X there are (roughly speaking) two stages to the compile. In the first, your source code is loaded and the compiler searches its include paths to find your includes. Here’s what clang’s defaults look like for the Xcode 6.4 command line tools:
As you can see, the include search starts with
/usr/local/include
and /usr/include
is the fourth item. So, in the case of a vanilla OS X install a binary attempting to compile using OpenSSL (let’s say #include <openssl/x509.h>
) would find the OpenSSL headers in /usr/include
after searching the previous 3 locations fruitlessly.Library Search Rhul
Once it’s found (and the C preprocessor has run and all the objects have been compiled) we now need to link it. When compiling something against OpenSSL you’ll link against
-lssl
, -lcrypto
, or both. These command line flags simply tell the linker to look for something named “libssl.dylib” or “libcrypto.dylib” in the library search paths. But what are those paths?This time we see two primary library search paths,
/usr/lib
and /usr/local/lib
…which are reversed in priority from our include search path.How to format sd card for photos library mac torrent. Insert the media into the SD card slot.
The result of this is that if you have something (like OpenSSL) that is present in both
/usr/local/{include,lib}
and /usr/{include,lib}
you’ll end up with the compiler using the headers from /usr/local/include
and then linking against the library in /usr/lib
. This can result in a variety of problems, the severity of which depend on how different the two versions of the library are and what features the binary you’re compiling is using.So why does this matter? Well, in El Capitan (10.11) Apple has chosen to remove the OpenSSL development headers, but not remove the dylibs. They deprecated use of system OpenSSL in Lion (10.7) so this makes sense on the surface, but the weird include/linker ordering means that if homebrew (or anything else living in your include/search paths) duplicates a system library bad things may occur. There are four possible paths (all of which are under the control of Apple and not us plebes):
- Change the linker order preference. Probably a good idea long term but likely to cause all sorts of unintended breakage as we find things that are implicitly depending on this crazy ordering.
- Re-add the OpenSSL headers for 0.9.8. Not a great option since 0.9.8 is scheduled for EOL at the end of this year and Apple has marked it deprecated in OS X since Lion (originally released July 20, 2011), but probably the safest and lowest friction option.
- Remove OpenSSL entirely. This would break any OS X app that links against it and would require Apple to ship updates to Ruby, Python, Apache, etc that statically link OpenSSL (or go down the route of a “private” dylib like they’ve done with OpenSSH in El Capitan)
- Do nothing and let this be a significant source of pain for developers during El Capitan’s lifecycle. This is the most likely scenario.
I favor either removing the OpenSSL dylibs entirely for El Capitan or re-adding the OpenSSL headers and then removing everything in the next major release, but I don’t envy whoever has to make this choice. Everything has downsides.
The setting you need to knowIf you’re still running Lion or Mountain Lion, making the /Library folder requires a little bit of work. You just need to know how to make the folder visible again.Mavericks now offers a simple setting to make the /Library folder visible. (I came up with—no joke—.) But in Mavericks and Yosemite, Apple has made the task much more convenient, providing an easily accessible setting for toggling the visibility of your user-level Library folder. Here’s how to use it:Open your home folder (/Users/ yourusername) in the Finder. Library reveal mac.
A short-hand signature is:
The general signature is:
This command is used to find a directory containing the named file.A cache entry named by
<VAR>
is created to store the resultof this command.If the file in a directory is found the result is stored in the variableand the search will not be repeated unless the variable is cleared.If nothing is found, the result will be<VAR>-NOTFOUND
, and the search will be attempted again thenext time find_path is invoked with the same variable.The name of the file in a directory thatis searched for is specified by the names listedafter the NAMES argument. Additional search locationscan be specified after the PATHS argument. If ENV var isfound in the HINTS or PATHS section the environment variable varwill be read and converted from a system environment variable toa cmake style list of paths. For example ENV PATH would be a wayto list the system path variable. The argumentafter DOC will be used for the documentation string inthe cache.PATH_SUFFIXES specifies additional subdirectories to check beloweach search path.If NO_DEFAULT_PATH is specified, then no additional paths areadded to the search.If NO_DEFAULT_PATH is not specified, the search process is as follows:
- Search paths specified in cmake-specific cache variables.These are intended to be used on the command line with a -DVAR=value.This can be skipped if NO_CMAKE_PATH is passed.
- <prefix>/include/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and<prefix>/include for each <prefix> in CMAKE_PREFIX_PATH
- CMAKE_INCLUDE_PATH
- CMAKE_FRAMEWORK_PATH
- Search paths specified in cmake-specific environment variables.These are intended to be set in the user’s shell configuration.This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.
- <prefix>/include/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and<prefix>/include for each <prefix> in CMAKE_PREFIX_PATH
- CMAKE_INCLUDE_PATH
- CMAKE_FRAMEWORK_PATH
- Search the paths specified by the HINTS option.These should be paths computed by system introspection, such as ahint provided by the location of another item already found.Hard-coded guesses should be specified with the PATHS option.
- Search the standard system environment variables.This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is an argument.
- PATH and INCLUDE
- Search cmake variables defined in the Platform filesfor the current system. This can be skipped if NO_CMAKE_SYSTEM_PATHis passed.
- <prefix>/include/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and<prefix>/include for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH
- CMAKE_SYSTEM_INCLUDE_PATH
- CMAKE_SYSTEM_FRAMEWORK_PATH
- Search the paths specified by the PATHS optionor in the short-hand version of the command.These are typically hard-coded guesses.
On Darwin or systems supporting OS X Frameworks, the cmake variableCMAKE_FIND_FRAMEWORK can be set to empty or one of the following:
- FIRST: Try to find frameworks before standard libraries or headers.This is the default on Darwin.
- LAST: Try to find frameworks after standard libraries or headers.
- ONLY: Only try to find frameworks.
- NEVER: Never try to find frameworks.
On Darwin or systems supporting OS X Application Bundles, the cmakevariable CMAKE_FIND_APPBUNDLE can be set to empty or one of thefollowing:
- FIRST: Try to find application bundles before standard programs.This is the default on Darwin.
- LAST: Try to find application bundles after standard programs.
- ONLY: Only try to find application bundles.
- NEVER: Never try to find application bundles.
The CMake variable
CMAKE_FIND_ROOT_PATH
specifies one or moredirectories to be prepended to all other search directories. Thiseffectively “re-roots” the entire search under given locations.Paths which are descendants of the CMAKE_STAGING_PREFIX
are excludedfrom this re-rooting, because that variable is always a path on the host system.By default the CMAKE_FIND_ROOT_PATH
is empty.The
CMAKE_SYSROOT
variable can also be used to specify exactly onedirectory to use as a prefix. Setting CMAKE_SYSROOT
also has othereffects. See the documentation for that variable for more.These variables are especially useful when cross-compiling topoint to the root directory of the target environment and CMake willsearch there too. By default at first the directories listed in
CMAKE_FIND_ROOT_PATH
are searched, then the CMAKE_SYSROOT
directory is searched, and then the non-rooted directories will besearched. The default behavior can be adjusted by settingCMAKE_FIND_ROOT_PATH_MODE_INCLUDE
. This behavior can be manuallyoverridden on a per-call basis. By using CMAKE_FIND_ROOT_PATH_BOTHthe search order will be as described above. IfNO_CMAKE_FIND_ROOT_PATH is used then CMAKE_FIND_ROOT_PATH
will not beused. If ONLY_CMAKE_FIND_ROOT_PATH is used then only the re-rooteddirectories and directories below CMAKE_STAGING_PREFIX
will be searched.The default search order is designed to be most-specific toleast-specific for common use cases.Projects may override the order by simply calling the commandmultiple times and using the
NO_*
options:Once one of the calls succeeds the result variable will be setand stored in the cache so that no call will search again.
When searching for frameworks, if the file is specified as A/b.h, thenthe framework search will look for A.framework/Headers/b.h. If thatis found the path will be set to the path to the framework. CMakewill convert this to the correct -F option to include the file.