diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-10-09 20:26:25 +0200 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-10-09 20:26:25 +0200 |
| commit | 1b1e9b85a51444751dddc0e94a09d19bd4f0885e (patch) | |
| tree | e44b66adea043c59a2be05683edc8bd4ab6982db /libpsn00b/cmake/internal_setup.cmake | |
| parent | 82a259240d9c63d4656b9dae0b46a3689840473b (diff) | |
| download | psn00bsdk-1b1e9b85a51444751dddc0e94a09d19bd4f0885e.tar.gz | |
Refactor CMake scripts, add separate debug/release builds
Diffstat (limited to 'libpsn00b/cmake/internal_setup.cmake')
| -rw-r--r-- | libpsn00b/cmake/internal_setup.cmake | 230 |
1 files changed, 118 insertions, 112 deletions
diff --git a/libpsn00b/cmake/internal_setup.cmake b/libpsn00b/cmake/internal_setup.cmake index d293127..e9f0db5 100644 --- a/libpsn00b/cmake/internal_setup.cmake +++ b/libpsn00b/cmake/internal_setup.cmake @@ -1,5 +1,5 @@ # PSn00bSDK internal setup script for CMake -# (C) 2021 spicyjpeg - MPL licensed +# (C) 2021-2022 spicyjpeg - MPL licensed # This script is included automatically when using the toolchain file and # defines helper functions. @@ -7,6 +7,10 @@ cmake_minimum_required(VERSION 3.20) include(GNUInstallDirs) +# Re-enable support for dynamic linking as CMake's "Generic" system type +# disables it. +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS ON) + # Fetch SDK version information from build.json. if(NOT DEFINED PSN00BSDK_VERSION) file(READ ${CMAKE_CURRENT_LIST_DIR}/../build.json _json) @@ -17,13 +21,9 @@ if(NOT DEFINED PSN00BSDK_VERSION) string(JSON PSN00BSDK_GIT_COMMIT GET ${_json} git_commit) endif() -## Settings (can be overridden by projects) - -set(PSN00BSDK_EXECUTABLE_SUFFIX ".exe") -set(PSN00BSDK_SHARED_LIBRARY_SUFFIX ".dll") -set(PSN00BSDK_SYMBOL_MAP_SUFFIX ".map") +include(${CMAKE_CURRENT_LIST_DIR}/../libpsn00b.cmake OPTIONAL) -## SDK libraries +## Settings (can be overridden by projects) # DON'T CHANGE THE ORDER or you'll break the libraries' internal dependencies. set( @@ -40,33 +40,23 @@ set( c ) -include(${CMAKE_CURRENT_LIST_DIR}/libpsn00b.cmake OPTIONAL) -include(${CMAKE_CURRENT_LIST_DIR}/flags.cmake) +set(PSN00BSDK_EXECUTABLE_LINK_LIBRARIES ${PSN00BSDK_LIBRARIES}) +set(PSN00BSDK_SHARED_LIBRARY_LINK_LIBRARIES "") -# Use the toolchain path to find libgcc (used to build libpsn00b). Of course -# different installers, packages and distros have different opinions when it -# comes to deciding where to install toolchains, so we have to bruteforce -# multiple combinations of paths. -if(CMAKE_C_COMPILER_VERSION) - string(REGEX MATCH "^([0-9]+)\." _dummy ${CMAKE_C_COMPILER_VERSION}) +set(PSN00BSDK_EXECUTABLE_SUFFIX ".exe") +set(PSN00BSDK_SHARED_LIBRARY_SUFFIX ".dll") +set(PSN00BSDK_SYMBOL_MAP_SUFFIX ".map") - find_library( - PSN00BSDK_LIBGCC gcc - HINTS - ${PSN00BSDK_TC}/lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} - ${PSN00BSDK_TC}/lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} - ${PSN00BSDK_TC}/lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} - ${PSN00BSDK_TC}/lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} - ${PSN00BSDK_TC}/../lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} - ${PSN00BSDK_TC}/../lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} - ${PSN00BSDK_TC}/../lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} - ${PSN00BSDK_TC}/../lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} - NO_DEFAULT_PATH - DOC "Path to libgcc (bundled with the GCC toolchain)" - ) +## Include paths + +set(PSN00BSDK_LDSCRIPTS ${CMAKE_CURRENT_LIST_DIR}/../ldscripts) +if(IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../include) + set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) +else() + set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../../../include/libpsn00b) endif() -## Tools +## Tool paths set( PSN00BSDK_TOOLS @@ -80,26 +70,41 @@ find_program(SMXLINK smxlink HINTS ${PSN00BSDK_TOOLS}) find_program(LZPACK lzpack HINTS ${PSN00BSDK_TOOLS}) find_program(MKPSXISO mkpsxiso HINTS ${PSN00BSDK_TOOLS}) -## Helper functions for executables +## libgcc -set(PSN00BSDK_LDSCRIPTS ${CMAKE_CURRENT_LIST_DIR}/../ldscripts) -if(IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../include) - set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) -else() - set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../../../include/libpsn00b) -endif() +# Use the toolchain path to find libgcc. Of course different installers, +# packages and distros have different opinions when it comes to deciding where +# to install toolchains, so we have to bruteforce multiple combinations of +# paths. +if(CMAKE_C_COMPILER_VERSION) + string(REGEX MATCH "^([0-9]+)\." _dummy ${CMAKE_C_COMPILER_VERSION}) -# psn00bsdk_add_executable( -# <target name> <STATIC|DYNAMIC> -# [EXCLUDE_FROM_ALL] -# <sources> ... -# ) -function(psn00bsdk_add_executable name type) - string(TOLOWER ${type} _type) - if(NOT ${_type} MATCHES "^(static|dynamic)$") - message(FATAL_ERROR "Invalid executable type: ${type} (must be STATIC or DYNAMIC)") + find_library( + PSN00BSDK_LIBGCC gcc #REQUIRED + HINTS + ${PSN00BSDK_TC}/lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} + ${PSN00BSDK_TC}/lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} + ${PSN00BSDK_TC}/lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} + ${PSN00BSDK_TC}/lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} + ${PSN00BSDK_TC}/../lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} + ${PSN00BSDK_TC}/../lib/gcc-cross/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} + ${PSN00BSDK_TC}/../lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_C_COMPILER_VERSION} + ${PSN00BSDK_TC}/../lib/gcc/${PSN00BSDK_TARGET}/${CMAKE_MATCH_1} + NO_DEFAULT_PATH + DOC "Path to libgcc (bundled with the GCC toolchain)" + ) + if(PSN00BSDK_LIBGCC STREQUAL "PSN00BSDK_LIBGCC-NOTFOUND") + message(FATAL_ERROR "Failed to find libgcc in the GCC toolchain's files. Check your toolchain settings, or set the path to libgcc using -DPSN00BSDK_LIBGCC.") endif() + add_library(gcc STATIC IMPORTED) + set_property(TARGET gcc PROPERTY IMPORTED_LOCATION ${PSN00BSDK_LIBGCC}) + link_libraries(gcc) +endif() + +## Target helpers + +function(psn00bsdk_add_executable name type) # Throw an error if elf2x was not found (which should never happen if the # SDK is installed properly). if(ELF2X STREQUAL "ELF2X-NOTFOUND") @@ -107,10 +112,10 @@ function(psn00bsdk_add_executable name type) endif() add_executable (${name} ${ARGN}) - target_link_libraries(${name} psn00bsdk_${_type}_exe ${PSN00BSDK_LIBRARIES}) set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX ".elf") target_link_options (${name} PRIVATE -T${PSN00BSDK_LDSCRIPTS}/exe.ld) + psn00bsdk_target_link_sdk (${name} PRIVATE EXECUTABLE ${type} ${PSN00BSDK_EXECUTABLE_LINK_LIBRARIES}) target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE}) # Add post-build steps to generate the .exe and symbol map once the @@ -123,30 +128,26 @@ function(psn00bsdk_add_executable name type) ) endfunction() -# psn00bsdk_add_library( -# <target name> <STATIC|SHARED|MODULE> -# [EXCLUDE_FROM_ALL] -# <sources> ... -# ) -# Note that SHARED and MODULE have the same meaning (both will create a DLL). -# SDK libraries are NOT statically linked in by default; if you need to link -# something, use target_link_libraries() manually. function(psn00bsdk_add_library name type) - string(TOUPPER ${type} _type_upper) - string(TOLOWER ${type} _type) - if(NOT ${_type} MATCHES "^(static|object|shared|module)$") - message(FATAL_ERROR "Invalid library type: ${type} (must be STATIC, OBJECT, SHARED or MODULE)") - endif() + string(TOUPPER ${type} _type) - add_library (${name} ${_type_upper} ${ARGN}) - target_link_libraries(${name} psn00bsdk_${_type}_lib) - - target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE}) + if(_type MATCHES "^(STATIC|OBJECT)$") + # Remove virtual target dependencies to make sure linking against the + # library does not also propagate static library flags. + add_library (${name} ${_type} ${ARGN}) + set_target_properties(${name} PROPERTIES PREFIX "lib" SUFFIX ".a") + set_target_properties(${name} PROPERTIES INTERFACE_LINK_LIBRARIES "") + target_link_libraries(${name} PRIVATE psn00bsdk_common) - if(${_type} MATCHES "^(shared|module)$") + target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE}) + elseif(_type MATCHES "^(SHARED|MODULE)$") + add_library (${name} ${_type} ${ARGN}) set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX ".so") target_link_options (${name} PRIVATE -T${PSN00BSDK_LDSCRIPTS}/dll.ld) + psn00bsdk_target_link_sdk (${name} PRIVATE SHARED_LIBRARY ${PSN00BSDK_SHARED_LIBRARY_LINK_LIBRARIES}) + target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE}) + # Add a post-build step to dump the DLL's raw contents into a new file # separate from the built ELF. add_custom_command( @@ -155,63 +156,48 @@ function(psn00bsdk_add_library name type) BYPRODUCTS ${name}${PSN00BSDK_SHARED_LIBRARY_SUFFIX} ) else() - set_target_properties(${name} PROPERTIES PREFIX "lib" SUFFIX ".a") - - # Remove virtual target dependencies to make sure linking against the - # library does not also propagate static library flags. - set_target_properties(${name} PROPERTIES INTERFACE_LINK_LIBRARIES "") + message(FATAL_ERROR "Invalid library type: ${type} (must be STATIC, OBJECT, SHARED or MODULE)") endif() endfunction() -# psn00bsdk_add_cd_image( -# <target name> -# <image file name> -# <mkpsxiso config template> -# [DEPENDS <dependencies> ...] -# [additional options passed to add_custom_target()] -# ) -function(psn00bsdk_add_cd_image name image_name config_file) - # Throw an error if mkpsxiso was not found. Performing this check manually - # (instead of just marking mkpsxiso as required) allows simple projects to - # be built even if mkpsxiso is not installed. - if(MKPSXISO STREQUAL "MKPSXISO-NOTFOUND") - message(FATAL_ERROR "Failed to locate mkpsxiso. If mkpsxiso wasn't installed alongside the SDK, check your PATH environment variable.") +## Linking helpers + +function(psn00bsdk_target_link_sdk name type target_type) + set(_libraries ${ARGN}) + string(TOUPPER ${target_type} _target_type) + + if(_target_type STREQUAL "EXECUTABLE") + list(POP_FRONT _libraries) + string(TOUPPER ${ARGV3} _exe_type) + + if(_exe_type MATCHES "^(STATIC|GPREL)$") + set(_suffix _exe_gprel) + elseif(_exe_type MATCHES "^(DYNAMIC|NOGPREL)$") + set(_suffix _exe_nogprel) + else() + message(FATAL_ERROR "Invalid executable type: ${ARGV3} (must be STATIC, GPREL, DYNAMIC or NOGPREL)") + endif() + elseif(_target_type STREQUAL "SHARED_LIBRARY") + set(_suffix _dll) + else() + message(FATAL_ERROR "Invalid target type: ${target_type} (must be EXECUTABLE or SHARED_LIBRARY)") endif() - cmake_path(HASH config_file _hash) - - set(CD_IMAGE_NAME ${image_name}) - set(CD_CONFIG_FILE cd_image_${_hash}.xml) - configure_file(${config_file} ${CD_CONFIG_FILE}) - - add_custom_target( - ${name} ALL - COMMAND ${MKPSXISO} -y ${CD_CONFIG_FILE} - BYPRODUCTS ${image_name}.bin ${image_name}.cue - COMMENT "Building CD image ${image_name}" - ${ARGN} - ) + list(TRANSFORM _libraries APPEND ${_suffix}) + target_link_libraries(${name} ${type} psn00bsdk${_suffix} ${_libraries}) endfunction() -## Helper functions for assets - -# psn00bsdk_target_incbin_a( -# <existing target name> <PRIVATE|PUBLIC|INTERFACE> -# <data symbol name> -# <size symbol name> -# <path to binary file> -# <linker section name> -# <alignment> -# ) function(psn00bsdk_target_incbin_a name type symbol_name size_name path section align) string(MAKE_C_IDENTIFIER ${symbol_name} _id) string(MAKE_C_IDENTIFIER ${size_name} _size) cmake_path(ABSOLUTE_PATH path OUTPUT_VARIABLE _path) + string(SHA1 _hash "${name} ${_id}") + set(_asm_file ${CMAKE_CURRENT_BINARY_DIR}/incbin_${_hash}.s) + # Generate an assembly source file that includes the binary file and add it # to the target's sources. The file is also added as a depedency to ensure # CMake builds it before the target (if it's not a static file). - set(_asm_file ${PROJECT_BINARY_DIR}/incbin_${name}_${_id}.s) file( CONFIGURE OUTPUT ${_asm_file} @@ -246,11 +232,6 @@ ${_size}: set_source_files_properties(${_asm_file} PROPERTIES OBJECT_DEPENDS ${_path}) endfunction() -# psn00bsdk_target_incbin( -# <existing target name> <PRIVATE|PUBLIC|INTERFACE> -# <symbol name> -# <path to binary file> -# ) function(psn00bsdk_target_incbin name type symbol_name path) string(MAKE_C_IDENTIFIER ${symbol_name} _id) @@ -264,3 +245,28 @@ function(psn00bsdk_target_incbin name type symbol_name path) 4 ) endfunction() + +## CD image and asset helpers + +function(psn00bsdk_add_cd_image name image_name config_file) + # Throw an error if mkpsxiso was not found. Performing this check manually + # (instead of just marking mkpsxiso as required) allows simple projects to + # be built even if mkpsxiso is not installed. + if(MKPSXISO STREQUAL "MKPSXISO-NOTFOUND") + message(FATAL_ERROR "Failed to locate mkpsxiso. If mkpsxiso wasn't installed alongside the SDK, check your PATH environment variable.") + endif() + + cmake_path(HASH config_file _hash) + + set(CD_IMAGE_NAME ${image_name}) + set(CD_CONFIG_FILE cd_image_${_hash}.xml) + configure_file(${config_file} ${CD_CONFIG_FILE}) + + add_custom_target( + ${name} ALL + COMMAND ${MKPSXISO} -y ${CD_CONFIG_FILE} + BYPRODUCTS ${image_name}.bin ${image_name}.cue + COMMENT "Building CD image ${image_name}" + ${ARGN} + ) +endfunction() |
