How to Link Libraries in shadPS4-Emu Build: A Complete CMake Guide
shadPS4 uses a centralized CMake configuration where internal libraries are source-file collections merged into the main executable, while third-party dependencies are discovered via find_package and linked through imported targets.
Linking libraries correctly is essential when building or extending shadPS4, the open-source PlayStation 4 emulator. Whether you are adding a new core component or integrating an external dependency, understanding how to link libraries in shadps4-emu build processes ensures your changes compile and link properly with the rest of the codebase.
Understanding the shadPS4 CMake Architecture
The emulator's build system is defined entirely in the top-level CMakeLists.txt at the repository root. This file handles three distinct categories of libraries: internal source collections, system dependencies, and vendored external code.
Internal Libraries as Source Collections
Rather than creating separate static library targets for each component, shadPS4 groups source files into CMake variables. For example, the AJM (Audio Job Manager) library is defined as:
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
src/core/libraries/ajm/ajm.h
… )
These variables are concatenated into a master CORE list, which is then passed directly to add_executable(shadps4 …). Because all sources compile into a single target, no explicit target_link_libraries call is required for internal components.
Third-Party Dependencies via find_package
External system libraries are located using standard CMake find_package calls located around lines 120–150 of the root CMakeLists.txt:
find_package(Boost 1.84.0 CONFIG)
find_package(CLI11 2.6.1 CONFIG)
find_package(FFmpeg 5.1.2 MODULE)
find_package(fmt 10.2.0 CONFIG)
When found, these create imported targets (e.g., Boost::boost, fmt::fmt) that CMake automatically links to the shadps4 executable through the target's link interface.
Vendored Libraries in externals/
Libraries that ship with the repository reside in the externals/ directory. The top-level CMakeLists.txt includes them via:
add_subdirectory(externals)
Each subdirectory contains its own CMakeLists.txt that defines a static library target (e.g., gcn). These targets are then added to the CORE variable or linked explicitly to the main executable.
How to Link Internal Libraries in shadPS4
To add a new internal component, you extend the source collection pattern used throughout the project.
-
Define a source variable in the root
CMakeLists.txt(place it near other library definitions):set(FOO_LIB src/core/libraries/foo/foo.cpp src/core/libraries/foo/foo.h src/core/libraries/foo/foo_helper.cpp src/core/libraries/foo/foo_helper.h) -
Append to the CORE collection (around line 250–260 where other libraries are merged):
set(CORE ${CORE} ${FOO_LIB}) -
Regenerate the build files:
cmake -B build cmake --build build
The new sources compile and link automatically because they are part of the unified shadps4 target.
How to Link External Dependencies in shadPS4 Build
For system libraries or packages installed via a package manager, use the find_package + target_link_libraries pattern.
Linking a Required System Package
Add the discovery and linking steps to the root CMakeLists.txt:
# Near line 120-150 with other find_package calls
find_package(spdlog 1.12.0 CONFIG REQUIRED)
# After the add_executable(shadps4 ...) block
target_link_libraries(shadps4 PRIVATE spdlog::spdlog)
Handling Optional Dependencies
For optional features like Discord RPC, wrap the logic in a conditional check:
if (ENABLE_DISCORD_RPC)
list(APPEND COMMON src/common/discord_rpc_handler.cpp
src/common/discord_rpc_handler.h)
find_package(discord-rpc CONFIG)
target_link_libraries(shadps4 PRIVATE discord-rpc::discord-rpc)
endif()
This ensures the library only links when the corresponding CMake option is enabled.
How to Add Vendored Libraries from externals/
When you need to include a library that must ship with the emulator source:
-
Create the library directory under
externals/mydep/with its ownCMakeLists.txt:# externals/mydep/CMakeLists.txt add_library(mydep STATIC src/mydep.c src/mydep.h) target_include_directories(mydep PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) -
Include the subdirectory in the root
CMakeLists.txt(around line 64 where other externals are added):add_subdirectory(externals/mydep) -
Link the target by appending it to the
COREvariable or usingtarget_link_libraries:set(CORE ${CORE} mydep) # OR explicitly: target_link_libraries(shadps4 PRIVATE mydep)
Summary
- shadPS4 uses a monolithic CMake structure where the root
CMakeLists.txtcontrols all linking. - Internal libraries are collections of source files merged into the
COREvariable; they require no explicittarget_link_librariesbecause they compile directly into theshadps4executable. - System dependencies are discovered via
find_packageand linked through imported targets likefmt::fmtorBoost::boost. - Vendored code in
externals/is built as static library subdirectories and linked viaadd_subdirectoryandtarget_link_libraries.
Frequently Asked Questions
Where is the main CMakeLists.txt located in shadPS4?
The primary build configuration file resides at the repository root as CMakeLists.txt. This single file orchestrates all library linking, source collection, and target creation for the emulator.
Do I need target_link_libraries for internal components?
No. Internal libraries in shadPS4 are implemented as CMake variables containing source file lists (e.g., AJM_LIB, FOO_LIB). These variables are appended to the master CORE list, which is passed directly to add_executable(shadps4 …). Because the sources compile into the same target, no explicit linking command is required.
How does shadPS4 handle optional dependencies like Discord RPC?
Optional features use CMake options (e.g., ENABLE_DISCORD_RPC). When enabled, the build system appends the relevant source files to the COMMON variable and calls find_package to locate the external library. The imported target (e.g., discord-rpc::discord-rpc) is then linked to the shadps4 target using target_link_libraries inside the conditional block.
Can I add system libraries using pkg-config instead of find_package?
While shadPS4 primarily uses find_package for dependency resolution, you can integrate pkg-config libraries by using CMake's pkg_check_modules command from the FindPkgConfig module. After locating the package, you would add the imported targets or compile/link flags to the shadps4 target, following the same pattern used for the existing find_package dependencies.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →