Add CMake project

This commit is contained in:
Duncan Ogilvie 2026-04-12 16:37:54 +02:00
parent 118945fbef
commit 84f8943a6e
15 changed files with 2845 additions and 369 deletions

3
.gitattributes vendored Normal file
View File

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

7
.gitignore vendored
View File

@ -9,3 +9,10 @@ docs/
.vs/
*.VC.db
*.aps
# cmkr
build*/
cmake-build*/
CMakerLists.txt
CMakeLists.txt.user
CMakeUserPresets.json

201
CMakeLists.txt generated Normal file
View File

@ -0,0 +1,201 @@
# 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
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS cmake.toml)
endif()
# Options
option(GLEEBUG_RESOURCES "" ON)
project(GleeBug
LANGUAGES
C
CXX
)
# Target: GleeBug
set(GleeBug_SOURCES
"GleeBug/Debugger.Breakpoint.h"
"GleeBug/Debugger.Dll.cpp"
"GleeBug/Debugger.Dll.h"
"GleeBug/Debugger.Global.h"
"GleeBug/Debugger.Loop.DebugString.cpp"
"GleeBug/Debugger.Loop.Dll.cpp"
"GleeBug/Debugger.Loop.Exception.cpp"
"GleeBug/Debugger.Loop.Process.cpp"
"GleeBug/Debugger.Loop.Rip.cpp"
"GleeBug/Debugger.Loop.Thread.cpp"
"GleeBug/Debugger.Loop.Unknown.cpp"
"GleeBug/Debugger.Loop.cpp"
"GleeBug/Debugger.NativeAttach.h"
"GleeBug/Debugger.Process.Breakpoint.cpp"
"GleeBug/Debugger.Process.Memory.cpp"
"GleeBug/Debugger.Process.cpp"
"GleeBug/Debugger.Process.h"
"GleeBug/Debugger.Thread.HardwareBreakpoint.cpp"
"GleeBug/Debugger.Thread.Registers.Flag.h"
"GleeBug/Debugger.Thread.Registers.GetSet.cpp"
"GleeBug/Debugger.Thread.Registers.Register.h"
"GleeBug/Debugger.Thread.Registers.cpp"
"GleeBug/Debugger.Thread.Registers.h"
"GleeBug/Debugger.Thread.cpp"
"GleeBug/Debugger.Thread.h"
"GleeBug/Debugger.cpp"
"GleeBug/Debugger.h"
"GleeBug/GleeBug.h"
"GleeBug/Static.BufferFile.cpp"
"GleeBug/Static.BufferFile.h"
"GleeBug/Static.File.cpp"
"GleeBug/Static.File.h"
"GleeBug/Static.Global.h"
"GleeBug/Static.Pattern.cpp"
"GleeBug/Static.Pattern.h"
"GleeBug/Static.Pe.Section.h"
"GleeBug/Static.Pe.cpp"
"GleeBug/Static.Pe.h"
"GleeBug/Static.Region.h"
"GleeBug/Zydis/Zydis.c"
"GleeBug/Zydis/Zydis.h"
"GleeBug/ntdll.h"
"GleeBug/oprintf.h"
"GleeBug/stringutils.cpp"
"GleeBug/stringutils.h"
cmake.toml
)
add_library(GleeBug STATIC)
target_sources(GleeBug PRIVATE ${GleeBug_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${GleeBug_SOURCES})
target_compile_definitions(GleeBug PUBLIC
NOMINMAX
)
target_compile_features(GleeBug PUBLIC
cxx_std_23
)
target_include_directories(GleeBug PUBLIC
.
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
target_link_libraries(GleeBug PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/GleeBug/ntdll_x64.lib"
)
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
target_link_libraries(GleeBug PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/GleeBug/ntdll_x86.lib"
)
endif()
# Target: MyDebugger
if(CMKR_ROOT_PROJECT) # root
set(MyDebugger_SOURCES
"MyDebugger/MyDebugger.h"
"MyDebugger/PeTests.h"
"MyDebugger/main.cpp"
cmake.toml
)
add_executable(MyDebugger)
target_sources(MyDebugger PRIVATE ${MyDebugger_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${MyDebugger_SOURCES})
if(NOT TARGET GleeBug)
message(FATAL_ERROR "Target \"GleeBug\" referenced by \"MyDebugger\" does not exist!")
endif()
target_link_libraries(MyDebugger PRIVATE
GleeBug
)
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 MyDebugger)
endif()
endif()
# Target: GleeBugStaticEngine
set(GleeBugStaticEngine_SOURCES
"StaticEngine/Emulator.h"
"StaticEngine/FileMap.h"
"StaticEngine/TitanEngine.h"
"StaticEngine/TitanEngineEmulator.cpp"
"StaticEngine/ntdll.h"
cmake.toml
)
add_library(GleeBugStaticEngine SHARED)
target_sources(GleeBugStaticEngine PRIVATE ${GleeBugStaticEngine_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${GleeBugStaticEngine_SOURCES})
if(NOT TARGET GleeBug)
message(FATAL_ERROR "Target \"GleeBug\" referenced by \"GleeBugStaticEngine\" does not exist!")
endif()
target_link_libraries(GleeBugStaticEngine PRIVATE
GleeBug
)
# Target: GleeBugTitanEngine
set(GleeBugTitanEngine_SOURCES
"TitanEngineEmulator/Emulator.h"
"TitanEngineEmulator/FileMap.h"
"TitanEngineEmulator/Global.Engine.Context.cpp"
"TitanEngineEmulator/Global.Engine.Context.h"
"TitanEngineEmulator/Hider.h"
"TitanEngineEmulator/PEB.h"
"TitanEngineEmulator/TitanEngine.h"
"TitanEngineEmulator/TitanEngineEmulator.cpp"
"TitanEngineEmulator/ntdll.h"
"TitanEngineEmulator/resource.h"
cmake.toml
)
if(GLEEBUG_RESOURCES) # GLEEBUG_RESOURCES
list(APPEND GleeBugTitanEngine_SOURCES
"TitanEngineEmulator/TitanEngine.rc"
)
endif()
add_library(GleeBugTitanEngine SHARED)
target_sources(GleeBugTitanEngine PRIVATE ${GleeBugTitanEngine_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${GleeBugTitanEngine_SOURCES})
if(NOT TARGET GleeBug)
message(FATAL_ERROR "Target \"GleeBug\" referenced by \"GleeBugTitanEngine\" does not exist!")
endif()
target_link_libraries(GleeBugTitanEngine PRIVATE
GleeBug
)
set(CMKR_TARGET GleeBugTitanEngine)
include(output-folders.cmake)

View File

@ -8,6 +8,10 @@
#define GLEEBUG_HWBP_COUNT 4
#define GLEEBUG_PAGE_SIZE 0x1000
#ifndef PAGE_SIZE
#define PAGE_SIZE 0x1000
#endif // PAGE_SIZE
namespace GleeBug
{
//forward declarations
@ -19,9 +23,7 @@ namespace GleeBug
struct BreakpointInfo;
struct MemoryBreakpointData;
//constants
const int HWBP_COUNT = GLEEBUG_HWBP_COUNT;
const int PAGE_SIZE = GLEEBUG_PAGE_SIZE;
//key typedefs
typedef std::pair<BreakpointType, ptr> BreakpointKey;

View File

@ -57,8 +57,9 @@ namespace GleeBug
case ZYDIS_MNEMONIC_SCASD:
case ZYDIS_MNEMONIC_SCASQ:
return (info.attributes & (ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPZ | ZYDIS_ATTRIB_HAS_REPNZ)) != 0;
default:
return false;
}
return false;
}
void Process::StepOver(const StepCallback & cbStep)

View File

@ -30,7 +30,6 @@ namespace GleeBug
SIZE_4 = 3 //11
};
#pragma pack(1)
struct DR7
{
BYTE DR7_MODE[HWBP_COUNT];

View File

@ -218,8 +218,8 @@ namespace GleeBug
{
uint16 index;
IMAGE_SECTION_HEADER header; //by value to prevent pointer invalidation
Region<uint8> beforeData;
Region<uint8> data;
Region<uint8> beforeData{};
Region<uint8> data{};
};
//sort sections on raw address to prevent read errors and have a contiguous buffer
@ -292,7 +292,7 @@ namespace GleeBug
//offset -> section index
auto offset = section.GetHeader().PointerToRawData;
//bigSoRD.exe: if raw size is bigger than virtual size, then virtual size is taken.
auto rsize = min(section.GetHeader().SizeOfRawData, section.GetHeader().Misc.VirtualSize);
auto rsize = std::min(section.GetHeader().SizeOfRawData, section.GetHeader().Misc.VirtualSize);
if(!rsize) //65535sects.exe
continue;
mOffsetSectionMap.insert({ Range(offset, offset + rsize - 1), section.GetIndex() });

View File

@ -16,7 +16,7 @@ namespace GleeBug
/**
\brief Default constructor (constructs an invalid region).
*/
explicit Region()
Region()
: Region(nullptr, INVALID_VALUE, INVALID_VALUE)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
#include <GleeBug/Debugger.h>
#include <GleeBug/Static.Pe.h>
#include <GleeBug/Static.Bufferfile.h>
#include <GleeBug/Static.BufferFile.h>
#include <GleeBug/Debugger.Thread.Registers.h>
#include <GleeBug/stringutils.h>
#include "TitanEngine.h"
@ -1060,10 +1060,10 @@ private: //functions
THREAD_BASIC_INFORMATION tbi;
if(!getThreadInfo(hThread, tbi))
return nullptr;
auto foundP = mProcesses.find(uint32(tbi.ClientId.UniqueProcess));
auto foundP = mProcesses.find(uint32(uintptr_t(tbi.ClientId.UniqueProcess)));
if(foundP == mProcesses.end())
return nullptr;
auto foundT = foundP->second->threads.find(uint32(tbi.ClientId.UniqueThread));
auto foundT = foundP->second->threads.find(uint32(uintptr_t(tbi.ClientId.UniqueThread)));
if(foundT == foundP->second->threads.end())
return nullptr;
return foundT->second.get();
@ -1277,7 +1277,7 @@ private: //functions
}
#endif
bool EngineExtractResource(char* szResourceName, wchar_t* szExtractedFileName)
bool EngineExtractResource(const char* szResourceName, const wchar_t* szExtractedFileName)
{
bool result = false;
HRSRC hResource = FindResourceA(engineHandle, (LPCSTR)szResourceName, "BINARY");

View File

@ -1,4 +1,3 @@
#include "ntdll.h"
#include "Emulator.h"
Emulator emu;

View File

@ -12,13 +12,22 @@ extern "C" {
#endif
#include <Windows.h>
#undef WIN32_NO_STATUS
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4005) // ntstatus.h can collide with winnt.h in unity builds
#endif
#include <ntstatus.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <intrin.h>
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
#ifndef FASTCALL
#define FASTCALL __fastcall
#endif
#ifndef _Reserved_
#define _Reserved_

36
cmake.toml Normal file
View File

@ -0,0 +1,36 @@
[project]
name = "GleeBug"
[options]
GLEEBUG_RESOURCES = true
[target.GleeBug]
type = "static"
sources = ["GleeBug/Zydis/*.c", "GleeBug/*.cpp"]
headers = ["GleeBug/Zydis/*.h", "GleeBug/*.h"]
include-directories = ["."]
compile-features = ["cxx_std_23"]
compile-definitions = ["NOMINMAX"]
x64.link-libraries = ["GleeBug/ntdll_x64.lib"]
x32.link-libraries = ["GleeBug/ntdll_x86.lib"]
[target.MyDebugger]
condition = "root"
type = "executable"
sources = ["MyDebugger/*.cpp"]
headers = ["MyDebugger/*.h"]
link-libraries = ["::GleeBug"]
[target.GleeBugStaticEngine]
type = "shared"
sources = ["StaticEngine/*.cpp"]
headers = ["StaticEngine/*.h"]
private-link-libraries = ["::GleeBug"]
[target.GleeBugTitanEngine]
type = "shared"
sources = ["TitanEngineEmulator/*.cpp"]
GLEEBUG_RESOURCES.sources = ["TitanEngineEmulator/TitanEngine.rc"]
headers = ["TitanEngineEmulator/*.h"]
private-link-libraries = ["::GleeBug"]
include-after = ["output-folders.cmake"]

260
cmkr.cmake vendored Normal file
View File

@ -0,0 +1,260 @@
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.46" 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(CMKR_DIRECTORY_PREFIX MATCHES "^~")
if(WIN32)
string(REGEX REPLACE "^~" "$ENV{USERPROFILE}" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
elseif(UNIX)
string(REGEX REPLACE "^~" "$ENV{HOME}" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
endif()
endif()
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()

37
output-folders.cmake Normal file
View File

@ -0,0 +1,37 @@
function(set_nested_output_directory TARGET SUBDIR)
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${SUBDIR}"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${SUBDIR}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${SUBDIR}"
)
elseif(CMAKE_CONFIGURATION_TYPES)
foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${CONFIG} CONFIG_UPPER)
set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_${CONFIG_UPPER}
"${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}/${SUBDIR}"
ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_UPPER}
"${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}/${SUBDIR}"
LIBRARY_OUTPUT_DIRECTORY_${CONFIG_UPPER}
"${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}/${SUBDIR}"
)
endforeach()
else()
set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${SUBDIR}"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${SUBDIR}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${SUBDIR}"
)
endif()
endfunction()
set_nested_output_directory(GleeBugTitanEngine "GleeBug")
set_target_properties(GleeBugTitanEngine PROPERTIES
OUTPUT_NAME "TitanEngine"
)
set_nested_output_directory(GleeBugStaticEngine "StaticEngine")
set_target_properties(GleeBugStaticEngine PROPERTIES
OUTPUT_NAME "TitanEngine"
)