mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-21 07:18:33 -05:00
Merge topic 'bin2c'
3dd49d857aci: Enable bin2c large file test on some builds3a893806bbcmake -E: Add bin2c mode8cca26e562cm::optional: Suppress GCC -Wmaybe-uninitialized false positive Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Acked-by: Brad King <brad.king@kitware.com> Merge-request: !11536
This commit is contained in:
@@ -6,6 +6,7 @@ set(CMake_TEST_CTestUpdate_GIT "ON" CACHE BOOL "")
|
||||
set(CMake_TEST_CTestUpdate_HG "ON" CACHE BOOL "")
|
||||
set(CMake_TEST_CTestUpdate_SVN "ON" CACHE BOOL "")
|
||||
if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
|
||||
set(CMake_TEST_BIN2C_LARGE_FILE "ON" CACHE BOOL "")
|
||||
set(CMake_TEST_CTestUpdate_P4 "ON" CACHE BOOL "")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ set(CMake_TEST_C_STANDARDS "90;99;11;17;23" CACHE STRING "")
|
||||
set(CMake_TEST_CXX_STANDARDS "98;11;14;17;20;23" CACHE STRING "")
|
||||
|
||||
if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
|
||||
set(CMake_TEST_BIN2C_LARGE_FILE "ON" CACHE BOOL "")
|
||||
set(CMake_TEST_CPACK_INNOSETUP "ON" CACHE STRING "")
|
||||
set(CMake_TEST_CPACK_NUGET "ON" CACHE STRING "")
|
||||
set(CMake_TEST_IAR_TOOLCHAINS "$ENV{CI_PROJECT_DIR}/.gitlab/iar" CACHE PATH "")
|
||||
|
||||
@@ -1027,6 +1027,75 @@ CMake provides builtin command-line tools through the signature
|
||||
|
||||
Available commands are:
|
||||
|
||||
.. option:: bin2c [<options>...] [--] [<input-file> [<output-file>]]
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
Convert a binary file to a C array. If input file is unspecified or ``-``,
|
||||
read from standard input instead of a file. If output file is unspecified or
|
||||
``-``, write to standard output instead of a file.
|
||||
|
||||
By default, this prints only the bytes. Enclosing text can be added with the
|
||||
``--template-file`` argument. You can also ``#include`` the bytes from
|
||||
another file, acting as a drop-in replacement for the ``#embed`` directive
|
||||
from C23 and C++26:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
unsigned char my_bytes[] = {
|
||||
/* #embed "bin2c_input.bin" */
|
||||
#include "bin2c_output.c.txt"
|
||||
};
|
||||
|
||||
.. program:: cmake-E_bin2c
|
||||
|
||||
.. option:: --signed
|
||||
|
||||
Print the bytes as signed integers rather than unsigned.
|
||||
|
||||
.. option:: --decimal
|
||||
|
||||
Print the bytes as decimal rather than hexadecimal.
|
||||
|
||||
.. option:: --trailing-comma
|
||||
|
||||
Append a trailing comma after the last byte (not included by default.)
|
||||
|
||||
.. option:: --template-file <template-file>
|
||||
|
||||
Format from a template file. The template file contains placeholders for
|
||||
the array and optionally the length (which will be a non-negative decimal
|
||||
integer). Such placeholders are enclosed in ``@`` at the beginning and end
|
||||
of the placeholder.
|
||||
|
||||
An example of a potential template file:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
unsigned char my_bytes[] = {@array@};
|
||||
|
||||
size_t length = @length@;
|
||||
|
||||
The array placeholder may occur at most once in the template file. The
|
||||
length placeholder may occur zero or more times after the array
|
||||
placeholder, but not before it.
|
||||
|
||||
Note that the length is the number of elements printed, and may not match
|
||||
the ``sizeof`` the resulting array if a type other than ``unsigned char``
|
||||
is used.
|
||||
|
||||
.. option:: --template-array-placeholder <placeholder-name>
|
||||
|
||||
Specify a name for the array placeholder in the template file. Set to
|
||||
``array`` by default.
|
||||
|
||||
.. option:: --template-length-placeholder <placeholder-name>
|
||||
|
||||
Specify a name for the length placeholder in the template file. Set to
|
||||
``length`` by default.
|
||||
|
||||
.. program:: cmake-E
|
||||
|
||||
.. option:: capabilities
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
E_bin2c
|
||||
-------
|
||||
|
||||
:manual:`cmake -E <cmake(1)>` gained a new ``bin2c`` mode.
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
#include <fcntl.h>
|
||||
@@ -16,6 +17,7 @@
|
||||
#include "cmCommandLineArgument.h"
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmDuration.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmList.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
@@ -60,6 +62,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -86,10 +89,18 @@ int cmcmd_cmake_module_compile_db(
|
||||
std::vector<std::string>::const_iterator argBeg,
|
||||
std::vector<std::string>::const_iterator argEnd);
|
||||
|
||||
std::ostream& operator<<(
|
||||
std::ostream& stream,
|
||||
std::function<std::ostream&(std::ostream&)> const& func)
|
||||
{
|
||||
return func(stream);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// ATTENTION If you add new commands, change here,
|
||||
// and in `cmakemain.cxx` in the options table
|
||||
char const* const HELP_AVAILABLE_COMMANDS = R"(Available commands:
|
||||
bin2c - Turn a binary file into a C array
|
||||
capabilities - Report capabilities built into cmake in JSON format
|
||||
cat [--] <files>... - concat the files and print them to the standard output
|
||||
chdir dir cmd [args...] - run command in a given directory
|
||||
@@ -676,6 +687,213 @@ struct CoCompileJob
|
||||
std::string Command;
|
||||
CoCompileHandler Handler;
|
||||
};
|
||||
|
||||
struct Bin2CTemplateFile
|
||||
{
|
||||
std::string ArrayPlaceholder{ "array"_s };
|
||||
std::string LengthPlaceholder{ "length"_s };
|
||||
std::istream* TemplateStream = nullptr;
|
||||
};
|
||||
|
||||
enum class Bin2CBase
|
||||
{
|
||||
Hex,
|
||||
Decimal,
|
||||
};
|
||||
|
||||
std::size_t const BIN2C_BUFFER_SIZE = 16384;
|
||||
std::size_t const BIN2C_ROW_WIDTH = 32;
|
||||
|
||||
inline std::size_t Bin2CColumnPosHex(std::size_t column)
|
||||
{
|
||||
return cmStrLen(" ") + column * cmStrLen(" 0x__,");
|
||||
}
|
||||
|
||||
inline std::size_t Bin2CColumnPosDecimal(std::size_t column)
|
||||
{
|
||||
return cmStrLen(" ") + column * cmStrLen("____,");
|
||||
}
|
||||
|
||||
inline char Bin2CDigit(unsigned char byte, int place)
|
||||
{
|
||||
return '0' + static_cast<char>((byte / place) % 10);
|
||||
}
|
||||
|
||||
inline void Bin2CPrintCharToBuffer(bool printSigned, Bin2CBase base,
|
||||
std::string& line, unsigned char byte,
|
||||
std::uint64_t pos)
|
||||
{
|
||||
static char const hextable[] = "0123456789ABCDEF";
|
||||
bool neg = false;
|
||||
if (printSigned && byte & 0x80) {
|
||||
neg = true;
|
||||
byte = ~byte + 1;
|
||||
}
|
||||
switch (base) {
|
||||
case Bin2CBase::Hex:
|
||||
if (printSigned) {
|
||||
line[Bin2CColumnPosHex(pos % BIN2C_ROW_WIDTH)] = neg ? '-' : ' ';
|
||||
}
|
||||
line[Bin2CColumnPosHex(pos % BIN2C_ROW_WIDTH) + cmStrLen(" 0x")] =
|
||||
hextable[byte >> 4];
|
||||
line[Bin2CColumnPosHex(pos % BIN2C_ROW_WIDTH) + cmStrLen(" 0x_")] =
|
||||
hextable[byte & 0xF];
|
||||
break;
|
||||
case Bin2CBase::Decimal:
|
||||
std::size_t negOffset = byte >= 100 ? cmStrLen("")
|
||||
: byte >= 10 ? cmStrLen("_")
|
||||
: cmStrLen("__");
|
||||
for (std::size_t i = cmStrLen(""); i < negOffset; i++) {
|
||||
line[Bin2CColumnPosDecimal(pos % BIN2C_ROW_WIDTH) + i] = ' ';
|
||||
}
|
||||
line[Bin2CColumnPosDecimal(pos % BIN2C_ROW_WIDTH) + negOffset] =
|
||||
neg ? '-' : ' ';
|
||||
if (byte >= 100) {
|
||||
line[Bin2CColumnPosDecimal(pos % BIN2C_ROW_WIDTH) + cmStrLen("_")] =
|
||||
Bin2CDigit(byte, 100);
|
||||
}
|
||||
if (byte >= 10) {
|
||||
line[Bin2CColumnPosDecimal(pos % BIN2C_ROW_WIDTH) + cmStrLen("__")] =
|
||||
Bin2CDigit(byte, 10);
|
||||
}
|
||||
line[Bin2CColumnPosDecimal(pos % BIN2C_ROW_WIDTH) + cmStrLen("___")] =
|
||||
Bin2CDigit(byte, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Bin2CPrintChar(std::ostream& sout, bool printSigned, Bin2CBase base,
|
||||
bool printFirstNewline, std::string& line,
|
||||
unsigned char byte, std::uint64_t& pos, bool& any)
|
||||
{
|
||||
if (!any) {
|
||||
if (printFirstNewline) {
|
||||
sout << "\n";
|
||||
}
|
||||
} else if (pos % BIN2C_ROW_WIDTH == 0) {
|
||||
sout << line;
|
||||
}
|
||||
Bin2CPrintCharToBuffer(printSigned, base, line, byte, pos);
|
||||
any = true;
|
||||
pos++;
|
||||
}
|
||||
|
||||
std::function<std::ostream&(std::ostream& sout)> Bin2CPrintChars(
|
||||
std::istream& sin, bool printTrailingComma, bool printSigned, Bin2CBase base,
|
||||
bool printFirstNewline, std::uint64_t* length = nullptr)
|
||||
{
|
||||
return [&sin, printTrailingComma, printSigned, base, printFirstNewline,
|
||||
length](std::ostream& sout) -> std::ostream& {
|
||||
// Construct a line buffer and modify the characters within it. This is
|
||||
// an order of magnitude faster than `sout <<`-ing everything.
|
||||
std::string line = " ";
|
||||
line.reserve(
|
||||
cmStrLen(" ") +
|
||||
(base == Bin2CBase::Hex ? cmStrLen(" 0x__,") : cmStrLen("____,")) *
|
||||
BIN2C_ROW_WIDTH +
|
||||
cmStrLen("\n"));
|
||||
for (std::size_t i = 0; i < BIN2C_ROW_WIDTH; i++) {
|
||||
line = cmStrCat(line, base == Bin2CBase::Hex ? " 0x__," : "____,");
|
||||
}
|
||||
line = cmStrCat(line, '\n');
|
||||
|
||||
bool any = false;
|
||||
std::uint64_t pos = 0;
|
||||
std::size_t readSize;
|
||||
std::vector<std::uint8_t> buffer(BIN2C_BUFFER_SIZE);
|
||||
do {
|
||||
sin.read(reinterpret_cast<char*>(buffer.data()), BIN2C_BUFFER_SIZE);
|
||||
readSize = sin.gcount();
|
||||
for (std::size_t i = 0; i < readSize; i++) {
|
||||
Bin2CPrintChar(sout, printSigned, base, printFirstNewline, line,
|
||||
buffer[i], pos, any);
|
||||
}
|
||||
} while (readSize >= BIN2C_BUFFER_SIZE);
|
||||
if (any) {
|
||||
std::size_t column = pos % BIN2C_ROW_WIDTH;
|
||||
if (column == 0) {
|
||||
column = BIN2C_ROW_WIDTH;
|
||||
}
|
||||
sout << line.substr(0,
|
||||
(base == Bin2CBase::Hex
|
||||
? Bin2CColumnPosHex(column)
|
||||
: Bin2CColumnPosDecimal(column)) -
|
||||
cmStrLen(","))
|
||||
<< (printTrailingComma ? ",\n" : "\n");
|
||||
}
|
||||
|
||||
if (length) {
|
||||
*length = pos;
|
||||
}
|
||||
return sout;
|
||||
};
|
||||
}
|
||||
|
||||
bool Bin2CFromTemplateFile(std::ostream& sout, std::istream& sin,
|
||||
Bin2CTemplateFile& templateFile,
|
||||
bool printTrailingComma, bool printSigned,
|
||||
Bin2CBase base)
|
||||
{
|
||||
cm::optional<std::uint64_t> length;
|
||||
std::string line;
|
||||
|
||||
bool hasNewline;
|
||||
while (cmSystemTools::GetLineFromStream(*templateFile.TemplateStream, line,
|
||||
&hasNewline)) {
|
||||
cm::optional<std::size_t> at;
|
||||
for (std::size_t i = 0; i < line.length(); i++) {
|
||||
if (line[i] == '@') {
|
||||
if (at) {
|
||||
cm::string_view variableName{ &line[*at + 1], i - (*at + 1) };
|
||||
at.reset();
|
||||
if (variableName == templateFile.ArrayPlaceholder) {
|
||||
if (length) {
|
||||
std::cerr << "Cannot print array twice\n";
|
||||
return false;
|
||||
}
|
||||
length.emplace();
|
||||
sout << Bin2CPrintChars(sin, printTrailingComma, printSigned, base,
|
||||
true, &*length);
|
||||
} else if (variableName == templateFile.LengthPlaceholder) {
|
||||
if (!length) {
|
||||
std::cerr << "Cannot print length before array\n";
|
||||
return false;
|
||||
}
|
||||
sout << *length;
|
||||
} else {
|
||||
sout << '@' << variableName;
|
||||
at = i; // Allow for `@` outside of placeholder expansion
|
||||
}
|
||||
} else {
|
||||
at = i;
|
||||
}
|
||||
} else if (!at) {
|
||||
sout << line[i];
|
||||
}
|
||||
}
|
||||
if (at) {
|
||||
sout << &line[*at];
|
||||
}
|
||||
if (hasNewline) {
|
||||
sout << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bin2C(std::ostream& sout, std::istream& sin,
|
||||
cm::optional<Bin2CTemplateFile>& templateFile,
|
||||
bool printTrailingComma, bool printSigned, Bin2CBase base)
|
||||
{
|
||||
if (templateFile) {
|
||||
return Bin2CFromTemplateFile(sout, sin, *templateFile, printTrailingComma,
|
||||
printSigned, base);
|
||||
}
|
||||
|
||||
sout << Bin2CPrintChars(sin, printTrailingComma, printSigned, base, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// called when args[0] == "__run_co_compile"
|
||||
@@ -1910,6 +2128,175 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// bin2c
|
||||
if (args[1] == "bin2c"_s) {
|
||||
auto const usage = []() {
|
||||
std::cerr << "bin2c Usage: -E bin2c "
|
||||
"[<options>...] "
|
||||
"[--] [<input-file> [<output-file>]]\n";
|
||||
return 1;
|
||||
};
|
||||
auto const isFilename = [](std::string const& arg) -> bool {
|
||||
return arg == "-"_s || !cmHasLiteralPrefix(arg, "-");
|
||||
};
|
||||
|
||||
static char const validPlaceholderChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789/_.+-";
|
||||
|
||||
std::string inputFile = "-";
|
||||
std::string outputFile = "-";
|
||||
cm::optional<Bin2CTemplateFile> templateFile;
|
||||
cm::optional<cm::string_view> templateFilename;
|
||||
bool printTrailingComma = false;
|
||||
bool printSigned = false;
|
||||
auto base = Bin2CBase::Hex;
|
||||
|
||||
auto const ensureTemplateFile = [&templateFile]() -> Bin2CTemplateFile& {
|
||||
if (!templateFile) {
|
||||
templateFile.emplace();
|
||||
}
|
||||
return *templateFile;
|
||||
};
|
||||
|
||||
using CommandArgument =
|
||||
cmCommandLineArgument<bool(std::string const& value)>;
|
||||
std::vector<CommandArgument> arguments = {
|
||||
CommandArgument{ "--template-file", CommandArgument::Values::One,
|
||||
[&ensureTemplateFile,
|
||||
&templateFilename](std::string const& arg) -> bool {
|
||||
ensureTemplateFile();
|
||||
templateFilename = arg;
|
||||
return true;
|
||||
} },
|
||||
CommandArgument{
|
||||
"--template-array-placeholder", CommandArgument::Values::One,
|
||||
[&ensureTemplateFile](std::string const& arg) -> bool {
|
||||
if (arg.find_first_not_of(validPlaceholderChars) !=
|
||||
std::string::npos) {
|
||||
std::cerr << "Invalid array placeholder name: \"" << arg
|
||||
<< "\"\n";
|
||||
return false;
|
||||
}
|
||||
ensureTemplateFile().ArrayPlaceholder = arg;
|
||||
return true;
|
||||
} },
|
||||
CommandArgument{
|
||||
"--template-length-placeholder", CommandArgument::Values::One,
|
||||
[&ensureTemplateFile](std::string const& arg) -> bool {
|
||||
if (arg.find_first_not_of(validPlaceholderChars) !=
|
||||
std::string::npos) {
|
||||
std::cerr << "Invalid length placeholder name: \"" << arg
|
||||
<< "\"\n";
|
||||
return false;
|
||||
}
|
||||
ensureTemplateFile().LengthPlaceholder = arg;
|
||||
return true;
|
||||
} },
|
||||
CommandArgument{ "--trailing-comma", CommandArgument::Values::Zero,
|
||||
CommandArgument::setToTrue(printTrailingComma) },
|
||||
CommandArgument{ "--signed", CommandArgument::Values::Zero,
|
||||
CommandArgument::setToTrue(printSigned) },
|
||||
CommandArgument{ "--decimal", CommandArgument::Values::Zero,
|
||||
[&base](std::string const&) -> bool {
|
||||
base = Bin2CBase::Decimal;
|
||||
return true;
|
||||
} },
|
||||
};
|
||||
|
||||
size_t i;
|
||||
for (i = 2; i < args.size(); i++) {
|
||||
bool matched = false;
|
||||
auto const& arg = args[i];
|
||||
if (arg == "--"_s) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
for (auto const& argument : arguments) {
|
||||
if (argument.matches(arg)) {
|
||||
matched = true;
|
||||
if (!argument.parse(arg, i, args)) {
|
||||
std::cerr << "\n";
|
||||
return usage();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFilename(arg)) {
|
||||
break;
|
||||
}
|
||||
if (!matched) {
|
||||
return usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (i < args.size() - 2) {
|
||||
return usage();
|
||||
}
|
||||
if (i < args.size()) {
|
||||
if (!isFilename(args[i])) {
|
||||
return usage();
|
||||
}
|
||||
inputFile = args[i];
|
||||
i++;
|
||||
}
|
||||
if (i < args.size()) {
|
||||
if (!isFilename(args[i])) {
|
||||
return usage();
|
||||
}
|
||||
outputFile = args[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
cmsys::ifstream templateStream;
|
||||
if (templateFilename) {
|
||||
templateStream.open(templateFilename->data());
|
||||
if (!templateStream) {
|
||||
std::cerr << "Could not open template file for reading: \""
|
||||
<< *templateFilename << "\"\n";
|
||||
return 1;
|
||||
}
|
||||
templateFile->TemplateStream = &templateStream;
|
||||
}
|
||||
|
||||
std::istream* sin = &std::cin;
|
||||
cmsys::ifstream fin;
|
||||
if (inputFile != "-"_s) {
|
||||
fin.open(inputFile.c_str(), std::ios::in | std::ios::binary);
|
||||
if (!fin) {
|
||||
std::cerr << "Could not open file for reading: \"" << inputFile
|
||||
<< "\"\n";
|
||||
return 1;
|
||||
}
|
||||
sin = &fin;
|
||||
#ifdef _WIN32
|
||||
} else {
|
||||
_setmode(fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::ostream* sout = &std::cout;
|
||||
cmGeneratedFileStream fout;
|
||||
if (outputFile != "-"_s) {
|
||||
fout.Open(outputFile);
|
||||
if (!fout) {
|
||||
std::cerr << "Could not open file for writing: \"" << outputFile
|
||||
<< "\"\n";
|
||||
return 1;
|
||||
}
|
||||
fout.SetCopyIfDifferent(true);
|
||||
sout = &fout;
|
||||
}
|
||||
|
||||
if (!Bin2C(*sout, *sin, templateFile, printTrailingComma, printSigned,
|
||||
base)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args[1] == "server") {
|
||||
cmSystemTools::Error(
|
||||
"CMake server mode has been removed in favor of the file-api.");
|
||||
|
||||
@@ -1536,3 +1536,8 @@ add_RunCMake_test(MsvcCharsetDefines
|
||||
-DCMake_TEST_CUDA=${CMake_TEST_CUDA}
|
||||
)
|
||||
set_property(TEST RunCMake.MsvcCharsetDefines APPEND PROPERTY LABELS "CUDA")
|
||||
|
||||
add_RunCMake_test(cmake-E-bin2c -DCMake_TEST_BIN2C_LARGE_FILE=${CMake_TEST_BIN2C_LARGE_FILE})
|
||||
if(CMake_TEST_BIN2C_LARGE_FILE)
|
||||
set_property(TEST RunCMake.cmake-E-bin2c PROPERTY TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 4.2)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
@@ -0,0 +1,60 @@
|
||||
include(RunCMake)
|
||||
|
||||
function(run_bin2c name contents_name)
|
||||
string(REPLACE ";" "\\;" ARGS "${ARGN}")
|
||||
run_cmake_command(${name}
|
||||
"${CMAKE_COMMAND}"
|
||||
"-DNAME=${name}"
|
||||
"-DINPUT_FILE=${RunCMake_TEST_BINARY_DIR}/${contents_name}.bin"
|
||||
"-DARGS=${ARGS}"
|
||||
-P "${RunCMake_SOURCE_DIR}/run_bin2c.cmake"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/generate_binaries-build")
|
||||
run_cmake_with_options(generate_binaries "-DCMake_TEST_BIN2C_LARGE_FILE:BOOL=${CMake_TEST_BIN2C_LARGE_FILE}")
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(generate_binaries-build "${CMAKE_COMMAND}" --build .)
|
||||
run_bin2c(basic basic)
|
||||
run_bin2c(empty empty)
|
||||
run_bin2c(text_lf text_lf)
|
||||
run_bin2c(text_crlf text_crlf)
|
||||
run_bin2c(text_align text_align)
|
||||
run_bin2c(long long)
|
||||
run_bin2c(double_hyphen basic --)
|
||||
run_bin2c(signed basic --signed)
|
||||
run_bin2c(long_signed long --signed)
|
||||
run_bin2c(decimal basic --decimal)
|
||||
run_bin2c(long_decimal long --decimal)
|
||||
run_bin2c(signed_decimal basic --signed --decimal)
|
||||
run_bin2c(long_signed_decimal long --signed --decimal)
|
||||
run_bin2c(trailing_comma basic --trailing-comma)
|
||||
run_bin2c(trailing_comma_empty empty --trailing-comma)
|
||||
run_bin2c(trailing_comma_text_align text_align --trailing-comma)
|
||||
run_bin2c(template_file basic --template-file "${RunCMake_SOURCE_DIR}/template_file.c.in.txt")
|
||||
run_bin2c(template_file_empty empty --template-file "${RunCMake_SOURCE_DIR}/template_file.c.in.txt")
|
||||
run_bin2c(template_file_trailing_comma basic --template-file "${RunCMake_SOURCE_DIR}/template_file.c.in.txt" --trailing-comma)
|
||||
run_bin2c(template_file_placeholders basic --template-file "${RunCMake_SOURCE_DIR}/template_file_placeholders.c.in.txt" --template-array-placeholder arr --template-length-placeholder len)
|
||||
|
||||
run_cmake_command(too_many_files ${CMAKE_COMMAND} -E bin2c a a a)
|
||||
run_cmake_command(arg_after_double_hyphen ${CMAKE_COMMAND} -E bin2c --array-name arr -- --size-name size)
|
||||
run_cmake_command(input_noexist ${CMAKE_COMMAND} -E bin2c noexist.bin)
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/not_a_dir" "")
|
||||
run_cmake_command(output_not_a_dir ${CMAKE_COMMAND} -E bin2c "${RunCMake_TEST_BINARY_DIR}/basic.bin" "not_a_dir/output_not_a_dir.c.txt")
|
||||
run_cmake_command(template_file_invalid_array_placeholder ${CMAKE_COMMAND} -E bin2c --template-file "${RunCMake_SOURCE_DIR}/template_file.c.in.txt" --template-array-placeholder "array*")
|
||||
run_cmake_command(template_file_invalid_length_placeholder ${CMAKE_COMMAND} -E bin2c --template-file "${RunCMake_SOURCE_DIR}/template_file.c.in.txt" --template-length-placeholder "length*")
|
||||
run_cmake_command(template_file_noexist ${CMAKE_COMMAND} -E bin2c --template-file noexist.c.in.txt a a)
|
||||
run_cmake_command(template_file_double_array ${CMAKE_COMMAND} -E bin2c --template-file "${RunCMake_SOURCE_DIR}/template_file_double_array.c.in.txt" "${RunCMake_TEST_BINARY_DIR}/basic.bin")
|
||||
run_cmake_command(template_file_length_before_array ${CMAKE_COMMAND} -E bin2c --template-file "${RunCMake_SOURCE_DIR}/template_file_length_before_array.c.in.txt" "${RunCMake_TEST_BINARY_DIR}/basic.bin")
|
||||
|
||||
if(CMake_TEST_BIN2C_LARGE_FILE)
|
||||
run_cmake_command(generate_binaries-verify_very_long_hash
|
||||
"${CMAKE_COMMAND}"
|
||||
--build .
|
||||
--target verify_very_long_hash
|
||||
)
|
||||
run_cmake_command(very_long
|
||||
"${CMAKE_COMMAND}"
|
||||
-P "${RunCMake_SOURCE_DIR}/very_long.cmake"
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^bin2c Usage: -E bin2c \[<options>\.\.\.\] \[--\] \[<input-file> \[<output-file>\]\]$
|
||||
@@ -0,0 +1 @@
|
||||
0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03
|
||||
@@ -0,0 +1 @@
|
||||
252, 253, 254, 255, 0, 1, 2, 3
|
||||
@@ -0,0 +1 @@
|
||||
0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03
|
||||
@@ -0,0 +1,66 @@
|
||||
enable_language(C)
|
||||
enable_language(CXX)
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/hashes.cmake")
|
||||
|
||||
function(verify_long_c filename expected_lf_hash expected_crlf_hash)
|
||||
file(SHA256 "${CMAKE_CURRENT_SOURCE_DIR}/${filename}" actual_hash)
|
||||
if(NOT actual_hash STREQUAL expected_lf_hash AND NOT actual_hash STREQUAL expected_crlf_hash)
|
||||
message(FATAL_ERROR "File ${CMAKE_CURRENT_SOURCE_DIR}/${filename} does not match expected hash and has likely been manually edited. Edit and re-run ${CMAKE_CURRENT_SOURCE_DIR}/generate_files.sh instead.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
verify_long_c(long.c.txt "${long_c_lf_hash}" "${long_c_crlf_hash}")
|
||||
verify_long_c(long_signed.c.txt "${long_signed_c_lf_hash}" "${long_signed_c_crlf_hash}")
|
||||
verify_long_c(long_decimal.c.txt "${long_decimal_c_lf_hash}" "${long_decimal_c_crlf_hash}")
|
||||
verify_long_c(long_signed_decimal.c.txt "${long_signed_decimal_c_lf_hash}" "${long_signed_decimal_c_crlf_hash}")
|
||||
|
||||
add_executable(generate_binary generate_binary.cpp)
|
||||
|
||||
function(generate_binary name)
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.bin"
|
||||
COMMAND generate_binary "${name}" "${CMAKE_CURRENT_BINARY_DIR}/${name}.bin"
|
||||
DEPENDS generate_binary
|
||||
)
|
||||
add_custom_target(
|
||||
verify_${name} ALL
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DFILENAME=${CMAKE_CURRENT_BINARY_DIR}/${name}.bin"
|
||||
"-DSHA256SUM=${${name}_hash}"
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/verify_binary.cmake"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${name}.bin"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
foreach(name IN ITEMS basic empty text_lf text_crlf text_align long)
|
||||
generate_binary("${name}")
|
||||
endforeach()
|
||||
|
||||
add_executable(verify_long_variants verify_long_variants.c)
|
||||
add_custom_target(verify_long_variants_contents ALL COMMAND verify_long_variants)
|
||||
|
||||
if(CMake_TEST_BIN2C_LARGE_FILE)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/very_long_params.cmake")
|
||||
|
||||
add_executable(generate_very_long generate_very_long.cpp)
|
||||
target_compile_definitions(generate_very_long PRIVATE JACK_COUNT=${jack_count})
|
||||
add_custom_target(
|
||||
verify_very_long_hash
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DGENERATE_VERY_LONG=$<TARGET_FILE:generate_very_long>"
|
||||
"-DSHA256SUM=${very_long_hash}"
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/verify_very_long_hash.cmake"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/very_long_executables.cmake"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DGENERATE_VERY_LONG=$<TARGET_FILE:generate_very_long>"
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/record_very_long.cmake"
|
||||
)
|
||||
add_custom_target(
|
||||
record_very_long ALL
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/very_long_executables.cmake"
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <fstream>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
|
||||
static unsigned char const long_contents[] = {
|
||||
#include "long.c.txt"
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
return 1;
|
||||
}
|
||||
std::string name = argv[1];
|
||||
std::ofstream fout(argv[2], std::ios::out | std::ios::binary);
|
||||
|
||||
if (name == "basic") {
|
||||
fout.write("\xFC\xFD\xFE\xFF\x00\x01\x02\x03", 8);
|
||||
} else if (name == "empty") {
|
||||
// Write nothing
|
||||
} else if (name == "text_lf") {
|
||||
fout << "All work and no play makes Jack a dull boy.\n";
|
||||
} else if (name == "text_crlf") {
|
||||
fout << "All work and no play makes Jack a dull boy.\r\n";
|
||||
} else if (name == "text_align") {
|
||||
fout << "This exactly 32 characters long!";
|
||||
} else if (name == "long") {
|
||||
fout.write(reinterpret_cast<char const*>(long_contents),
|
||||
sizeof(long_contents));
|
||||
}
|
||||
|
||||
fout.flush();
|
||||
fout.close();
|
||||
return 0;
|
||||
}
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script generates the following files:
|
||||
#
|
||||
# - long.c.txt
|
||||
# - long_signed.c.txt
|
||||
# - long_decimal.c.txt
|
||||
# - long_signed_decimal.c.txt
|
||||
# - hashes.cmake
|
||||
#
|
||||
# Run with --very-long to generate the following additional files:
|
||||
#
|
||||
# - very_long_params.cmake
|
||||
#
|
||||
# Any changes to those files should be made here, and then the script rerun.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly dir="$(realpath "$(dirname "$0")")"
|
||||
readonly jack_count="$(((1024 * 1024 * 1024 * 4 / 64) + 1))"
|
||||
readonly jack_byte_count="$((jack_count * 64))"
|
||||
|
||||
generate_very_long=0
|
||||
|
||||
for arg in "${@}"; do
|
||||
case "$arg" in
|
||||
--very-long)
|
||||
generate_very_long=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
random_bytes() {
|
||||
python3 -c '
|
||||
import random
|
||||
import sys
|
||||
|
||||
buf = random.Random(12345).randbytes(65536)
|
||||
for i in range(256):
|
||||
assert i in buf
|
||||
|
||||
sys.stdout.buffer.write(buf)
|
||||
'
|
||||
}
|
||||
|
||||
bin2c() {
|
||||
od -vtx1 -Anone -w32 \
|
||||
| awk '{ print toupper($0) }' \
|
||||
| sed -E \
|
||||
-e 's/^ / 0x/g' \
|
||||
-e 's/([0-9A-F]) ([0-9A-F])/\1, 0x\2/g' \
|
||||
-e 's/$/,/g' \
|
||||
-e '$ s/,$//g'
|
||||
}
|
||||
|
||||
bin2c_signed() {
|
||||
local sed_args=()
|
||||
local i
|
||||
for i in {128..255}; do
|
||||
sed_args+=(-e "$(python3 -c 'import sys; n = int(sys.argv[1]); print(f"s/ 0x{n:02X}/-0x{256-n:02X}/g")' "$i")")
|
||||
done
|
||||
bin2c | sed -E "${sed_args[@]}"
|
||||
}
|
||||
|
||||
bin2c_decimal() {
|
||||
local sed_args=()
|
||||
local i
|
||||
for i in {0..255}; do
|
||||
sed_args+=(-e "$(python3 -c 'import sys; n = int(sys.argv[1]); print(f"s/ 0x{n:02X}/{n: 4}/g")' "$i")")
|
||||
done
|
||||
bin2c | sed -E "${sed_args[@]}"
|
||||
}
|
||||
|
||||
bin2c_signed_decimal() {
|
||||
local sed_args=()
|
||||
local i
|
||||
for i in {0..127}; do
|
||||
sed_args+=(-e "$(python3 -c 'import sys; n = int(sys.argv[1]); print(f"s/ 0x{n:02X}/{n: 4}/g")' "$i")")
|
||||
done
|
||||
for i in {128..156}; do
|
||||
sed_args+=(-e "$(python3 -c 'import sys; n = int(sys.argv[1]); print(f"s/ 0x{n:02X}/-{256-n}/g")' "$i")")
|
||||
done
|
||||
for i in {157..246}; do
|
||||
sed_args+=(-e "$(python3 -c 'import sys; n = int(sys.argv[1]); print(f"s/ 0x{n:02X}/ -{256-n}/g")' "$i")")
|
||||
done
|
||||
for i in {247..255}; do
|
||||
sed_args+=(-e "$(python3 -c 'import sys; n = int(sys.argv[1]); print(f"s/ 0x{n:02X}/ -{256-n}/g")' "$i")")
|
||||
done
|
||||
bin2c | sed -E "${sed_args[@]}"
|
||||
}
|
||||
|
||||
cmake_hash() {
|
||||
local name="$1"
|
||||
echo " Computing ${name}_hash..." >&2
|
||||
local hash="$(sha256sum | cut -d' ' -f1)"
|
||||
echo "set(${name}_hash $hash)"
|
||||
}
|
||||
|
||||
very_long_c() {
|
||||
local nl="$1"
|
||||
echo -n "static unsigned char const array[] = {$nl"
|
||||
python3 -c '
|
||||
import sys
|
||||
|
||||
jack_count = int(sys.argv[1])
|
||||
nl = sys.argv[2]
|
||||
|
||||
def jack(trailing_comma):
|
||||
sys.stdout.buffer.write(
|
||||
(
|
||||
" "
|
||||
"0x20, 0x41, 0x6C, 0x6C, 0x20, 0x20, 0x20, 0x77, "
|
||||
"0x6F, 0x72, 0x6B, 0x20, 0x20, 0x20, 0x61, 0x6E, "
|
||||
"0x64, 0x20, 0x20, 0x20, 0x6E, 0x6F, 0x20, 0x20, "
|
||||
"0x20, 0x70, 0x6C, 0x61, 0x79, 0x20, 0x20, 0x20,"
|
||||
f"{nl}"
|
||||
" "
|
||||
"0x6D, 0x61, 0x6B, 0x65, 0x73, 0x20, 0x20, 0x20, "
|
||||
"0x4A, 0x61, 0x63, 0x6B, 0x20, 0x20, 0x20, 0x61, "
|
||||
"0x20, 0x20, 0x20, 0x64, 0x75, 0x6C, 0x6C, 0x20, "
|
||||
f"0x20, 0x20, 0x62, 0x6F, 0x79, 0x2E, 0x20, 0x0A{trailing_comma}"
|
||||
f"{nl}"
|
||||
).encode()
|
||||
)
|
||||
|
||||
for _ in range(jack_count - 1):
|
||||
jack(",")
|
||||
jack("")
|
||||
' "$jack_count" "$nl"
|
||||
echo -n "};$nl"
|
||||
echo -n "$nl"
|
||||
echo -n "static size_t const length = $jack_byte_count;$nl"
|
||||
}
|
||||
|
||||
echo "Generating long.c.txt..." >&2
|
||||
random_bytes | bin2c > "$dir/long.c.txt"
|
||||
|
||||
echo "Generating long_signed.c.txt..." >&2
|
||||
random_bytes | bin2c_signed > "$dir/long_signed.c.txt"
|
||||
|
||||
echo "Generating long_decimal.c.txt..." >&2
|
||||
random_bytes | bin2c_decimal > "$dir/long_decimal.c.txt"
|
||||
|
||||
echo "Generating long_signed_decimal.c.txt..." >&2
|
||||
random_bytes | bin2c_signed_decimal > "$dir/long_signed_decimal.c.txt"
|
||||
|
||||
echo "Generating hashes.cmake..." >&2
|
||||
(
|
||||
echo -en '# Automatically generated by generate_files.sh. Do not edit!\n\n'
|
||||
echo -en '\xFC\xFD\xFE\xFF\x00\x01\x02\x03' | cmake_hash basic
|
||||
echo -en '' | cmake_hash empty
|
||||
echo -en 'All work and no play makes Jack a dull boy.\n' | cmake_hash text_lf
|
||||
echo -en 'All work and no play makes Jack a dull boy.\r\n' | cmake_hash text_crlf
|
||||
echo -en 'This exactly 32 characters long!' | cmake_hash text_align
|
||||
random_bytes | cmake_hash long
|
||||
cat "$dir/long.c.txt" | cmake_hash long_c_lf
|
||||
cat "$dir/long.c.txt" | unix2dos | cmake_hash long_c_crlf
|
||||
cat "$dir/long_signed.c.txt" | cmake_hash long_signed_c_lf
|
||||
cat "$dir/long_signed.c.txt" | unix2dos | cmake_hash long_signed_c_crlf
|
||||
cat "$dir/long_decimal.c.txt" | cmake_hash long_decimal_c_lf
|
||||
cat "$dir/long_decimal.c.txt" | unix2dos | cmake_hash long_decimal_c_crlf
|
||||
cat "$dir/long_signed_decimal.c.txt" | cmake_hash long_signed_decimal_c_lf
|
||||
cat "$dir/long_signed_decimal.c.txt" | unix2dos | cmake_hash long_signed_decimal_c_crlf
|
||||
) > "$dir/hashes.cmake"
|
||||
|
||||
if [[ "$generate_very_long" == 1 ]]; then
|
||||
echo "Generating very_long_params.cmake..." >&2
|
||||
(
|
||||
echo -en '# Automatically generated by generate_files.sh. Do not edit!\n\n'
|
||||
echo "set(jack_count $jack_count)"
|
||||
python3 -c '
|
||||
import sys
|
||||
|
||||
for _ in range(int(sys.argv[1])):
|
||||
sys.stdout.buffer.write(b" All work and no play makes Jack a dull boy. \n")
|
||||
' "$jack_count" | cmake_hash very_long
|
||||
very_long_c $'\n' | cmake_hash very_long_c_lf
|
||||
very_long_c $'\r\n' | cmake_hash very_long_c_crlf
|
||||
) > "$dir/very_long_params.cmake"
|
||||
fi
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <fcntl.h> // for _O_BINARY
|
||||
# include <io.h> // for _setmode
|
||||
# include <stdio.h> // for _fileno
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
|
||||
for (unsigned long i = 0; i < JACK_COUNT; i++) {
|
||||
std::cout
|
||||
<< " All work and no play makes Jack a dull boy. \n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Automatically generated by generate_files.sh. Do not edit!
|
||||
|
||||
set(basic_hash 31ca2bb38aec879274fa64fafcb97acddd2d99fd819c53a7a9ae1348fbad2dfb)
|
||||
set(empty_hash e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)
|
||||
set(text_lf_hash 4489c0acf5973358718c763d3c20287308c7e31e3cd46fdc1a72c8cc0b0a5ef4)
|
||||
set(text_crlf_hash e09ddeeb9ac62ef0d166e6fb1fe7c61f10c3a762f95b041aaa165dddde85c5b3)
|
||||
set(text_align_hash b8a6df236221d02cc182d8b804ce9b1e81fd249315720285f6c76b334b79bb49)
|
||||
set(long_hash bddb0b20d82ce70b45ab5eea8b995b5167b0cd0d5d576f742dbc193c9ec2aaa4)
|
||||
set(long_c_lf_hash af57e8d44a0e3fb0c9a62fbaf7ab41b65defb2060b27e3ffa7dcd7b413dc5315)
|
||||
set(long_c_crlf_hash acd5a942383012686e6af4e70a7bee1b87d733471e62ee01819b5f9067d02c60)
|
||||
set(long_signed_c_lf_hash c672b69f369caa025ee2551af90c875f31ffad3a2ad25df4988bb9ff9502613b)
|
||||
set(long_signed_c_crlf_hash ecb581a199807dcdc3e4caf2dfe3b0726dd10433e9dbf77135758b17d50a47f9)
|
||||
set(long_decimal_c_lf_hash 1c9548162df08215a77d2d7a481c6ec3e5f183c4536eb5242815824b777593c6)
|
||||
set(long_decimal_c_crlf_hash dbb973461b30b508bec064cea682b49ce7a6e135ba75ca05b562205fae7b1a1e)
|
||||
set(long_signed_decimal_c_lf_hash a9478f529b0c93e871294a91f650c6594463646fb2f6909ec55325cd283548f1)
|
||||
set(long_signed_decimal_c_crlf_hash e1b9e2e2fc3b8aead92573ea4fee73e72e50f5efefda2cccce7b83dc7fdbe487)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^Could not open file for reading: "noexist\.bin"$
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
^CMake Error: Cannot open file for write: [^
|
||||
]*/Tests/RunCMake/cmake-E-bin2c/generate_binaries-build/not_a_dir/output_not_a_dir\.c\.txt\.tmp[^
|
||||
]*
|
||||
CMake Error: : System Error: (Not a directory|No such file or directory)
|
||||
Could not open file for writing: "not_a_dir/output_not_a_dir\.c\.txt"$
|
||||
@@ -0,0 +1,6 @@
|
||||
file(CONFIGURE
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/very_long_executables.cmake"
|
||||
CONTENT [==[set(generate_very_long [====[@GENERATE_VERY_LONG@]====])
|
||||
]==]
|
||||
@ONLY
|
||||
)
|
||||
@@ -0,0 +1,64 @@
|
||||
set(expected_output_file "${CMAKE_CURRENT_LIST_DIR}/${NAME}.c.txt")
|
||||
|
||||
function(run_bin2c output_file)
|
||||
execute_process(
|
||||
${ARGN}
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E compare_files --ignore-eol "${expected_output_file}" "${output_file}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
if(result)
|
||||
file(READ "${expected_output_file}" expected_output)
|
||||
file(READ "${output_file}" actual_output)
|
||||
string(REPLACE "\n" "\n " formatted_expected_output "${expected_output}")
|
||||
string(REPLACE "\n" "\n " formatted_actual_output "${actual_output}")
|
||||
set(formatted_binary_input)
|
||||
file(READ "${INPUT_FILE}" binary_contents HEX)
|
||||
string(LENGTH "${binary_contents}" binary_length)
|
||||
if(binary_length LESS 256)
|
||||
set(formatted_binary_input "\nHexadecimal contents of ${INPUT_FILE}:\n ${binary_contents}")
|
||||
endif()
|
||||
message(FATAL_ERROR "${output_file} does not match ${expected_output_file}.\nExpected output:\n ${formatted_expected_output}\nActual output:\n ${formatted_actual_output}${formatted_binary_input}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-no-input-arg-no-output-arg.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS}
|
||||
INPUT_FILE "${INPUT_FILE}"
|
||||
OUTPUT_FILE "${output_file}"
|
||||
)
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-stdin-no-output-arg.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS} -
|
||||
INPUT_FILE "${INPUT_FILE}"
|
||||
OUTPUT_FILE "${output_file}"
|
||||
)
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-input-file-no-output-arg.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS} "${INPUT_FILE}"
|
||||
OUTPUT_FILE "${output_file}"
|
||||
)
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-stdin-stdout.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS} - -
|
||||
INPUT_FILE "${INPUT_FILE}"
|
||||
OUTPUT_FILE "${output_file}"
|
||||
)
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-input-file-stdout.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS} "${INPUT_FILE}" -
|
||||
OUTPUT_FILE "${output_file}"
|
||||
)
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-stdin-output-file.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS} - "${output_file}"
|
||||
INPUT_FILE "${INPUT_FILE}"
|
||||
)
|
||||
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/${NAME}-input-file-output-file.c.txt")
|
||||
run_bin2c("${output_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E bin2c ${ARGS} "${INPUT_FILE}" "${output_file}"
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
-0x04,-0x03,-0x02,-0x01, 0x00, 0x01, 0x02, 0x03
|
||||
@@ -0,0 +1 @@
|
||||
-4, -3, -2, -1, 0, 1, 2, 3
|
||||
@@ -0,0 +1,6 @@
|
||||
static unsigned char const array[] = {@array@};
|
||||
|
||||
static size_t const length = @length@;
|
||||
static size_t const @length2 = @length@ull;
|
||||
static int const unclosed = @array
|
||||
static int const other = @other@;
|
||||
@@ -0,0 +1,8 @@
|
||||
static unsigned char const array[] = {
|
||||
0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03
|
||||
};
|
||||
|
||||
static size_t const length = 8;
|
||||
static size_t const @length2 = 8ull;
|
||||
static int const unclosed = @array
|
||||
static int const other = @other@;
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^Cannot print array twice$
|
||||
@@ -0,0 +1,2 @@
|
||||
@array@
|
||||
@array@
|
||||
@@ -0,0 +1,6 @@
|
||||
static unsigned char const array[] = {};
|
||||
|
||||
static size_t const length = 0;
|
||||
static size_t const @length2 = 0ull;
|
||||
static int const unclosed = @array
|
||||
static int const other = @other@;
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,3 @@
|
||||
^Invalid array placeholder name: "array\*"
|
||||
|
||||
bin2c Usage: -E bin2c \[<options>\.\.\.\] \[--\] \[<input-file> \[<output-file>\]\]$
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,3 @@
|
||||
^Invalid length placeholder name: "length\*"
|
||||
|
||||
bin2c Usage: -E bin2c \[<options>\.\.\.\] \[--\] \[<input-file> \[<output-file>\]\]$
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^Cannot print length before array$
|
||||
@@ -0,0 +1,3 @@
|
||||
static size_t const length = @length@;
|
||||
|
||||
static unsigned char const array[] = {@array@};
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^Could not open template file for reading: "noexist.c.in.txt"$
|
||||
@@ -0,0 +1,5 @@
|
||||
static unsigned char const array[] = {@arr@};
|
||||
static unsigned char const array2[] = {@array@};
|
||||
|
||||
static size_t const length = @len@;
|
||||
static size_t const length2 = @length@;
|
||||
@@ -0,0 +1,7 @@
|
||||
static unsigned char const array[] = {
|
||||
0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03
|
||||
};
|
||||
static unsigned char const array2[] = {@array@};
|
||||
|
||||
static size_t const length = 8;
|
||||
static size_t const length2 = @length@;
|
||||
@@ -0,0 +1,8 @@
|
||||
static unsigned char const array[] = {
|
||||
0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03,
|
||||
};
|
||||
|
||||
static size_t const length = 8;
|
||||
static size_t const @length2 = 8ull;
|
||||
static int const unclosed = @array
|
||||
static int const other = @other@;
|
||||
@@ -0,0 +1 @@
|
||||
0x54, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6C, 0x79, 0x20, 0x33, 0x32, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x21
|
||||
@@ -0,0 +1,2 @@
|
||||
0x41, 0x6C, 0x6C, 0x20, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6E, 0x6F, 0x20, 0x70, 0x6C, 0x61, 0x79, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x73, 0x20, 0x4A, 0x61, 0x63, 0x6B, 0x20,
|
||||
0x61, 0x20, 0x64, 0x75, 0x6C, 0x6C, 0x20, 0x62, 0x6F, 0x79, 0x2E, 0x0D, 0x0A
|
||||
@@ -0,0 +1,2 @@
|
||||
0x41, 0x6C, 0x6C, 0x20, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6E, 0x6F, 0x20, 0x70, 0x6C, 0x61, 0x79, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x73, 0x20, 0x4A, 0x61, 0x63, 0x6B, 0x20,
|
||||
0x61, 0x20, 0x64, 0x75, 0x6C, 0x6C, 0x20, 0x62, 0x6F, 0x79, 0x2E, 0x0A
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^bin2c Usage: -E bin2c \[<options>\.\.\.\] \[--\] \[<input-file> \[<output-file>\]\]$
|
||||
@@ -0,0 +1 @@
|
||||
0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03,
|
||||
@@ -0,0 +1 @@
|
||||
0x54, 0x68, 0x69, 0x73, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6C, 0x79, 0x20, 0x33, 0x32, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x21,
|
||||
@@ -0,0 +1,4 @@
|
||||
file(SHA256 "${FILENAME}" hash)
|
||||
if(NOT hash STREQUAL "${SHA256SUM}")
|
||||
message(FATAL_ERROR "Expected hash of ${FILENAME}:\n ${SHA256SUM}\nActual hash:\n ${hash}")
|
||||
endif()
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <string.h>
|
||||
|
||||
unsigned char const long_unsigned[] = {
|
||||
#include "long.c.txt"
|
||||
};
|
||||
|
||||
char const long_signed[] = {
|
||||
#include "long_signed.c.txt"
|
||||
};
|
||||
|
||||
unsigned char const long_decimal[] = {
|
||||
#include "long_decimal.c.txt"
|
||||
};
|
||||
|
||||
char const long_signed_decimal[] = {
|
||||
#include "long_signed_decimal.c.txt"
|
||||
};
|
||||
|
||||
#define VERIFY(contents) \
|
||||
do { \
|
||||
if (sizeof(long_unsigned) != sizeof(contents)) { \
|
||||
return 1; \
|
||||
} \
|
||||
if (memcmp(long_unsigned, contents, sizeof(contents))) { \
|
||||
return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
VERIFY(long_signed);
|
||||
VERIFY(long_decimal);
|
||||
VERIFY(long_signed_decimal);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
execute_process(
|
||||
COMMAND "${GENERATE_VERY_LONG}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E sha256sum -
|
||||
OUTPUT_VARIABLE output
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
string(SUBSTRING "${output}" 0 64 actual_sha256sum)
|
||||
if(NOT actual_sha256sum STREQUAL SHA256SUM)
|
||||
message(FATAL_ERROR "Expected sha256sum for generate_very_long output:\n ${SHA256SUM}\nActual sha256sum:\n ${actual_sha256sum}")
|
||||
endif()
|
||||
@@ -0,0 +1,3 @@
|
||||
static unsigned char const array[] = {@array@};
|
||||
|
||||
static size_t const length = @length@;
|
||||
@@ -0,0 +1,14 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/very_long_params.cmake")
|
||||
include("${CMAKE_CURRENT_BINARY_DIR}/very_long_executables.cmake")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${generate_very_long}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E bin2c --template-file "${CMAKE_CURRENT_LIST_DIR}/very_long.c.in.txt"
|
||||
COMMAND "${CMAKE_COMMAND}" -E sha256sum -
|
||||
OUTPUT_VARIABLE output
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
string(SUBSTRING "${output}" 0 64 actual_hash)
|
||||
if(NOT actual_hash STREQUAL very_long_c_lf_hash AND NOT actual_hash STREQUAL very_long_c_crlf_hash)
|
||||
message(FATAL_ERROR "Expected hash of output to be ${very_long_c_lf_hash} or ${very_long_c_crlf_hash}, got ${actual_hash}")
|
||||
endif()
|
||||
@@ -0,0 +1,6 @@
|
||||
# Automatically generated by generate_files.sh. Do not edit!
|
||||
|
||||
set(jack_count 67108865)
|
||||
set(very_long_hash 2a380908971dada85a00911e27ec09e3d7b2bb06d8ae27666124b4f1e083c789)
|
||||
set(very_long_c_lf_hash 9bc3b09a80513e68a56dac9c69b0151cc6fa663c41df6e1b0435c96e16629d37)
|
||||
set(very_long_c_crlf_hash 7049e591c1acbe404b521026924392389a7c29f80c69dc6ce56596d800e7462f)
|
||||
@@ -12,6 +12,9 @@
|
||||
#if defined(CMake_HAVE_CXX_OPTIONAL)
|
||||
# include <optional> // IWYU pragma: export
|
||||
#else
|
||||
# if defined(__GNUC__) && !defined(__clang__)
|
||||
# include <cstring>
|
||||
# endif
|
||||
# include <memory>
|
||||
|
||||
# include <cm/utility>
|
||||
@@ -121,7 +124,13 @@ private:
|
||||
T value;
|
||||
|
||||
// Explicit constructor and destructor is required to make this work
|
||||
_mem_union() noexcept {}
|
||||
_mem_union() noexcept
|
||||
{
|
||||
# if defined(__GNUC__) && !defined(__clang__)
|
||||
// Some versions of GCC complain about uninitialized memory
|
||||
std::memset(this, 0, sizeof(*this));
|
||||
# endif
|
||||
}
|
||||
~_mem_union() noexcept {}
|
||||
} _mem;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user