| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmFileCommand_ReadMacho.h" | |
| #include "cmArgumentParser.h" | |
| #include "cmExecutionStatus.h" | |
| #include "cmMakefile.h" | |
| #include "cmRange.h" | |
| #include "cmStringAlgorithms.h" | |
| #include "cmSystemTools.h" | |
| #if defined(CMake_USE_MACH_PARSER) | |
| # include "cmMachO.h" | |
| #endif | |
| #include <cmext/string_view> | |
| bool HandleReadMachoCommand(std::vector<std::string> const& args, | |
| cmExecutionStatus& status) | |
| { | |
| if (args.size() < 4) { | |
| status.SetError("READ_MACHO must be called with at least three additional " | |
| "arguments."); | |
| return false; | |
| } | |
| std::string const& fileNameArg = args[1]; | |
| struct Arguments | |
| { | |
| std::string Architectures; | |
| std::string Error; | |
| }; | |
| static auto const parser = | |
| cmArgumentParser<Arguments>{} | |
| .Bind("ARCHITECTURES"_s, &Arguments::Architectures) | |
| .Bind("CAPTURE_ERROR"_s, &Arguments::Error); | |
| Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2), | |
| /*unparsedArguments=*/nullptr); | |
| if (!arguments.Architectures.empty()) { | |
| // always return something sensible for ARCHITECTURES | |
| status.GetMakefile().AddDefinition(arguments.Architectures, "unknown"_s); | |
| } | |
| if (!cmSystemTools::FileExists(fileNameArg, true)) { | |
| if (arguments.Error.empty()) { | |
| status.SetError(cmStrCat("READ_MACHO given FILE \"", fileNameArg, | |
| "\" that does not exist.")); | |
| return false; | |
| } | |
| status.GetMakefile().AddDefinition( | |
| arguments.Error, cmStrCat(fileNameArg, " does not exist")); | |
| return true; | |
| } | |
| #if defined(CMake_USE_MACH_PARSER) | |
| cmMachO macho(fileNameArg.c_str()); | |
| if (!macho) { | |
| if (arguments.Error.empty()) { | |
| status.SetError(cmStrCat("READ_MACHO given FILE:\n ", fileNameArg, | |
| "\nthat is not a valid Macho-O file.")); | |
| return false; | |
| } | |
| status.GetMakefile().AddDefinition( | |
| arguments.Error, cmStrCat(fileNameArg, " is not a valid Macho-O file")); | |
| return true; | |
| } else if (!macho.GetErrorMessage().empty()) { | |
| if (arguments.Error.empty()) { | |
| status.SetError(cmStrCat( | |
| "READ_MACHO given FILE:\n ", fileNameArg, | |
| "\nthat is not a supported Macho-O file: ", macho.GetErrorMessage())); | |
| return false; | |
| } | |
| status.GetMakefile().AddDefinition( | |
| arguments.Error, | |
| cmStrCat(fileNameArg, | |
| " is not a supported Macho-O file: ", macho.GetErrorMessage())); | |
| return true; | |
| } | |
| std::string output; | |
| if (!arguments.Architectures.empty()) { | |
| auto archs = macho.GetArchitectures(); | |
| output = cmJoin(archs, ";"); | |
| // Save the output in a makefile variable. | |
| status.GetMakefile().AddDefinition(arguments.Architectures, output); | |
| } | |
| #else | |
| if (arguments.Error.empty()) { | |
| status.SetError("READ_MACHO support not available on this platform."); | |
| return false; | |
| } | |
| status.GetMakefile().AddDefinition( | |
| arguments.Error, "READ_MACHO support not available on this platform."); | |
| #endif // CMake_USE_MACH_PARSER | |
| return true; | |
| } |