From 1b1e9b85a51444751dddc0e94a09d19bd4f0885e Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Sun, 9 Oct 2022 20:26:25 +0200 Subject: Refactor CMake scripts, add separate debug/release builds --- examples/lowlevel/cartrom/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/lowlevel') diff --git a/examples/lowlevel/cartrom/CMakeLists.txt b/examples/lowlevel/cartrom/CMakeLists.txt index 7d5e86e..2efe6cf 100644 --- a/examples/lowlevel/cartrom/CMakeLists.txt +++ b/examples/lowlevel/cartrom/CMakeLists.txt @@ -17,7 +17,7 @@ file(GLOB _sources *.c *.s) # executable has to be created manually and converted into raw binary format # (for testing on emulators or flashing to a cheat cartridge). add_executable (cartrom ${_sources}) -target_link_libraries(cartrom psn00bsdk_static_exe) +target_link_libraries(cartrom psn00bsdk_exe_nogprel) set_target_properties(cartrom PROPERTIES PREFIX "" SUFFIX ".elf") target_link_options (cartrom PRIVATE -T${PROJECT_SOURCE_DIR}/rom.ld) -- cgit v1.2.3 From 1a468c901a7b473a556c6a572c03c68186f03f89 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Tue, 11 Oct 2022 11:17:28 +0200 Subject: Update CMake scripts to use generator expressions --- examples/lowlevel/cartrom/CMakeLists.txt | 10 ++- libpsn00b/CMakeLists.txt | 29 ++++--- libpsn00b/cmake/flags.cmake | 127 ++++++++++------------------ libpsn00b/cmake/internal_setup.cmake | 137 ++++++++++++++++++------------- libpsn00b/cmake/sdk.cmake | 14 ++-- 5 files changed, 156 insertions(+), 161 deletions(-) (limited to 'examples/lowlevel') diff --git a/examples/lowlevel/cartrom/CMakeLists.txt b/examples/lowlevel/cartrom/CMakeLists.txt index 2efe6cf..6a94d9f 100644 --- a/examples/lowlevel/cartrom/CMakeLists.txt +++ b/examples/lowlevel/cartrom/CMakeLists.txt @@ -1,7 +1,7 @@ # PSn00bSDK example CMake script # (C) 2021 spicyjpeg - MPL licensed -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) project( cartrom @@ -17,9 +17,13 @@ file(GLOB _sources *.c *.s) # executable has to be created manually and converted into raw binary format # (for testing on emulators or flashing to a cheat cartridge). add_executable (cartrom ${_sources}) -target_link_libraries(cartrom psn00bsdk_exe_nogprel) -set_target_properties(cartrom PROPERTIES PREFIX "" SUFFIX ".elf") target_link_options (cartrom PRIVATE -T${PROJECT_SOURCE_DIR}/rom.ld) +set_target_properties( + cartrom PROPERTIES + PREFIX "" + SUFFIX ".elf" + PSN00BSDK_TARGET_TYPE EXECUTABLE_NOGPREL +) target_include_directories(cartrom PRIVATE ${PROJECT_SOURCE_DIR}) diff --git a/libpsn00b/CMakeLists.txt b/libpsn00b/CMakeLists.txt index 71cc659..602b3c8 100644 --- a/libpsn00b/CMakeLists.txt +++ b/libpsn00b/CMakeLists.txt @@ -1,7 +1,7 @@ # libpsn00b build script -# (C) 2021 spicyjpeg - MPL licensed +# (C) 2021-2022 spicyjpeg - MPL licensed -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) # ${PROJECT_SOURCE_DIR} is not available until project() is called. set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/sdk.cmake) @@ -17,6 +17,9 @@ include(${PROJECT_SOURCE_DIR}/cmake/flags.cmake) ## Libraries +set(_types EXECUTABLE_GPREL EXECUTABLE_NOGPREL SHARED_LIBRARY) +set(_suffixes _exe_gprel _exe_nogprel _dll) + foreach(_library IN LISTS PSN00BSDK_LIBRARIES) # libc needs special handling due to the different directory name. if(${_library} STREQUAL "c") @@ -30,17 +33,26 @@ foreach(_library IN LISTS PSN00BSDK_LIBRARIES) ${_path}/*.s ${_path}/*.c ${_path}/*.cpp ) - foreach(_suffix IN ITEMS _exe_nogprel _exe_gprel _dll) + # Build a separate version of the library for each supported target type + # and create a virtual target that links the appropriate version of the + # library. + add_library(${_library} INTERFACE) + + foreach(_type _suffix IN ZIP_LISTS _types _suffixes) set(_name ${_library}${_suffix}) list(APPEND _libraries ${_name}) psn00bsdk_add_library(${_name} STATIC ${_sources}) - target_link_libraries(${_name} PUBLIC psn00bsdk${_suffix}) + set_target_properties(${_name} PROPERTIES PSN00BSDK_TARGET_TYPE ${_type}) + target_link_libraries( + ${_library} INTERFACE + $<$>,${_type}>:${_name}> + ) endforeach() endforeach() # Add binary assets to each version of the libraries. -foreach(_suffix IN ITEMS _exe_nogprel _exe_gprel _dll) +foreach(_suffix IN LISTS _suffixes) psn00bsdk_target_incbin( psxgpu${_suffix} PRIVATE _gpu_debug_font psxgpu/dbugfont.tim @@ -50,12 +62,7 @@ endforeach() ## Installation install( - TARGETS - psn00bsdk_common - psn00bsdk_exe_gprel - psn00bsdk_exe_nogprel - psn00bsdk_dll - ${_libraries} + TARGETS psn00bsdk ${PSN00BSDK_LIBRARIES} ${_libraries} DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpsn00b/$> EXPORT libpsn00b ) diff --git a/libpsn00b/cmake/flags.cmake b/libpsn00b/cmake/flags.cmake index fea26cd..e56d3fc 100644 --- a/libpsn00b/cmake/flags.cmake +++ b/libpsn00b/cmake/flags.cmake @@ -6,122 +6,85 @@ # only used when building libpsn00b, as CMake automatically saves these targets # into the export script once libpsn00b is installed. -## Options common to all target types +add_library (psn00bsdk INTERFACE) +link_libraries(psn00bsdk) -# - Define PSN00BSDK=1 -# - Always generate debug symbols (stripped by elf2x) -# - 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 - -add_library(psn00bsdk_common INTERFACE) target_compile_options( - psn00bsdk_common INTERFACE - # CPU options - -msoft-float - -march=r3000 - -mtune=r3000 - -mabi=32 - -mno-mt - -mno-llsc - -mdivide-breaks + psn00bsdk INTERFACE + # Options common to all target types + -g + -Wa,--strip-local-absolute -O2 - # Standard library options -ffreestanding -fno-builtin -nostdlib - # Other options - -g - -Wa,--strip-local-absolute -fdata-sections -ffunction-sections -fsigned-char -fno-strict-overflow -fdiagnostics-color=always + -msoft-float + -march=r3000 + -mtune=r3000 + -mabi=32 + -mno-mt + -mno-llsc + -mdivide-breaks $<$: - # C++ options + # Options common to all target types (C++) -fno-exceptions -fno-rtti -fno-unwind-tables -fno-threadsafe-statics -fno-use-cxa-atexit > -) -target_link_options( - psn00bsdk_common INTERFACE - -nostdlib - -Wl,-gc-sections -) -target_compile_definitions( - psn00bsdk_common INTERFACE - PSN00BSDK=1 - $<$: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 addressing) - -add_library(psn00bsdk_exe_gprel INTERFACE) -target_link_libraries(psn00bsdk_exe_gprel INTERFACE psn00bsdk_common) -target_compile_options( - psn00bsdk_exe_gprel INTERFACE + $<$>,EXECUTABLE_GPREL>: + # Options for executables with $gp-relative addressing -G8 -fno-pic -mno-abicalls -mgpopt -mno-extern-sdata -) -target_link_options( - psn00bsdk_exe_gprel INTERFACE - -G8 - -static -) - -## Options for executables with support for dynamic linking - -# - Position-independent code disabled -# - $gp-relative addressing disabled -# - ABI-compatible calls disabled (must be performed manually) - -add_library(psn00bsdk_exe_nogprel INTERFACE) -target_link_libraries(psn00bsdk_exe_nogprel INTERFACE psn00bsdk_common) -target_compile_options( - psn00bsdk_exe_nogprel INTERFACE + > + $<$>,EXECUTABLE_NOGPREL>: + # Options for executables without $gp-relative addressing -G0 -fno-pic -mno-abicalls -mno-gpopt -) -target_link_options( - psn00bsdk_exe_nogprel INTERFACE - -G0 - -static -) - -## Options for dynamically-linked libraries - -# - Position-independent code enabled -# - $gp-relative addressing disabled (incompatible with ABI calls) -# - ABI-compatible calls enabled - -add_library(psn00bsdk_dll INTERFACE) -target_link_libraries(psn00bsdk_dll INTERFACE psn00bsdk_common) -target_compile_options( - psn00bsdk_dll INTERFACE + > + $<$>,SHARED_LIBRARY>: + # Options for DLLs -G0 -fPIC -mabicalls -mno-gpopt -mshared + > ) target_link_options( - psn00bsdk_dll INTERFACE + psn00bsdk INTERFACE + # Options common to all target types + -nostdlib + -Wl,-gc-sections + $<$>,EXECUTABLE_GPREL>: + # Options for executables with $gp-relative addressing + -G8 + -static + > + $<$>,EXECUTABLE_NOGPREL>: + # Options for executables without $gp-relative addressing + -G0 + -static + > + $<$>,SHARED_LIBRARY>: + # Options for DLLs -G0 -shared + > +) +target_compile_definitions( + psn00bsdk INTERFACE + PSN00BSDK=1 + $<$:DEBUG=1> ) diff --git a/libpsn00b/cmake/internal_setup.cmake b/libpsn00b/cmake/internal_setup.cmake index e9f0db5..6fecb9f 100644 --- a/libpsn00b/cmake/internal_setup.cmake +++ b/libpsn00b/cmake/internal_setup.cmake @@ -4,13 +4,26 @@ # This script is included automatically when using the toolchain file and # defines helper functions. -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) include(GNUInstallDirs) -# Re-enable support for dynamic linking as CMake's "Generic" system type -# disables it. +## CMake configuration + +# Setting these variables and properties would technically be the toolchain +# script's responsibility, however they are overridden by project() so their +# setting is deferred to this script. +set(CMAKE_EXECUTABLE_SUFFIX ".elf") +set(CMAKE_STATIC_LIBRARY_PREFIX "lib") +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +set(CMAKE_SHARED_LIBRARY_PREFIX "") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") +set(CMAKE_SHARED_MODULE_PREFIX "") +set(CMAKE_SHARED_MODULE_SUFFIX ".so") + set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS ON) +## PSn00bSDK initialization + # Fetch SDK version information from build.json. if(NOT DEFINED PSN00BSDK_VERSION) file(READ ${CMAKE_CURRENT_LIST_DIR}/../build.json _json) @@ -22,8 +35,9 @@ if(NOT DEFINED PSN00BSDK_VERSION) endif() include(${CMAKE_CURRENT_LIST_DIR}/../libpsn00b.cmake OPTIONAL) - -## Settings (can be overridden by projects) +if(TARGET psn00bsdk) + link_libraries(psn00bsdk) +endif() # DON'T CHANGE THE ORDER or you'll break the libraries' internal dependencies. set( @@ -40,6 +54,8 @@ set( c ) +## Settings (can be overridden by projects) + set(PSN00BSDK_EXECUTABLE_LINK_LIBRARIES ${PSN00BSDK_LIBRARIES}) set(PSN00BSDK_SHARED_LIBRARY_LINK_LIBRARIES "") @@ -47,6 +63,12 @@ set(PSN00BSDK_EXECUTABLE_SUFFIX ".exe") set(PSN00BSDK_SHARED_LIBRARY_SUFFIX ".dll") set(PSN00BSDK_SYMBOL_MAP_SUFFIX ".map") +define_property( + TARGET PROPERTY PSN00BSDK_TARGET_TYPE + BRIEF_DOCS "Type of this target (EXECUTABLE_GPREL, EXECUTABLE_NOGPREL or SHARED_LIBRARY)" + FULL_DOCS "Type of this target (if executable or DLL) or of the executable/DLL this target is going to be linked to (if static library)" +) + ## Include paths set(PSN00BSDK_LDSCRIPTS ${CMAKE_CURRENT_LIST_DIR}/../ldscripts) @@ -56,6 +78,8 @@ else() set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../../../include/libpsn00b) endif() +include_directories(AFTER ${PSN00BSDK_INCLUDE}) + ## Tool paths set( @@ -97,14 +121,24 @@ if(CMAKE_C_COMPILER_VERSION) 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) + add_library (gcc STATIC IMPORTED) + set_target_properties(gcc PROPERTIES IMPORTED_LOCATION ${PSN00BSDK_LIBGCC}) + link_libraries (gcc) endif() ## Target helpers function(psn00bsdk_add_executable name type) + string(TOUPPER ${type} _type) + + if(_type MATCHES "^(STATIC|GPREL)$") + set(_type EXECUTABLE_GPREL) + elseif(_type MATCHES "^(DYNAMIC|NOGPREL)$") + set(_type EXECUTABLE_NOGPREL) + else() + message(FATAL_ERROR "Invalid executable type: ${type} (must be STATIC, GPREL, DYNAMIC or NOGPREL)") + endif() + # Throw an error if elf2x was not found (which should never happen if the # SDK is installed properly). if(ELF2X STREQUAL "ELF2X-NOTFOUND") @@ -112,19 +146,34 @@ function(psn00bsdk_add_executable name type) endif() add_executable (${name} ${ARGN}) - 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}) + set_target_properties(${name} PROPERTIES PSN00BSDK_TARGET_TYPE ${_type}) + target_link_libraries(${name} PRIVATE ${PSN00BSDK_EXECUTABLE_LINK_LIBRARIES}) + target_link_options (${name} PRIVATE -T$) # Add post-build steps to generate the .exe and symbol map once the # executable is built. + # FIXME: CMake does not (yet) allow target-dependent generator expressions + # to specify the byproducts, so we have to make sure the generated files + # have no prefix/suffix and are in the current build directory. + #set(_repl PATH:REPLACE_EXTENSION,LAST_ONLY,$) 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 $${name}${PSN00BSDK_SYMBOL_MAP_SUFFIX} - BYPRODUCTS ${name}${PSN00BSDK_EXECUTABLE_SUFFIX} ${name}${PSN00BSDK_SYMBOL_MAP_SUFFIX} + TARGET ${name} POST_BUILD + COMMAND + ${ELF2X} -q + $> + #$> + $ + COMMAND + ${TOOLCHAIN_NM} -f posix -l -n + $> + #$$> + $$ + BYPRODUCTS + #$<${_repl},${PSN00BSDK_EXECUTABLE_SUFFIX}> + #$<${_repl},${PSN00BSDK_SYMBOL_MAP_SUFFIX}> + ${CMAKE_CURRENT_BINARY_DIR}/${name}${PSN00BSDK_EXECUTABLE_SUFFIX} + ${CMAKE_CURRENT_BINARY_DIR}/${name}${PSN00BSDK_SYMBOL_MAP_SUFFIX} + VERBATIM ) endfunction() @@ -132,28 +181,27 @@ function(psn00bsdk_add_library name type) string(TOUPPER ${type} _type) 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) - - target_include_directories(${name} PRIVATE ${PSN00BSDK_INCLUDE}) + #target_link_libraries(${name} PRIVATE psn00bsdk) 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}) + set_target_properties(${name} PROPERTIES PSN00BSDK_TARGET_TYPE SHARED_LIBRARY) + target_link_libraries(${name} PRIVATE ${PSN00BSDK_SHARED_LIBRARY_LINK_LIBRARIES}) + target_link_options (${name} PRIVATE -T$) # Add a post-build step to dump the DLL's raw contents into a new file # separate from the built ELF. + #set(_repl PATH:REPLACE_EXTENSION,LAST_ONLY,$) 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} + TARGET ${name} POST_BUILD + COMMAND + ${CMAKE_OBJCOPY} -O binary + $> + #$> + $ + #BYPRODUCTS $<${_repl},${PSN00BSDK_SHARED_LIBRARY_SUFFIX}> + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${name}${PSN00BSDK_SHARED_LIBRARY_SUFFIX} + VERBATIM ) else() message(FATAL_ERROR "Invalid library type: ${type} (must be STATIC, OBJECT, SHARED or MODULE)") @@ -162,31 +210,6 @@ endfunction() ## 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() - - list(TRANSFORM _libraries APPEND ${_suffix}) - target_link_libraries(${name} ${type} psn00bsdk${_suffix} ${_libraries}) -endfunction() - 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) diff --git a/libpsn00b/cmake/sdk.cmake b/libpsn00b/cmake/sdk.cmake index 37b9fd0..facee26 100644 --- a/libpsn00b/cmake/sdk.cmake +++ b/libpsn00b/cmake/sdk.cmake @@ -1,7 +1,7 @@ # PSn00bSDK toolchain setup file for CMake # (C) 2021-2022 spicyjpeg - MPL licensed -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) set( PSN00BSDK_TC "" @@ -70,10 +70,9 @@ endif() ## Toolchain executables -# ${CMAKE_EXECUTABLE_SUFFIX} seems not to work in toolchain scripts, so we -# can't rely on it to determine the host OS extension for executables. The best -# workaround I found is to extract the extension from the path returned by -# find_program() using a regex. +# As we have overridden ${CMAKE_EXECUTABLE_SUFFIX} we can't rely on it to +# determine the host OS extension for executables. A workaround is to extract +# the extension from the path returned by find_program() using a regex. set(_prefix ${_bin}/${PSN00BSDK_TARGET}) string(REGEX MATCH ".+-gcc(.*)$" _dummy ${_gcc}) @@ -90,7 +89,6 @@ set(TOOLCHAIN_NM ${_prefix}-nm${CMAKE_MATCH_1}) ## 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. +# Continue initialization by running internal_setup.cmake after project() is +# invoked. set(CMAKE_PROJECT_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/internal_setup.cmake) -- cgit v1.2.3