diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2006-04-13 15:00:52 (GMT) |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2006-04-13 15:00:52 (GMT) |
commit | cae4e6b37a6ff7caf0748f2702fb503a9c95dcc8 (patch) | |
tree | 51115b16145313311c88cfd50409672c5f2b335e /Source/cmFindProgramCommand.cxx | |
parent | b323c3f51cc4caf7f8c26f86ba3dd4a08e964c4b (diff) | |
download | CMake-cae4e6b37a6ff7caf0748f2702fb503a9c95dcc8.zip CMake-cae4e6b37a6ff7caf0748f2702fb503a9c95dcc8.tar.gz CMake-cae4e6b37a6ff7caf0748f2702fb503a9c95dcc8.tar.bz2 |
ENH: add patch for finding applications on OSX
Diffstat (limited to 'Source/cmFindProgramCommand.cxx')
-rw-r--r-- | Source/cmFindProgramCommand.cxx | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 5b08fc8..5e750bb 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -17,6 +17,10 @@ #include "cmFindProgramCommand.h" #include "cmCacheManager.h" #include <stdlib.h> + +#if defined(__APPLE__) +#include <CoreFoundation/CoreFoundation.h> +#endif cmFindProgramCommand::cmFindProgramCommand() { @@ -48,8 +52,8 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) { return true; } - std::string result = cmSystemTools::FindProgram(this->Names, - this->SearchPaths, true); + + std::string result = FindProgram(this->Names); if(result != "") { // Save the value in the cache @@ -67,3 +71,91 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) return true; } +std::string cmFindProgramCommand::FindProgram(std::vector<std::string> names) +{ + std::string program = ""; + + // First/last order taken care of in cmFindBase when the paths are setup. + if(this->SearchAppBundleFirst || this->SearchAppBundleLast) + { + program = FindAppBundle(names); + } + if(program.empty() && !this->SearchAppBundleOnly) + { + program = cmSystemTools::FindProgram(names, this->SearchPaths, true); + } + + return program; +} + +std::string cmFindProgramCommand::FindAppBundle(std::vector<std::string> names) +{ + for(std::vector<std::string>::const_iterator name = names.begin(); + name != names.end() ; ++name) + { + + std::string appName = *name + std::string(".app"); + std::string appPath = cmSystemTools::FindDirectory(appName.c_str(), this->SearchPaths, true); + + if ( !appPath.empty() ) + { + std::string executable = GetBundleExecutable(appPath); + if (!executable.empty()) + { + return cmSystemTools::CollapseFullPath(executable.c_str()); + } + } + } + + // Couldn't find app bundle + return ""; +} + +std::string cmFindProgramCommand::GetBundleExecutable(std::string bundlePath) +{ + std::string executable = ""; + +#if defined(__APPLE__) + // Started with an example on developer.apple.com about finding bundles + // and modified from that. + + // Get a CFString of the app bundle path + // XXX - Is it safe to assume everything is in UTF8? + CFStringRef bundlePathCFS = CFStringCreateWithCString(kCFAllocatorDefault , + bundlePath.c_str(), kCFStringEncodingUTF8 ); + + // Make a CFURLRef from the CFString representation of the bundle’s path. + CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, + bundlePathCFS, + kCFURLPOSIXPathStyle, + true ); + + // Make a bundle instance using the URLRef. + CFBundleRef appBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL ); + + // returned executableURL is relative to <appbundle>/Contents/MacOS/ + CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle); + + if (executableURL != NULL) + { + const int MAX_OSX_PATH_SIZE = 1024; + char buffer[MAX_OSX_PATH_SIZE]; + + // Convert the CFString to a C string + CFStringGetCString( CFURLGetString(executableURL), buffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 ); + + // And finally to a c++ string + executable = bundlePath + "/Contents/MacOS/" + std::string(buffer); + } + + // Any CF objects returned from functions with "create" or + // "copy" in their names must be released by us! + CFRelease( bundlePathCFS ); + CFRelease( bundleURL ); + CFRelease( appBundle ); + CFRelease( executableURL ); +#endif + + return executable; +} + |