Skip to content

Commit 95619a3

Browse files
committed
refactor: replace cmake with cc crate, add CI check for generated headers
Remove the cmake build dependency so downstream users only need a C compiler to build this crate. The cmake-generated headers (config.h, export.h) are now pre-committed under generated/ and compiled directly via the cc crate. Add scripts/generate-headers.sh to regenerate them when the libversion submodule is updated, and a CI job to verify they stay in sync. Signed-off-by: Xiangzhe <xiangzhedev@gmail.com>
1 parent cceb675 commit 95619a3

7 files changed

Lines changed: 136 additions & 80 deletions

File tree

.github/workflows/ci.yml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ env:
88
CARGO_TERM_COLOR: always
99

1010
jobs:
11+
check-generated:
12+
name: Check Generated Headers
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v6
16+
with:
17+
submodules: true
18+
- run: sudo apt-get update && sudo apt-get install -y cmake
19+
- run: bash scripts/generate-headers.sh
20+
- name: Verify generated headers are up to date
21+
run: |
22+
if ! git diff --exit-code generated/; then
23+
echo "::error::Generated headers are out of date. Run 'bash scripts/generate-headers.sh' and commit the changes."
24+
exit 1
25+
fi
26+
1127
clippy-sarif:
1228
name: Clippy SARIF
1329
runs-on: ubuntu-latest
@@ -21,7 +37,7 @@ jobs:
2137
- uses: dtolnay/rust-toolchain@stable
2238
with:
2339
components: clippy
24-
- run: sudo apt-get update && sudo apt-get install -y cmake libclang-dev
40+
- run: sudo apt-get update && sudo apt-get install -y libclang-dev
2541
- run: cargo install clippy-sarif sarif-fmt
2642
- run: >
2743
cargo clippy --all-targets --all-features --message-format=json -- -Dwarnings |
@@ -51,7 +67,7 @@ jobs:
5167
- uses: dtolnay/rust-toolchain@stable
5268
with:
5369
components: clippy
54-
- run: sudo apt-get update && sudo apt-get install -y cmake libclang-dev
70+
- run: sudo apt-get update && sudo apt-get install -y libclang-dev
5571
- run: cargo clippy --all-targets --all-features -- -D warnings
5672

5773
test:
@@ -62,5 +78,5 @@ jobs:
6278
with:
6379
submodules: true
6480
- uses: dtolnay/rust-toolchain@stable
65-
- run: sudo apt-get update && sudo apt-get install -y cmake libclang-dev
81+
- run: sudo apt-get update && sudo apt-get install -y libclang-dev
6682
- run: cargo test

Cargo.lock

Lines changed: 0 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ license = "MIT"
99
repository = "https://github.com/DUpdateSystem/libversion-sys"
1010
homepage = "https://github.com/DUpdateSystem/libversion-sys"
1111
documentation = "https://docs.rs/libversion-sys"
12-
exclude = [".github/", ".gitignore", ".gitmodules"]
12+
exclude = [".github/", ".gitignore", ".gitmodules", "scripts/"]
1313

1414
[build-dependencies]
15-
cmake = "0.1"
1615
cc = "1"
1716
bindgen = "0.72"

build.rs

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,25 @@
11
use std::env;
2-
use std::path::{Path, PathBuf};
3-
4-
/// When cross-compiling for Android, the `cmake` crate (cmake-rs) sets
5-
/// `CMAKE_SYSTEM_NAME=Android` but does **not** set `CMAKE_ANDROID_NDK`.
6-
/// CMake ≥ 3.21's `Platform/Android-Determine.cmake` then fails because it
7-
/// cannot locate the NDK.
8-
///
9-
/// Detection strategy:
10-
/// 1. Check well-known environment variables (`ANDROID_NDK_ROOT`, etc.).
11-
/// 2. Infer from the C compiler path that `cc` selects for this target.
12-
/// NDK compilers live at `<NDK>/toolchains/llvm/prebuilt/<host>/bin/…`,
13-
/// so we walk up from the compiler looking for the `toolchains` dir.
14-
fn detect_android_ndk() -> Option<PathBuf> {
15-
// 1. Prefer explicit env vars (same ones CMake itself checks)
16-
for var in ["ANDROID_NDK_ROOT", "ANDROID_NDK_HOME", "ANDROID_NDK"] {
17-
if let Ok(val) = env::var(var) {
18-
let p = PathBuf::from(&val);
19-
if p.is_dir() {
20-
return Some(p);
21-
}
22-
}
23-
}
24-
25-
// 2. Infer from the C compiler path
26-
let compiler = cc::Build::new()
27-
.cargo_metadata(false)
28-
.opt_level(0)
29-
.warnings(false)
30-
.try_get_compiler()
31-
.ok()?;
32-
let cc_path = compiler.path().canonicalize().ok()?;
33-
let mut dir: &Path = cc_path.parent()?;
34-
loop {
35-
if dir.file_name().and_then(|n| n.to_str()) == Some("toolchains")
36-
&& dir.join("llvm").is_dir()
37-
{
38-
return dir.parent().map(|p| p.to_path_buf());
39-
}
40-
dir = dir.parent()?;
41-
}
42-
}
2+
use std::path::PathBuf;
433

444
fn main() {
45-
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
46-
47-
// Build libversion static library using cmake
48-
let mut cmake_cfg = cmake::Config::new("libversion");
49-
cmake_cfg.build_target("libversion_static");
50-
51-
// Work around cmake-rs not setting CMAKE_ANDROID_NDK for Android targets.
52-
53-
if target_os == "android"
54-
&& let Some(ndk_root) = detect_android_ndk()
55-
{
56-
cmake_cfg.define("CMAKE_ANDROID_NDK", &ndk_root);
57-
}
58-
59-
let dst = cmake_cfg.build();
60-
61-
let build_dir = dst.join("build").join("libversion");
62-
println!("cargo:rustc-link-search=native={}", build_dir.display());
63-
println!("cargo:rustc-link-lib=static=version");
5+
// Build libversion static library using cc.
6+
// The cmake-generated headers (config.h, export.h) are pre-committed under
7+
// generated/ — run `bash scripts/generate-headers.sh` to regenerate them
8+
// whenever the libversion submodule is updated.
9+
cc::Build::new()
10+
.file("libversion/libversion/compare.c")
11+
.file("libversion/libversion/private/compare.c")
12+
.file("libversion/libversion/private/parse.c")
13+
.include("libversion") // source headers (libversion/version.h, etc.)
14+
.include("generated") // pre-generated headers (libversion/config.h, libversion/export.h)
15+
.define("LIBVERSION_STATIC_DEFINE", None)
16+
.compile("version");
6417

6518
// Generate FFI bindings via bindgen
6619
let bindings = bindgen::Builder::default()
6720
.header("wrapper.h")
68-
// cmake-generated headers (config.h, export.h) are in build/libversion/
69-
.clang_arg(format!("-I{}", dst.join("build").display()))
70-
// source headers are under libversion/ (the submodule root)
71-
.clang_arg("-Ilibversion")
72-
// static build: LIBVERSION_EXPORT expands to nothing
21+
.clang_arg("-Igenerated") // pre-generated config.h, export.h
22+
.clang_arg("-Ilibversion") // source headers
7323
.clang_arg("-DLIBVERSION_STATIC_DEFINE")
7424
.default_enum_style(bindgen::EnumVariation::Consts)
7525
.allowlist_function("version_compare.*")

generated/libversion/config.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2018 Dmitry Marakasov <amdmi3@amdmi3.ru>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
* THE SOFTWARE.
21+
*/
22+
23+
#ifndef LIBVERSION_CONFIG_H
24+
#define LIBVERSION_CONFIG_H
25+
26+
#define LIBVERSION_VERSION_MAJOR 3
27+
#define LIBVERSION_VERSION_MINOR 0
28+
#define LIBVERSION_VERSION_PATCH 4
29+
30+
#define LIBVERSION_VERSION "3.0.4"
31+
32+
#endif /* LIBVERSION_CONFIG_H */

generated/libversion/export.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
#ifndef LIBVERSION_EXPORT_H
3+
#define LIBVERSION_EXPORT_H
4+
5+
#ifdef LIBVERSION_STATIC_DEFINE
6+
# define LIBVERSION_EXPORT
7+
# define LIBVERSION_NO_EXPORT
8+
#else
9+
# ifndef LIBVERSION_EXPORT
10+
# ifdef libversion_EXPORTS
11+
/* We are building this library */
12+
# define LIBVERSION_EXPORT __attribute__((visibility("default")))
13+
# else
14+
/* We are using this library */
15+
# define LIBVERSION_EXPORT __attribute__((visibility("default")))
16+
# endif
17+
# endif
18+
19+
# ifndef LIBVERSION_NO_EXPORT
20+
# define LIBVERSION_NO_EXPORT __attribute__((visibility("hidden")))
21+
# endif
22+
#endif
23+
24+
#ifndef LIBVERSION_DEPRECATED
25+
# define LIBVERSION_DEPRECATED __attribute__ ((__deprecated__))
26+
#endif
27+
28+
#ifndef LIBVERSION_DEPRECATED_EXPORT
29+
# define LIBVERSION_DEPRECATED_EXPORT LIBVERSION_EXPORT LIBVERSION_DEPRECATED
30+
#endif
31+
32+
#ifndef LIBVERSION_DEPRECATED_NO_EXPORT
33+
# define LIBVERSION_DEPRECATED_NO_EXPORT LIBVERSION_NO_EXPORT LIBVERSION_DEPRECATED
34+
#endif
35+
36+
/* NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if) */
37+
#if 0 /* DEFINE_NO_DEPRECATED */
38+
# ifndef LIBVERSION_NO_DEPRECATED
39+
# define LIBVERSION_NO_DEPRECATED
40+
# endif
41+
#endif
42+
43+
#endif /* LIBVERSION_EXPORT_H */

scripts/generate-headers.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Regenerate cmake-produced headers (config.h, export.h) from the libversion
4+
# submodule so that the normal build (which uses the cc crate) never needs
5+
# cmake installed.
6+
#
7+
# Usage: bash scripts/generate-headers.sh
8+
#
9+
# Run this script whenever the libversion submodule is updated.
10+
11+
set -euo pipefail
12+
13+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
14+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
15+
TMPDIR="$(mktemp -d)"
16+
17+
trap 'rm -rf "$TMPDIR"' EXIT
18+
19+
echo "Running cmake configure on libversion submodule..."
20+
cmake -S "$PROJECT_ROOT/libversion" -B "$TMPDIR" >/dev/null 2>&1
21+
22+
mkdir -p "$PROJECT_ROOT/generated/libversion"
23+
cp "$TMPDIR/libversion/config.h" "$PROJECT_ROOT/generated/libversion/config.h"
24+
cp "$TMPDIR/libversion/export.h" "$PROJECT_ROOT/generated/libversion/export.h"
25+
26+
echo "Generated headers updated in generated/libversion/"

0 commit comments

Comments
 (0)