Open7

build.rs で cmake が生成したリンクの依存関係を使いたい

oshitekuoshiteku

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!");
}
oshitekuoshiteku

なので, cmake が探してきてくれたライブラリと、そのありかのパスを build.rs が自動的に読み込むようにしたい。

oshitekuoshiteku

とりあえず 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
oshitekuoshiteku

生成された 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"
	},
...