diff options
| author | John "Lameguy" Wilbert Villamor <lameguy64@gmail.com> | 2021-10-15 09:22:45 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-15 09:22:45 +0800 |
| commit | dd0f088aaa4c6bf013643be2d1d8621dbffdb000 (patch) | |
| tree | d848d6ce007d8bb9357c8b99d6a0a39ec41d244e /doc | |
| parent | 9e08d1047fa8deeb3ccb3ce9bb11d69e25a52d56 (diff) | |
| parent | eb719a424e6a16fb64209139a32c9f8a7235a929 (diff) | |
| download | psn00bsdk-dd0f088aaa4c6bf013643be2d1d8621dbffdb000.tar.gz | |
Merge pull request #38 from spicyjpeg/cmake
Full CMake support (in place of makefiles)
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/cmake_reference.md | 207 | ||||
| -rw-r--r-- | doc/dev notes.txt | 65 |
2 files changed, 272 insertions, 0 deletions
diff --git a/doc/cmake_reference.md b/doc/cmake_reference.md new file mode 100644 index 0000000..3b586ab --- /dev/null +++ b/doc/cmake_reference.md @@ -0,0 +1,207 @@ + +# PSn00bSDK CMake reference + +## Setup + +The only requirement to use the SDK in CMake is to set the +`CMAKE_TOOLCHAIN_FILE` variable to `INSTALL_PATH/lib/libpsn00b/cmake/sdk.cmake` +(where `INSTALL_PATH` is the install prefix PSn00bSDK is installed to). This +can be done on the command line (`-DCMAKE_TOOLCHAIN_FILE=...`), in +`CMakeLists.txt` (before calling `project()`) or using a +[preset](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html). + +It's recommended to put this snippet in `CMakeLists.txt` to automatically set +the toolchain file according to the `PSN00BSDK_LIBS` environment variable: + +```cmake +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND DEFINED ENV{PSN00BSDK_LIBS}) + set(CMAKE_TOOLCHAIN_FILE $ENV{PSN00BSDK_LIBS}/cmake/sdk.cmake) +endif() +``` + +See the [template](../template/CMakeLists.txt) for an example CMake script +showing how to build a simple project. + +## Targets + +These targets are defined when using PSn00bSDK. There is no need to explicitly +link against any of these, as the helper commands (see below) handle linking +behind the scenes. To avoid conflicts, however, no target should be given any +of these names. + +- `c`, `psxgpu`, `psxgte`, `psxspu`, `psxcd`, `psxsio`, `psxetc`, `psxapi`, `lzp` +- `psn00bsdk_common`, `psn00bsdk_object_lib` +- `psn00bsdk_static_exe` +- `psn00bsdk_dynamic_exe` +- `psn00bsdk_static_lib` +- `psn00bsdk_shared_lib`, `psn00bsdk_module_lib` + +## Commands + +- `psn00bsdk_add_executable(<name> <STATIC|DYNAMIC> [EXCLUDE_FROM_ALL] [sources...])` + + A wrapper around `add_executable()` to create PS1 executables. Three files + will be generated for each call to this function: + + - `<name>.elf` (regular ELF executable) + - `<name>.exe` (executable converted to the format expected by the PS1) + - `<name>.map` (symbol map file for dynamic linking/introspection) + + The `.exe` and `.map` extensions can be customized by overriding + `PSN00BSDK_EXECUTABLE_SUFFIX` and `PSN00BSDK_SYMBOL_MAP_SUFFIX` prior to + creating the executable. + + The second argument (mandatory) specifies whether the executable is going to + load DLLs at runtime. If set to `STATIC`, $gp-relative addressing (i.e. + reusing the $gp register normally used for DLL addressing) will be enabled, + slightly reducing executable size and RAM usage but breaking compatibility + with the dynamic linker. + +- `psn00bsdk_add_library(<name> <STATIC|OBJECT|SHARED|MODULE> [EXCLUDE_FROM_ALL] [sources...])` + + Wraps `add_library()` to create static libraries or dynamically-linked + libraries (DLLs). + + The second argument (mandatory, unlike `add_library()`) specifies the type of + library to create. `STATIC` will create a static library named `lib<name>.a`. + `SHARED` and `MODULE` will compile a DLL, producing the following files (note + that there is no `lib` prefix for DLLs): + + - `<name>.so` (regular ELF shared library) + - `<name>.dll` (raw binary with some ELF headers prepended) + + As with executables, the `.dll` extension can be customized by setting + `PSN00BSDK_SHARED_LIBRARY_SUFFIX`. + +- `psn00bsdk_add_cd_image(<name> <image name> <config file> [...])` + + Creates a new target that will build a CD image using `mkpsxiso`. + + The first argument is the name of the target to create; next up is the name + of the generated image file (`<image name>.bin` + `<image name>.cue`). The + third argument is the path to the XML file passed to `mkpsxiso`. + + The XML file is "configured" by CMake, i.e. any `${var}` or `@var@` + expressions are replaced with the values of the respective variables. In + particular `${CD_IMAGE_NAME}` is replaced with the second argument passed to + `psn00bsdk_add_cd_image()`; the file must properly set the output file names + like this: + + ```xml + <?xml version="1.0" encoding="utf-8"?> + <iso_project + image_name="${CD_IMAGE_NAME}.bin" + cue_sheet="${CD_IMAGE_NAME}.cue" + > + ``` + + Any additional argument is passed through to the underlying call to + `add_custom_target()`, so most of the options supported by + `add_custom_target()` are also supported here. + +## Definitions + +When compiling executables and libraries using the above commands the following +preprocessor macros are automatically `#define`'d: + +- `PLAYSTATION` + + Always set to 1. Can be used to implement different options or code paths for + libraries, so they can target both the host and PS1 (as it won't be defined + when compiling outside of the SDK). + +- `DEBUG` + + Defined and set to 1 in a debug configuration, i.e. when the + `CMAKE_BUILD_TYPE` variable is set to `Debug`. This value is used by the + PSn00bSDK libraries, and should be used in executables, to enable additional + debug logging. + + Note that the default CMake configuration is usually debug, so it's + recommended to specify `-DCMAKE_BUILD_TYPE=Release` to get rid of the logging + overhead in release builds and reduce executable size. + +## Cached settings + +These variables are stored in CMake's cache and can be edited by the project's +build script, from the CMake command line when configuring the project +(`-Dname=value`) or using an editor such as the CMake GUI. + +- `PSN00BSDK_TARGET` (`STRING`) + + The GCC toolchain's target triplet. PSn00bSDK assumes the toolchain targets + `mipsel-unknown-elf` by default, however this can be changed to e.g. use a + MIPS toolchain that was compiled for a slightly-different-but-equivalent + target. + + The following GCC target triplets have been confirmed to work with PSn00bSDK: + + - `mipsel-unknown-elf` + - `mipsel-none-elf` + +- `PSN00BSDK_TC` (`PATH`) + + Path to the GCC toolchain's installation prefix/directory. By default this is + initialized to the value of the `PSN00BSDK_TC` environment variable (if set). + Note that modifying the environment variable after the project has been + configured will *NOT* update this cache entry unless the project's cache is + cleared manually. + + If not set, CMake will attempt to find the toolchain in the `PATH` + environment variable and store its path in this variable (so the search does + not have to be repeated). + + **IMPORTANT**: if the toolchain's target is not `mipsel-unknown-elf`, + `PSN00BSDK_TARGET` must be set regardless of whether or not `PSN00BSDK_TC` is + also set. + +- `PSN00BSDK_LIBGCC` (`FILEPATH`) + + Path to the `libgcc.a` library bundled with the GCC toolchain. The contents + of this library are merged into `libc` when building the SDK, so this + variable is only actually needed when compiling `libpsn00b`. Setting this + variable manually usually isn't necessary as CMake will locate `libgcc.a` + automatically after finding the toolchain. + +## Internal settings + +These settings are not stored in CMake's cache and can only be set from within +the build script. + +- `PSN00BSDK_LIBRARIES` + + List of libraries to link all created targets against. By default this + includes all PSn00bSDK libraries. + +- `PSN00BSDK_EXECUTABLE_SUFFIX`, `PSN00BSDK_SHARED_LIBRARY_SUFFIX`, + `PSN00BSDK_SYMBOL_MAP_SUFFIX` + + File extensions to use for generated PS1 files. The default values are + `.exe`, `.dll` and `.map` respectively. Note that file names and extensions + can be changed anyway when building a CD image. + +## Read-only variables + +- `PSN00BSDK_VERSION` + + The SDK's version number (`major.minor.patch`). + +- `PSN00BSDK_TOOLS`, `PSN00BSDK_INCLUDE`, `PSN00BSDK_LDSCRIPTS` + + Lists of paths used internally. Should not be set, manipulated or overridden + by scripts. + +- `TOOLCHAIN_NM` + + Path to the `nm` executable used to generate symbol maps. Although not used + internally by CMake, this program is part of the GCC toolchain. + +- `ELF2X`, `ELF2CPE`, `MKPSXISO`, `LZPACK`, `SMXLINK` + + Paths to the PSn00bSDK tools' executables. As no functions are currently + provided for building assets, `LZPACK` and `SMXLINK` can be used with + `add_custom_command()`/`add_custom_target()` to convert models and generate + LZP archives as part of the build pipeline. + +----------------------------------------- +_Last updated on 2021-09-27 by spicyjpeg_ diff --git a/doc/dev notes.txt b/doc/dev notes.txt index 47aa2df..8fd8d7f 100644 --- a/doc/dev notes.txt +++ b/doc/dev notes.txt @@ -92,3 +92,68 @@ power operator, not xor): * If you are overriding any of the memory allocation functions, DO NOT ENABLE LINK-TIME OPTIMIZATION. GCC has a long-standing bug with LTO and weak functions written in assembly, also LTO hasn't been tested at all yet. + +Obscure CMake issues and related stuff: + +* Toolchain files are loaded "early" according to the CMake docs. What this +means in practice is that a lot of commands, such as find_*(), won't work +properly in a toolchain script as they rely on variables initialized by the +project() command. The poorly documented solution to this is to move such +commands to a separate file and set CMAKE_PROJECT_INCLUDE to point to it, so +project() will execute it immediately after initialization. + +* After executing the toolchain file, CMake generates and attempts to build +several dummy projects to test the compiler. Each of these projects re-includes +the toolchain script (which is why you'll see commands executed multiple times) +and uses the same variable values as the main project, however CMake will *NOT* +pass custom variables through by default. If your toolchain script has options +that can be set via custom variables (like PSN00BSDK_TC and PSN00BSDK_PREFIX in +PSn00bSDK), you'll have to set CMAKE_TRY_COMPILE_PLATFORM_VARIABLES to a list +of variable names to be exported to generated dummy projects. + +* There is no way to use multiple toolchains (PS1 + host) in a single project, +even if you use add_subdirectory() to execute multiple project files (which, +confusingly, adds their targets to the parent project rather than treating them +as separate projects). Thankfully though CMake provides support for automating +the build process of independent CMake projects via the ExternalProject module. +Which brings me to the next issue... + +* If you run CPack on a "superbuild" project (i.e. a project that calls +ExternalProject_Add() to configure, compile and install subprojects at build +time), you'll likely run into a weird issue with CPack bundling folders from +your build directory into DEB and RPM packages. This is caused by the DEB/RPM +generators running "cmake --install" in a chroot/fakeroot to prepare the files +to be packaged, which seems to interfere with absolute paths in the project +cache or something like that (?). The only workaround I know of is to use +CPACK_PRE_BUILD_SCRIPTS to trigger a custom script that deletes anything other +than the actual files to be packaged (see cpack/fakeroot_fix.cmake). + +* Depending on how you find external dependencies (find_package(), vcpkg, +pkg-config...), CMake may end up outputting an executable that relies on a DLL +installed system-wide. To correctly install the DLL alongside the executable +you have to specify a regex as follows: + + install( + TARGETS my_executable + RUNTIME_DEPENDENCIES + PRE_EXCLUDE_REGEXES ".*" + PRE_INCLUDE_REGEXES "tinyxml2" + ) + +CMake will scan the executable at install time and copy all the required DLLs +that match the second regex. If no regex is specified CMake will also copy OS +DLLs like libc or msvcrt, which usually isn't the desired behavior. + +* Using interface targets to set include directories can be finicky. Not only +do you have to use generator expressions to conditionally use different paths +depending on whether the targets are installed, but CMake can get confused on +which options to pass to the compiler. I spent hours trying to get CMake to use +-I rather than -isystem for include directories (for some reason GCC would +ignore -isystem completely). I eventually gave up and just set the include +directories manually for each target, and for some reason CMake actually +started passing -I instead of -isystem to GCC. + +* Not a CMake/CPack bug per se, but NSIS is picky about the banner and header +images shown in generated installers. They must be Windows BMP version 3 files +with no alpha channel, no compression and no metadata. They can either be +24-bit RGB or indexed, though it's common to use indexed colors to save space. |
