Skip to content

Commit

Permalink
feat: initial Vcpkg + CMake build for Windows. It don't need prebuilt…
Browse files Browse the repository at this point in the history
… binaries
  • Loading branch information
shenlebantongying committed May 14, 2024
1 parent e7c5967 commit 3856e1e
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 47 deletions.
87 changes: 66 additions & 21 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
cmake_minimum_required(VERSION 3.25) # ubuntu 23.04 Fedora 36

# Qt6.4+ only

option(WITH_FFMPEG_PLAYER "Enable support for FFMPEG player" ON)
option(WITH_EPWING_SUPPORT "Enable epwing support" ON)
option(WITH_ZIM "enable zim support" ON)
Expand All @@ -11,13 +9,18 @@ option(WITH_TTS "enable QTexttoSpeech support" ON)
option(USE_SYSTEM_FMT "use system fmt instead of bundled one" OFF)
option(USE_SYSTEM_TOML "use system toml++ instead of bundled one" OFF)

# vcpkg build - only tested on Windows, does not support FFMPEG
option(USE_VCPKG "uses VCPKG for providing dependencies" OFF)

## Change binary & resources folder to parallel install with original GD.
## This flag should be avoided because it leads to small regressions:
## 1. There are personal scripts assuming the binary name to be "goldendict" -> require everyone to change the name in their script
## 2. There are icon themes that assuming the icon name to be "goldendict" -> invalidate the GD icon when using a icon theme
## 3. There are dictionary packages that install files to "/usr/share/goldendict/content" -> nullify the auto dict discovery
option(USE_ALTERNATIVE_NAME "Force the name goldendict-ng " OFF)

set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}") # to put staff in the ./cmake folder

include(FeatureSummary)

project(goldendict-ng
Expand Down Expand Up @@ -144,6 +147,10 @@ target_include_directories(${GOLDENDICT} PRIVATE
${PROJECT_SOURCE_DIR}/src/ui
)

if (WIN32)
target_include_directories(${GOLDENDICT} PRIVATE ${PROJECT_SOURCE_DIR}/src/windows)
endif ()

if (NOT USE_SYSTEM_TOML)
target_include_directories(${GOLDENDICT} PRIVATE ${PROJECT_SOURCE_DIR}/thirdparty/tomlplusplus)
endif ()
Expand All @@ -161,6 +168,13 @@ target_compile_definitions(${GOLDENDICT} PUBLIC
MAKE_CHINESE_CONVERSION_SUPPORT
)

if (WIN32)
target_compile_definitions(${GOLDENDICT} PUBLIC
__WIN32
INCLUDE_LIBRARY_PATH
)
endif ()

if (WITH_FFMPEG_PLAYER)
target_compile_definitions(${GOLDENDICT} PUBLIC MAKE_FFMPEG_PLAYER)
endif ()
Expand All @@ -180,10 +194,12 @@ endif ()

#### libraries linking && includes for Win or Unix

if (WIN32)
include(CMake_Win.cmake)
if (USE_VCPKG)
include(Deps_Vcpkg)
elseif (WIN32)
include(Deps_Win)
else ()
include(CMake_Unix.cmake)
include(Deps_Unix)
endif ()

#### add translations
Expand All @@ -197,9 +213,12 @@ if (WIN32)
else ()
set_source_files_properties(${TRANS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/locale")
endif ()
# a wrapper over qt_add_lupdate and qt_add_lrelease

qt_add_translations(${GOLDENDICT} TS_FILES ${TRANS_FILES}
QM_FILES_OUTPUT_VARIABLE qm_files)
if (WIN32) # TODO: check other OS
add_dependencies(${GOLDENDICT} "goldendict-ng_lrelease")
endif ()

#### installation or assemble redistribution

Expand Down Expand Up @@ -279,34 +298,60 @@ if (LINUX OR BSD)
endif ()

if (WIN32)

set_target_properties(${GOLDENDICT}
PROPERTIES
WIN32_EXECUTABLE TRUE
RUNTIME_OUTPUT_DIRECTORY "${GD_WIN_OUTPUT_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${GD_WIN_OUTPUT_DIR}"
)

add_custom_target(windeploy
COMMENT "Deploy everything to the output dir"
DEPENDS ${GOLDENDICT} # build this target will check if Goldendict.exe is already built
COMMAND ${WINDEPLOYQT_EXECUTABLE} --no-quick-import "${GD_WIN_OUTPUT_DIR}/${GOLDENDICT}.exe" --plugindir "${GD_WIN_OUTPUT_DIR}/plugins"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/opencc" "${GD_WIN_OUTPUT_DIR}/opencc"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/LICENSE.txt" "${GD_WIN_OUTPUT_DIR}/LICENSE.txt"
COMMAND ${CMAKE_COMMAND} -E rm -f "${GD_WIN_OUTPUT_DIR}/goldendict.exe.manifest" "${GD_WIN_OUTPUT_DIR}/eb.dll.manifest"
WORKING_DIRECTORY ${GD_WIN_OUTPUT_DIR}
)
if (NOT USE_VCPKG)
add_custom_target(windeploy
COMMENT "Deploy everything to the output dir"
DEPENDS ${GOLDENDICT} # build this target will check if Goldendict.exe is already built
COMMAND ${WINDEPLOYQT_EXECUTABLE} --no-quick-import "${GD_WIN_OUTPUT_DIR}/${GOLDENDICT}.exe" --plugindir "${GD_WIN_OUTPUT_DIR}/plugins"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/opencc" "${GD_WIN_OUTPUT_DIR}/opencc"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/LICENSE.txt" "${GD_WIN_OUTPUT_DIR}/LICENSE.txt"
COMMAND ${CMAKE_COMMAND} -E rm -f "${GD_WIN_OUTPUT_DIR}/goldendict.exe.manifest" "${GD_WIN_OUTPUT_DIR}/eb.dll.manifest"
WORKING_DIRECTORY ${GD_WIN_OUTPUT_DIR}
)

# use CPack to make the output folder as NSIS installer
install(
DIRECTORY "${GD_WIN_OUTPUT_DIR}/"
DESTINATION .
)
else () # VCPKG deploy
set(CMAKE_INSTALL_PREFIX "${GD_WIN_OUTPUT_DIR}" CACHE PATH "If you see this message, don't change this unless you want look into CMake build script. If you are an expert, yes, this is wrong. Help welcomed." FORCE)

qt_generate_deploy_script(
TARGET ${GOLDENDICT}
OUTPUT_SCRIPT deploy_script
CONTENT "qt_deploy_runtime_dependencies(
EXECUTABLE \"${CMAKE_INSTALL_PREFIX}/goldendict.exe\"
BIN_DIR .
LIB_DIR .
)"
)

install(SCRIPT ${deploy_script})
install(DIRECTORY "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/opencc" DESTINATION .)
# TODO: do we really need to carry a copy of openSSL?
install(FILES "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libssl-3-x64.dll" DESTINATION .)
install(FILES "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/libcrypto-3-x64.dll" DESTINATION .)
endif ()

set(CPACK_PACKAGE_FILE_NAME "${Qt6Widgets_VERSION}-${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
# trick CPack to make the output folder as NSIS installer
install(DIRECTORY "${GD_WIN_OUTPUT_DIR}/"
DESTINATION .
FILES_MATCHING
PATTERN "*"
PATTERN "*.pdb" EXCLUDE
PATTERN "*.ilk" EXCLUDE)


set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-Qt${Qt6Widgets_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_GENERATOR "7Z;NSIS")
set(CPACK_NSIS_MANIFEST_DPI_AWARE ON)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
include(CPack)

endif ()

feature_summary(WHAT ALL DESCRIPTION "Build configuration:")
File renamed without changes.
35 changes: 35 additions & 0 deletions cmake/Deps_Vcpkg.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
find_package(BZip2 REQUIRED)
find_package(Iconv REQUIRED)
find_package(LibLZMA REQUIRED)
find_package(Vorbis CONFIG REQUIRED)
find_package(ZLIB REQUIRED)

find_package(PkgConfig REQUIRED)
pkg_check_modules(PKGCONFIG_DEPS IMPORTED_TARGET
hunspell
libzim
lzo2
opencc
xapian-core
)

target_link_libraries(${GOLDENDICT}
PRIVATE
PkgConfig::PKGCONFIG_DEPS
BZip2::BZip2
Iconv::Iconv
LibLZMA::LibLZMA
Vorbis::vorbis
Vorbis::vorbisfile
ZLIB::ZLIB
)

if (WITH_EPWING_SUPPORT)
add_subdirectory(thirdparty/eb EXCLUDE_FROM_ALL)
target_include_directories(${GOLDENDICT} PRIVATE
thirdparty
)
target_link_libraries(${GOLDENDICT} PRIVATE eb)

set_target_properties(eb PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${GD_WIN_OUTPUT_DIR})
endif ()
5 changes: 0 additions & 5 deletions CMake_Win.cmake → cmake/Deps_Win.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
target_compile_definitions(${GOLDENDICT} PUBLIC
__WIN32
INCLUDE_LIBRARY_PATH # temporal hack to let singleapplication compile
)

target_include_directories(${GOLDENDICT} PUBLIC
${CMAKE_SOURCE_DIR}/winlibs/include/
)
Expand Down
2 changes: 1 addition & 1 deletion goldendict.pro
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ win32 {
}

RC_ICONS += icons/programicon.ico icons/programicon_old.ico
INCLUDEPATH += winlibs/include
INCLUDEPATH += winlibs/include src/windows

# Enable console in Debug mode on Windows, with useful logging messages
Debug:CONFIG += console
Expand Down
30 changes: 15 additions & 15 deletions winlibs/include/stub_msvc.h → src/windows/stub_msvc.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#include <string>
#ifdef _MSC_VER
#if !defined(strcasecmp)
# define strcasecmp _strcmpi
#endif
#if !defined(strncasecmp)
# define strncasecmp _strnicmp
#endif

#ifndef _SSIZE_T
#define _SSIZE_T
#define ssize_t long
#endif
#endif

#include <string>
#ifdef _MSC_VER
#if !defined(strcasecmp)
# define strcasecmp _strcmpi
#endif
#if !defined(strncasecmp)
# define strncasecmp _strnicmp
#endif

#ifndef _SSIZE_T
#define _SSIZE_T
#define ssize_t long
#endif
#endif

14 changes: 14 additions & 0 deletions vcpkg-configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"default-registry": {
"kind": "git",
"baseline": "a1212c93cabaa9c5c36c1ffdb4bddd59fdf31e43",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [
{
"kind": "artifact",
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
"name": "microsoft"
}
]
}
17 changes: 17 additions & 0 deletions vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "goldendict-ng",
"version": "24.5.5",
"dependencies": [
"bzip2",
"hunspell",
"libiconv",
"liblzma",
"libvorbis",
"libzim",
"lzo",
"opencc",
"xapian",
"zlib",
"openssl"
]
}
25 changes: 20 additions & 5 deletions website/docs/howto/build_from_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,36 @@ Install Qt6(msvc) through the standard installer and pass Qt's path to CMake
```
-DCMAKE_PREFIX_PATH=F:\Qt\6.4.1\msvc2019_64
```

The built artifacts will end up in `build_dir/goldendict`

To run the built `goldendict.exe` directly, you have to add `F:\Qt\6.5.2\msvc2019_64\bin` to your PATH environment variable
#### Using pre-built winlibs

To have a redistributable goldendict (runable on someone else's computer by just copying the folder), you can build the deployment target which will copy necessary files to the folder
Use `windeploy` target to copy necessary runtime files.

```
cmake --build . --target windeploy
```

The `build_dir/goldendict` will be ready to share with others.
Or you can also manually run `windeployqt.exe {your_build_dir}/goldendict.exe` which will copy the qt related things to `build_dir`.

#### Using Vcpkg

The dependencies can be built via Vcpkg instead of using the pre-built ones.

Vcpkg CMake build utilize the "manifest mode", all you need to do is basically
set `CMAKE_TOOLCHAIN_FILE` as described [here](https://learn.microsoft.com/en-us/vcpkg/consume/manifest-mode?tabs=cmake%2Cbuild-MSBuild#2---integrate-vcpkg-with-your-build-system).

Add this to cmake command:
```sh
-DUSE_VCPKG=ON
```

Use`windeployqt.exe {your_build_dir}/goldendict.exe` which will copy the qt related `.dll` and other necessary files automatically.
Most `.dll` built by vcpkg will be automatically copied, but the Qt ones won't.

You can
* run `cmake --install .` (recommended)
* manually run windeployqt
* add `${Qt's install path}\Qt\6.5.2\msvc2019_64\bin` to your PATH environment variable

### macOS

Expand Down

0 comments on commit 3856e1e

Please sign in to comment.