Initial cmkr project

This commit is contained in:
Duncan Ogilvie
2021-12-24 22:49:47 +01:00
parent e51200fdc8
commit 70208f72f6
9 changed files with 458 additions and 6 deletions
+3
View File
@@ -3,3 +3,6 @@
/msvc/.vs
*.user
/src/.vs
.vscode/
build*/
+181
View File
@@ -0,0 +1,181 @@
# 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()
# Regenerate CMakeLists.txt automatically in the root project
set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMKR_ROOT_PROJECT ON)
# Bootstrap cmkr
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)
endif()
# Create a configure-time dependency on cmake.toml to improve IDE support
if(CMKR_ROOT_PROJECT)
configure_file(cmake.toml cmake.toml COPYONLY)
endif()
project(zasm
LANGUAGES
CXX
)
# Packages
find_package(Zydis REQUIRED)
find_package(GTest)
# Options
option(ZASM_BUILD_TESTS OFF)
# Target zasm
set(CMKR_TARGET zasm)
set(zasm_SOURCES "")
list(APPEND zasm_SOURCES
"src/zasm/src/assembler/assembler.cpp"
"src/zasm/src/assembler/assembler.instructions.cpp"
"src/zasm/src/decoder/decoder.cpp"
"src/zasm/src/encoder/encoder.cpp"
"src/zasm/src/encoder/generator.cpp"
"src/zasm/src/program/data.cpp"
"src/zasm/src/program/program.cpp"
"src/zasm/src/program/program.serialization.cpp"
"src/zasm/src/zasm.cpp"
"include/zasm/assembler/assembler.hpp"
"include/zasm/core/bitsize.hpp"
"include/zasm/core/errors.hpp"
"include/zasm/core/expected.hpp"
"include/zasm/core/objectpool.hpp"
"include/zasm/core/stringpool.hpp"
"include/zasm/decoder/decoder.hpp"
"include/zasm/encoder/encoder.hpp"
"include/zasm/program/data.hpp"
"include/zasm/program/immediate.hpp"
"include/zasm/program/instruction.hpp"
"include/zasm/program/label.hpp"
"include/zasm/program/memory.hpp"
"include/zasm/program/node.hpp"
"include/zasm/program/operand.hpp"
"include/zasm/program/program.hpp"
"include/zasm/program/register.hpp"
"include/zasm/zasm.hpp"
)
list(APPEND zasm_SOURCES
cmake.toml
)
set(CMKR_SOURCES ${zasm_SOURCES})
add_library(zasm STATIC)
if(zasm_SOURCES)
target_sources(zasm PRIVATE ${zasm_SOURCES})
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${zasm_SOURCES})
add_library(zasm::zasm ALIAS zasm)
target_compile_features(zasm PUBLIC
cxx_std_17
)
target_include_directories(zasm PUBLIC
include
)
target_link_libraries(zasm PUBLIC
Zydis::Zydis
)
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
# Target tests
if(ZASM_BUILD_TESTS) # tests
set(CMKR_TARGET tests)
set(tests_SOURCES "")
list(APPEND tests_SOURCES
"src/tests/main.cpp"
"src/tests/tests/instructions.x64.cpp"
"src/tests/tests/serialization.cpp"
"src/tests/testutils.cpp"
"src/tests/instructiontest.hpp"
"src/tests/testutils.hpp"
)
list(APPEND tests_SOURCES
cmake.toml
)
set(CMKR_SOURCES ${tests_SOURCES})
add_executable(tests)
if(tests_SOURCES)
target_sources(tests PRIVATE ${tests_SOURCES})
endif()
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 tests)
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${tests_SOURCES})
target_link_libraries(tests PRIVATE
zasm::zasm
GTest::gtest
)
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
endif()
# Target testing
if(ZASM_BUILD_TESTS) # tests
set(CMKR_TARGET testing)
set(testing_SOURCES "")
list(APPEND testing_SOURCES
"src/testing/testing.cpp"
)
list(APPEND testing_SOURCES
cmake.toml
)
set(CMKR_SOURCES ${testing_SOURCES})
add_executable(testing)
if(testing_SOURCES)
target_sources(testing PRIVATE ${testing_SOURCES})
endif()
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 testing)
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${testing_SOURCES})
target_link_libraries(testing PRIVATE
zasm::zasm
)
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
endif()
+44
View File
@@ -0,0 +1,44 @@
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[project]
name = "zasm"
languages = ["CXX"]
[options]
ZASM_BUILD_TESTS = false
[conditions]
tests = "ZASM_BUILD_TESTS"
[find-package.Zydis]
[find-package.GTest]
required = false
[target.zasm]
type = "static"
alias = "zasm::zasm"
sources = [
"src/zasm/**.cpp",
"include/zasm/**.hpp",
]
include-directories = ["include"]
compile-features = ["cxx_std_17"]
link-libraries = ["Zydis::Zydis"]
[target.tests]
condition = "tests"
type = "executable"
sources = [
"src/tests/**.cpp",
"src/tests/**.hpp",
]
link-libraries = [
"zasm::zasm",
"GTest::gtest",
]
[target.testing]
condition = "tests"
type = "executable"
sources = ["src/testing/testing.cpp"]
link-libraries = ["zasm::zasm"]
+222
View File
@@ -0,0 +1,222 @@
include_guard()
# 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()
# 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.0" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
# 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")
# 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} AND EXISTS "$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()
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}")
# Handle upgrading logic
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr")
if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$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 EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}")
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}"
)
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()
+1 -1
View File
@@ -150,7 +150,7 @@ namespace zasm
template<class _Objty, class... _Types> void construct(_Objty* _Ptr, _Types&&... _Args)
{
::new ((void*)_Ptr) _Objty(_STD forward<_Types>(_Args)...);
::new ((void*)_Ptr) _Objty(std::forward<_Types>(_Args)...);
}
template<class _Uty> void destroy(_Uty* _Ptr)
+2 -1
View File
@@ -1,5 +1,6 @@
#include <chrono>
#include <iostream>
#include <iomanip>
#include <zasm/zasm.hpp>
static std::string getHexDump(const uint8_t* buf, size_t len)
@@ -8,7 +9,7 @@ static std::string getHexDump(const uint8_t* buf, size_t len)
for (size_t i = 0; i < len; i++)
{
char temp[3]{};
sprintf_s(temp, "%02X", buf[i]);
snprintf(temp, std::size(temp), "%02X", buf[i]);
res += temp;
}
return res;
+1 -1
View File
@@ -772,7 +772,7 @@ namespace zasm::tests
INSTRUCTION_TEST(0F2000 , mov(rax, cr0));
INSTRUCTION_TEST(48899C1180000000 , mov(qword_ptr(rcx, rdx, 1, 128), rbx));
INSTRUCTION_TEST(B901000000 , mov(ecx, Imm(1)));
INSTRUCTION_TEST(48BB8877665544332211 , mov(rbx, Imm(0x001122334455667788)));
INSTRUCTION_TEST(48BB8877665544332211 , mov(rbx, Imm(0x001122334455667788LL)));
INSTRUCTION_TEST(8EE2 , mov(fs, dx));
INSTRUCTION_TEST(48C784118000000001000000 , mov(qword_ptr(rcx, rdx, 1, 128), Imm(1)));
INSTRUCTION_TEST(0F2011 , mov(rcx, cr2));
+1 -1
View File
@@ -31,7 +31,7 @@ namespace zasm::tests
char temp[3]{};
for (size_t i = 0; i < size; i++)
{
sprintf_s(temp, "%02X", data[i]);
snprintf(temp, std::size(temp), "%02X", data[i]);
res += temp;
}
return res;
+3 -2
View File
@@ -1,5 +1,6 @@
#include "zasm/program/data.hpp"
#include <cstdlib>
#include <cstring>
#include <limits>
@@ -14,7 +15,7 @@ namespace zasm
}
else
{
void* data = malloc(len);
void* data = std::malloc(len);
std::memcpy(data, ptr, len);
_storage.ptr = data;
@@ -27,7 +28,7 @@ namespace zasm
if (_size & kInlineDataFlag)
return;
free(const_cast<void*>(_storage.ptr));
std::free(const_cast<void*>(_storage.ptr));
_storage.ptr = nullptr;
}