aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b
diff options
context:
space:
mode:
authorspicyjpeg <88942473+spicyjpeg@users.noreply.github.com>2021-09-12 19:39:02 +0200
committerspicyjpeg <88942473+spicyjpeg@users.noreply.github.com>2021-09-12 19:39:02 +0200
commitc6548f077282f871bc22bd05595d3a1139f50a80 (patch)
treeb5771fabdfd86fa2e2076ee08029d358c92f017d /libpsn00b
parentffa679d4d24b891cb59aba10946368f2ec00c391 (diff)
downloadpsn00bsdk-c6548f077282f871bc22bd05595d3a1139f50a80.tar.gz
Added preliminary files for CMake/CPack support
Diffstat (limited to 'libpsn00b')
-rw-r--r--libpsn00b/cmake/internal_setup.cmake158
-rw-r--r--libpsn00b/cmake/sdk.cmake78
-rw-r--r--libpsn00b/cmake/virtual_targets.cmake109
3 files changed, 345 insertions, 0 deletions
diff --git a/libpsn00b/cmake/internal_setup.cmake b/libpsn00b/cmake/internal_setup.cmake
new file mode 100644
index 0000000..e9423a4
--- /dev/null
+++ b/libpsn00b/cmake/internal_setup.cmake
@@ -0,0 +1,158 @@
+# PSn00bSDK internal setup script for CMake
+# (C) 2021 spicyjpeg - MPL licensed
+
+# This script is included automatically when using the toolchain file and
+# defines helper functions.
+
+cmake_minimum_required(VERSION 3.21)
+include(GNUInstallDirs)
+
+## Settings (can be overridden by projects)
+
+set(PSN00BSDK_EXECUTABLE_SUFFIX ".exe")
+set(PSN00BSDK_SHARED_LIBRARY_SUFFIX ".dll")
+set(PSN00BSDK_SYMBOL_MAP_SUFFIX ".map")
+
+## SDK libraries
+
+# DON'T CHANGE THE ORDER or you'll break the libraries' internal dependencies.
+set(PSN00BSDK_LIBRARIES psxgpu psxgte psxspu psxcd psxsio psxetc psxapi lzp c)
+
+include(${CMAKE_CURRENT_LIST_DIR}/libpsn00b.cmake OPTIONAL)
+if(NOT TARGET psn00bsdk_common)
+ include(${CMAKE_CURRENT_LIST_DIR}/virtual_targets.cmake)
+endif()
+
+# 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})
+
+ 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)"
+ )
+endif()
+
+## Tools
+
+set(
+ PSN00BSDK_TOOLS
+ ${CMAKE_CURRENT_LIST_DIR}/../../../${CMAKE_INSTALL_BINDIR}
+ ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}
+)
+
+find_program(ELF2X elf2x HINTS ${PSN00BSDK_TOOLS})
+find_program(ELF2CPE elf2cpe HINTS ${PSN00BSDK_TOOLS})
+find_program(SMXLINK elf2x HINTS ${PSN00BSDK_TOOLS})
+find_program(LZPACK lzpack HINTS ${PSN00BSDK_TOOLS})
+find_program(MKPSXISO mkpsxiso HINTS ${PSN00BSDK_TOOLS})
+
+## Helper functions for executables
+
+set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include)
+set(PSN00BSDK_LDSCRIPTS ${CMAKE_CURRENT_LIST_DIR}/../ldscripts)
+
+# 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)")
+ endif()
+
+ add_executable (${name} ${ARGN})
+ target_link_libraries(${name} psn00bsdk_${_type}_exe)
+ set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX ".elf")
+ target_link_options (${name} PRIVATE -T${PSN00BSDK_LDSCRIPTS}/exe.ld)
+
+ target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE})
+
+ # Add post-build steps to generate the .exe and symbol map once the
+ # executable is built. CMake 3.21 added support for target-dependent
+ # generator expressions (catchy name lol) in add_custom_command(), so I'm
+ # making heavy use of those here.
+ add_custom_command(
+ TARGET ${name} POST_BUILD
+ COMMAND ${ELF2X} -q ${name}.elf ${name}${PSN00BSDK_EXECUTABLE_SUFFIX}
+ COMMAND ${TOOLCHAIN_NM} -f posix -l -n ${name}.elf $<ANGLE-R>${name}${PSN00BSDK_SYMBOL_MAP_SUFFIX}
+ BYPRODUCTS ${name}${PSN00BSDK_EXECUTABLE_SUFFIX} ${name}${PSN00BSDK_SYMBOL_MAP_SUFFIX}
+ )
+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()
+
+ add_library (${name} ${_type_upper} ${ARGN})
+ target_link_libraries(${name} psn00bsdk_${_type}_lib)
+
+ target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE})
+
+ if(${_type} MATCHES "^(shared|module)$")
+ set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX ".so")
+ target_link_options (${name} PRIVATE -T${PSN00BSDK_LDSCRIPTS}/dll.ld)
+
+ # Add a post-build step to dump the DLL's raw contents into a new file
+ # separate from the built ELF.
+ add_custom_command(
+ TARGET ${name} POST_BUILD
+ COMMAND ${CMAKE_OBJCOPY} -O binary ${name}.so ${name}${PSN00BSDK_SHARED_LIBRARY_SUFFIX}
+ 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 "")
+ 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)
+ set(CD_IMAGE_NAME ${image_name})
+ configure_file(${config_file} _gen_${config_file})
+
+ add_custom_target(
+ ${name} ALL
+ COMMAND ${MKPSXISO} -y -q _gen_${config_file}
+ BYPRODUCTS ${image_name}.bin ${image_name}.cue
+ COMMENT "Building CD image ${image_name}"
+ ${ARGN}
+ )
+endfunction()
+
+## Helper functions for assets (TODO)
diff --git a/libpsn00b/cmake/sdk.cmake b/libpsn00b/cmake/sdk.cmake
new file mode 100644
index 0000000..82e921c
--- /dev/null
+++ b/libpsn00b/cmake/sdk.cmake
@@ -0,0 +1,78 @@
+# PSn00bSDK toolchain setup file for CMake
+# (C) 2021 spicyjpeg - MPL licensed
+
+cmake_minimum_required(VERSION 3.21)
+
+set(
+ PSN00BSDK_TC $ENV{PSN00BSDK_TC}
+ CACHE PATH "Path to the GCC toolchain's installation directory"
+)
+set(
+ PSN00BSDK_TARGET mipsel-unknown-elf
+ CACHE STRING "GCC toolchain target triplet"
+)
+
+## CMake configuration
+
+set(CMAKE_SYSTEM_NAME PlayStation)
+set(CMAKE_SYSTEM_PROCESSOR mipsel)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+#set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+
+# Tell CMake not to run the linker when compiling test programs. This dodges
+# missing C++ standard library errors.
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+## Toolchain path setup
+
+# Attempt to find GCC. PSN00BSDK_TC can be left unset if the toolchain can be
+# found in the PATH environment variable.
+find_program(
+ _gcc ${PSN00BSDK_TARGET}-gcc
+ HINTS
+ ${PSN00BSDK_TC}/bin
+ ${PSN00BSDK_TC}/../bin
+ ${CMAKE_CURRENT_LIST_DIR}/../../../${PSN00BSDK_TARGET}/bin
+ PATHS
+ "C:/Program Files/${PSN00BSDK_TARGET}/bin"
+ "C:/${PSN00BSDK_TARGET}/bin"
+ /usr/local/${PSN00BSDK_TARGET}/bin
+ /usr/${PSN00BSDK_TARGET}/bin
+ NO_CACHE REQUIRED
+)
+cmake_path(GET _gcc PARENT_PATH _bin)
+cmake_path(GET _bin PARENT_PATH _toolchain)
+
+# Overwrite the empty cache entry, so it won't have to be found again.
+if(NOT IS_DIRECTORY PSN00BSDK_TC)
+ set(
+ PSN00BSDK_TC ${_toolchain}
+ CACHE PATH "Path to the GCC toolchain's installation directory"
+ FORCE
+ )
+endif()
+
+## Toolchain executables
+
+set(_prefix ${_bin}/${PSN00BSDK_TARGET})
+
+set(CMAKE_ASM_COMPILER ${_prefix}-gcc${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_C_COMPILER ${_prefix}-gcc${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_CXX_COMPILER ${_prefix}-g++${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_AR ${_prefix}-ar${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_LINKER ${_prefix}-ld${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_RANLIB ${_prefix}-ranlib${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_OBJCOPY ${_prefix}-objcopy${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_SIZE ${_prefix}-size${CMAKE_EXECUTABLE_SUFFIX})
+set(CMAKE_STRIP ${_prefix}-strip${CMAKE_EXECUTABLE_SUFFIX})
+set(TOOLCHAIN_NM ${_prefix}-nm${CMAKE_EXECUTABLE_SUFFIX})
+
+## SDK setup
+
+# We can't set up the SDK here as the find_*() functions may fail if they are
+# called before project(). We can however set a script to be executed right
+# after project() is invoked.
+set(CMAKE_PROJECT_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/internal_setup.cmake)
diff --git a/libpsn00b/cmake/virtual_targets.cmake b/libpsn00b/cmake/virtual_targets.cmake
new file mode 100644
index 0000000..df1df79
--- /dev/null
+++ b/libpsn00b/cmake/virtual_targets.cmake
@@ -0,0 +1,109 @@
+# libpsn00b interface targets
+# (C) 2021 spicyjpeg - MPL licensed
+
+# This script creates several "virtual" targets (psn00bsdk_*) that set include
+# directories and compiler flags when a target is linked against them. These
+# all end up in the autogenerated libpsn00b setup script after installation,
+# so this file is only included when building libpsn00b.
+
+# The following targets are currently defined:
+# - psn00bsdk_common
+# - psn00bsdk_object_lib (same as psn00bsdk_common)
+# - psn00bsdk_static_exe
+# - psn00bsdk_dynamic_exe
+# - psn00bsdk_static_lib
+# - psn00bsdk_shared_lib
+# - psn00bsdk_module_lib (same as psn00bsdk_shared_lib)
+
+include(GNUInstallDirs)
+
+set(PSN00BSDK_VIRTUAL_TARGETS "")
+
+macro(_add_interface_target name)
+ add_library(${name} INTERFACE)
+ list(APPEND PSN00BSDK_VIRTUAL_TARGETS ${name})
+
+ target_compile_options(
+ ${name} INTERFACE
+ ${_aflags}
+ $<$<COMPILE_LANGUAGE:C,CXX>:${_cflags}>
+ $<$<COMPILE_LANGUAGE:CXX>:${_cxxflags}>
+ )
+ target_link_options (${name} INTERFACE ${_ldflags})
+ target_link_libraries(${name} INTERFACE ${ARGN})
+endmacro()
+
+macro(_add_alias_target name)
+ #add_library(${name} ALIAS ${ARGN})
+ add_library(${name} INTERFACE)
+ list(APPEND PSN00BSDK_VIRTUAL_TARGETS ${name})
+
+ target_link_libraries(${name} INTERFACE ${ARGN})
+endmacro()
+
+# Options common to all target types:
+# - Define PLAYSTATION=1 and set include directories
+# - Optimize for MIPS R3000
+# - Inject zero checks into division operations (will throw breaks)
+# - All standard libraries (including libgcc) disabled
+# - Put all symbols into separate sections when building
+# - C++ features that require runtime support disabled
+# - Unused section stripping enabled
+set(_aflags -msoft-float -march=r3000 -mtune=r3000 -mabi=32)
+set(_cflags -mdivide-breaks -O2 -ffreestanding -fno-builtin -nostdlib -fdata-sections -ffunction-sections -fsigned-char -fno-strict-overflow -fdiagnostics-color=always)
+set(_cxxflags -fno-exceptions -fno-rtti -fno-unwind-tables -fno-threadsafe-statics -fno-use-cxa-atexit)
+set(_ldflags -nostdlib -Wl,-gc-sections)
+
+_add_interface_target(psn00bsdk_common)
+_add_alias_target (psn00bsdk_object_lib psn00bsdk_common)
+
+target_compile_definitions(
+ psn00bsdk_common INTERFACE
+ PLAYSTATION=1
+ $<$<CONFIG:DEBUG>:DEBUG=1>
+)
+
+# Options for executables without support for dynamic linking:
+# - Position-independent code disabled
+# - GP-relative addressing enabled only for local symbols
+# - ABI-compatible calls disabled (incompatible with GP-relative addr)
+set(_aflags -G8)
+set(_cflags -mno-abicalls -mgpopt -mno-extern-sdata)
+set(_cxxflags)
+set(_ldflags -G8 -static)
+
+_add_interface_target(psn00bsdk_static_exe psn00bsdk_common ${PSN00BSDK_LIBRARIES})
+
+# Options for executables with support for dynamic linking:
+# - Position-independent code disabled
+# - GP-relative addressing disabled
+# - ABI-compatible calls disabled (must be performed manually)
+set(_aflags -G0)
+set(_cflags -mno-abicalls -mno-gpopt)
+set(_cxxflags)
+set(_ldflags -G0 -static)
+
+_add_interface_target(psn00bsdk_dynamic_exe psn00bsdk_common ${PSN00BSDK_LIBRARIES})
+
+# Options for static libraries:
+# - GP-relative addressing disabled
+# - ABI-compatible calls disabled
+# - Local stripping enabled
+set(_aflags -G0 -Wa,--strip-local-absolute)
+set(_cflags -mno-abicalls -mno-gpopt)
+set(_cxxflags)
+set(_ldflags)
+
+_add_interface_target(psn00bsdk_static_lib psn00bsdk_common)
+
+# Options for dynamically-loaded libraries:
+# - Position-independent code enabled
+# - GP-relative addressing disabled (incompatible with ABI calls)
+# - ABI-compatible calls enabled
+set(_aflags -G0)
+set(_cflags -mabicalls -mshared -mno-gpopt -fPIC)
+set(_cxxflags)
+set(_ldflags -G0 -shared)
+
+_add_interface_target(psn00bsdk_shared_lib psn00bsdk_common)
+_add_alias_target (psn00bsdk_module_lib psn00bsdk_shared_lib)