-
Notifications
You must be signed in to change notification settings - Fork 390
Implement building GenMC C++ code #4453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Add genmc-sys crate for building GenMC C++ code. - Implemented program features: - Handling of atomic loads, stores, allocations and deallocations. - Implement consistent address allocations for globals - Non-global addresses allocated by GenMC. - Limitation: No address randomization. - Limitation: No address reuse. - Handling of non-atomic memory accesses. - Limitation: need to split up NA reads and stores into max 8 byte chunks. - Limitation: no mixed size access support. - Limitation: Incomplete (unsound) handling of uninitialized memory. - Implement Pointer conversions to and from GenMC - Limitation: Aliasing model checking must be disabled. - Handling of Read-Modify-Write, Compare-Exchange and Atomic Exchange operations. - Limitation: Compare-Exchange currently ignores possibility of spurious failures. - Limitation: Compare-Exchange failure memory ordering is ignored. - Handling of thread creation and finishing. - Added Miri to GenMC thread id mapping. - Implement mutex lock, try_lock and unlock. - Make use of annotations to reduce number of blocked executions for programs with mutexes. - Add estimation mode for Miri-GenMC. - Limitation: Printing currently handled on C++ side (Should be moved once VerificationResult is available to Rust code) - Thread scheduling in Miri done through GenMC, add loop over eval_entry function. - Rebase GenMC to use new scheduler. - Added GenMC `__VERIFIER_assume` equivalent for Miri (`miri_genmc_verifier_assume`) - Add warnings for GenMC mode for unsupported features. - Add a lot of test, including translation of GenMC litmus tests. - Only run tests if 'genmc' feature enabled. - WIP: try implementing NonNullUniquePtr wrapper for CXX. - WIP: work on mixed atomic/non-atomics. - Partially working, some issues with globals - FIX: Make naming consistent with GenMC for blocked execution - Add git support to build, move C++ files into genmc-sys crate - Implement building GenMC-Miri after GenMC codebase split. - WIP: temporarily point GenMC repo to private branch.
@rustbot author |
Reminder, once the PR becomes ready for a review, use |
@rustbot ready |
Here's my first round of comments. :) @rustbot author |
Should the build script not download anything if cargo is invoked with |
Co-authored-by: Ralf Jung <post@ralfj.de>
genmc-sys/build.rs
Outdated
// FIXME(GenMC,HACK): Required for unknown reasons on older cmake (version 3.22.1, works without this with version 3.31.6) | ||
// Without this, the files are written into the source directory by the cmake configure step, and then | ||
// the build step cannot find these files, because it correctly tries using the `target` directory. | ||
let out_dir = std::env::var("OUT_DIR").unwrap(); | ||
let genmc_build_path: PathBuf = [&out_dir, "build"].into_iter().collect(); | ||
config.configure_arg(format!("-B {}", genmc_build_path.display())); | ||
|
||
// Enable only the components of GenMC that we need: | ||
config.define("BUILD_LLI", "OFF"); | ||
config.define("BUILD_INSTRUMENTATION", "OFF"); | ||
config.define("BUILD_MODEL_CHECKER", "ON"); | ||
|
||
config.build_target(GENMC_MODEL_CHECKER); | ||
let _dst = config.build(); | ||
|
||
let genmc_model_checker_build_directory = genmc_build_path.join(GENMC_MODEL_CHECKER); | ||
println!("cargo::rustc-link-search=native={}", genmc_model_checker_build_directory.display()); | ||
println!("cargo::rustc-link-lib=static={GENMC_MODEL_CHECKER}"); | ||
|
||
genmc_build_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite happy with this code yet:
- The Hack at the top seems to be required for building on older Ubuntu, which isn't relevant yet for Miri's CI, but might be if this should build in rustc's CI (or someone tries to compile Miri-GenMC on an older OS).
- I suspect it's due to version differences with the older cmake that's installed there, possibly an edge case that's not handled by the cmake crate. We can either leave it as is or try to investigate further.
- The "build" path extension seems to be undocumented by the cmake crate (it is added here), so it might not be a good idea to depend on that.
- This might be unlikely to change, especially since the cmake crate lives in the
rust-lang
Github project too. - We may be able to use the return value (
_dst
) fromconfig.build()
instead (which should be the install directory), but I haven't yet figured out why the producedmodel_checker
library is not in that directory. I'll have to investigate this further.
- This might be unlikely to change, especially since the cmake crate lives in the
As discussed, I've switched to using a config.h file instead of compile definitions. This config file lives in the build directory (at {genmc_build_path}/config.h
), which is then included in the cxx_bridge
build step (That's why we return that path here).
With this config.h, no more manual settings syncing is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- What is that
-B
flag and why is setting it a hack? - If the cmake crate currently provides no way of getting the build dir, then maybe open an issue to ask for such an API, and reference it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The -B
flags sets the build directory, which I would expect to be taken care of automatically by the cmake
crate. When I tested it on Ubuntu 22.04, the first of the two cmake
command invocation used the wrong directory without this (first invocation is a configure step, the second invocation is the actual build).
The difference between the OSes makes me think this is not intended behavior, maybe I should make a bug report for that too.
genmc-sys/build.rs
Outdated
// Adding that path here would also trigger an unnecessary rebuild after the repo is cloned (since cargo detects that as a file modification). | ||
println!("cargo::rerun-if-changed={RUST_CXX_BRIDGE_FILE_PATH}"); | ||
println!("cargo::rerun-if-changed=./src_cpp"); | ||
println!("cargo::rerun-if-changed={GENMC_LOCAL_PATH}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, adding this path to the rerun-if-changed
if the path doesn't exist yet causes full rebuilds on every build. I think the non-existing directory is seen as a change by cargo.
Here is the output from running CARGO_LOG=cargo::core::compiler::fingerprint=info ./miri build --features=genmc
after a complete build without any file modifications (as described here):
cargo::core::compiler::fingerprint: stale: missing "/path/to/miri/genmc-sys/./genmc/"
cargo::core::compiler::fingerprint: fingerprint dirty for miri v0.1.0 (/path/to/miri)
Is this intended behavior for cargo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just add GENMC_LOCAL_PATH
only if you actually use the local path, not the download?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I think then we wouldn't trigger an automatic rebuild if a user adds the ./genmc
directory. That's probably still better than constantly rebuilding, since this case should be rare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you are using the existence of the directory as the signal for using it... yeah that doesn't work with cargo's model, it seems. I'll ask the cargo devs about it, but for now, let's use an env var to signal explicitly that you want a local build instead of a download, and then add that env var to rerun-if-changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also see rust-lang/cargo#6003
// FIXME(GenMC, build): decide whether to keep debug enabled or not (without this: calling BUG() ==> UB). | ||
// FIXME(GenMC, build): decide on which profile to use. | ||
|
||
/// Enable/disable additional debug checks, prints and options for GenMC. | ||
const ENABLE_GENMC_DEBUG: bool = true; | ||
/// The profile with which to build GenMC. | ||
const GENMC_CMAKE_PROFILE: &str = "RelWithDebInfo"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reminder to discuss this with Michalis before merging since the original comment is now marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the default used by GenMC itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Profile: RelWithDebInfo
(with -O2 -g
)
GENMC_DEBUG: OFF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do the same then for release builds. For debug builds it'd make sense to set GENMC_DEBUG to On.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't find any way for the build script to even detect if debug_assertions
is enabled.
In the list of env vars set for a build script, there is only:
DEBUG
, which I assume is whether or not debug info is included (assuming it matches the "debug" in Cargo.toml)PROFILE
, which I don't think will help us much for Miri since IIRCmiri-script
never uses--release
anyway (?)
I can't really imagine that we are the first who would like to know if debug assertions are enabled from a build script, so I might be missing something here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PROFILE, which I don't think will help us much for Miri since IIRC miri-script never uses --release anyway (?)
./miri install
uses --release
, as does the dist build.
So if debug_assertions cannot be checked (I didn't find a way either) I think PROFILE is exactly what you should check.
Yeah I don't think we have a way to check for that. Please ask on some RUst forum (URLO on Zulip) what the typical approach here is, I don't know. |
genmc-sys/build.rs
Outdated
// Adding that path here would also trigger an unnecessary rebuild after the repo is cloned (since cargo detects that as a file modification). | ||
println!("cargo::rerun-if-changed={RUST_CXX_BRIDGE_FILE_PATH}"); | ||
println!("cargo::rerun-if-changed=./src_cpp"); | ||
println!("cargo::rerun-if-changed={GENMC_LOCAL_PATH}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just add GENMC_LOCAL_PATH
only if you actually use the local path, not the download?
which one, adding the warning?
Ah, sorry, stopped reading too early...
Add the flag to disable SB to the tests.
|
|
||
pub(crate) const GENMC_GITHUB_URL: &str = "https://github.com/Patrick-6/genmc.git"; | ||
pub(crate) const GENMC_COMMIT: &str = "2f503036ae14dc91746bfc292d142f332f31727e"; | ||
pub(crate) const GENMC_DOWNLOAD_PATH: &str = "./downloaded/genmc/"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For all these paths it'd be good to know what they are relative to.^^
|
||
// Build all required components: | ||
let genmc_install_dir = build_genmc_model_checker(&genmc_path); | ||
build_cxx_bridge(&genmc_path, &genmc_install_dir); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should only use genmc_install_dir
since the headers should also be installed.
This PR is in preparation for adding GenMC support to Miri.
It adds the
genmc-sys
crate, which can automatically load GenMC from a git repo (temporarily pointing to a private repo, but will point to the GenMC Github repo after everything is implemented)This PR doesn't add any functionality for GenMC mode, only a test for calling C++ functions from Rust code through the
cxx
crate.