Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: add cmake support #995

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/cmake-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: cmake ci
on: [workflow_dispatch]
jobs:
build:
runs-on: macos-14
steps:
- name: Checkout last commit
uses: actions/checkout@v4
with:
submodules: recursive
- name: Configure build environment
run: |
brew install ninja rsync
- name: Build
run: |
make -Clibrime deps
bash librime/install-plugins.sh hchunhui/librime-lua lotem/librime-octagram rime/librime-predict
cmake -S. -Bbuild -GNinja -DCMAKE_OSX_DEPLOYMENT_TARGET=13 -DCMAKE_BUILD_TYPE=Release
ninja -Cbuild
20 changes: 10 additions & 10 deletions Assets.xcassets/RimeIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,61 +1,61 @@
{
"images" : [
{
"filename" : "rime-16 1.png",
"filename" : "icon-16x16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "rime-32 1.png",
"filename" : "icon-16x16@2.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "rime-32.png",
"filename" : "icon-32x32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "rime-64.png",
"filename" : "icon-32x32@2.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "rime-128.png",
"filename" : "icon-128x128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "rime-256.png",
"filename" : "icon-128x128@2.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "rime-256.png",
"filename" : "icon-256x256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "rime-512.png",
"filename" : "icon-256x256@2.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "rime-512.png",
"filename" : "icon-512x512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "rime-1024.png",
"filename" : "icon-512x512@2.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
cmake_minimum_required(VERSION 3.30)
project(squirrel VERSION 1.0.2 LANGUAGES CXX Swift)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

# ##############################################################################
# Options
# ##############################################################################
set(DEV_ID "UNSET" CACHE STRING "Dev ID for code-signing")
set(SIGN_KEY "UNSET" CACHE STRING "Sign key for code-signing")
option(FIXUP_WHEN_BUILD "Fix-up the app bundle in build time" ON)

if(NOT (DEV_ID STREQUAL "UNSET") AND (SIGN_KEY STREQUAL "UNSET"))
set(SIGN_KEY "Developer ID Application: ${DEV_ID}")
endif()

# ##############################################################################
# Dependencies
# ##############################################################################
include(AddSparkle)
include(AddRime)

# ##############################################################################
# Squirrel.app
# ##############################################################################
file(GLOB SRCS "${PROJECT_SOURCE_DIR}/Sources/*.swift")
add_executable(Squirrel MACOSX_BUNDLE ${SRCS})
target_compile_options(Squirrel PRIVATE
-import-objc-header "${PROJECT_SOURCE_DIR}/Sources/Squirrel-Bridging-Header.h"
-enable-bare-slash-regex
)
target_include_directories(Squirrel PRIVATE
"${PROJECT_SOURCE_DIR}/Sources"
"${PROJECT_SOURCE_DIR}/librime/src"
)
target_link_libraries(Squirrel PRIVATE rime Sparkle)

set(BUNDLE_PATH "${PROJECT_BINARY_DIR}/Squirrel.app")
set(BUNDLE_CONTENTS_DIR "${BUNDLE_PATH}/Contents")
set(BUNDLE_BIN_DIR "${BUNDLE_CONTENTS_DIR}/MacOS")
set(BUNDLE_RESOURCES_DIR "${BUNDLE_CONTENTS_DIR}/Resources")
set(BUNDLE_FRAMEWORKS_DIR "${BUNDLE_CONTENTS_DIR}/Frameworks")
set(BUNDLE_SHARED_SUPPORT_DIR "${BUNDLE_CONTENTS_DIR}/SharedSupport")

set_target_properties(Squirrel PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER im.rime.inputmethod.Squirrel
MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION}
)

# Copy additional binaries
file(GLOB RIME_PROGRAMS "${CMAKE_BINARY_DIR}/librime/bin/rime_*")
add_custom_command(TARGET Squirrel POST_BUILD
COMMAND cp -a "${CMAKE_BINARY_DIR}/librime/bin/rime_*" ${BUNDLE_BIN_DIR})

# Copy resources
add_subdirectory(resources)

# Copy built-in schemas
add_subdirectory(data)

# Copy linked frameworks and libraries
add_custom_command(TARGET Squirrel POST_BUILD
COMMAND rsync -a "${CMAKE_CURRENT_BINARY_DIR}/librime/lib/" "${BUNDLE_FRAMEWORKS_DIR}"
--exclude pkgconfig
)
add_custom_command(TARGET Squirrel POST_BUILD
COMMAND rsync -a "${CMAKE_BINARY_DIR}/Sparkle.framework"
"${BUNDLE_FRAMEWORKS_DIR}"
--exclude=Headers --exclude=PrivateHeaders --exclude=Modules
)

# Fix linking so that the bundle is standalone
set(FIXUP_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/fixup.cmake)
set(FIXUP_DIRS "${BUNDLE_FRAMEWORKS_DIR}")
file(WRITE ${FIXUP_SCRIPT} "
include(BundleUtilities)
file(GLOB PLUGINS ${BUNDLE_FRAMEWORKS_DIR}/rime-plugins/*.dylib)
fixup_bundle(\"${BUNDLE_PATH}\" \"\${PLUGINS}\" \"${FIXUP_DIRS}\")
")
if(${FIXUP_WHEN_BUILD})
add_custom_command(TARGET Squirrel POST_BUILD
COMMAND ${CMAKE_COMMAND} -P ${FIXUP_SCRIPT}
)
endif()

# Install (for development)
set(CMAKE_SKIP_RPATH TRUE) # done by fixup_bundle
install(SCRIPT ${FIXUP_SCRIPT})
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target sign)")
install(TARGETS Squirrel BUNDLE DESTINATION "/Library/Input\ Methods")

# ##############################################################################
# Distribution
# ##############################################################################
add_subdirectory(package)
22 changes: 22 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,25 @@ make clean-package
If you want to clean all above, do all.

That's it, a verbal journal. Thanks for riming with Squirrel.

## Build with CMake

Alternatively, Squirrel can be built with CMake.

(Note that universal binaries are not supported, and Xcode command line tools are still required.)

```sh
# Prepare librime
make -Clibrime deps
bash librime/install-plugins.sh hchunhui/librime-lua lotem/librime-octagram rime/librime-predict # and more...

# Build squirrel
cmake -S. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 -DDEV_ID='YourDevID'
cd build
ninja # Create build/Squirrel.app
ninja sign # Code-sign build/Squirrel.app (*)
ninja package # Create package/Squirrel.pkg (*)
ninja install # Directly install to '/Library/Input Methods' (*)
```

(*) `sign`, `install`, and `package` require code-signing `DEV_ID` or `SIGN_KEY` to be set. `SIGN_KEY` will take precedence over `DEV_ID`.
2 changes: 1 addition & 1 deletion action-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

rime_version=latest
rime_git_hash=24f0f7b
rime_git_hash=0cf0e63
sparkle_version=2.6.2

rime_archive="rime-${rime_git_hash}-macOS-universal.tar.bz2"
Expand Down
22 changes: 22 additions & 0 deletions cmake/AddRime.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
include(ExternalProject)

ExternalProject_Add(BuildRime
SOURCE_DIR "${PROJECT_SOURCE_DIR}/librime"
INSTALL_DIR "${PROJECT_BINARY_DIR}/librime"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DBUILD_MERGED_PLUGINS=OFF
-DENABLE_EXTERNAL_PLUGINS=ON
-DBUILD_TEST=OFF
)

add_library(rime INTERFACE)
add_dependencies(rime BuildRime)
target_include_directories(rime INTERFACE "${PROJECT_BINARY_DIR}/librime/include")
target_link_directories(rime INTERFACE "${PROJECT_BINARY_DIR}/librime/lib/")
target_link_libraries(rime INTERFACE -lrime)

find_path(X11Keysym X11/keysym.h)
target_include_directories(rime INTERFACE ${X11Keysym})
18 changes: 18 additions & 0 deletions cmake/AddSparkle.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
include(ExternalProject)

ExternalProject_Add(BuildSparkle
SOURCE_DIR "${PROJECT_SOURCE_DIR}/Sparkle"

CONFIGURE_COMMAND ""

BUILD_COMMAND xcodebuild -project "<SOURCE_DIR>/Sparkle.xcodeproj" -scheme Sparkle -configuration Release
BUILD_IN_SOURCE TRUE

# Install Sparkle.framework
INSTALL_COMMAND cp -a "<SOURCE_DIR>/build/Release/Sparkle.framework" "${CMAKE_BINARY_DIR}"
)

add_library(Sparkle INTERFACE)
add_dependencies(Sparkle BuildSparkle)
target_include_directories(Sparkle INTERFACE "${CMAKE_BINARY_DIR}/Sparkle.framework/Headers")
target_link_libraries(Sparkle INTERFACE "${CMAKE_BINARY_DIR}/Sparkle.framework")
10 changes: 10 additions & 0 deletions cmake/AppleUtils.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
macro(process_xcstrings path outdir)
get_filename_component(basename ${path} NAME_WLE)
set(target ${outdir}/en.lproj/${basename}.strings)
add_custom_command(
OUTPUT ${target}
COMMAND xcrun xcstringstool compile ${path} --output-directory ${outdir}
COMMENT "Process ${basename}.xcstrings"
)
add_custom_target(xcstrings_${basename} ALL DEPENDS ${target})
endmacro()
21 changes: 21 additions & 0 deletions data/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
set(OUTDIR "${BUNDLE_SHARED_SUPPORT_DIR}")

# ##############################################################################
# Plum
# ##############################################################################
add_custom_command(
OUTPUT "${OUTDIR}/default.yaml"
COMMAND make "OUTPUT=${OUTDIR}" -C "${PROJECT_SOURCE_DIR}/plum"
COMMENT "plum: update default schemas")
add_custom_target(plum-data ALL
DEPENDS "${OUTDIR}/default.yaml")

# ##############################################################################
# OpenCC
# ##############################################################################
add_custom_command(
OUTPUT "${OUTDIR}/opencc/s2t.json"
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/librime/share/opencc ${OUTDIR}/opencc
COMMENT "opencc: copy data")
add_custom_target(opencc-data ALL
DEPENDS "${OUTDIR}/opencc/s2t.json")
2 changes: 1 addition & 1 deletion librime
12 changes: 12 additions & 0 deletions package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_custom_target(sign
COMMAND codesign --deep --force --options runtime --timestamp --verbose
--entitlements "${PROJECT_SOURCE_DIR}/resources/Squirrel.entitlements"
--sign "${SIGN_KEY}" "${BUNDLE_PATH}"
DEPENDS Squirrel
)

add_custom_target(package
COMMAND ./make_package
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS sign
)
9 changes: 8 additions & 1 deletion package/make_package
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ INSTALL_LOCATION='/Library/Input Methods'
cd "$(dirname $0)"
source common.sh

if [ -e "${PROJECT_ROOT}/build/Squirrel.app" ]; then
ROOT=`mktemp -d`
cp -a "${PROJECT_ROOT}/build/Squirrel.app" "$ROOT"
else
ROOT="${PROJECT_ROOT}/${DERIVED_DATA_PATH}/Build/Products/Release"
fi

pkgbuild \
--info PackageInfo \
--root "${PROJECT_ROOT}/${DERIVED_DATA_PATH}/Build/Products/Release" \
--root "$ROOT" \
--filter '.*\.swiftmodule$' \
--component-plist Squirrel-component.plist \
--identifier "${BUNDLE_IDENTIFIER}" \
Expand Down
31 changes: 31 additions & 0 deletions resources/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Info.plist
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist" INFO_PLIST)
string(REPLACE "$(PRODUCT_BUNDLE_IDENTIFIER)" "@MACOSX_BUNDLE_GUI_IDENTIFIER@" INFO_PLIST "${INFO_PLIST}")
string(REPLACE "$(CURRENT_PROJECT_VERSION)" "@MACOSX_BUNDLE_BUNDLE_VERSION@" INFO_PLIST "${INFO_PLIST}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/Info.plist" "${INFO_PLIST}")
set_target_properties(Squirrel PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
)

# Static resources
set(FILES
${PROJECT_SOURCE_DIR}/README.md
${PROJECT_SOURCE_DIR}/LICENSE.txt
rime.pdf
)
foreach(f ${FILES})
get_filename_component(filename ${f} NAME)
configure_file(${f} ${BUNDLE_RESOURCES_DIR}/${filename} COPYONLY)
endforeach()

# Localization
include(AppleUtils)
process_xcstrings(${CMAKE_CURRENT_SOURCE_DIR}/Localizable.xcstrings ${BUNDLE_RESOURCES_DIR})
process_xcstrings(${CMAKE_CURRENT_SOURCE_DIR}/InfoPlist.xcstrings ${BUNDLE_RESOURCES_DIR})

# RimeIcon.icns
add_custom_command(
OUTPUT ${BUNDLE_RESOURCES_DIR}/RimeIcon.icns
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/Assets.xcassets/RimeIcon.appiconset ${CMAKE_BINARY_DIR}/RimeIcon.iconset && iconutil -c icns ${CMAKE_BINARY_DIR}/RimeIcon.iconset -o ${BUNDLE_RESOURCES_DIR}/RimeIcon.icns
)
add_custom_target(RimeIcon.icns ALL DEPENDS ${BUNDLE_RESOURCES_DIR}/RimeIcon.icns)
Loading