[cmake] replace custom file2hex tool

Use CMake to read file and convert to C array of hex values
This commit is contained in:
akallabeth 2024-09-25 06:55:21 +02:00
parent f3055f9644
commit fe590801a1
No known key found for this signature in database
GPG Key ID: A49454A3FC909FD5
5 changed files with 89 additions and 214 deletions

View File

@ -15,27 +15,33 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if(CMAKE_CROSSCOMPILING)
find_package(SdlCommonRes2bin)
else()
add_executable(sdl-common-res2bin
convert_res_to_c.cpp
)
export(TARGETS sdl-common-res2bin FILE
"${CMAKE_BINARY_DIR}/SdlCommonRes2binConfig.cmake")
endif()
set(FACTORY_SRCS "")
set(FACTORY_HDR "")
set(FACTORY_CLASSES "")
include(ConvertFileToHexArray)
macro(convert_to_bin FILE FILE_TYPE)
get_filename_component(FILE_NAME ${FILE} NAME)
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" TARGET_NAME ${FILE_NAME})
set(FILE_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin)
set(FILE_BYPRODUCTS ${FILE_BIN_DIR}/${TARGET_NAME}.hpp ${FILE_BIN_DIR}/${TARGET_NAME}.cpp)
set(FILENAME ${FILE_NAME})
set(CLASSNAME ${TARGET_NAME})
set(CLASSTYPE ${FILE_TYPE})
file_to_hex_array("${FILE}" FILEDATA)
configure_file(resource.hpp.in
${FILE_BIN_DIR}/${TARGET_NAME}.hpp
@ONLY
)
configure_file(resource.cpp.in
${FILE_BIN_DIR}/${TARGET_NAME}.cpp
@ONLY
)
list(APPEND FACTORY_HDR
${FILE_BIN_DIR}/${TARGET_NAME}.hpp
@ -44,17 +50,8 @@ macro(convert_to_bin FILE FILE_TYPE)
${FILE_BIN_DIR}/${TARGET_NAME}.cpp
)
list(APPEND FACTORY_CLASSES
${TARGET_NAME}
)
add_custom_command(
OUTPUT ${FILE_BYPRODUCTS}
COMMAND ${CMAKE_COMMAND} -E make_directory ${FILE_BIN_DIR}
COMMAND $<TARGET_FILE:sdl-common-res2bin> ${FILE} ${FILE_TYPE} ${TARGET_NAME} ${FILE_BIN_DIR}
COMMENT "create image resources"
DEPENDS sdl-common-res2bin
DEPENDS ${FILE}
list(APPEND FACTORY_CLASSES
${TARGET_NAME}
)
endmacro()

View File

@ -1,191 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <fstream>
#include <algorithm>
#include <iomanip>
#include <iostream>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
#endif
static void usage(const char* prg)
{
std::cerr << prg << " <file> <type> <class name> <dst path>" << std::endl;
}
static int write_comment_header(std::ostream& out, const fs::path& prg, const std::string& fname)
{
out << "/* AUTOGENERATED file, do not edit" << std::endl
<< " *" << std::endl
<< " * generated by '" << prg.filename() << "'" << std::endl
<< " *" << std::endl
<< " * contains the converted file '" << fname << "'" << std::endl
<< " */" << std::endl
<< std::endl;
return 0;
}
static int write_cpp_header(std::ostream& out, const fs::path& prg, const fs::path& file,
const std::string& name, const std::string& type)
{
auto fname = file.filename().string();
auto rc = write_comment_header(out, prg, fname);
if (rc != 0)
return rc;
out << "#include <vector>" << std::endl
<< "#include \"" << name << ".hpp\"" << std::endl
<< std::endl
<< "std::string " << name << "::name() {" << std::endl
<< "return \"" << fname << "\";" << std::endl
<< "}" << std::endl
<< "std::string " << name << "::type() {" << std::endl
<< "return \"" << type << "\";" << std::endl
<< "}" << std::endl
<< std::endl
<< "const SDLResourceFile " << name << "::_initializer(type(), name(), init());"
<< std::endl
<< std::endl
<< "std::vector<unsigned char> " << name << "::init() {" << std::endl
<< "static const unsigned char data[] = {" << std::endl;
return 0;
}
static int readwrite(std::ofstream& out, std::ifstream& ifs)
{
size_t pos = 0;
char c = 0;
std::ios backup(nullptr);
backup.copyfmt(out);
while (ifs.read(&c, 1) && ifs.good())
{
unsigned val = c & 0xff;
out << "0x" << std::hex << std::setfill('0') << std::setw(2) << val;
if (ifs.peek() != EOF)
out << ",";
if ((pos++ % 16) == 15)
out << std::endl;
}
out.copyfmt(backup);
return 0;
}
static int write_cpp_trailer(std::ostream& out)
{
out << std::endl;
out << "};" << std::endl;
out << std::endl;
out << "return std::vector<unsigned char>(data, data + sizeof(data));" << std::endl;
out << "}" << std::endl;
return 0;
}
static int write_hpp_header(const fs::path& prg, const fs::path& file, const std::string& name,
const std::string& fname)
{
std::ofstream out(file, std::ios::out);
if (!out.is_open())
{
std::cerr << "Failed to open output file '" << file << "'" << std::endl;
return -1;
}
auto rc = write_comment_header(out, prg, fname);
if (rc != 0)
return rc;
out << "#pragma once" << std::endl
<< std::endl
<< "#include <vector>" << std::endl
<< "#include <string>" << std::endl
<< "#include \"sdl_resource_file.hpp\"" << std::endl
<< std::endl
<< "class " << name << " {" << std::endl
<< "friend class SDLResourceManager;" << std::endl
<< "public:" << std::endl
<< name << "() = delete;" << std::endl
<< std::endl
<< "static std::string name();" << std::endl
<< "static std::string type();" << std::endl
<< std::endl
<< "protected:" << std::endl
<< "static std::vector<unsigned char> init();" << std::endl
<< "static const SDLResourceFile _initializer;" << std::endl
<< std::endl
<< "};" << std::endl;
return 0;
}
int main(int argc, char* argv[])
{
fs::path prg(argv[0]);
if (argc != 5)
{
usage(argv[0]);
return -1;
}
fs::path file(argv[1]);
std::string etype = argv[2];
std::string cname = argv[3];
fs::path dst(argv[4]);
fs::path hdr(argv[4]);
dst /= cname + ".cpp";
hdr /= cname + ".hpp";
std::ofstream out;
out.open(dst);
if (!out.is_open())
{
std::cerr << "Failed to open output file '" << dst << "'" << std::endl;
return -2;
}
std::ifstream ifs(file, std::ios::in | std::ios::binary);
if (!ifs.is_open())
{
std::cerr << "Failed to open input file '" << file << "'" << std::endl;
return -3;
}
auto rc = write_cpp_header(out, prg, file, cname, etype);
if (rc != 0)
return -1;
rc = readwrite(out, ifs);
if (rc != 0)
return rc;
rc = write_cpp_trailer(out);
if (rc != 0)
return rc;
return write_hpp_header(prg, hdr, cname, file.filename().string());
}

View File

@ -0,0 +1,26 @@
/* AUTOGENERATED file, do not edit
*
* part of @PROJECT_NAME@
* generated by 'CMake' from common/res/resource.cpp.in
*
* contains the converted file '@FILENAME@'
*/
#include <vector>
#include "@CLASSNAME@.hpp"
std::string @CLASSNAME@::name() {
return "@FILENAME@";
}
std::string @CLASSNAME@::type() {
return "@CLASSTYPE@";
}
const SDLResourceFile @CLASSNAME@::_initializer(type(), name(), init());
std::vector<unsigned char> @CLASSNAME@::init() {
static const unsigned char data[] = {
@FILEDATA@
};
return std::vector<unsigned char>(data, data + sizeof(data));
}

View File

@ -0,0 +1,27 @@
/* AUTOGENERATED file, do not edit
*
* part of @PROJECT_NAME@
* generated by 'CMake' from common/res/resource.hpp.in
*
* contains the converted file '@FILENAME@'
*/
#pragma once
#include <vector>
#include <string>
#include "sdl_resource_file.hpp"
class @CLASSNAME@
{
friend class SDLResourceManager;
public:
@CLASSNAME@() = delete;
static std::string name();
static std::string type();
protected:
static std::vector<unsigned char> init();
static const SDLResourceFile _initializer;
};

View File

@ -0,0 +1,16 @@
function(file_to_hex_array FILE DATA)
# Read the ASCII file as hex.
file(READ "${FILE}" HEX_CONTENTS HEX)
# Separate into individual bytes.
string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" SEPARATED_HEX "${HEX_CONTENTS}")
# Append the "0x" to each byte.
list(JOIN SEPARATED_HEX ", 0x" FORMATTED_HEX)
# JOIN misses the first byte's "0x", so add it here.
string(PREPEND FORMATTED_HEX "0x")
# Set the variable named by DATA argument to the formatted hex string.
set(${DATA} ${FORMATTED_HEX} PARENT_SCOPE)
endfunction()