diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bebe02..6d07319 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -490,6 +490,7 @@ add_custom_command( set(spec_targets) set(spec_files) set(spec_dirs) +include(cmake/modules/sleighCompile.cmake) # Example: '/Ghidra/Processors/8051/data/languages/mx51.slaspec' foreach(spec_file ${spec_file_list}) # Get 'mx51' @@ -515,21 +516,15 @@ foreach(spec_file ${spec_file_list}) # Add relative spec processor directory for later processing list(APPEND spec_dirs "${spec_proc_dir}") - # Compile the sla file - add_custom_command( - OUTPUT "${spec_out}" - DEPENDS "${spec_file}" "${spec_files_build_log_dir}" - COMMAND "$" ${spec_file} "${spec_out}" > ${spec_build_log} 2>&1 - WORKING_DIRECTORY "${spec_dir}" - COMMENT "sleigh: Compiling the ${spec_name} spec file (${spec_build_log})" - BYPRODUCTS ${spec_build_log} - VERBATIM - ) - string(REPLACE "." "_" spec_target_name ${spec_name}) set(spec_target "sleigh_spec_${spec_target_name}") - add_custom_target(${spec_target} - DEPENDS ${spec_out} + + # Compile the sla file + sleigh_compile( + TARGET "${spec_target}" + SLASPEC "${spec_file}" + LOG_FILE "${spec_build_log}" + OUT_FILE "${spec_out}" ) add_dependencies(${spec_target} sleigh_copy_${proc_name}_dir) @@ -754,6 +749,11 @@ if(NOT CMAKE_SKIP_INSTALL_RULES) RENAME sleighConfig.cmake DESTINATION "${sleigh_INSTALL_CMAKEDIR}" ) + + install( + FILES cmake/modules/sleighCompile.cmake + DESTINATION "${sleigh_INSTALL_CMAKEDIR}/modules" + ) endif() add_subdirectory(tools) diff --git a/README.md b/README.md index 066fd1b..ed8b522 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,18 @@ FindSpecFile(std::string_view file_name, The `sleigh::FindSpecFile` function will search the the paths provided by the user via the `search_paths` argument for a spec file with the name `file_name`. The default argument for `search_paths` is `sleigh::gDefaultSearchPaths` which contains the install/build directories that the CMake project was configured with as well as a set of common installation locations. +## Integration as a Dependency + +An installation of sleigh provides a CMake interface that can be used to assist in building your project. + +An example of how to use the CMake package config file can be found in the [find_package](tests/find_package/CMakeLists.txt) example. + +We also provide a CMake helper function [`sleigh_compile`](cmake/modules/sleighCompile.cmake) to compile your own `.slaspec` files using the installed sleigh compiler from this project. + +Lastly, the installed compiled sleigh files can be located through the CMake variable `SLEIGH_INSTALL_SPECDIR`, which is an absolute path to the root directory for where the compiled sleigh files are located---you should manually inspect this to know what to expect. + +Referencing the [CMake config file](cmake/install-config.cmake.in) is also suggested for learning more about the exposed CMake variables and modules. + ## License See the LICENSE file in the top directory of this repo. diff --git a/cmake/install-config.cmake.in b/cmake/install-config.cmake.in index fcf9618..b6bc496 100644 --- a/cmake/install-config.cmake.in +++ b/cmake/install-config.cmake.in @@ -4,3 +4,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/sleighTargets.cmake") # Path relative-root to reach installed specfiles directory set_and_check(SLEIGH_INSTALL_SPECDIR "@PACKAGE_sleigh_INSTALL_SPECDIR@") + +# Helpers exposed by default when finding sleigh +include("${CMAKE_CURRENT_LIST_DIR}/modules/sleighCompile.cmake") diff --git a/cmake/modules/sleighCompile.cmake b/cmake/modules/sleighCompile.cmake new file mode 100644 index 0000000..712f4bd --- /dev/null +++ b/cmake/modules/sleighCompile.cmake @@ -0,0 +1,66 @@ +# +# Copyright (c) 2022-present, Trail of Bits, Inc. +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +cmake_minimum_required(VERSION 3.15) + +# Takes the following required arguments: +# +# TARGET: Named CMake target for performing sleigh compilation +# SLASPEC: Path to slaspec file +# LOG_FILE: File to write logs +# OUT_FILE: Compiled sleigh output file (should be in build directory somewhere) +# +# NOTE: This doesn't track _all_ dependencies for the slaspec compilation due +# to the ability for slaspec files to include other files. If you want to +# rebuild the sleigh file then you must delete the OUT_FILE +function(sleigh_compile) + set(options) + set(oneValueArgs TARGET SLASPEC LOG_FILE OUT_FILE) + set(multiValueArgs) + cmake_parse_arguments(parsed + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) + + # Sanity checking for caller + if(parsed_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Bad arguments: ${parsed_UNPARSED_ARGUMENTS}") + endif() + if(parsed_KEYWORDS_MISSING_VALUES) + message(FATAL_ERROR "Missing values for: ${parsed_KEYWORDS_MISSING_VALUES}") + endif() + + # Setup variables for paths/filenames + set(spec_file "${parsed_SLASPEC}") + get_filename_component(spec_name "${spec_file}" NAME_WE) + get_filename_component(spec_dir "${spec_file}" DIRECTORY) + + set(spec_build_log "${parsed_LOG_FILE}") + get_filename_component(spec_build_log_dir "${spec_build_log}" DIRECTORY) + + set(spec_out "${parsed_OUT_FILE}") + get_filename_component(spec_out_dir "${spec_out}" DIRECTORY) + + # Custom command to compile the sla file + add_custom_command( + OUTPUT "${spec_out}" + MAIN_DEPENDENCY "${spec_file}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${spec_out_dir}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${spec_build_log_dir}" + COMMAND "$" ${spec_file} "${spec_out}" > "${spec_build_log}" 2>&1 + WORKING_DIRECTORY "${spec_dir}" + COMMENT "sleigh: Compiling the '${spec_name}' spec file (logs written in '${spec_build_log}')" + BYPRODUCTS "${spec_build_log}" + VERBATIM + ) + + # Custom target for others to depend on + add_custom_target(${parsed_TARGET} DEPENDS "${spec_out}") +endfunction() diff --git a/tests/find_package/CMakeLists.txt b/tests/find_package/CMakeLists.txt index d946329..955007a 100644 --- a/tests/find_package/CMakeLists.txt +++ b/tests/find_package/CMakeLists.txt @@ -6,7 +6,7 @@ # the LICENSE file found in the root directory of this source tree. # -cmake_minimum_required(VERSION 3.21.0) +cmake_minimum_required(VERSION 3.15.0) project("sleigh_find_package_test") find_package(sleigh REQUIRED)