CMake로 [Rust] C/C++의 소스 코드를 구축하고 활용하는 방법

12642 단어 C++RustCcmaketech

1. 시작


Rust에서 C/C++ 라이브러리를 사용할 때는 다음 방법을 고려할 수 있습니다.
  • 제3파티의crate
  • 를 이용
  • 직접 인터페이스 FFI(Foreign Function Interface)
  • 그러나 이 라이브러리의 모든 API를 이용하거나 자신의 FFI 물건을 귀찮다고 하거나 Rust에서 C/C++ 인터페이스로 꺼내면 주위가 어려워진다.이러한 상황에서 프로그램 라이브러리의 부분을 참조하여 C/C++ 패키지로 인터페이스를 연결하거나Rust에서 모듈화를 쉽게 처리하면 FFI 그 모듈은 더욱 간단하고 편리할 것이다.
    이 글에서는 이러한 상황에서 C/C++의 소스 코드는 CMake(CMake Lists.txt)로 관리 구축되며, Rust의 Cargo로 통합 구축된다.

    2.크막크레인


    cmake라는 크레인을 이용하다.이 기능을 사용하면 Cargo에 있는 기존CMakeLists.txt 파일의 내용에 따라 C/C++의 원본 코드를 구축할 수 있습니다.

    3. 디렉토리 구조(예)


    이번에 설명에 사용된 목록은 다음과 같다.C/C++의 원본 코드는 lib/cmake-example 디렉터리 아래에서 모듈로 설정한 다음 src/main.rs에서 호출됩니다.
    Cargo.toml
    ├── src/
    │   └── main.rs
    ├── lib/
    │   └── cmake-example/
    │   │   └── Cargo.toml
    │   │   └── build.rs
    │   │   └── src/
    │   │   │  └── lib.rs
    │   │   │  └── bindings.rs
    │   │   │  └── cpp/
    │   │   │  │   └── example.cc
    │   │   │  │   └── example.h
    │   │   │  │   └── CMakeLists.txt
    

    4.C/C++ (lib/cmake-example) 측면의 대응


    먼저 C/C++ 측의 대응 내용을 설명합니다.

    lib/cmake-example/Cargo.Toml 만들기

    build-dependenciescmake.또한 dependencies에 추가libc.
    lib/cmake-example/Cargo.toml
    [package]
    name = "cmake-example"
    version = "0.1.0"
    authors = ["name"]
    edition = "2018"
    build = "build.rs" # ビルドスクリプトはbuild.rsファイル
    
    [dependencies]
    libc = "0.2.94"
    
    [build-dependencies]
    cmake = "0.1"
    # bindgen = "0.58.1"  # bindgenを利用すれば自動でC/C++のFFIのソースコードを生成可能
    

    스크립트를 만드는build입니다.생성rs


    CMake를 실행하고 C/C++를 만드는 구축 스크립트를 만듭니다.C/C++ 코드를 Rust에 통합해서 사용하면 C/C++ 구축 성과는 static 라이브러리 (. a) 파일로 하면 됩니다. (Rust 코드가 생성한 이진법에만 포함되기 때문입니다.)다른 한편, C/C++에서 사용하는 세 번째 파티의 라이브러리는dynamic에 연결해야 합니다.
    build.rs
    use cmake;
    
    fn main() {
        // CMakeLists.txtが存在するディレクトリを指定します
        // lib/cmake-exampleディレクトリからの相対位置となります
        let dst = cmake::build("src/cpp");
        println!("cargo:rustc-link-search=native={}", dst.display());
    
        // staticライブラリとして他に利用するライブラリはなし
        println!("cargo:rustc-link-lib=static=");
    
        // C++ソースコードの場合は必ずこれを追加すること
        println!("cargo:rustc-link-lib=dylib=stdc++");
    
        // CMakeLists.txt内の記述とは別に、その他のライブラリは必要なものを全て記述する必要あり
        println!("cargo:rustc-link-lib=dylib=EGL");
        println!("cargo:rustc-link-lib=dylib=GLESv2");
        println!("cargo:rustc-link-lib=dylib=X11");
    
        // pkg-configでヒットしないライブラリは以下のように直接パス指定が可能
        let soil_lib_dir = "/usr/lib";
        println!("cargo:rustc-link-search={}", soil_lib_dir);
        println!("cargo:rustc-link-lib=dylib=SOIL");
    }
    

    CMakeLists.txt 준비

    CMakeLists.txt C/C++ 구축 시 사용하는 형식을 직접 사용할 수 있으나 다음과 같은 두 가지를 주의해야 한다.
  • static 라이브러리에 구축
  • 설치
  • 를 써야 합니다.
    샘플은 아래와 같다.
    CMakeLists.txt의 예
    cmake_minimum_required(VERSION 3.10)
    project("cmake example for Rust" LANGUAGES CXX C)
    
    set(CMAKE_CXX_STANDARD 17)
    
    find_package(PkgConfig)
    pkg_check_modules(EGL REQUIRED egl)
    pkg_check_modules(GLES2 REQUIRED glesv2)
    pkg_check_modules(X11 REQUIRED x11)
    
    set(TARGET cmake-example)
    
    # 必ずstaticライブラリにビルドすること
    add_library(${TARGET}
      STATIC
        example.cc
    )
    
    target_link_libraries(${TARGET}
      PRIVATE
        ${EGL_LIBRARIES}
        ${GLES2_LIBRARIES}
        ${X11_LIBRARIES}
    )
    
    target_include_directories(${TARGET}
      PRIVATE
        ${EGL_INCLUDE_DIR}
        ${GLES2_INCLUDE_DIR}
        ${X11_INCLUDE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}
    )
    
    # 必ずこれが必要です
    install (TARGETS ${TARGET} DESTINATION .)
    

    bindings.문서 작성


    C/C++ 라이브러리 바인딩에 사용할 코드를 만듭니다.이번에는 설명 없이bindgen 크레인을 이용하여 이 원본 코드를 자동으로 생성할 수 있다.이번 수동 제작은자신의 C/C++ 소스 코드 내용에 따라 이것을 만드십시오.
    예제
    extern "C" {
        pub fn foo();
    }
    

    lib.문서 작성


    상기 제작된 bindings.rslib.rs만 포함할 예정입니다.여기 도착하면 메인이야.rs방면에서 참조하여 사용할 수 있습니다.
    lib.rs
    #![allow(non_upper_case_globals)]
    #![allow(non_camel_case_types)]
    #![allow(non_snake_case)]
    
    include!("bindings.rs");
    

    5. Rust(노선)측의 대응


    다음은 Rust 주요 섹션의 대응 내용입니다.

    Cargo.toml 편집

    dependencieslib/cmake-example.
    Cargo.toml
    [dependencies]
    cmake-example = { path = "lib/cmake-example" }
    

    src/main.문서 작성


    나머지는 Rust 코드에서 C/C++를 호출하는 코드뿐입니다.
    main.rs
    extern crate cmake_example;
    
    fn main() {
        unsafe {
            cmake_example::foo();
        }
    }
    

    좋은 웹페이지 즐겨찾기