Introduce "generator expressions" to add_test()
[cmake.git] / Source / cmFindProgramCommand.cxx
blobf05a7b99af1153d23e2c2391a3bd09a401f769f5
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFindProgramCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008-06-09 15:58:29 $
7 Version: $Revision: 1.43 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmFindProgramCommand.h"
18 #include "cmCacheManager.h"
19 #include <stdlib.h>
21 #if defined(__APPLE__)
22 #include <CoreFoundation/CoreFoundation.h>
23 #endif
25 cmFindProgramCommand::cmFindProgramCommand()
27 cmSystemTools::ReplaceString(this->GenericDocumentation,
28 "FIND_XXX", "find_program");
29 cmSystemTools::ReplaceString(this->GenericDocumentation,
30 "CMAKE_XXX_PATH", "CMAKE_PROGRAM_PATH");
31 cmSystemTools::ReplaceString(this->GenericDocumentation,
32 "CMAKE_XXX_MAC_PATH",
33 "CMAKE_APPBUNDLE_PATH");
34 cmSystemTools::ReplaceString(this->GenericDocumentation,
35 "CMAKE_SYSTEM_XXX_MAC_PATH",
36 "CMAKE_SYSTEM_APPBUNDLE_PATH");
37 cmSystemTools::ReplaceString(this->GenericDocumentation,
38 "XXX_SYSTEM", "");
39 cmSystemTools::ReplaceString(this->GenericDocumentation,
40 "CMAKE_SYSTEM_XXX_PATH",
41 "CMAKE_SYSTEM_PROGRAM_PATH");
42 cmSystemTools::ReplaceString(this->GenericDocumentation,
43 "SEARCH_XXX_DESC", "program");
44 cmSystemTools::ReplaceString(this->GenericDocumentation,
45 "SEARCH_XXX", "program");
46 cmSystemTools::ReplaceString(this->GenericDocumentation,
47 "XXX_SUBDIR", "[s]bin");
48 cmSystemTools::ReplaceString(this->GenericDocumentation,
49 "CMAKE_FIND_ROOT_PATH_MODE_XXX",
50 "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM");
53 // cmFindProgramCommand
54 bool cmFindProgramCommand
55 ::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
57 this->VariableDocumentation = "Path to a program.";
58 this->CMakePathName = "PROGRAM";
59 // call cmFindBase::ParseArguments
60 if(!this->ParseArguments(argsIn))
62 return false;
64 if(this->AlreadyInCache)
66 // If the user specifies the entry on the command line without a
67 // type we should add the type and docstring but keep the original
68 // value.
69 if(this->AlreadyInCacheWithoutMetaInfo)
71 this->Makefile->AddCacheDefinition(this->VariableName.c_str(), "",
72 this->VariableDocumentation.c_str(),
73 cmCacheManager::FILEPATH);
75 return true;
78 std::string result = FindProgram(this->Names);
79 if(result != "")
81 // Save the value in the cache
82 this->Makefile->AddCacheDefinition(this->VariableName.c_str(),
83 result.c_str(),
84 this->VariableDocumentation.c_str(),
85 cmCacheManager::FILEPATH);
87 return true;
89 this->Makefile->AddCacheDefinition(this->VariableName.c_str(),
90 (this->VariableName + "-NOTFOUND").c_str(),
91 this->VariableDocumentation.c_str(),
92 cmCacheManager::FILEPATH);
93 return true;
96 std::string cmFindProgramCommand::FindProgram(std::vector<std::string> names)
98 std::string program = "";
100 if(this->SearchAppBundleFirst || this->SearchAppBundleOnly)
102 program = FindAppBundle(names);
104 if(program.empty() && !this->SearchAppBundleOnly)
106 program = cmSystemTools::FindProgram(names, this->SearchPaths, true);
109 if(program.empty() && this->SearchAppBundleLast)
111 program = this->FindAppBundle(names);
113 return program;
116 std::string cmFindProgramCommand
117 ::FindAppBundle(std::vector<std::string> names)
119 for(std::vector<std::string>::const_iterator name = names.begin();
120 name != names.end() ; ++name)
123 std::string appName = *name + std::string(".app");
124 std::string appPath = cmSystemTools::FindDirectory(appName.c_str(),
125 this->SearchPaths,
126 true);
128 if ( !appPath.empty() )
130 std::string executable = GetBundleExecutable(appPath);
131 if (!executable.empty())
133 return cmSystemTools::CollapseFullPath(executable.c_str());
138 // Couldn't find app bundle
139 return "";
142 std::string cmFindProgramCommand::GetBundleExecutable(std::string bundlePath)
144 std::string executable = "";
145 (void)bundlePath;
146 #if defined(__APPLE__)
147 // Started with an example on developer.apple.com about finding bundles
148 // and modified from that.
150 // Get a CFString of the app bundle path
151 // XXX - Is it safe to assume everything is in UTF8?
152 CFStringRef bundlePathCFS =
153 CFStringCreateWithCString(kCFAllocatorDefault ,
154 bundlePath.c_str(), kCFStringEncodingUTF8 );
156 // Make a CFURLRef from the CFString representation of the
157 // bundle’s path.
158 CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
159 bundlePathCFS,
160 kCFURLPOSIXPathStyle,
161 true );
163 // Make a bundle instance using the URLRef.
164 CFBundleRef appBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
166 // returned executableURL is relative to <appbundle>/Contents/MacOS/
167 CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
169 if (executableURL != NULL)
171 const int MAX_OSX_PATH_SIZE = 1024;
172 char buffer[MAX_OSX_PATH_SIZE];
174 // Convert the CFString to a C string
175 CFStringGetCString( CFURLGetString(executableURL), buffer,
176 MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 );
178 // And finally to a c++ string
179 executable = bundlePath + "/Contents/MacOS/" + std::string(buffer);
182 // Any CF objects returned from functions with "create" or
183 // "copy" in their names must be released by us!
184 CFRelease( bundlePathCFS );
185 CFRelease( bundleURL );
186 CFRelease( appBundle );
187 CFRelease( executableURL );
188 #endif
190 return executable;