Open7
build.rs で cmake が生成したリンクの依存関係を使いたい
build.rs で
- cmake を使う C++ ライブラリのビルドと
- そのライブラリが依存する動的ライブラリとのリンク
を行う場合, cmake で find_package 等して集めてきた動的ライブラリのパスを再び設定しないといけない。
しかし, CMakeLists.txt ががっつり書かれていて, かつマルチプラットフォーム対応等々を考えなければいけない状況だとこれは結構つらい…
extern crate bindgen;
use std::env;
use std::path::{Path, PathBuf};
fn main() {
let dst = cmake::Config::new("hoge")
.build_target("hoge")
.build();
println!("cargo:rustc-link-lib=static=hoge");
println!("cargo:rustc-link-search=native={}/build", dst.display());
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=AppKit");
// ↓このあたりの設定は hoge/CMakeLists.txt と重複してしまう
println!("cargo:rustc-link-lib=dylib=fuga1");
println!("cargo:rustc-link-search=native={}", env!("FUGA1_DIR"));
println!("cargo:rustc-link-lib=dylib=fuga2");
println!("cargo:rustc-link-search=native={}", env!("FUGA2_DIR"));
println!("cargo:rustc-link-lib=framework=fuga3");
println!("cargo:rustc-link-search=framework={}", env!("FUGA3_DIR"));
println!("cargo:rustc-link-lib=dylib=c++");
println!("cargo:rerun-if-changed=wrapper.h");
let bindings = bindgen::Builder::default()
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
なので, cmake が探してきてくれたライブラリと、そのありかのパスを build.rs が自動的に読み込むようにしたい。
cmake には cmake-file-api という仕組みがあり, これにより configure した後でリンカの設定を取って来ることが可能。
とりあえず cmake-file-api を試してみる。
まず, cmake のビルドディレクトリに空のファイルを作る
$ cd build
$ mkdir -p .cmake/api/v1/query
$ touch .cmake/api/v1/query/codemodel-v2
そして cmake を実行し configure すると, json ファイルが生成される
$ ls .cmake/api/v1/reply
codemodel-v2-8a3e787080aa0a020e3a.json target-hoge-Release-33c602b035a57b4de5a3.json
directory-.-Release-f5ebdc15457944623624.json target-hoge_autogen-Release-4ed0570165a592f7f418.json
index-2022-02-06T11-14-44-0178.json
生成された json ファイルの中から link の部分を抜粋 (obs-browser での実行例)
...
"link" :
{
"commandFragments" :
[
{
"fragment" : "-L/opt/homebrew/opt/llvm/lib",
"role" : "flags"
},
{
"fragment" : "-Wl,-rpath,/Users/oshiteku/ghq/github.com/PatTheMav/obs-studio/build/libobs -Wl,-rpath,/Users/oshiteku/ghq/github.com/PatTheMav/obs-studio/build/UI/obs-frontend-api -Wl,-rpath,/Users/oshiteku/ghq/github.com/PatTheMav/obs-build-dependencies/obs-deps/lib",
"role" : "libraries"
},
{
"backtrace" : 2,
"fragment" : "/Users/oshiteku/ghq/github.com/PatTheMav/obs-studio/build/libobs/libobs.framework/libobs",
"role" : "libraries"
},
{
"backtrace" : 2,
"fragment" : "/Users/oshiteku/ghq/github.com/PatTheMav/obs-studio/build/UI/obs-frontend-api/libobs-frontend-api.dylib",
"role" : "libraries"
},
{
"backtrace" : 2,
"fragment" : "/Users/oshiteku/ghq/github.com/PatTheMav/obs-build-dependencies/cef_binary_4638_macos_arm64/build/libcef_dll_wrapper/libcef_dll_wrapper.a",
"role" : "libraries"
},
{
"fragment" : "-framework",
"role" : "libraries"
},
{
"fragment" : "CoreFoundation",
"role" : "libraries"
},
{
"fragment" : "-framework",
"role" : "libraries"
},
{
"fragment" : "AppKit",
"role" : "libraries"
},
{
"backtrace" : 2,
"fragment" : "/Users/oshiteku/ghq/github.com/PatTheMav/obs-build-dependencies/obs-deps/lib/QtWidgets.framework/QtWidgets",
"role" : "libraries"
},
{
"fragment" : "/Users/oshiteku/ghq/github.com/PatTheMav/obs-build-dependencies/obs-deps/lib/QtGui.framework/QtGui",
"role" : "libraries"
},
{
"fragment" : "/Users/oshiteku/ghq/github.com/PatTheMav/obs-build-dependencies/obs-deps/lib/QtCore.framework/QtCore",
"role" : "libraries"
}
],
"language" : "CXX"
},
...
↑ の json の形式から cargo:rustc-link-lib
の形式に変換しなければいけないので, 一筋縄ではいかない気がする。
何か良い方法ご存知の方いれば教えて下さい