mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-24 07:08:38 -05:00
file: Add undocumented READ_MACHO subcommand on macOS
Provide a way to parse the architectures of a Mach-O binary. Issue: #25952
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
/* 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 <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;
|
||||
}
|
||||
Reference in New Issue
Block a user