Port to cmkr and macos

This commit is contained in:
Duncan Ogilvie 2023-11-27 14:02:37 +01:00
parent 8e19f7ce0d
commit b24d73c7b7
9 changed files with 445 additions and 55 deletions

3
.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
# cmkr
/**/CMakeLists.txt linguist-generated
/**/cmkr.cmake linguist-vendored

6
.gitignore vendored
View File

@ -10,3 +10,9 @@ expected.out
cmake-build*/ cmake-build*/
build*/ build*/
.idea/ .idea/
.cache/
*.pp.h
# cmkr
CMakerLists.txt
CMakeLists.txt.user

80
CMakeLists.txt generated Normal file
View File

@ -0,0 +1,80 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/build-cpp/cmkr for more information
cmake_minimum_required(VERSION 3.15)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
endif()
set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMKR_ROOT_PROJECT ON)
# Bootstrap cmkr and automatically regenerate CMakeLists.txt
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
# Enable folder support
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Create a configure-time dependency on cmake.toml to improve IDE support
configure_file(cmake.toml cmake.toml COPYONLY)
endif()
project(btparser)
# Target: btparser
set(btparser_SOURCES
"btparser/lexer.cpp"
"btparser/preprocessor.cpp"
"btparser/types.cpp"
"btparser/typesparser.cpp"
"btparser/ast.h"
"btparser/helpers.h"
"btparser/keywords.h"
"btparser/lexer.h"
"btparser/operators.h"
"btparser/preprocessor.h"
"btparser/testfiles.h"
"btparser/types.h"
cmake.toml
)
add_library(btparser STATIC)
target_sources(btparser PRIVATE ${btparser_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${btparser_SOURCES})
target_compile_features(btparser PUBLIC
cxx_std_14
)
target_include_directories(btparser PUBLIC
btparser
)
# Target: test
if(CMKR_ROOT_PROJECT) # root
set(test_SOURCES
"btparser/main.cpp"
cmake.toml
)
add_executable(test)
target_sources(test PRIVATE ${test_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${test_SOURCES})
target_link_libraries(test PRIVATE
btparser
)
get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
if(NOT CMKR_VS_STARTUP_PROJECT)
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT test)
endif()
endif()

View File

@ -2,9 +2,33 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <windows.h>
#include <cstdint> #include <cstdint>
#ifdef _WIN32
#include <windows.h>
#else
#endif // _WIN32
#if defined(_MSC_VER)
#include <intrin.h>
#elif defined(__clang__)
#define __debugbreak() __builtin_debugtrap()
#elif defined(__GNUC__)
#define __debugbreak() __builtin_trap()
#else
#warning Unsupported platform/compiler
#include <signal.h>
#define __debugbreak() raise(SIGTRAP)
#endif // _MSC_VER
#ifndef _MSC_VER
template<size_t Count, typename... Args>
static int sprintf_s(char (&dst)[Count], const char* fmt, Args&&... args)
{
return snprintf(dst, Count, fmt, std::forward<Args>(args)...);
}
#endif // _MSC_VER
namespace StringUtils namespace StringUtils
{ {
inline std::string sprintf(const char* format, ...) inline std::string sprintf(const char* format, ...)
@ -14,7 +38,11 @@ namespace StringUtils
std::vector<char> buffer(256, '\0'); std::vector<char> buffer(256, '\0');
while(true) while(true)
{ {
#ifdef _WIN32
int res = _vsnprintf_s(buffer.data(), buffer.size(), _TRUNCATE, format, args); int res = _vsnprintf_s(buffer.data(), buffer.size(), _TRUNCATE, format, args);
#else
int res = vsnprintf(buffer.data(), buffer.size(), format, args);
#endif // _WIN32
if(res == -1) if(res == -1)
{ {
buffer.resize(buffer.size() * 2); buffer.resize(buffer.size() * 2);
@ -52,7 +80,9 @@ namespace StringUtils
return "\\\""; return "\\\"";
default: default:
if(!isprint(ch)) //unknown unprintable character if(!isprint(ch)) //unknown unprintable character
{
sprintf_s(buf, "\\x%02X", ch); sprintf_s(buf, "\\x%02X", ch);
}
else else
*buf = ch; *buf = ch;
return buf; return buf;
@ -65,19 +95,7 @@ namespace StringUtils
return escaped; return escaped;
} }
inline std::string Utf16ToUtf8(const std::wstring & wstr) #ifdef _WIN32
{
std::string convertedString;
auto requiredSize = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
if(requiredSize > 0)
{
std::vector<char> buffer(requiredSize);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &buffer[0], requiredSize, nullptr, nullptr);
convertedString.assign(buffer.begin(), buffer.end() - 1);
}
return convertedString;
}
inline std::wstring Utf8ToUtf16(const std::string & str) inline std::wstring Utf8ToUtf16(const std::string & str)
{ {
std::wstring convertedString; std::wstring convertedString;
@ -90,6 +108,7 @@ namespace StringUtils
} }
return convertedString; return convertedString;
} }
#endif // _WIN32
inline void Split(const std::string& s, char delim, std::vector<std::string>& elems) inline void Split(const std::string& s, char delim, std::vector<std::string>& elems)
{ {
@ -119,42 +138,44 @@ namespace StringUtils
} }
}; };
#include <fstream>
namespace FileHelper namespace FileHelper
{ {
inline bool ReadAllData(const std::string & fileName, std::vector<uint8_t> & content) inline bool ReadAllData(const std::string & fileName, std::vector<uint8_t> & content)
{ {
auto hFile = CreateFileW(StringUtils::Utf8ToUtf16(fileName).c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); std::ifstream file(fileName, std::ios::binary);
auto result = false;
if(hFile != INVALID_HANDLE_VALUE) if (!file.is_open())
{ {
unsigned int filesize = GetFileSize(hFile, nullptr); return false;
if(!filesize)
{
content.clear();
result = true;
} }
else
{ // Get the size of the file
content.resize(filesize); file.seekg(0, std::ios::end);
DWORD read = 0; std::streampos fileSize = file.tellg();
result = !!ReadFile(hFile, content.data(), filesize, &read, nullptr); file.seekg(0, std::ios::beg);
}
CloseHandle(hFile); // Resize the vector to fit the entire file
} content.resize(static_cast<size_t>(fileSize));
return result;
// Read the file into the vector
file.read(reinterpret_cast<char*>(&content[0]), fileSize);
return !file.bad();
} }
inline bool WriteAllData(const std::string & fileName, const void* data, size_t size) inline bool WriteAllData(const std::string & fileName, const void* data, size_t size)
{ {
auto hFile = CreateFileW(StringUtils::Utf8ToUtf16(fileName).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr); std::ofstream file(fileName, std::ios::binary);
auto result = false;
if(hFile != INVALID_HANDLE_VALUE) if (!file.is_open())
{ {
DWORD written = 0; return false;
result = !!WriteFile(hFile, data, DWORD(size), &written, nullptr);
CloseHandle(hFile);
} }
return result;
// Write the data to the file
file.write(static_cast<const char*>(data), size);
return !file.bad();
} }
inline bool ReadAllText(const std::string & fileName, std::string & content) inline bool ReadAllText(const std::string & fileName, std::string & content)

View File

@ -1,8 +1,8 @@
#include "lexer.h" #include "lexer.h"
#include <cctype>
#include <windows.h>
#include "helpers.h" #include "helpers.h"
#include <cctype>
#define MAKE_OP_TRIPLE(ch1, ch2, ch3) (ch3 << 16 | ch2 << 8 | ch1) #define MAKE_OP_TRIPLE(ch1, ch2, ch3) (ch3 << 16 | ch2 << 8 | ch1)
#define MAKE_OP_DOUBLE(ch1, ch2) (ch2 << 8 | ch1) #define MAKE_OP_DOUBLE(ch1, ch2) (ch2 << 8 | ch1)
#define MAKE_OP_SINGLE(ch1) (ch1) #define MAKE_OP_SINGLE(ch1) (ch1)

View File

@ -1,11 +1,10 @@
#include <windows.h>
#include <stdio.h>
#include "testfiles.h" #include "testfiles.h"
#include "lexer.h" #include "lexer.h"
#include "parser.h"
#include "helpers.h" #include "helpers.h"
#include "preprocessor.h" #include "preprocessor.h"
#include "types.h" #include "types.h"
#include <stdio.h>
#include <unordered_set> #include <unordered_set>
bool TestLexer(Lexer& lexer, const std::string& filename) bool TestLexer(Lexer& lexer, const std::string& filename)
@ -156,7 +155,7 @@ static void HandleVTable(Types::Model& model)
bool DebugParser(const std::string& filename) bool DebugParser(const std::string& filename)
{ {
std::string data; std::string data;
if (!FileHelper::ReadAllText("tests\\" + filename, data)) if (!FileHelper::ReadAllText(filename, data))
{ {
printf("Failed to read: %s\n", filename.c_str()); printf("Failed to read: %s\n", filename.c_str());
return false; return false;
@ -173,7 +172,14 @@ bool DebugParser(const std::string& filename)
return false; return false;
} }
FileHelper::WriteAllText("tests\\" + filename + ".pp.h", ppData); auto basename = filename;
auto lastSlashIdx = basename.find_last_of("\\/");
if(lastSlashIdx != std::string::npos)
{
basename = basename.substr(lastSlashIdx + 1);
}
FileHelper::WriteAllText(basename + ".pp.h", ppData);
std::vector<std::string> errors; std::vector<std::string> errors;
Types::Model model; Types::Model model;
@ -191,15 +197,13 @@ bool DebugParser(const std::string& filename)
return true; return true;
} }
int main() int main(int argc, char** argv)
{ {
//GenerateExpectedTests(); if(argc < 2)
auto ticks = GetTickCount(); {
DebugParser("cursor.hpp"); printf("Usage: test my.h\n");
//Lexer lexer; return EXIT_FAILURE;
//DebugLexer(lexer, "AndroidManifestTemplate.bt", false); }
//RunLexerTests(); DebugParser(argv[1]);
printf("finished in %ums\n", (unsigned int)(GetTickCount() - ticks)); return EXIT_SUCCESS;
system("pause");
return 0;
} }

View File

@ -1,9 +1,11 @@
#include "types.h" #include "types.h"
#include "helpers.h" #include "helpers.h"
#include <algorithm> #include <algorithm>
#include <unordered_set> #include <unordered_set>
#include <ctime> #include <ctime>
using namespace Types; using namespace Types;
#define EXCLUSIVE_ACQUIRE(x) #define EXCLUSIVE_ACQUIRE(x)

21
cmake.toml Normal file
View File

@ -0,0 +1,21 @@
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[project]
name = "btparser"
[target.btparser]
type = "static"
sources = [
"btparser/lexer.cpp",
"btparser/preprocessor.cpp",
"btparser/types.cpp",
"btparser/typesparser.cpp",
]
headers = ["btparser/*.h"]
include-directories = ["btparser"]
compile-features = ["cxx_std_14"]
[target.test]
condition = "root"
type = "executable"
sources = ["btparser/main.cpp"]
link-libraries = ["btparser"]

253
cmkr.cmake vendored Normal file
View File

@ -0,0 +1,253 @@
include_guard()
# Change these defaults to point to your infrastructure if desired
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "v0.2.26" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
if(CMAKE_SCRIPT_MODE_FILE)
set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build")
set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}")
endif()
# Set these from the command line to customize for development/debugging purposes
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration")
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
# Disable cmkr if generation is disabled
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
message(STATUS "[cmkr] Skipping automatic cmkr generation")
unset(CMKR_BUILD_SKIP_GENERATION CACHE)
macro(cmkr)
endmacro()
return()
endif()
# Disable cmkr if no cmake.toml file is found
if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
macro(cmkr)
endmacro()
return()
endif()
# Convert a Windows native path to CMake path
if(CMKR_EXECUTABLE MATCHES "\\\\")
string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE)
unset(CMKR_EXECUTABLE_CMAKE)
endif()
# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher)
function(cmkr_exec)
execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})")
endif()
endfunction()
# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment)
if(WIN32)
set(CMKR_EXECUTABLE_NAME "cmkr.exe")
else()
set(CMKR_EXECUTABLE_NAME "cmkr")
endif()
# Use cached cmkr if found
if(DEFINED ENV{CMKR_CACHE})
set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}")
string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$")
set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/")
endif()
# Build in release mode for the cache
set(CMKR_BUILD_TYPE "Release")
else()
set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_")
endif()
set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}")
set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}")
# Helper function to check if a string starts with a prefix
# Cannot use MATCHES, see: https://github.com/build-cpp/cmkr/issues/61
function(cmkr_startswith str prefix result)
string(LENGTH "${prefix}" prefix_length)
string(LENGTH "${str}" str_length)
if(prefix_length LESS_EQUAL str_length)
string(SUBSTRING "${str}" 0 ${prefix_length} str_prefix)
if(prefix STREQUAL str_prefix)
set("${result}" ON PARENT_SCOPE)
return()
endif()
endif()
set("${result}" OFF PARENT_SCOPE)
endfunction()
# Handle upgrading logic
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD)
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMKR_DIRECTORY_PREFIX}" CMKR_STARTSWITH_CACHE)
if(CMKR_STARTSWITH_BUILD)
if(DEFINED ENV{CMKR_CACHE})
message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'")
if(EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
else()
unset(CMKR_EXECUTABLE CACHE)
endif()
else()
message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE)
endif()
elseif(DEFINED ENV{CMKR_CACHE} AND CMKR_STARTSWITH_CACHE)
message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE)
endif()
endif()
if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}")
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE)
message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found")
elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'")
else()
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
message(STATUS "[cmkr] Fetching cmkr...")
if(EXISTS "${CMKR_DIRECTORY}")
cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}")
endif()
find_package(Git QUIET REQUIRED)
cmkr_exec("${GIT_EXECUTABLE}"
clone
--config advice.detachedHead=false
--branch ${CMKR_TAG}
--depth 1
${CMKR_REPO}
"${CMKR_DIRECTORY}"
)
if(CMKR_COMMIT_HASH)
execute_process(
COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}"
RESULT_VARIABLE CMKR_EXEC_RESULT
WORKING_DIRECTORY "${CMKR_DIRECTORY}"
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'")
endif()
endif()
message(STATUS "[cmkr] Building cmkr (using system compiler)...")
cmkr_exec("${CMAKE_COMMAND}"
--no-warn-unused-cli
"${CMKR_DIRECTORY}"
"-B${CMKR_DIRECTORY}/build"
"-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}"
"-DCMAKE_UNITY_BUILD=ON"
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
)
cmkr_exec("${CMAKE_COMMAND}"
--build "${CMKR_DIRECTORY}/build"
--config "${CMKR_BUILD_TYPE}"
--parallel
)
cmkr_exec("${CMAKE_COMMAND}"
--install "${CMKR_DIRECTORY}/build"
--config "${CMKR_BUILD_TYPE}"
--prefix "${CMKR_DIRECTORY}"
--component cmkr
)
if(NOT EXISTS ${CMKR_EXECUTABLE})
message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'")
endif()
cmkr_exec("${CMKR_EXECUTABLE}" version)
message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}")
endif()
execute_process(COMMAND "${CMKR_EXECUTABLE}" version
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
endif()
# Use cmkr.cmake as a script
if(CMAKE_SCRIPT_MODE_FILE)
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
execute_process(COMMAND "${CMKR_EXECUTABLE}" init
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new")
else()
message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build")
endif()
else()
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to generate project.")
else()
message(STATUS "[cmkr] Configure using: cmake -B build")
endif()
endif()
endif()
# This is the macro that contains black magic
macro(cmkr)
# When this macro is called from the generated file, fake some internal CMake variables
get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE)
if(CMKR_CURRENT_LIST_FILE)
set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}")
get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
endif()
# File-based include guard (include_guard is not documented to work)
get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD)
if(NOT CMKR_INCLUDE_GUARD)
set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE)
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE)
# Generate CMakeLists.txt
cmkr_exec("${CMKR_EXECUTABLE}" gen
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST)
# Delete the temporary file if it was left for some reason
set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt")
if(EXISTS "${CMKR_TEMP_FILE}")
file(REMOVE "${CMKR_TEMP_FILE}")
endif()
if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST)
# Copy the now-generated CMakeLists.txt to CMakerLists.txt
# This is done because you cannot include() a file you are currently in
configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY)
# Add the macro required for the hack at the start of the cmkr macro
set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES
CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}"
)
# 'Execute' the newly-generated CMakeLists.txt
include("${CMKR_TEMP_FILE}")
# Delete the generated file
file(REMOVE "${CMKR_TEMP_FILE}")
# Do not execute the rest of the original CMakeLists.txt
return()
endif()
# Resume executing the unmodified CMakeLists.txt
endif()
endmacro()