CMakeを使っていた所、CMakeのバージョンが原因でGLEWを検索できない問題に出会った。こういう出会いは大切にしたい。そこでCMakeについて考える事にした。
WebでアクセスできるCMakeの情報をざっくりまとめる
CMakeとHomeBrew
macOSでCMakeを使う場合いくつかの方法があるが、ここではHomeBrewを使ってCMakeをインストールする。HomeBrewとはmacOS用のパッケージマネージャで、様々なツールを brew
コマンドでインストールできる。
どのようにインストールするかといった情報は、フォーミュラと呼ばれるRubyスクリプトで記述されていて、通常はhttps://github.com/Homebrew/homebrew-coreで管理されているが、これは自分で作成する事もできる。CMakeのフォーミュラはhttps://github.com/Homebrew/homebrew-core/blob/master/Formula/cmake.rbにある。現在のmasterブランチにあるフォーミュラを確認すると 3.27.0
のバージョンのCMakeがインストールされる事がわかる。
とりあえず雑にCMakeをインストールしておく事にする。
brew install cmake
シンプルなCMakeの構成
CMakeを使ってビルドができるように構成を整えていく。
simpleというディレクトリを作成し、その中に最小の構成を作成する。
mkdir -p simple
このディレクトリの中にプログラムのソースコードとなるファイルを作成する。ここでは便宜上 main.c
というファイルを作成し、とりあえずCで実装する。
#include <stdio.h>
int main () {
printf("Ok\n");
}
次にCMakeの設定を作成する。 CMakeLists.txt
という名前でファイルを作成し add_executable
コマンドを使い、先程の main.c
を登録する。ここでは testing
という実行可能ファイルを出力するように設定する。
add_executable (testing main.c)
以下のようなディレクトリの構成となった。
tree simple
simple |-- CMakeLists.txt `-- main.c 1 directory, 2 files
これをビルドしていく。CMakeでは2つのコマンドを実行する事でビルドを行う。1つめは cmake -S ディレクトリ
で、CMakeの設定を元にビルドに必要なファイルを生成する。
cmake -S simple -B .build
-- The C compiler identification is AppleClang 13.1.6.13160021 -- The CXX compiler identification is AppleClang 13.1.6.13160021 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.7s) -- Generating done (0.0s) -- Build files have been written to: /opt/ng/symdon/pages/posts/1678518623/.build
-B .build
にはファイルを生成するディレクトリを指定するが、これは省略する事もできる。
省略すると現在の作業ディレクトリに生成される。幾つかのディレクトリとファイルが生成され、ビルドのための準備が整えられる。整うと .build
ディレクトリは次のような構成となる。
tree .build
.build |-- CMakeCache.txt |-- CMakeFiles | |-- 3.26.4 | | |-- CMakeCCompiler.cmake | | |-- CMakeCXXCompiler.cmake | | |-- CMakeDetermineCompilerABI_C.bin | | |-- CMakeDetermineCompilerABI_CXX.bin | | |-- CMakeSystem.cmake | | |-- CompilerIdC | | | |-- CMakeCCompilerId.c | | | |-- CMakeCCompilerId.o | | | `-- tmp | | `-- CompilerIdCXX | | |-- CMakeCXXCompilerId.cpp | | |-- CMakeCXXCompilerId.o | | `-- tmp | |-- CMakeConfigureLog.yaml | |-- CMakeDirectoryInformation.cmake | |-- CMakeScratch | |-- Makefile.cmake | |-- Makefile2 | |-- TargetDirectories.txt | |-- cmake.check_cache | |-- pkgRedirects | |-- progress.marks | `-- testing.dir | |-- DependInfo.cmake | |-- build.make | |-- cmake_clean.cmake | |-- compiler_depend.make | |-- compiler_depend.ts | |-- depend.make | |-- flags.make | |-- link.txt | `-- progress.make |-- Makefile `-- cmake_install.cmake 10 directories, 28 files
生成したファイルを使い、実行可能ファイルをビルドする。ビルドには cmake -build
コマンドを実行する。
cmake --build .build
[100%] Built target testing
正常にビルドされると .build/testing
という実行可能ファイルが生成される。
.build/testing
Ok
GLEWを読み込むような構成を作る
この問題に取り組もうと思ったきっかけは Evolution Gym
というツールをビルドしようとした時に、GLEWやGLFWを読み込めなくて苦労した事がきっかけだった。その時は pip
を使用し Evolution Gym
のインストールを試みると、 pip
は以下のエラーを出力していた。
Obtaining file:///opt/ng/evogym Installing build dependencies ... done Checking if build backend supports build_editable ... done Getting requirements to build editable ... done Preparing editable metadata (pyproject.toml) ... done Building wheels for collected packages: evogym Building editable for evogym (pyproject.toml) ... error error: subprocess-exited-with-error × Building editable for evogym (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [136 lines of output] running editable_wheel creating /private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info writing /private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info/PKG-INFO writing dependency_links to /private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info/dependency_links.txt writing top-level names to /private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info/top_level.txt writing manifest file '/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info/SOURCES.txt' reading manifest file '/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file '/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym.egg-info/SOURCES.txt' creating '/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym-1.0.0.dist-info' creating /private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-wheel-id944k49/.tmp-s0dt4vyl/evogym-1.0.0.dist-info/WHEEL running build_py running build_ext -- The C compiler identification is AppleClang 13.1.6.13160021 -- The CXX compiler identification is AppleClang 13.1.6.13160021 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Found OpenGL: /Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk/System/Library/Frameworks/OpenGL.framework CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message): Could NOT find GLEW (missing: GLEW_INCLUDE_DIRS GLEW_LIBRARIES) Call Stack (most recent call first): /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE) /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindGLEW.cmake:238 (find_package_handle_standard_args) CMakeLists.txt:22 (find_package) -- Configuring incomplete, errors occurred! Traceback (most recent call last): File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 155, in run self._create_wheel_file(bdist_wheel) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 344, in _create_wheel_file files, mapping = self._run_build_commands(dist_name, unpacked, lib, tmp) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 267, in _run_build_commands self._run_build_subcommands() File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 294, in _run_build_subcommands self.run_command(name) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/cmd.py", line 318, in run_command self.distribution.run_command(command) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/dist.py", line 1234, in run_command super().run_command(command) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 988, in run_command cmd_obj.run() File "<string>", line 32, in run File "<string>", line 57, in build_extension File "/usr/local/Cellar/[email protected]/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/subprocess.py", line 413, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['cmake', '/opt/ng/evogym/evogym/simulator', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/opt/ng/evogym/evogym', '-DPYTHON_EXECUTABLE=/Users/sximada/.venv/py311/bin/python3.11', '-DCMAKE_BUILD_TYPE=Release']' returned non-zero exit status 1. /private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py:988: _DebuggingTips: Problem in editable installation. !! ******************************************************************************** An error happened while installing `evogym` in editable mode. The following steps are recommended to help debug this problem: - Try to install the project normally, without using the editable mode. Does the error still persist? (If it does, try fixing the problem before attempting the editable mode). - If you are using binary extensions, make sure you have all OS-level dependencies installed (e.g. compilers, toolchains, binary libraries, ...). - Try the latest version of setuptools (maybe the error was already fixed). - If you (or your project dependencies) are using any setuptools extension or customization, make sure they support the editable mode. After following the steps above, if the problem still persists and you think this is related to how setuptools handles editable installations, please submit a reproducible example (see https://stackoverflow.com/help/minimal-reproducible-example) to: https://github.com/pypa/setuptools/issues See https://setuptools.pypa.io/en/latest/userguide/development_mode.html for details. ******************************************************************************** !! cmd_obj.run() Traceback (most recent call last): File "/Users/sximada/.venv/py311/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module> main() File "/Users/sximada/.venv/py311/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main json_out['return_val'] = hook(**hook_input['kwargs']) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sximada/.venv/py311/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 273, in build_editable return hook(wheel_directory, config_settings, metadata_directory) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 445, in build_editable return self._build_with_temp_dir( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 401, in _build_with_temp_dir self.run_setup() File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 338, in run_setup exec(code, locals()) File "<string>", line 61, in <module> File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/__init__.py", line 107, in setup return distutils.core.setup(**attrs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 185, in setup return run_commands(dist) ^^^^^^^^^^^^^^^^^^ File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 201, in run_commands dist.run_commands() File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 969, in run_commands self.run_command(cmd) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/dist.py", line 1234, in run_command super().run_command(command) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 988, in run_command cmd_obj.run() File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 155, in run self._create_wheel_file(bdist_wheel) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 344, in _create_wheel_file files, mapping = self._run_build_commands(dist_name, unpacked, lib, tmp) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 267, in _run_build_commands self._run_build_subcommands() File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/command/editable_wheel.py", line 294, in _run_build_subcommands self.run_command(name) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/cmd.py", line 318, in run_command self.distribution.run_command(command) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/dist.py", line 1234, in run_command super().run_command(command) File "/private/var/folders/0m/47l1rtnx3s9dzk560gpfykh00000gp/T/pip-build-env-v_3va8s2/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 988, in run_command cmd_obj.run() File "<string>", line 32, in run File "<string>", line 57, in build_extension File "/usr/local/Cellar/[email protected]/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/subprocess.py", line 413, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['cmake', '/opt/ng/evogym/evogym/simulator', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/opt/ng/evogym/evogym', '-DPYTHON_EXECUTABLE=/Users/sximada/.venv/py311/bin/python3.11', '-DCMAKE_BUILD_TYPE=Release']' returned non-zero exit status 1. [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building editable for evogym Failed to build evogym ERROR: Could not build wheels for evogym, which is required to install pyproject.toml-based projects [notice] A new release of pip is available: 23.1.2 -> 23.2.1 [notice] To update, run: pip install --upgrade pip
もう、この時点でいろんな事を諦めてしまいそうだが、エラーメッセージの最後の方をよく見ると次の出力がある。
subprocess.CalledProcessError: Command '['cmake', '/opt/ng/evogym/evogym/simulator', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/opt/ng/evogym/evogym', '-DPYTHON_EXECUTABLE=/Users/sximada/.venv/py311/bin/python3.11', '-DCMAKE_BUILD_TYPE=Release']' returned non-zero exit status 1.
このログからcmakeコマンドを使ってシミュレータをビルドしようとして、失敗している事が何となくわかる。このコマンドは手でも実行できそうであるため、実行する事にした。実行するのは以下のようなコマンドだ。
cmake /opt/ng/evogym/evogym/simulator -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/opt/ng/evogym/evogym -DPYTHON_EXECUTABLE=/Users/sximada/.venv/py311/bin/python3.11 -DCMAKE_BUILD_TYPE=Release
これは当然失敗するのだが、エラーメッセージからヒントを得られる。
bash-5.2$ cmake /opt/ng/evogym/evogym/simulator -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/opt/ng/evogym/evogy CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake Could NOT find GLEW (missing: GLEW_INCLUDE_DIRS GLEW_LIBRARIES) Call Stack (most recent call first): /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_ /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindGLEW.cmake:238 (find_package_handle_standard CMakeLists.txt:22 (find_package) -- Configuring incomplete, errors occurred!
ここまで来るとようやく FindGLEW.cmake
でGLEWが見つけられていないという想像が付く。環境変数が足りていないようにも思える。そこで、それなりの値を設定して再度実行する事にした。
bash-5.2$ export GLEW_INCLUDE_DIRS=/opt/ng/evogym/evogym/simulator/externals/glew/include bash-5.2$ export GLEW_LIBRARIES=/opt/ng/evogym/evogym/simulator/externals/glew/lib/libGLEW.2.2.0.dylib bash-5.2$ cmake /opt/ng/evogym/evogym/simulator -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/opt/ng/evogym/evogym -DPYTHON_EXECUTABLE=/Users/sximada/.venv/py311/bin/python3.11 -DCMAKE_BUILD_TYPE=Release CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message): Could NOT find GLEW (missing: GLEW_INCLUDE_DIRS GLEW_LIBRARIES) Call Stack (most recent call first): /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE) /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindGLEW.cmake:238 (find_package_handle_standard_args) CMakeLists.txt:22 (find_package) -- Configuring incomplete, errors occurred!
これでも特に変化はない。本当にやりたい事は、この問題を解消する事だけれど、ここまでやってみて、それはちょっと込み入っているように思えた。だから、もっと小さな構成を作って調査を進めたい。ここでは、先程の simple
配下のファイルををベースにして、 use-glew
ディレクトリを作り、GLEWを利用するようなコードを実装する事で、ビルド時に Evolution Gym
と同じようなエラーを発生させられるような構成を作る。通常ではGLEWは別途インストールする必要があるのだが Evolution Gym
はGLEW自体を git submodule
に登録し内包しているため、外部からそのソースコードツリーの位置を指定する事で、探索する方法を探す。
ソースコードの構成は次のよにした。
tree use-glew
use-glew |-- CMakeLists-static.txt |-- CMakeLists.txt |-- FindGLEW.cmake |-- a.out `-- main.c 1 directory, 5 files
main.c
はGLEWのヘッダファイルをインクルードしている。当然このままではエラーが発生するが、本当にエラーが発生するかを確認する。
cmake -S use-glew -B .build-glew
cmake --build .build-glew
-- Configuring done (0.0s) -- Generating done (0.0s) -- Build files have been written to: /opt/ng/symdon/pages/posts/1678518623/.build-glew [ 50%] Building C object CMakeFiles/testing.dir/main.c.o
途中まで実行されるが、ビルド時にエラーが発生し、以下のエラーメッセージが出力される。
/opt/ng/symdon/pages/posts/1678518623/use-glew/main.c:2:10: fatal error: 'GL/glew.h' file not found #include "GL/glew.h" ^~~~~~~~~~~ 1 error generated. make[2]: *** [CMakeFiles/testing.dir/main.c.o] Error 1 make[1]: *** [CMakeFiles/testing.dir/all] Error 2 make: *** [all] Error 2
これは当然の結果で GL/glew.h
を探せていないからだ。CMakeでこれを探し出し、ビルドファイル内に構成する方法が知りたいのだが、まずは Evolution Gym
のビルド時に発生したものと同じ状況を作成したい。 CMake
では find_package
コマンドを使う事で依存ライブラリを探せるようになっている。そこで find_package
に GLEW
を指定する事にした。 CMakeLists.txt
は以下のような定義となった。
cmake_minimum_required(VERSION 3.0)
project(test_glew)
find_package(GLEW REQUIRED)
add_executable (testing main.c)
この状態で再度ビルドする。
cmake -S use-glew -B .build-glew
-- Configuring incomplete, errors occurred!
これはビルドまで行かずに失敗する。
CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message): Could NOT find GLEW (missing: GLEW_INCLUDE_DIRS GLEW_LIBRARIES) Call Stack (most recent call first): /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE) /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindGLEW.cmake:238 (find_package_handle_standard_args) CMakeLists.txt:3 (find_package) [ Babel evaluation exited with code 1 ]
エラーメッセージは Evolution Gym
のインストール時に見かけたものと同じだ。これを解消したい。find_packageでGLEWの探索パスを変数として読み込ませる方法を調べる事ができなかった。そこで FindGLEW.cmake
を自作する事にした。
use-glew/FindGLEW.cmake
# FindGLEW.cmake
# Search for GLEW library and include directories
find_path(GLEW_INCLUDE_DIR GL/glew.h)
find_library(GLEW_LIBRARY NAMES GLEW GLEW32)
if (GLEW_INCLUDE_DIR AND GLEW_LIBRARY)
set(GLEW_FOUND TRUE)
else()
set(GLEW_FOUND FALSE)
endif()
if (GLEW_FOUND)
if (NOT GLEW_FIND_QUIETLY)
message(STATUS "Found GLEW: ${GLEW_LIBRARY}")
endif ()
else()
if (GLEW_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find GLEW")
endif ()
endif()
mark_as_advanced(GLEW_INCLUDE_DIR GLEW_LIBRARY)
そして、このFindGLEW.cmakeを読み込んで利用するように CMakeLists.txt
を変更した。
use-glew/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(test_glew)
set(CMAKE_MODULE_PATH "/opt/ng/symdon/pages/posts/1678518623/use-glew") # 自前のFindGLEW.cmakeを使用する
set(GLEW_INCLUDE_DIR "/opt/ng/evogym/evogym/simulator/externals/glew/include")
set(GLEW_LIBRARY "/opt/ng/evogym/build/temp.macosx-10.9-x86_64-cpython-37/externals/libglew.a")
find_package(GLEW REQUIRED) # 自前のFindGLEW.cmakeを使用してGLEWを見つける
add_executable(testing main.c)
target_include_directories(testing PRIVATE ${GLEW_INCLUDE_DIR})
target_link_libraries(testing PRIVATE ${GLEW_LIBRARY})
この状態で構成ファイルの生成を行う。
cmake -S use-glew -B .build-glew
-- Found GLEW: /opt/ng/evogym/evogym/simulator/externals/glew/lib/libGLEW.2.2.0.dylib -- Configuring done (0.0s) -- Generating done (0.0s) -- Build files have been written to: /opt/ng/symdon/pages/posts/1678518623/.build-glew
成功した。次にビルドを試みる。
cmake --build .build-glew
[100%] Built target testing
成功した。実行してみる。
./.build-glew/testing
dyld[38598]: Library not loaded: '/usr/local/lib/libGLEW.2.2.0.dylib' Referenced from: '/opt/ng/symdon/pages/posts/1678518623/.build-glew/testing' Reason: tried: '/usr/local/lib/libGLEW.2.2.0.dylib' (no such file), '/usr/lib/libGLEW.2.2.0.dylib' (no such file) bash: line 1: 38598 Abort trap: 6 ./.build-glew/testing [ Babel evaluation exited with code 134 ]
リンクに失敗しているようだった。この理由を調査する必要がある。この /usr/local/lib/libGLEW.2.2.0.dylib
は存在しているかといえば、HomeBrew等を使ってGLEWをインストールしていないから、このファイルは存在しない。では libGLEW.2.2.0.dylib
はどこにあるのかというと、 /opt/ng/evogym/evogym/simulator/externals/glew/lib/libGLEW.2.2.0.dylib
にあり、これは環境変数 GLEW_LIBRARIES
に指定したものだ。dylibにリンクする際のパスに正しいものが設定されていない事により、ライブラリが読み込めないでいた。
実際、DYLD_LIBRARY_PATHを指定すると先程ビルドしたバイナリでも実行できる。
DYLD_LIBRARY_PATH=/opt/ng/evogym/evogym/simulator/externals/glew/lib ./.build-glew/testing
Ok
この環境変数を指定しても良いが、できれば静的リンクさせたい。少し別の作業をしていたら lib
ディレクトリにライブラリファイルが無くなっていた。どこにビルドされているのか確認すると、 /opt/ng/evogym/build/temp.macosx-10.9-x86_64-cpython-37/externals
配下に作られていた。今回確認したいのはGLEWのビルド方法ではない。だから、もう何も考えずこのファイルを使う事にした。要点としては GLEW_LIBRARY
に静的リンクファイルを指定する事だ。
このファイルを使うため、シンボリックリンクとして CMakeLists.txt
を置き換える。
ln -sf CMakeLists-static.txt use-glew/CMakeLists.txt
構成ファイルを生成する。
cmake -S use-glew -B .build-glew
-- The C compiler identification is AppleClang 13.1.6.13160021 -- The CXX compiler identification is AppleClang 13.1.6.13160021 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Found GLEW: /opt/ng/evogym/build/temp.macosx-10.9-x86_64-cpython-37/externals/libglew.a -- Configuring done (0.8s) -- Generating done (0.0s) -- Build files have been written to: /opt/ng/symdon/pages/posts/1678518623/.build-glew
成功した。次にビルドを試みる。
cmake --build .build-glew
[ 50%] Building C object CMakeFiles/testing.dir/main.c.o [100%] Linking C executable testing [100%] Built target testing
実行する。
./.build-glew/testing
Ok
成功した。ライブラリを正しく探したり、指定したりする方法を試した。CMakeについて少し詳しくなれた気がする。
古いCMakeをHomeBrewでインストールする
以前、動作確認を行っていた時は 3.25
だった。その時は、
インストールが必要になったバージョンは3.22系と3.24系だった。そこで、それらのフォーミュラを個人用のHomebrew Tapに追加する。
古いバージョンは現在のmacOS用のバイナリが提供されていない。その場合はソースコードからビルドする --build-from-source
オプションを指定する。
CMake 3.22用ののフォーミュラには Modules/Internal/CPack/CPack.OSXScriptLauncher.in
のリンクを削除するワークアラウンドと思われるコードがある。
しかし私の環境では、このコードはエラーしてしまい、正常にインストールできなかった。そのため、このコードはコメントアウトした。
インストールはこのようにする。
3.24系は上記のようなコメントアウトは必要なかった。ただし、やはりバイナリは無いのでソースコードからビルドする。
リポジトリに置いておく。