/src/CMake/Source/cmExtraSublimeTextGenerator.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmExtraSublimeTextGenerator.h" |
4 | | |
5 | | #include <cstring> |
6 | | #include <memory> |
7 | | #include <set> |
8 | | #include <sstream> |
9 | | #include <utility> |
10 | | |
11 | | #include "cmsys/RegularExpression.hxx" |
12 | | |
13 | | #include "cmGeneratedFileStream.h" |
14 | | #include "cmGeneratorExpression.h" |
15 | | #include "cmGeneratorTarget.h" |
16 | | #include "cmGlobalGenerator.h" |
17 | | #include "cmList.h" |
18 | | #include "cmLocalGenerator.h" |
19 | | #include "cmMakefile.h" |
20 | | #include "cmMessageType.h" |
21 | | #include "cmSourceFile.h" |
22 | | #include "cmStateTypes.h" |
23 | | #include "cmStringAlgorithms.h" |
24 | | #include "cmSystemTools.h" |
25 | | #include "cmValue.h" |
26 | | #include "cmake.h" |
27 | | |
28 | | /* |
29 | | Sublime Text 2 Generator |
30 | | Author: Morné Chamberlain |
31 | | This generator was initially based off of the CodeBlocks generator. |
32 | | |
33 | | Some useful URLs: |
34 | | Homepage: |
35 | | http://www.sublimetext.com/ |
36 | | |
37 | | File format docs: |
38 | | http://www.sublimetext.com/docs/2/projects.html |
39 | | http://sublimetext.info/docs/en/reference/build_systems.html |
40 | | */ |
41 | | |
42 | | cmExternalMakefileProjectGeneratorFactory* |
43 | | cmExtraSublimeTextGenerator::GetFactory() |
44 | 35 | { |
45 | 35 | static cmExternalMakefileProjectGeneratorSimpleFactory< |
46 | 35 | cmExtraSublimeTextGenerator> |
47 | 35 | factory("Sublime Text 2", |
48 | 35 | "Generates Sublime Text 2 project files (deprecated)."); |
49 | | |
50 | 35 | if (factory.GetSupportedGlobalGenerators().empty()) { |
51 | | #if defined(_WIN32) |
52 | | factory.AddSupportedGlobalGenerator("MinGW Makefiles"); |
53 | | factory.AddSupportedGlobalGenerator("NMake Makefiles"); |
54 | | // disable until somebody actually tests it: |
55 | | // factory.AddSupportedGlobalGenerator("MSYS Makefiles"); |
56 | | #endif |
57 | 1 | factory.AddSupportedGlobalGenerator("Ninja"); |
58 | 1 | factory.AddSupportedGlobalGenerator("Unix Makefiles"); |
59 | 1 | } |
60 | | |
61 | 35 | return &factory; |
62 | 35 | } |
63 | | |
64 | | cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator() |
65 | 0 | { |
66 | 0 | this->ExcludeBuildFolder = false; |
67 | 0 | } |
68 | | |
69 | | void cmExtraSublimeTextGenerator::Generate() |
70 | 0 | { |
71 | 0 | this->ExcludeBuildFolder = this->GlobalGenerator->GlobalSettingIsOn( |
72 | 0 | "CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE"); |
73 | 0 | this->EnvSettings = this->GlobalGenerator->GetSafeGlobalSetting( |
74 | 0 | "CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS"); |
75 | | |
76 | | // for each sub project in the project create a sublime text 2 project |
77 | 0 | for (auto const& it : this->GlobalGenerator->GetProjectMap()) { |
78 | | // create a project file |
79 | 0 | this->CreateProjectFile(it.second); |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | | void cmExtraSublimeTextGenerator::CreateProjectFile( |
84 | | std::vector<cmLocalGenerator*> const& lgs) |
85 | 0 | { |
86 | 0 | std::string outputDir = lgs[0]->GetCurrentBinaryDirectory(); |
87 | 0 | std::string projectName = lgs[0]->GetProjectName(); |
88 | |
|
89 | 0 | std::string const filename = |
90 | 0 | cmStrCat(outputDir, '/', projectName, ".sublime-project"); |
91 | |
|
92 | 0 | this->CreateNewProjectFile(lgs, filename); |
93 | 0 | } |
94 | | |
95 | | void cmExtraSublimeTextGenerator::CreateNewProjectFile( |
96 | | std::vector<cmLocalGenerator*> const& lgs, std::string const& filename) |
97 | 0 | { |
98 | 0 | cmMakefile const* mf = lgs[0]->GetMakefile(); |
99 | |
|
100 | 0 | cmGeneratedFileStream fout(filename); |
101 | 0 | if (!fout) { |
102 | 0 | return; |
103 | 0 | } |
104 | | |
105 | 0 | std::string const& sourceRootRelativeToOutput = cmSystemTools::RelativePath( |
106 | 0 | lgs[0]->GetBinaryDirectory(), lgs[0]->GetSourceDirectory()); |
107 | | // Write the folder entries to the project file |
108 | 0 | fout << "{\n"; |
109 | 0 | fout << "\t\"folders\":\n\t[\n\t"; |
110 | 0 | if (!sourceRootRelativeToOutput.empty()) { |
111 | 0 | fout << "\t{\n\t\t\t\"path\": \"" << sourceRootRelativeToOutput << "\""; |
112 | 0 | std::string const& outputRelativeToSourceRoot = |
113 | 0 | cmSystemTools::RelativePath(lgs[0]->GetSourceDirectory(), |
114 | 0 | lgs[0]->GetBinaryDirectory()); |
115 | 0 | if ((!outputRelativeToSourceRoot.empty()) && |
116 | 0 | ((outputRelativeToSourceRoot.length() < 3) || |
117 | 0 | (outputRelativeToSourceRoot.substr(0, 3) != "../"))) { |
118 | 0 | if (this->ExcludeBuildFolder) { |
119 | 0 | fout << ",\n\t\t\t\"folder_exclude_patterns\": [\"" |
120 | 0 | << outputRelativeToSourceRoot << "\"]"; |
121 | 0 | } |
122 | 0 | } |
123 | 0 | } else { |
124 | 0 | fout << "\t{\n\t\t\t\"path\": \"./\""; |
125 | 0 | } |
126 | 0 | fout << "\n\t\t}"; |
127 | | // End of the folders section |
128 | 0 | fout << "\n\t]"; |
129 | | |
130 | | // Write the beginning of the build systems section to the project file |
131 | 0 | fout << ",\n\t\"build_systems\":\n\t[\n\t"; |
132 | | |
133 | | // Set of include directories over all targets (sublime text/sublimeclang |
134 | | // doesn't currently support these settings per build system, only project |
135 | | // wide |
136 | 0 | MapSourceFileFlags sourceFileFlags; |
137 | 0 | this->AppendAllTargets(lgs, mf, fout, sourceFileFlags); |
138 | | |
139 | | // End of build_systems |
140 | 0 | fout << "\n\t]"; |
141 | 0 | std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); |
142 | 0 | cmList tokens{ this->EnvSettings }; |
143 | |
|
144 | 0 | if (!this->EnvSettings.empty()) { |
145 | 0 | fout << ","; |
146 | 0 | fout << "\n\t\"env\":"; |
147 | 0 | fout << "\n\t{"; |
148 | 0 | fout << "\n\t\t" << systemName << ":"; |
149 | 0 | fout << "\n\t\t{"; |
150 | 0 | for (std::string const& t : tokens) { |
151 | 0 | size_t const pos = t.find_first_of('='); |
152 | |
|
153 | 0 | if (pos != std::string::npos) { |
154 | 0 | std::string varName = t.substr(0, pos); |
155 | 0 | std::string varValue = t.substr(pos + 1); |
156 | |
|
157 | 0 | fout << "\n\t\t\t\"" << varName << "\":\"" << varValue << "\""; |
158 | 0 | } else { |
159 | 0 | std::ostringstream e; |
160 | 0 | e << "Could not parse Env Vars specified in " |
161 | 0 | "\"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS\"" |
162 | 0 | << ", corrupted string " << t; |
163 | 0 | mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); |
164 | 0 | } |
165 | 0 | } |
166 | 0 | fout << "\n\t\t}"; |
167 | 0 | fout << "\n\t}"; |
168 | 0 | } |
169 | 0 | fout << "\n}"; |
170 | 0 | } |
171 | | |
172 | | void cmExtraSublimeTextGenerator::AppendAllTargets( |
173 | | std::vector<cmLocalGenerator*> const& lgs, cmMakefile const* mf, |
174 | | cmGeneratedFileStream& fout, MapSourceFileFlags& sourceFileFlags) |
175 | 0 | { |
176 | 0 | std::string const& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); |
177 | 0 | std::string compiler; |
178 | 0 | if (!lgs.empty()) { |
179 | 0 | this->AppendTarget(fout, "all", lgs[0], nullptr, make.c_str(), mf, |
180 | 0 | compiler.c_str(), sourceFileFlags, true); |
181 | 0 | this->AppendTarget(fout, "clean", lgs[0], nullptr, make.c_str(), mf, |
182 | 0 | compiler.c_str(), sourceFileFlags, false); |
183 | 0 | } |
184 | | |
185 | | // add all executable and library targets and some of the GLOBAL |
186 | | // and UTILITY targets |
187 | 0 | for (cmLocalGenerator* lg : lgs) { |
188 | 0 | cmMakefile* makefile = lg->GetMakefile(); |
189 | 0 | auto const& targets = lg->GetGeneratorTargets(); |
190 | 0 | for (auto const& target : targets) { |
191 | 0 | std::string targetName = target->GetName(); |
192 | 0 | switch (target->GetType()) { |
193 | 0 | case cmStateEnums::GLOBAL_TARGET: { |
194 | | // Only add the global targets from CMAKE_BINARY_DIR, |
195 | | // not from the subdirs |
196 | 0 | if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) { |
197 | 0 | this->AppendTarget(fout, targetName, lg, nullptr, make.c_str(), |
198 | 0 | makefile, compiler.c_str(), sourceFileFlags, |
199 | 0 | false); |
200 | 0 | } |
201 | 0 | } break; |
202 | 0 | case cmStateEnums::UTILITY: |
203 | | // Add all utility targets, except the Nightly/Continuous/ |
204 | | // Experimental-"sub"targets as e.g. NightlyStart |
205 | 0 | if ((cmHasLiteralPrefix(targetName, "Nightly") && |
206 | 0 | (targetName != "Nightly")) || |
207 | 0 | (cmHasLiteralPrefix(targetName, "Continuous") && |
208 | 0 | (targetName != "Continuous")) || |
209 | 0 | (cmHasLiteralPrefix(targetName, "Experimental") && |
210 | 0 | (targetName != "Experimental"))) { |
211 | 0 | break; |
212 | 0 | } |
213 | | |
214 | 0 | this->AppendTarget(fout, targetName, lg, nullptr, make.c_str(), |
215 | 0 | makefile, compiler.c_str(), sourceFileFlags, |
216 | 0 | false); |
217 | 0 | break; |
218 | 0 | case cmStateEnums::EXECUTABLE: |
219 | 0 | case cmStateEnums::STATIC_LIBRARY: |
220 | 0 | case cmStateEnums::SHARED_LIBRARY: |
221 | 0 | case cmStateEnums::MODULE_LIBRARY: |
222 | 0 | case cmStateEnums::OBJECT_LIBRARY: { |
223 | 0 | this->AppendTarget(fout, targetName, lg, target.get(), make.c_str(), |
224 | 0 | makefile, compiler.c_str(), sourceFileFlags, |
225 | 0 | false); |
226 | 0 | std::string fastTarget = cmStrCat(targetName, "/fast"); |
227 | 0 | this->AppendTarget(fout, fastTarget, lg, target.get(), make.c_str(), |
228 | 0 | makefile, compiler.c_str(), sourceFileFlags, |
229 | 0 | false); |
230 | 0 | } break; |
231 | 0 | default: |
232 | 0 | break; |
233 | 0 | } |
234 | 0 | } |
235 | 0 | } |
236 | 0 | } |
237 | | |
238 | | void cmExtraSublimeTextGenerator::AppendTarget( |
239 | | cmGeneratedFileStream& fout, std::string const& targetName, |
240 | | cmLocalGenerator* lg, cmGeneratorTarget* target, char const* make, |
241 | | cmMakefile const* makefile, char const* /*compiler*/, |
242 | | MapSourceFileFlags& sourceFileFlags, bool firstTarget) |
243 | 0 | { |
244 | |
|
245 | 0 | if (target) { |
246 | 0 | std::vector<cmSourceFile*> sourceFiles; |
247 | 0 | target->GetSourceFiles(sourceFiles, |
248 | 0 | makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); |
249 | 0 | for (cmSourceFile* sourceFile : sourceFiles) { |
250 | 0 | auto sourceFileFlagsIter = |
251 | 0 | sourceFileFlags.find(sourceFile->ResolveFullPath()); |
252 | 0 | if (sourceFileFlagsIter == sourceFileFlags.end()) { |
253 | 0 | sourceFileFlagsIter = |
254 | 0 | sourceFileFlags |
255 | 0 | .insert(MapSourceFileFlags::value_type( |
256 | 0 | sourceFile->ResolveFullPath(), std::vector<std::string>())) |
257 | 0 | .first; |
258 | 0 | } |
259 | 0 | std::vector<std::string>& flags = sourceFileFlagsIter->second; |
260 | 0 | std::string flagsString = |
261 | 0 | this->ComputeFlagsForObject(sourceFile, lg, target); |
262 | 0 | std::string definesString = this->ComputeDefines(sourceFile, lg, target); |
263 | 0 | std::string includesString = |
264 | 0 | this->ComputeIncludes(sourceFile, lg, target); |
265 | 0 | flags.clear(); |
266 | 0 | cmsys::RegularExpression flagRegex; |
267 | | // Regular expression to extract compiler flags from a string |
268 | | // https://gist.github.com/3944250 |
269 | 0 | char const* regexString = |
270 | 0 | R"((^|[ ])-[DIOUWfgs][^= ]+(=\"[^"]+\"|=[^"][^ ]+)?)"; |
271 | 0 | flagRegex.compile(regexString); |
272 | 0 | std::string workString = |
273 | 0 | cmStrCat(flagsString, ' ', definesString, ' ', includesString); |
274 | 0 | while (flagRegex.find(workString)) { |
275 | 0 | std::string::size_type start = flagRegex.start(); |
276 | 0 | if (workString[start] == ' ') { |
277 | 0 | start++; |
278 | 0 | } |
279 | 0 | flags.push_back(workString.substr(start, flagRegex.end() - start)); |
280 | 0 | if (flagRegex.end() < workString.size()) { |
281 | 0 | workString = workString.substr(flagRegex.end()); |
282 | 0 | } else { |
283 | 0 | workString.clear(); |
284 | 0 | } |
285 | 0 | } |
286 | 0 | } |
287 | 0 | } |
288 | | |
289 | | // Ninja uses ninja.build files (look for a way to get the output file name |
290 | | // from cmMakefile or something) |
291 | 0 | std::string makefileName; |
292 | 0 | if (this->GlobalGenerator->GetName() == "Ninja") { |
293 | 0 | makefileName = "build.ninja"; |
294 | 0 | } else { |
295 | 0 | makefileName = "Makefile"; |
296 | 0 | } |
297 | 0 | if (!firstTarget) { |
298 | 0 | fout << ",\n\t"; |
299 | 0 | } |
300 | 0 | fout << "\t{\n\t\t\t\"name\": \"" << lg->GetProjectName() << " - " |
301 | 0 | << targetName << "\",\n"; |
302 | 0 | fout << "\t\t\t\"cmd\": [" |
303 | 0 | << this->BuildMakeCommand(make, makefileName, targetName) << "],\n"; |
304 | 0 | fout << "\t\t\t\"working_dir\": \"${project_path}\",\n"; |
305 | 0 | fout << "\t\t\t\"file_regex\": \"" |
306 | 0 | "^(..[^:]*)(?::|\\\\()([0-9]+)(?::|\\\\))(?:([0-9]+):)?\\\\s*(.*)" |
307 | 0 | "\"\n"; |
308 | 0 | fout << "\t\t}"; |
309 | 0 | } |
310 | | |
311 | | // Create the command line for building the given target using the selected |
312 | | // make |
313 | | std::string cmExtraSublimeTextGenerator::BuildMakeCommand( |
314 | | std::string const& make, std::string const& makefile, |
315 | | std::string const& target) |
316 | 0 | { |
317 | 0 | std::string command = cmStrCat('"', make, '"'); |
318 | 0 | std::string generator = this->GlobalGenerator->GetName(); |
319 | 0 | if (generator == "NMake Makefiles") { |
320 | 0 | std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); |
321 | 0 | command = cmStrCat(std::move(command), R"(, "/NOLOGO", "/f", ")", |
322 | 0 | std::move(makefileName), "\", \"", target, '"'); |
323 | 0 | } else if (generator == "Ninja") { |
324 | 0 | std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); |
325 | 0 | command = cmStrCat(std::move(command), R"(, "-f", ")", |
326 | 0 | std::move(makefileName), "\", \"", target, '"'); |
327 | 0 | } else { |
328 | 0 | std::string makefileName; |
329 | 0 | if (generator == "MinGW Makefiles") { |
330 | | // no escaping of spaces in this case, see |
331 | | // https://gitlab.kitware.com/cmake/cmake/-/issues/10014 |
332 | 0 | makefileName = makefile; |
333 | 0 | } else { |
334 | 0 | makefileName = cmSystemTools::ConvertToOutputPath(makefile); |
335 | 0 | } |
336 | 0 | command = cmStrCat(std::move(command), R"(, "-f", ")", |
337 | 0 | std::move(makefileName), "\", \"", target, '"'); |
338 | 0 | } |
339 | 0 | return command; |
340 | 0 | } |
341 | | |
342 | | // TODO: Most of the code is picked up from the Ninja generator, refactor it. |
343 | | std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( |
344 | | cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* gtgt) |
345 | 0 | { |
346 | 0 | std::string flags; |
347 | 0 | std::string language = source->GetOrDetermineLanguage(); |
348 | 0 | if (language.empty()) { |
349 | 0 | language = "C"; |
350 | 0 | } |
351 | | |
352 | | // Explicitly add the explicit language flag before any other flag |
353 | | // so user flags can override it. |
354 | 0 | gtgt->AddExplicitLanguageFlags(flags, *source); |
355 | |
|
356 | 0 | std::string const& config = |
357 | 0 | lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); |
358 | |
|
359 | 0 | lg->GetTargetCompileFlags(gtgt, config, language, flags); |
360 | | |
361 | | // Add source file specific flags. |
362 | 0 | cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gtgt, |
363 | 0 | language); |
364 | |
|
365 | 0 | std::string const COMPILE_FLAGS("COMPILE_FLAGS"); |
366 | 0 | if (cmValue cflags = source->GetProperty(COMPILE_FLAGS)) { |
367 | 0 | lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS)); |
368 | 0 | } |
369 | |
|
370 | 0 | std::string const COMPILE_OPTIONS("COMPILE_OPTIONS"); |
371 | 0 | if (cmValue coptions = source->GetProperty(COMPILE_OPTIONS)) { |
372 | 0 | lg->AppendCompileOptions( |
373 | 0 | flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS)); |
374 | 0 | } |
375 | |
|
376 | 0 | return flags; |
377 | 0 | } |
378 | | |
379 | | // TODO: Refactor with |
380 | | // void cmMakefileTargetGenerator::WriteTargetLanguageFlags(). |
381 | | std::string cmExtraSublimeTextGenerator::ComputeDefines( |
382 | | cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* target) |
383 | | |
384 | 0 | { |
385 | 0 | std::set<std::string> defines; |
386 | 0 | cmMakefile* makefile = lg->GetMakefile(); |
387 | 0 | std::string const& language = source->GetOrDetermineLanguage(); |
388 | 0 | std::string const& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); |
389 | 0 | cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, |
390 | 0 | language); |
391 | | |
392 | | // Add preprocessor definitions for this target and configuration. |
393 | 0 | lg->GetTargetDefines(target, config, language, defines); |
394 | 0 | std::string const COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); |
395 | 0 | if (cmValue compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { |
396 | 0 | lg->AppendDefines( |
397 | 0 | defines, genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS)); |
398 | 0 | } |
399 | |
|
400 | 0 | std::string defPropName = |
401 | 0 | cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); |
402 | 0 | if (cmValue config_compile_defs = source->GetProperty(defPropName)) { |
403 | 0 | lg->AppendDefines( |
404 | 0 | defines, |
405 | 0 | genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS)); |
406 | 0 | } |
407 | |
|
408 | 0 | std::string definesString; |
409 | 0 | lg->JoinDefines(defines, definesString, language); |
410 | |
|
411 | 0 | return definesString; |
412 | 0 | } |
413 | | |
414 | | std::string cmExtraSublimeTextGenerator::ComputeIncludes( |
415 | | cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* target) |
416 | | |
417 | 0 | { |
418 | 0 | std::vector<std::string> includes; |
419 | 0 | cmMakefile* makefile = lg->GetMakefile(); |
420 | 0 | std::string const& language = source->GetOrDetermineLanguage(); |
421 | 0 | std::string const& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); |
422 | 0 | cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, |
423 | 0 | language); |
424 | | |
425 | | // Add include directories for this source file |
426 | 0 | std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); |
427 | 0 | if (cmValue cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { |
428 | 0 | lg->AppendIncludeDirectories( |
429 | 0 | includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), |
430 | 0 | *source); |
431 | 0 | } |
432 | | |
433 | | // Add include directory flags. |
434 | 0 | lg->GetIncludeDirectories(includes, target, language, config); |
435 | |
|
436 | 0 | std::string includesString = |
437 | 0 | lg->GetIncludeFlags(includes, target, language, config, false); |
438 | |
|
439 | 0 | return includesString; |
440 | 0 | } |
441 | | |
442 | | bool cmExtraSublimeTextGenerator::Open(std::string const& bindir, |
443 | | std::string const& projectName, |
444 | | bool dryRun) |
445 | 0 | { |
446 | 0 | cmValue sublExecutable = |
447 | 0 | this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition( |
448 | 0 | "CMAKE_SUBLIMETEXT_EXECUTABLE"); |
449 | 0 | if (!sublExecutable) { |
450 | 0 | return false; |
451 | 0 | } |
452 | 0 | if (cmIsNOTFOUND(*sublExecutable)) { |
453 | 0 | return false; |
454 | 0 | } |
455 | | |
456 | 0 | std::string filename = |
457 | 0 | cmStrCat(bindir, '/', projectName, ".sublime-project"); |
458 | 0 | if (dryRun) { |
459 | 0 | return cmSystemTools::FileExists(filename, true); |
460 | 0 | } |
461 | | |
462 | 0 | return cmSystemTools::RunSingleCommand( |
463 | 0 | { *sublExecutable, "--project", filename }); |
464 | 0 | } |