From b5e4ec35e3b97ce90bf13ca9b7f03dd8d2af7c69 Mon Sep 17 00:00:00 2001 From: emufan4568 Date: Thu, 14 Jul 2022 18:42:33 +0300 Subject: [PATCH] Introduce vcpkg for dependency management * Manually including libraries into the project while a perfectly acceptable solution leads to slow updates and large maintainance costs. To address this shortcoming we are introducing a package manager namely vcpkg into the codebase to handle the download and build of most external dependencies. Conan was also considered but vcpkg was chosen due to the centralized nature of the project. To achieve the integration the CMake configuration has been altered but not by much: 1. Packages handled by vcpkg have been moved from externals/CMakeLists.txt to the root one to make them available to all subdirectories. 2. In addition now find_package is used in accordance to the vcpkg recommendations. 3. All libraries built by vcpkg have been updated to their latest available version, except for Qt because our codebase isn't compatible with Qt 6.0 yet. Currently there are build issues caused by the fmtlib upgrade. Another question is how to handle large libraries like Qt, Boost and SDL2 which will be addressed in a later commit. --- .gitmodules | 3 + CMakeLists.txt | 164 +++++++++++-------------- externals/CMakeLists.txt | 94 +------------- externals/vcpkg | 1 + src/common/CMakeLists.txt | 2 +- src/tests/CMakeLists.txt | 2 +- src/video_core/CMakeLists.txt | 7 +- src/web_service/CMakeLists.txt | 2 +- src/web_service/announce_room_json.cpp | 2 +- src/web_service/telemetry_json.cpp | 2 +- src/web_service/verify_login.cpp | 2 +- vcpkg.json | 47 +++++++ 12 files changed, 135 insertions(+), 193 deletions(-) create mode 160000 externals/vcpkg create mode 100644 vcpkg.json diff --git a/.gitmodules b/.gitmodules index 533cd078e..cec5bad83 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,6 @@ [submodule "externals/Vulkan-Headers"] path = externals/Vulkan-Headers url = https://github.com/KhronosGroup/Vulkan-Headers +[submodule "externals/vcpkg"] + path = externals/vcpkg + url = https://github.com/microsoft/vcpkg diff --git a/CMakeLists.txt b/CMakeLists.txt index 179a30e48..58e86f117 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,13 +9,15 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul include(DownloadExternals) include(CMakeDependentOption) +# Include vcpkg toolchain file +set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "Vcpkg toolchain file") + project(citra LANGUAGES C CXX ASM) # Set bundled sdl2/qt as dependent options. # OFF by default, but if ENABLE_SDL2 and MSVC are true then ON option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) -CMAKE_DEPENDENT_OPTION(CITRA_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) - option(ENABLE_QT "Enable the Qt frontend" ON) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) CMAKE_DEPENDENT_OPTION(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) @@ -41,8 +43,6 @@ CMAKE_DEPENDENT_OPTION(ENABLE_MF "Use Media Foundation decoder (preferred over F CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ON "MINGW" OFF) -option(USE_SYSTEM_BOOST "Use the system Boost libs (instead of the bundled ones)" OFF) - CMAKE_DEPENDENT_OPTION(ENABLE_FDK "Use FDK AAC decoder" OFF "NOT ENABLE_FFMPEG_AUDIO_DECODER;NOT ENABLE_MF" OFF) if(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit) @@ -138,64 +138,79 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/$) # System imported libraries # ====================== +# Boost +find_package(Boost REQUIRED COMPONENTS serialization) + +# Catch2 +find_package(Catch2 CONFIG REQUIRED) + +# Crypto++ +find_package(cryptopp CONFIG REQUIRED) + +# Xbyak +if (ARCHITECTURE_x86_64) + find_package(xbyak REQUIRED CONFIG) +endif() + +# libfmt +find_package(fmt CONFIG REQUIRED) + +# Zstandard +find_package(ZSTD CONFIG REQUIRED) + +# ENet +find_package(unofficial-enet CONFIG REQUIRED) + +# DiscordRPC +if (USE_DISCORD_PRESENCE) + find_package(discord-rpc CONFIG REQUIRED) +endif() + +if (ENABLE_WEB_SERVICE) + # OpenSSL + find_package(OpenSSL 1.1) + + # JSON + find_package(nlohmann_json CONFIG REQUIRED) + + # httplib + find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") + add_library(httplib INTERFACE) + target_include_directories(httplib INTERFACE ${CPP_HTTPLIB_INCLUDE_DIRS}) + + # cpp-jwt + find_package(cpp-jwt REQUIRED) +endif() + +# lodepng +find_package(lodepng REQUIRED) + +# (xperia64): Only use libyuv on Android b/c of build issues on Windows and mandatory JPEG +if(ANDROID) + # libyuv + find_package(yuv CONFIG REQUIRED) +endif() + # Prefer the -pthread flag on Linux. set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) if (ENABLE_SDL2) - if (CITRA_USE_BUNDLED_SDL2) - # Detect toolchain and platform - if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) - set(SDL2_VER "SDL2-2.0.16") - else() - message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRA_USE_BUNDLED_SDL2 and provide your own.") - endif() - - if (DEFINED SDL2_VER) - download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX) - endif() - - set(SDL2_FOUND YES) - set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers") - set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library") - set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll") - else() - find_package(SDL2 REQUIRED) - endif() + find_package(SDL2 CONFIG REQUIRED) if (SDL2_FOUND) - # TODO(yuriks): Make FindSDL2.cmake export an IMPORTED library instead add_library(SDL2 INTERFACE) - target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") - target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") + target_link_libraries(SDL2 INTERFACE SDL2::SDL2 SDL2::SDL2main) endif() else() set(SDL2_FOUND NO) endif() if (ENABLE_QT) - if (CITRA_USE_BUNDLED_QT) - if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) - set(QT_VER qt-5.10.0-msvc2017_64) - else() - message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable CITRA_USE_BUNDLED_QT and provide your own.") - endif() - - if (DEFINED QT_VER) - download_bundled_external("qt/" ${QT_VER} QT_PREFIX) - endif() - - set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") - else() - # Passing an empty HINTS seems to cause default system paths to get ignored in CMake 2.8 so - # make sure to not pass anything if we don't have one. - set(QT_PREFIX_HINT) - endif() - - find_package(Qt5 REQUIRED COMPONENTS Widgets Multimedia ${QT_PREFIX_HINT}) + find_package(Qt5 REQUIRED COMPONENTS Widgets Multimedia) if (ENABLE_QT_TRANSLATION) - find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT}) + find_package(Qt5 REQUIRED COMPONENTS LinguistTools) endif() endif() @@ -205,29 +220,20 @@ if(NOT APPLE) find_package(LibUSB) endif() if (NOT LIBUSB_FOUND) - add_subdirectory(externals/libusb) - set(LIBUSB_INCLUDE_DIR "") - set(LIBUSB_LIBRARIES usb) + find_package(libusb CONFIG) + + if (NOT ${libusb_FOUND}) + set(LIBUSB_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIR}) + set(LIBUSB_LIBRARIES ${LIBUSB_LIBRARY}) + endif() endif() if (ENABLE_FFMPEG) - if (CITRA_USE_BUNDLED_FFMPEG) - if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) - set(FFmpeg_VER "ffmpeg-4.1-win64") - else() - message(FATAL_ERROR "No bundled FFmpeg binaries for your toolchain. Disable CITRA_USE_BUNDLED_FFMPEG and provide your own.") - endif() - - if (DEFINED FFmpeg_VER) - download_bundled_external("ffmpeg/" ${FFmpeg_VER} FFmpeg_PREFIX) - set(FFMPEG_DIR "${FFmpeg_PREFIX}") - endif() - endif() - + find_package(PkgConfig REQUIRED) if (ENABLE_FFMPEG_VIDEO_DUMPER) - find_package(FFmpeg REQUIRED COMPONENTS avcodec avformat avutil swscale swresample) + find_package(FFMPEG REQUIRED COMPONENTS libavcodec libavformat libavutil libswresample) else() - find_package(FFmpeg REQUIRED COMPONENTS avcodec) + find_package(FFMPEG REQUIRED COMPONENTS libavcodec) endif() if ("${FFmpeg_avcodec_VERSION}" VERSION_LESS "57.48.101") message(FATAL_ERROR "Found version for libavcodec is too low. The required version is at least 57.48.101 (included in FFmpeg 3.1 and later).") @@ -265,15 +271,8 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$") endif() if (ENABLE_VULKAN) - # Find the VulkanSDK - find_package(Vulkan REQUIRED) - - set(SHADERC_SKIP_TESTS ON) - add_subdirectory(externals/shaderc) - set(SHADERC_DEP shaderc) - - # Include Vulkan Memory Allocator - add_subdirectory(externals/vma) + find_library(SHADERC_LIB shaderc) + find_library(SHADERC_UTIL_LIB shaderc_util) endif() # Setup a custom clang-format target (if clang-format can be found) that will run @@ -351,13 +350,6 @@ function(get_timestamp _var) set(${_var} "${timestamp}" PARENT_SCOPE) endfunction() -# Prevent boost from linking against libs when building -add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY - -DBOOST_SYSTEM_NO_LIB - -DBOOST_DATE_TIME_NO_LIB - -DBOOST_REGEX_NO_LIB -) - # generate git/build information include(GetGitRevisionDescription) get_git_head_revision(GIT_REF_SPEC GIT_REV) @@ -365,21 +357,9 @@ git_describe(GIT_DESC --always --long --dirty) git_branch_name(GIT_BRANCH) get_timestamp(BUILD_DATE) -if (NOT USE_SYSTEM_BOOST) - add_definitions( -DBOOST_ALL_NO_LIB ) -endif() - enable_testing() add_subdirectory(externals) -# Boost -if (USE_SYSTEM_BOOST) - find_package(Boost 1.70.0 COMPONENTS serialization REQUIRED) -else() - add_library(Boost::boost ALIAS boost) - add_library(Boost::serialization ALIAS boost_serialization) -endif() - add_subdirectory(src) add_subdirectory(dist/installer) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index b2df1930c..e7b3be124 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -9,34 +9,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) include(DownloadExternals) include(ExternalProject) -# Boost -set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost") -set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost") -set(Boost_NO_SYSTEM_PATHS ON) -add_library(boost INTERFACE) -target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR}) - -# Boost::serialization -file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp") -add_library(boost_serialization STATIC ${boost_serialization_SRC}) -target_link_libraries(boost_serialization PUBLIC boost) - -# Add additional boost libs here; remember to ALIAS them in the root CMakeLists! - -# Catch -add_library(catch-single-include INTERFACE) -target_include_directories(catch-single-include INTERFACE catch/single_include) - -# Crypto++ -add_subdirectory(cryptopp) - -# Xbyak -if (ARCHITECTURE_x86_64) - add_library(xbyak INTERFACE) - target_include_directories(xbyak SYSTEM INTERFACE ./xbyak/xbyak) - target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES) -endif() - # Dynarmic if (ARCHITECTURE_x86_64 OR ARCHITECTURE_ARM64) set(DYNARMIC_TESTS OFF) @@ -45,18 +17,11 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_ARM64) add_subdirectory(dynarmic) endif() -# libfmt -add_subdirectory(fmt) -add_library(fmt::fmt ALIAS fmt) - # getopt if (MSVC) add_subdirectory(getopt) endif() -# Glad -add_subdirectory(glad) - # inih add_subdirectory(inih) @@ -79,68 +44,13 @@ target_include_directories(SoundTouch INTERFACE ./soundtouch/include) # Teakra add_subdirectory(teakra EXCLUDE_FROM_ALL) -# Zstandard -add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL) -target_include_directories(libzstd_static INTERFACE $) - -# ENet -add_subdirectory(enet) -target_include_directories(enet INTERFACE ./enet/include) - # Cubeb if (ENABLE_CUBEB) set(BUILD_TESTS OFF CACHE BOOL "") add_subdirectory(cubeb EXCLUDE_FROM_ALL) endif() -# DiscordRPC -if (USE_DISCORD_PRESENCE) - add_subdirectory(discord-rpc EXCLUDE_FROM_ALL) - target_include_directories(discord-rpc INTERFACE ./discord-rpc/include) +if (ENABLE_WEB_SERVICE AND ANDROID) + add_subdirectory(android-ifaddrs) endif() -if (ENABLE_WEB_SERVICE) - find_package(OpenSSL 1.1) - if (OPENSSL_FOUND) - set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) - else() - # LibreSSL - set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "") - set(OPENSSLDIR "/etc/ssl/") - add_subdirectory(libressl EXCLUDE_FROM_ALL) - target_include_directories(ssl INTERFACE ./libressl/include) - target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP) - get_directory_property(OPENSSL_LIBRARIES - DIRECTORY libressl - DEFINITION OPENSSL_LIBS) - endif() - # JSON - add_library(json-headers INTERFACE) - target_include_directories(json-headers INTERFACE ./json) - - if(ANDROID) - add_subdirectory(android-ifaddrs) - endif() - - # httplib - add_library(httplib INTERFACE) - target_include_directories(httplib INTERFACE ./httplib) - target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT) - target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES}) - - # cpp-jwt - SET(CPP_JWT_USE_VENDORED_NLOHMANN_JSON ON CACHE BOOL "Use included json-hpp") - add_library(cpp-jwt INTERFACE) - target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include) - target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON) -endif() - -# lodepng -add_subdirectory(lodepng) - -# (xperia64): Only use libyuv on Android b/c of build issues on Windows and mandatory JPEG -if(ANDROID) - # libyuv - add_subdirectory(libyuv) - target_include_directories(yuv INTERFACE ./libyuv/include) -endif() diff --git a/externals/vcpkg b/externals/vcpkg new file mode 160000 index 000000000..8b14e7e87 --- /dev/null +++ b/externals/vcpkg @@ -0,0 +1 @@ +Subproject commit 8b14e7e8729c532b7c2be9e603b7ee886b62db6b diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index eaae35330..7c5ccb7c0 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -131,7 +131,7 @@ endif() create_target_directory_groups(common) -target_link_libraries(common PUBLIC fmt microprofile Boost::boost Boost::serialization) +target_link_libraries(common PUBLIC fmt::fmt microprofile Boost::boost Boost::serialization) target_link_libraries(common PRIVATE libzstd_static) if (ARCHITECTURE_x86_64) target_link_libraries(common PRIVATE xbyak) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index c6b222ef0..b7d27e508 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -24,6 +24,6 @@ endif() create_target_directory_groups(tests) target_link_libraries(tests PRIVATE common core video_core audio_core) -target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include nihstro-headers Threads::Threads) +target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} Catch2::Catch2 nihstro-headers Threads::Threads) add_test(NAME tests COMMAND tests) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3fed8319c..10fa3aeee 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -174,14 +174,15 @@ endif() create_target_directory_groups(video_core) +find_package(glad CONFIG REQUIRED) target_link_libraries(video_core PUBLIC common core) -target_link_libraries(video_core PRIVATE glad nihstro-headers Boost::serialization) +target_link_libraries(video_core PRIVATE glad::glad nihstro-headers Boost::serialization) # Include Vulkan headers target_include_directories(video_core PRIVATE ../../externals/Vulkan-Headers/include) target_include_directories(video_core PRIVATE ../../externals/vma/include) -target_link_libraries(video_core PRIVATE ${SHADERC_DEP}) +target_link_libraries(video_core PRIVATE ${SHADERC_LIB} ${SHADERC_UTIL_LIB}) if (ARCHITECTURE_x86_64) - target_link_libraries(video_core PUBLIC xbyak) + target_link_libraries(video_core PUBLIC xbyak::xbyak) endif() diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index b43eae5d1..5725dbb02 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt @@ -14,7 +14,7 @@ add_library(web_service STATIC create_target_directory_groups(web_service) target_compile_definitions(web_service PRIVATE -DCPPHTTPLIB_OPENSSL_SUPPORT) -target_link_libraries(web_service PRIVATE common network json-headers ${OPENSSL_LIBS} httplib cpp-jwt) +target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json ${OPENSSL_LIBS} httplib cpp-jwt) if (ANDROID) target_link_libraries(web_service PRIVATE ifaddrs) elseif(WIN32) diff --git a/src/web_service/announce_room_json.cpp b/src/web_service/announce_room_json.cpp index e64bd7ea4..4a2c9a8a5 100644 --- a/src/web_service/announce_room_json.cpp +++ b/src/web_service/announce_room_json.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include -#include +#include #include "common/detached_tasks.h" #include "common/logging/log.h" #include "web_service/announce_room_json.h" diff --git a/src/web_service/telemetry_json.cpp b/src/web_service/telemetry_json.cpp index 97d19f696..608fb78a6 100644 --- a/src/web_service/telemetry_json.cpp +++ b/src/web_service/telemetry_json.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include #include "common/detached_tasks.h" #include "common/web_result.h" #include "web_service/telemetry_json.h" diff --git a/src/web_service/verify_login.cpp b/src/web_service/verify_login.cpp index ca4b43b93..bfaa5b70a 100644 --- a/src/web_service/verify_login.cpp +++ b/src/web_service/verify_login.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include #include "common/web_result.h" #include "web_service/verify_login.h" #include "web_service/web_backend.h" diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 000000000..ba5287546 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", + "name": "citra-emu", + "version-string": "0.0.0", + "dependencies": [ + "boost-serialization", + "boost-system", + "boost-range", + "boost-optional", + "boost-icl", + "boost-date-time", + "boost-crc", + "boost-container", + "boost-asio", + "catch2", + "cpp-jwt", + "cryptopp", + "discord-rpc", + "enet", + "fmt", + { + "name": "glad", + "features": [ + "gl-api-33", + "gles2-api-32" + ] + }, + "glm", + "ffmpeg", + "fdk-aac", + "cpp-httplib", + "libressl", + "inih", + "nlohmann-json", + "libusb", + "libyuv", + "lodepng", + "shaderc", + "soundtouch", + "xbyak", + "zstd", + "sdl2", + "sdl2-image", + "qt5-base", + "qt5-multimedia" + ] +} \ No newline at end of file