/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt 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 bool HandleReadMachoCommand(std::vector 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{} .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; }