本記事はJUCE Advent Calendar 2022 の12月8日向けに投稿した記事です。
対象バージョン
- JUCE 7.0.3
- Visual Studio 2022
- Xcode 14.1
- CMake 3.15以上
- Git 2.0以上
まとめ
- JUCEにvcpkgを組み合わせることで、コマンドラインからC/C++パッケージをJUCEプロジェクトに追加することができます。
- 実例として、vcpkgからSoundTouchを取得してJUCEプロジェクトに組み込んだオーディオプラグインを作ってみました。
JUCEとは
JUCE (Jules' Utility Class Extensions)は、C++言語によるマルチメディア系アプリケーションの開発を支援するフレームワークです。
ライブラリの一部モジュールとして独自のGUIシステムを実装しており、開発者はそのAPIを利用することで、クロスプラットフォームなGUIアプリケーションを統一したコードベースで実装することができます。
公式サイト
vcpkgとは
vcpkgは、Microsoft社が開発・保守しているC/C++言語向けのパッケージマネージャです。クロスプラットフォーム設計のパッケージマネージャとなっており、Windows、macOS、Linuxから利用することができます。
vcpkgを使用することで、ライブラリ毎に個別にビルド、インクルード、リンクする作業の手間をvcpkgが代わりに行ってくれます。複数のライブラリを利用するような大規模なアプリケーション開発で効果を発揮します。
公式サイト
CMakeとは
CMakeは、主にC言語、C++言語などC系言語のビルドにおけるクロスプラットフォームビルド環境を提供するビルドマネジメントツールの一つです。ソフトウェアのビルドにおける一連の処理をCMakeLists.txtに記述し、CMakeプログラムを通じて各種プラットフォーム用のビルドツールに向けたプロジェクトを出力することができます。
公式サイト
JUCEライブラリ と CMake
2020年にリリースされたJUCE 6から、ビルドマネジメントツール『CMake』のサポートが追加されました。
JUCEがCMakeをサポートすることで以下のメリットを得ることができるようになりました。
- ビルド設定をCMake用のフォーマットで記述することができる
- CMakeのエコシステムの恩恵を受けることができる
- CMakeが独自に提供する機能を利用することができる
- CMakeに対応した他のライブラリとのインテグレーションが容易になる
JUCEとvcpkgを組み合わせるにあたって
本記事を執筆している時点では、JUCEをvcpkg経由で取得することはできません。そのため、JUCEをインテグレーションするという作業については、以下で解説するように自前でCMakeListsを書く必要があります。
実例のソースコードリポジトリ
JUCEとvcpkgを組み合わせる方法の事例を示すリポジトリを以下に用意しました。
このリポジトリに含まれるソースをビルドすると、以下のようなGUIを持つオーディオプラグインが生成されます。
任意のWAVファイルをロードすることができるワンショット・サンプラーとなっており、シンセサイザーのサウンドに対してSoundTouchライブラリによるピッチシフト処理を適用しています。
・音声サンプルデータの経路
シンセサイザー(juce::Synthesiser)→ピッチシフター(SoundTouch)→オーディオバッファ出力(プラグイン・インターフェース)
本記事では、アプリケーションの実装については解説せず、プロジェクトを構成するCMake用ファイルおよびシェルスクリプトの要点について解説します。
リポジトリのクローン操作について
当ソースコードリポジトリでは、GitHubに置かれたvcpkg
,JUCE
リポジトリをGitサブモジュールとして取り込んでいます。
そのため、リポジトリのクローン時にはサブモジュールも併せてクローンするようにしてください。
git clone --recursive https://github.com/COx2/juce_meets_soundtouch.git
リポジトリのディレクトリ構成について
juce_meets_soundtouch
├── External ......... Gitサブモジュールを配置するディレクトリ
├── Resources ........ バイナリ化してアプリケーションで利用するリソースファイルを配置するディレクトリ
├── Scripts .......... ビルド用のスクリプトを配置するディレクトリ
└── Source ........... ソースファイルを配置するディレクトリ
プロジェクトのビルド手順について
当ソースコードリポジトリでは、vcpkgのインストール処理とCMakeのビルド処理をシェルスクリプトにまとめています。
Windows
./Scripts/install_vcpkg_x64-windows.bat
./Scripts/build_windows_vs2022.bat
macOS
./Scripts/install_vcpkg_x64-osx.command
./Scripts/build_macos_xcode.command
Linux
./Scripts/install_vcpkg_x64-linux.sh
./Scripts/build_linux_ninja.sh
vcpkgのインストールスクリプト
vcpkgのインストール処理における主要な処理について紹介します。
Windows
@echo off
set SCRIPT_DIRECTORY=%~dp0
cd "%SCRIPT_DIRECTORY%\..\External\vcpkg"
call .\bootstrap-vcpkg.bat
.\vcpkg install soundtouch:x64-windows-static
exit /B 0
vcpkgの初期化処理
call .\bootstrap-vcpkg.bat
SoundTouchパッケージ(Windows用静的ライブラリ)の追加処理
.\vcpkg install soundtouch:x64-windows-static
macOS
#!/bin/bash
set -e -u -o pipefail
realpath() {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
SCRIPT_NAME="$(basename "$(realpath "$0")")"
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
cd "${SCRIPT_DIR}/../External/vcpkg"
./bootstrap-vcpkg.sh
./vcpkg install soundtouch:x64-osx
vcpkgの初期化処理
./bootstrap-vcpkg.sh
SoundTouchパッケージ(macOS用)の追加処理
./vcpkg install soundtouch:x64-osx
Linux
#!/bin/bash
set -e -u -o pipefail
realpath() {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
SCRIPT_NAME="$(basename "$(realpath "$0")")"
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
cd "${SCRIPT_DIR}/../External/vcpkg"
./bootstrap-vcpkg.sh
./vcpkg install soundtouch:x64-linux
vcpkgの初期化処理
./bootstrap-vcpkg.sh
SoundTouchパッケージ(Linux用)の追加処理
./vcpkg install soundtouch:x64-linux
CMakeLists.txt
当ソースコードリポジトリのルートディレクトリに置かれたCMakeLists.txtの一部を示します。
移行、vcpkgとのインテグレーションに関連する重要な点について解説します。
cmake_minimum_required(VERSION 3.15)
# To be enabled integrate vcpkg installed packages.
# NOTE: CMAKE_TOOLCHAIN_FILE is should setted in startup
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/External/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE PATH "toolchain file")
project(JUCE_MEETS_SOUNDTOUCH VERSION 0.0.1)
# static linking in Windows
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Adds all the module sources so they appear correctly in the IDE
set_property(GLOBAL PROPERTY USE_FOLDERS YES)
option(JUCE_ENABLE_MODULE_SOURCE_GROUPS "Enable Module Source Groups" ON)
# Add JUCE Package
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/External/JUCE)
# Add SoundTouch package
find_package(SoundTouch CONFIG REQUIRED)
juce_add_plugin(JuceMeetsSoundTouch
VERSION 0.0.1
# ICON_BIG ...
# ICON_SMALL ...
# COMPANY_NAME ...
IS_SYNTH TRUE
NEEDS_MIDI_INPUT TRUE
# NEEDS_MIDI_OUTPUT TRUE/FALSE
# IS_MIDI_EFFECT TRUE/FALSE
# EDITOR_WANTS_KEYBOARD_FOCUS TRUE/FALSE
# COPY_PLUGIN_AFTER_BUILD TRUE/FALSE
PLUGIN_MANUFACTURER_CODE COx2
PLUGIN_CODE Jmst
FORMATS AU VST3 Standalone
PRODUCT_NAME "JUCE meets SoundTouch")
juce_generate_juce_header(JuceMeetsSoundTouch)
set_property(TARGET JuceMeetsSoundTouch PROPERTY CXX_STANDARD 17)
...中略
target_sources(JuceMeetsSoundTouch
PRIVATE
${APP_SOURCES}
)
target_compile_definitions(JuceMeetsSoundTouch
PRIVATE
# JUCE_WEB_BROWSER and JUCE_USE_CURL would be on by default, but you might not need them.
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
JUCE_VST3_CAN_REPLACE_VST2=0
JUCE_APPLICATION_NAME_STRING="$<TARGET_PROPERTY:JuceMeetsSoundTouch,JUCE_PRODUCT_NAME>"
JUCE_APPLICATION_VERSION_STRING="$<TARGET_PROPERTY:JuceMeetsSoundTouch,JUCE_VERSION>"
DONT_SET_USING_JUCE_NAMESPACE=1)
...中略
juce_add_binary_data(PcmSamplesData SOURCES ${PCM_SAMPLES_RESOURCES})
target_link_libraries(JuceMeetsSoundTouch
PRIVATE
SoundTouch::SoundTouch
PcmSamplesData
juce::juce_audio_utils
PUBLIC
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
juce::juce_recommended_warning_flags)
ツールチェインファイルの指定
このJUCEプロジェクトが参照するvcpkgおよびパッケージ一式を指定します。
コマンドラインから引数として-DCMAKE_TOOLCHAIN_FILE=/Path/to/vcpkg
渡すことで指定することも可能です。
# To be enabled integrate vcpkg installed packages.
# NOTE: CMAKE_TOOLCHAIN_FILE is should setted in startup
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/External/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE PATH "toolchain file")
SoundTouchパッケージをCMakeプロジェクトに取り込む
# Add SoundTouch package
find_package(SoundTouch CONFIG REQUIRED)
この記述内容は、vcpkgからパッケージを追加する操作をした際に実行結果の表示で案内されます。
上記ツールチェインファイルで指定したvcpkg配下からパッケージを探してもらうことができます。
vcpkgコマンドラインツールからの案内
soundtouch provides CMake targets:
# this is heuristically generated, and may not be correct
find_package(SoundTouch CONFIG REQUIRED)
target_link_libraries(main PRIVATE SoundTouch::SoundTouch)
この案内に従って、該当する記述をCMakeLists.txtに追加しています。
SoundTouchライブラリを実行可能プログラムにリンクさせる
target_link_libraries(JuceMeetsSoundTouch
PRIVATE
SoundTouch::SoundTouch
...
この記述内容も上記と同様に、vcpkgからパッケージを追加する操作をした際に実行結果の表示で案内されます。
上記ツールチェインファイルで指定したvcpkg配下からパッケージを探してもらうことができます。
vcpkgコマンドラインツールからの案内
soundtouch provides CMake targets:
# this is heuristically generated, and may not be correct
find_package(SoundTouch CONFIG REQUIRED)
target_link_libraries(main PRIVATE SoundTouch::SoundTouch)
この案内に従って該当する記述をCMakeLists.txtに追加しています。
ビルド実行命令の記述
CMakeのGenerate処理を実行する際にの引数として-DVCPKG_TARGET_TRIPLET
を指定してください。引数として渡す値はvcpkg操作時に選択したパッケージと同じtripletを渡すことでvcpkgでインストールしたパッケージとリンクされます。
Windows
…中略
cmake -B Build-Release -G "%GENERATOR_VS2022%" . -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=x64-windows-static
cmake --build Build-Release --config Release
…中略
macOS
…中略
cmake -B Build-Release -G "Xcode" . -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -DVCPKG_TARGET_TRIPLET=x64-osx
cmake --build Build-Release --config Release
…中略
Linux
…中略
cmake -B Build-Release -G "Ninja" . -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=x64-linux
cmake --build Build-Release --config Release
…中略