This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Check if Rust lib needs rebuilding. (#13759)
This protects against the common mistake of failing to remember to rebuild Rust code after making changes.
- Loading branch information
1 parent
4c4889c
commit ebfeac7
Showing
7 changed files
with
149 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add a check for editable installs if the Rust library needs rebuilding. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
//! This build script calculates the hash of all files in the `src/` | ||
//! directory and adds it as an environment variable during build time. | ||
//! | ||
//! This is used so that the python code can detect when the built native module | ||
//! does not match the source in-tree, helping to detect the case where the | ||
//! source has been updated but the library hasn't been rebuilt. | ||
|
||
use std::path::PathBuf; | ||
|
||
use blake2::{Blake2b512, Digest}; | ||
|
||
fn main() -> Result<(), std::io::Error> { | ||
let mut dirs = vec![PathBuf::from("src")]; | ||
|
||
let mut paths = Vec::new(); | ||
while let Some(path) = dirs.pop() { | ||
let mut entries = std::fs::read_dir(path)? | ||
.map(|res| res.map(|e| e.path())) | ||
.collect::<Result<Vec<_>, std::io::Error>>()?; | ||
|
||
entries.sort(); | ||
|
||
for entry in entries { | ||
if entry.is_dir() { | ||
dirs.push(entry) | ||
} else { | ||
paths.push(entry.to_str().expect("valid rust paths").to_string()); | ||
} | ||
} | ||
} | ||
|
||
paths.sort(); | ||
|
||
let mut hasher = Blake2b512::new(); | ||
|
||
for path in paths { | ||
let bytes = std::fs::read(path)?; | ||
hasher.update(bytes); | ||
} | ||
|
||
let hex_digest = hex::encode(hasher.finalize()); | ||
println!("cargo:rustc-env=SYNAPSE_RUST_DIGEST={hex_digest}"); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
def sum_as_string(a: int, b: int) -> str: ... | ||
def get_rust_file_digest() -> str: ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Copyright 2022 The Matrix.org Foundation C.I.C. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import os | ||
import sys | ||
from hashlib import blake2b | ||
|
||
import synapse | ||
from synapse.synapse_rust import get_rust_file_digest | ||
|
||
|
||
def check_rust_lib_up_to_date() -> None: | ||
"""For editable installs check if the rust library is outdated and needs to | ||
be rebuilt. | ||
""" | ||
|
||
if not _dist_is_editable(): | ||
return | ||
|
||
synapse_dir = os.path.dirname(synapse.__file__) | ||
synapse_root = os.path.abspath(os.path.join(synapse_dir, "..")) | ||
|
||
# Double check we've not gone into site-packages... | ||
if os.path.basename(synapse_root) == "site-packages": | ||
return | ||
|
||
# ... and it looks like the root of a python project. | ||
if not os.path.exists("pyproject.toml"): | ||
return | ||
|
||
# Get the hash of all Rust source files | ||
hash = _hash_rust_files_in_directory(os.path.join(synapse_root, "rust", "src")) | ||
|
||
if hash != get_rust_file_digest(): | ||
raise Exception("Rust module outdated. Please rebuild using `poetry install`") | ||
|
||
|
||
def _hash_rust_files_in_directory(directory: str) -> str: | ||
"""Get the hash of all files in a directory (recursively)""" | ||
|
||
directory = os.path.abspath(directory) | ||
|
||
paths = [] | ||
|
||
dirs = [directory] | ||
while dirs: | ||
dir = dirs.pop() | ||
with os.scandir(dir) as d: | ||
for entry in d: | ||
if entry.is_dir(): | ||
dirs.append(entry.path) | ||
else: | ||
paths.append(entry.path) | ||
|
||
# We sort to make sure that we get a consistent and well-defined ordering. | ||
paths.sort() | ||
|
||
hasher = blake2b() | ||
|
||
for path in paths: | ||
with open(os.path.join(directory, path), "rb") as f: | ||
hasher.update(f.read()) | ||
|
||
return hasher.hexdigest() | ||
|
||
|
||
def _dist_is_editable() -> bool: | ||
"""Is distribution an editable install?""" | ||
for path_item in sys.path: | ||
egg_link = os.path.join(path_item, "matrix-synapse.egg-link") | ||
if os.path.isfile(egg_link): | ||
return True | ||
return False |