diff --git a/external/angle/CMakeLists.txt b/external/angle/CMakeLists.txt index 60664fb..bd043b6 100644 --- a/external/angle/CMakeLists.txt +++ b/external/angle/CMakeLists.txt @@ -21,4 +21,8 @@ if (WIN32) INTERFACE desktop-app::win_directx_helper ) + target_compile_definitions(external_angle + INTERFACE + KHRONOS_STATIC + ) endif() diff --git a/external/jemalloc/CMakeLists.txt b/external/jemalloc/CMakeLists.txt index 7aa2cc7..377cf1d 100644 --- a/external/jemalloc/CMakeLists.txt +++ b/external/jemalloc/CMakeLists.txt @@ -18,28 +18,26 @@ endif() if (NOT JEMALLOC_FOUND) add_library(external_jemalloc_bundled STATIC IMPORTED GLOBAL) + set(jemalloc_loc ${third_party_loc}/jemalloc) include(ExternalProject) ExternalProject_Add(jemalloc - URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 - CONFIGURE_COMMAND cd "${CMAKE_CURRENT_BINARY_DIR}/jemalloc-prefix/src/jemalloc" && ./configure + SOURCE_DIR ${jemalloc_loc} + CONFIGURE_COMMAND cd "${jemalloc_loc}" && ./autogen.sh INSTALL_COMMAND : BUILD_IN_SOURCE 1 - BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/jemalloc-prefix/src/jemalloc/lib/libjemalloc.a + BUILD_BYPRODUCTS ${jemalloc_loc}/lib/libjemalloc.a ) - ExternalProject_Get_property(jemalloc SOURCE_DIR) - ExternalProject_Get_property(jemalloc BINARY_DIR) - - file(MAKE_DIRECTORY "${SOURCE_DIR}/include") + file(MAKE_DIRECTORY "${jemalloc_loc}/include") set_target_properties(external_jemalloc_bundled PROPERTIES - IMPORTED_LOCATION "${BINARY_DIR}/lib/libjemalloc.a" + IMPORTED_LOCATION "${jemalloc_loc}/lib/libjemalloc.a" ) target_include_directories(external_jemalloc_bundled SYSTEM INTERFACE - ${SOURCE_DIR}/include + ${jemalloc_loc}/include ) target_link_libraries(external_jemalloc_bundled diff --git a/external/qt/CMakeLists.txt b/external/qt/CMakeLists.txt index c877682..2635442 100644 --- a/external/qt/CMakeLists.txt +++ b/external/qt/CMakeLists.txt @@ -276,29 +276,6 @@ else() INTERFACE ${qt_loc}/mkspecs/linux-g++ ) - target_link_options(external_qt - INTERFACE - -static-libstdc++ - -pthread - -rdynamic - ) - if (DESKTOP_APP_USE_ALLOCATION_TRACER) - target_link_options(external_qt - INTERFACE - # -Wl,-wrap,__malloc - -Wl,-wrap,__libc_malloc - -Wl,-wrap,malloc - -Wl,-wrap,valloc - -Wl,-wrap,pvalloc - -Wl,-wrap,calloc - -Wl,-wrap,realloc - -Wl,-wrap,memalign - -Wl,-wrap,aligned_alloc - -Wl,-wrap,posix_memalign - -Wl,-wrap,free - -Wl,--no-as-needed,-lrt - ) - endif() target_link_static_libraries(external_qt INTERFACE proxy @@ -320,13 +297,6 @@ else() xcb-render-util xcb-keysyms ) - if (DESKTOP_APP_USE_ALLOCATION_TRACER) - target_link_libraries(external_qt - INTERFACE - desktop-app::linux_allocation_tracer - $ - ) - endif() if (Qt5WaylandClient_FOUND) target_link_libraries(external_qt INTERFACE diff --git a/init_target.cmake b/init_target.cmake index 3ee7e94..2f52b57 100644 --- a/init_target.cmake +++ b/init_target.cmake @@ -18,19 +18,19 @@ endfunction() function(init_target target_name) # init_target(my_target folder_name) if (ARGC GREATER 1) if (${ARGV1} STREQUAL cxx_std_14 OR ${ARGV1} STREQUAL cxx_std_11 OR ${ARGV1} STREQUAL cxx_std_17) - target_compile_features(${target_name} PUBLIC ${ARGV1}) + target_compile_features(${target_name} PRIVATE ${ARGV1}) else() - target_compile_features(${target_name} PUBLIC ${MAXIMUM_CXX_STANDARD}) + target_compile_features(${target_name} PRIVATE ${MAXIMUM_CXX_STANDARD}) init_target_folder(${target_name} ${ARGV1}) endif() else() - target_compile_features(${target_name} PUBLIC ${MAXIMUM_CXX_STANDARD}) + target_compile_features(${target_name} PRIVATE ${MAXIMUM_CXX_STANDARD}) endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set_target_properties(${target_name} PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() - target_link_libraries(${target_name} PUBLIC desktop-app::common_options) + target_link_libraries(${target_name} PRIVATE desktop-app::common_options) if (NOT DESKTOP_APP_USE_PACKAGED) set_target_properties(${target_name} PROPERTIES LINK_SEARCH_START_STATIC 1) endif() diff --git a/linux_allocation_tracer/CMakeLists.txt b/linux_allocation_tracer/CMakeLists.txt index ea8c3cc..ddac091 100644 --- a/linux_allocation_tracer/CMakeLists.txt +++ b/linux_allocation_tracer/CMakeLists.txt @@ -21,6 +21,4 @@ PRIVATE linux_allocation_trace_reader.cpp ) -target_link_options(allocation_trace_reader PRIVATE -static-libstdc++) - set_target_properties(allocation_trace_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/linux_allocation_tracer/linux_allocation_trace_reader.cpp b/linux_allocation_tracer/linux_allocation_trace_reader.cpp index a1cf487..d78f8f1 100644 --- a/linux_allocation_tracer/linux_allocation_trace_reader.cpp +++ b/linux_allocation_tracer/linux_allocation_trace_reader.cpp @@ -1,10 +1,9 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// #include #include #include diff --git a/linux_allocation_tracer/linux_allocation_tracer.cpp b/linux_allocation_tracer/linux_allocation_tracer.cpp index 03cfa7b..99a88fd 100644 --- a/linux_allocation_tracer/linux_allocation_tracer.cpp +++ b/linux_allocation_tracer/linux_allocation_tracer.cpp @@ -1,10 +1,9 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// #include "linux_allocation_tracer.h" #include diff --git a/linux_allocation_tracer/linux_allocation_tracer.h b/linux_allocation_tracer/linux_allocation_tracer.h index f9e362f..90c71f8 100644 --- a/linux_allocation_tracer/linux_allocation_tracer.h +++ b/linux_allocation_tracer/linux_allocation_tracer.h @@ -1,10 +1,9 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// #pragma once #include diff --git a/nuget.cmake b/nuget.cmake index b420923..7aba5c9 100644 --- a/nuget.cmake +++ b/nuget.cmake @@ -69,7 +69,6 @@ function(nuget_add_webview target_name) PRIVATE ${webview2_loc_native}/${webview2_lib_folder}/WebView2LoaderStatic.lib ) - endfunction() function(nuget_add_winrt target_name) diff --git a/options_linux.cmake b/options_linux.cmake index fdd75d4..73ce72a 100644 --- a/options_linux.cmake +++ b/options_linux.cmake @@ -40,12 +40,8 @@ if (DESKTOP_APP_SPECIAL_TARGET) target_compile_options(common_options INTERFACE -g0) target_link_options(common_options INTERFACE -g0) else() - target_compile_options(common_options INTERFACE $,,-g>) - target_link_options(common_options INTERFACE $,,-g>) - if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - target_compile_options(common_options INTERFACE $,,-flto>) - target_link_options(common_options INTERFACE $,,-flto -fuse-linker-plugin>) - endif() + target_compile_options(common_options INTERFACE $,,-g -flto>) + target_link_options(common_options INTERFACE $,,-g -flto -fuse-linker-plugin>) endif() endif() @@ -54,6 +50,53 @@ INTERFACE desktop-app::external_jemalloc ) +if (DESKTOP_APP_USE_ALLOCATION_TRACER) + target_link_options(common_options + INTERFACE + # -Wl,-wrap,__malloc + -Wl,-wrap,__libc_malloc + -Wl,-wrap,malloc + -Wl,-wrap,valloc + -Wl,-wrap,pvalloc + -Wl,-wrap,calloc + -Wl,-wrap,realloc + -Wl,-wrap,memalign + -Wl,-wrap,aligned_alloc + -Wl,-wrap,posix_memalign + -Wl,-wrap,free + -Wl,--no-as-needed,-lrt + ) + target_link_libraries(common_options + INTERFACE + desktop-app::linux_allocation_tracer + $ + ) +endif() + +if (NOT DESKTOP_APP_USE_PACKAGED) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_link_options(common_options + INTERFACE + -static-libstdc++ + ) + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_link_static_libraries(common_options + INTERFACE + c++ + c++abi + ) + target_link_options(common_options + INTERFACE + -nostdlib++ + ) + endif() + target_link_options(common_options + INTERFACE + -pthread + -rdynamic + ) +endif() + if (DESKTOP_APP_USE_PACKAGED) find_library(ATOMIC_LIBRARY atomic) else() diff --git a/run_cmake.py b/run_cmake.py index 754af06..ae4b89d 100644 --- a/run_cmake.py +++ b/run_cmake.py @@ -1,10 +1,9 @@ -''' -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. +# This file is part of Desktop App Toolkit, +# a set of libraries for developing nice desktop applications. +# +# For license and copyright information please follow this link: +# https://github.com/desktop-app/legal/blob/master/LEGAL -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -''' import sys, os, shutil, subprocess def run(project, arguments, buildType=''): diff --git a/validate_d3d_compiler.cmake b/validate_d3d_compiler.cmake new file mode 100644 index 0000000..5330b52 --- /dev/null +++ b/validate_d3d_compiler.cmake @@ -0,0 +1,82 @@ +# This file is part of Desktop App Toolkit, +# a set of libraries for developing nice desktop applications. +# +# For license and copyright information please follow this link: +# https://github.com/desktop-app/legal/blob/master/LEGAL + +function(validate_d3d_error text) + if (NOT DESKTOP_APP_SPECIAL_TARGET STREQUAL "") + message(FATAL_ERROR ${text}) + else() + message(WARNING ${text}) + endif() +endfunction() + +function(validate_d3d_compiler target_name) + if (build_win64) + set(modules_subdir x64) + else() + set(modules_subdir x86) + endif() + set(modules_hash_loc ${CMAKE_BINARY_DIR}/modules/${modules_subdir}) + set(modules_debug_loc ${CMAKE_BINARY_DIR}/Debug/modules/${modules_subdir}) + set(modules_release_loc ${CMAKE_BINARY_DIR}/Release/modules/${modules_subdir}) + + set(key_path ${modules_hash_loc}/d3d/d3dcompiler_47) + set(module_debug_path ${modules_debug_loc}/d3d) + set(module_release_path ${modules_release_loc}/d3d) + + set(key "") + if (EXISTS ${key_path}) + file(READ ${key_path} key) + endif() + + if (NOT "$ENV{WindowsSdkDir}" STREQUAL "") + set(windows_sdk_loc $ENV{WindowsSdkDir} CACHE INTERNAL "Windows SDK Path" FORCE) + endif() + + string(LENGTH "${key}" key_length) + if (NOT "${key_length}" STREQUAL "32" + OR NOT EXISTS ${module_debug_path}/d3dcompiler_47.dll + OR NOT EXISTS ${module_release_path}/d3dcompiler_47.dll) + + if ("${windows_sdk_loc}" STREQUAL "") + validate_d3d_error("Could not find Windows SDK.") + return() + endif() + set(sdk_compiler ${windows_sdk_loc}/Redist/D3D/${modules_subdir}/d3dcompiler_47.dll) + + find_package(Python REQUIRED) + execute_process( + COMMAND + ${Python_EXECUTABLE} + ${cmake_helpers_loc}/validate_d3d_compiler.py + ${sdk_compiler} + OUTPUT_VARIABLE key + ERROR_VARIABLE error + ) + if (NOT "${error}" STREQUAL "") + validate_d3d_error(${error}) + return() + endif() + + file(MAKE_DIRECTORY ${modules_debug_loc}/d3d) + file(COPY ${sdk_compiler} DESTINATION ${module_debug_path}) + + file(MAKE_DIRECTORY ${modules_release_loc}/d3d) + file(COPY ${sdk_compiler} DESTINATION ${module_release_path}) + + file(MAKE_DIRECTORY ${modules_hash_loc}/d3d) + file(WRITE ${key_path} ${key}) + endif() + + target_compile_definitions(${target_name} + PRIVATE + DESKTOP_APP_D3DCOMPILER_HASH=${key} + ) + + target_link_libraries(${target_name} + PRIVATE + desktop-app::external_openssl + ) +endfunction() diff --git a/validate_d3d_compiler.py b/validate_d3d_compiler.py new file mode 100644 index 0000000..3106ea0 --- /dev/null +++ b/validate_d3d_compiler.py @@ -0,0 +1,35 @@ +# This file is part of Desktop App Toolkit, +# a set of libraries for developing nice desktop applications. +# +# For license and copyright information please follow this link: +# https://github.com/desktop-app/legal/blob/master/LEGAL + +from __future__ import print_function +import sys, os, re, hashlib + +def error(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + sys.exit(1) + +try: + from win32api import GetFileVersionInfo +except ImportError: + error('Python module "pywin32" is not installed.\n\nTry "' + sys.executable + ' -m pip install pywin32".') + +if len(sys.argv) < 2: + error('Expected input path to "d3dcompiler_47.dll".') + +inputPath = sys.argv[1] +if not os.path.exists(inputPath): + error('File "' + inputPath + '" doesn\'t exist.') + +info = GetFileVersionInfo(inputPath, '\\') +version = [ info['FileVersionMS'] // 65536, info['FileVersionMS'] % 65536, info['FileVersionLS'] // 65536, info['FileVersionLS'] % 65536 ] +if (version != [10, 0, 20348, 1 ]): + error('Bad "d3dcompiler_47.dll" version: ' + '.'.join(str(x) for x in version)) + +bufferSize = 1024 * 1024 +sha256 = hashlib.sha256() + +with open(inputPath, 'rb') as f: + print(hashlib.sha256(f.read()).hexdigest()) diff --git a/variables.cmake b/variables.cmake index 59a60e0..ce56f8b 100644 --- a/variables.cmake +++ b/variables.cmake @@ -96,10 +96,16 @@ else() report_bad_special_target() endif() endif() - if (DESKTOP_APP_SPECIAL_TARGET AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CMAKE_AR "gcc-ar") - set(CMAKE_RANLIB "gcc-ranlib") - set(CMAKE_NM "gcc-nm") + if (DESKTOP_APP_SPECIAL_TARGET) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_AR "gcc-ar") + set(CMAKE_RANLIB "gcc-ranlib") + set(CMAKE_NM "gcc-nm") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_AR "llvm-ar") + set(CMAKE_RANLIB "llvm-ranlib") + set(CMAKE_NM "llvm-nm") + endif() endif() endif() diff --git a/win_directx_helper/CMakeLists.txt b/win_directx_helper/CMakeLists.txt index c98935c..889f8a9 100644 --- a/win_directx_helper/CMakeLists.txt +++ b/win_directx_helper/CMakeLists.txt @@ -12,3 +12,10 @@ nice_target_sources(win_directx_helper ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE win_directx_helper.cpp ) + +validate_d3d_compiler(win_directx_helper) + +target_link_libraries(win_directx_helper +PUBLIC + desktop-app::external_openssl +) diff --git a/win_directx_helper/win_directx_helper.cpp b/win_directx_helper/win_directx_helper.cpp index d987a32..13a90f0 100644 --- a/win_directx_helper/win_directx_helper.cpp +++ b/win_directx_helper/win_directx_helper.cpp @@ -7,15 +7,45 @@ #include #include +#include +extern "C" { +#include +} // extern "C" #include +#include +#include #define LOAD_SYMBOL(handle, func) LoadSymbol(handle, #func, func) namespace DirectX { namespace { +constexpr auto kMaxPathLong = 32767; + using Handle = HINSTANCE; +// d3dcompiler_47.dll + +HRESULT (__stdcall *D3DCompile)( + LPCVOID pSrcData, + SIZE_T SrcDataSize, + LPCSTR pFileName, + CONST D3D_SHADER_MACRO* pDefines, + ID3DInclude* pInclude, + LPCSTR pEntrypoint, + LPCSTR pTarget, + UINT Flags1, + UINT Flags2, + ID3DBlob** ppCode, + ID3DBlob** ppErrorMsgs); + +HRESULT (__stdcall *D3DDisassemble)( + _In_reads_bytes_(SrcDataSize) LPCVOID pSrcData, + _In_ SIZE_T SrcDataSize, + _In_ UINT Flags, + _In_opt_ LPCSTR szComments, + _Out_ ID3DBlob** ppDisassembly); + // d3d9.dll IDirect3D9 * (__stdcall *Direct3DCreate9)(UINT SDKVersion); @@ -56,6 +86,102 @@ inline bool LoadSymbol(Handle handle, const char *name, Function &func) { return (func != nullptr); } +// For win_directx_helper. +std::string FileSha256(const wchar_t *path) { + using uchar = unsigned char; + constexpr auto kLimit = 10 * 1024 * 1024; + auto buffer = std::vector(kLimit); + auto size = DWORD(); + + const auto file = CreateFile( + path, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr); + if (file == INVALID_HANDLE_VALUE) { + return {}; + } + const auto read = ReadFile(file, buffer.data(), kLimit, &size, nullptr); + CloseHandle(file); + + if (!read || !size || size >= kLimit) { + return {}; + } + auto binary = std::array{}; + SHA256(buffer.data(), size, binary.data()); + const auto hex = [](uchar value) { + return (value >= 10) ? ('a' + (value - 10)) : ('0' + value); + }; + auto result = std::string(); + result.reserve(binary.size() * 2); + auto index = 0; + for (const auto byte : binary) { + result.push_back(hex(byte / 16)); + result.push_back(hex(byte % 16)); + } + return result; +} + +bool ResolveD3DCompiler(const wchar_t *path) { + const auto d3dcompiler = LoadLibrary(path); + return true + && LOAD_SYMBOL(d3dcompiler, D3DCompile) + && LOAD_SYMBOL(d3dcompiler, D3DDisassemble); +} + +bool ResolveD3DCompiler() { + static const auto loaded = [] { +#ifdef DESKTOP_APP_D3DCOMPILER_HASH + auto exePath = std::array{ 0 }; + const auto exeLength = GetModuleFileName( + nullptr, + exePath.data(), + kMaxPathLong + 1); + if (!exeLength || exeLength >= kMaxPathLong + 1) { + return false; + } + const auto exe = std::wstring(exePath.data()); + const auto last1 = exe.find_last_of('\\'); + const auto last2 = exe.find_last_of('/'); + const auto last = std::max( + (last1 == std::wstring::npos) ? -1 : int(last1), + (last2 == std::wstring::npos) ? -1 : int(last2)); + if (last < 0) { + return false; + } + +#if defined _WIN64 + const auto arch = L"x64"; +#elif defined _WIN32 // _WIN64 + const auto arch = L"x86"; +#else // _WIN64 || _WIN32 +#error "Invalid configuration." +#endif // _WIN64 || _WIN32 + +#define DESKTOP_APP_STRINGIFY2(x) #x +#define DESKTOP_APP_STRINGIFY(x) DESKTOP_APP_STRINGIFY2(x) + const auto hash = DESKTOP_APP_STRINGIFY(DESKTOP_APP_D3DCOMPILER_HASH); +#undef DESKTOP_APP_STRINGIFY +#undef DESKTOP_APP_STRINGIFY2 + + const auto compiler = exe.substr(0, last + 1) + + L"modules\\" + arch + L"\\d3d\\d3dcompiler_47.dll"; + const auto path = compiler.c_str(); + if (FileSha256(path) == hash && ResolveD3DCompiler(path)) { + return true; + } +#elif defined DESKTOP_APP_SPECIAL_TARGET // DESKTOP_APP_D3DCOMPILER_HASH +#error "Special target build should have d3dcompiler hash." +#endif // !DESKTOP_APP_D3DCOMPILER_HASH && DESKTOP_APP_SPECIAL_TARGET + + return ResolveD3DCompiler(L"d3dcompiler_47.dll"); + }(); + return loaded; +} + bool ResolveD3D9() { static const auto loaded = [] { const auto d3d9 = LoadLibrary(L"d3d9.dll"); @@ -63,7 +189,7 @@ bool ResolveD3D9() { LOAD_SYMBOL(d3d9, D3DPERF_EndEvent); LOAD_SYMBOL(d3d9, D3DPERF_SetMarker); LOAD_SYMBOL(d3d9, D3DPERF_GetStatus); - return true + return ResolveD3DCompiler() && LOAD_SYMBOL(d3d9, Direct3DCreate9); }(); return loaded; @@ -72,7 +198,7 @@ bool ResolveD3D9() { bool ResolveD3D11() { static const auto loaded = [] { const auto d3d11 = LoadLibrary(L"d3d11.dll"); - return true + return ResolveD3DCompiler() && LOAD_SYMBOL(d3d11, D3D11CreateDevice); }(); return loaded; @@ -91,6 +217,10 @@ bool ResolveDXGI() { } // namespace } // namespace DirectX +bool DirectXResolveCompiler() { + return DirectX::ResolveD3DCompiler(); +} + namespace D = DirectX; extern "C" {