From bc96ce9eef9cf14c941855f7bc2e852f6d4cafd1 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 15:21:33 +0000 Subject: [PATCH 1/9] wip: add bindings to repo --- lib/build.rs | 73 +++++- lib/src/gen/bindings.rs | 534 ++++++++++++++++++++++++++++++++++++++++ lib/src/lib.rs | 2 +- 3 files changed, 595 insertions(+), 14 deletions(-) create mode 100644 lib/src/gen/bindings.rs diff --git a/lib/build.rs b/lib/build.rs index af6bfcc..1efec19 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -40,17 +40,20 @@ fn get_lib_search_paths() -> Vec { paths.insert(0, libquil_src_path.to_string()); } + let ld_library_path: Option<&'static str> = option_env!("LD_LIBRARY_PATH"); + if let Some(ld_library_path) = ld_library_path { + paths.insert(0, ld_library_path.to_string()); + } + paths } -fn main() -> Result<(), Error> { - let libquil_header_path = get_header_path()?; +// #[cfg(feature = "codegen")] +fn codegen() -> Result<(), Error> { + use std::fs::OpenOptions; + use std::io::Write; - for path in get_lib_search_paths() { - println!("cargo:rustc-link-search={}", path); - } - - println!("cargo:rustc-link-lib=quil"); + let libquil_header_path = get_header_path()?; // Tell cargo to rerun if the libquil implementation has changed println!( @@ -58,12 +61,6 @@ fn main() -> Result<(), Error> { libquil_header_path.clone().display() ); - // If this isn't set on MacOS, memory allocation errors occur when trying to initialize the - // library - if cfg!(target_os = "macos") { - println!("cargo:rustc-link-arg=-pagezero_size 0x100000"); - } - // The bindgen::Builder is the main entry point // to bindgen, and lets you build up options for // the resulting bindings. @@ -86,5 +83,55 @@ fn main() -> Result<(), Error> { .write_to_file(out_path.join("bindings.rs")) .expect("Should be able to write bindings to file."); + let gen_code_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("src") + .join("gen"); + + for entry in std::fs::read_dir(PathBuf::from(&out_path)) + .expect("OUT_DIR environment variable should point to a valid directory") + { + let src_path = entry.expect("OUT_DIR should contain files").path(); + if src_path.to_string_lossy().ends_with(".rs") { + let dest = gen_code_dir.join( + src_path + .file_name() + .expect("path should include a valid file name"), + ); + + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(dest.clone()) + .expect( + format!("Should open file '{}' for writing", dest.to_string_lossy()).as_str(), + ); + writeln!( + file, + "{}", + std::fs::read_to_string(src_path).expect("Should read file contents") + ) + .expect("Should write file contents"); + } + } + + Ok(()) +} + +fn main() -> Result<(), Error> { + for path in get_lib_search_paths() { + println!("cargo:rustc-link-search={}", path); + } + + println!("cargo:rustc-link-lib=quil"); + + // If this isn't set on MacOS, memory allocation errors occur when trying to initialize the + // library + if cfg!(target_os = "macos") { + println!("cargo:rustc-link-arg=-pagezero_size 0x100000"); + } + + codegen()?; + Ok(()) } diff --git a/lib/src/gen/bindings.rs b/lib/src/gen/bindings.rs new file mode 100644 index 0000000..82a52f0 --- /dev/null +++ b/lib/src/gen/bindings.rs @@ -0,0 +1,534 @@ +/* automatically generated by rust-bindgen */ + +pub const libquil_error_t_LIBQUIL_ERROR_SUCCESS: libquil_error_t = 0; +pub const libquil_error_t_LIBQUIL_ERROR_FAIL: libquil_error_t = 1; +pub type libquil_error_t = u32; +extern "C" { + pub static mut libquil_error: ::std::option::Option< + unsafe extern "C" fn(result: *mut *mut ::std::os::raw::c_char) -> libquil_error_t, + >; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct quil_program__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_quil_program__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(quil_program__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(quil_program__)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).unused as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(quil_program__), + "::", + stringify!(unused) + ) + ); +} +pub type quil_program = *mut quil_program__; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct chip_specification__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_chip_specification__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(chip_specification__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(chip_specification__)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).unused as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(chip_specification__), + "::", + stringify!(unused) + ) + ); +} +pub type chip_specification = *mut chip_specification__; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct quilc_version_info__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_quilc_version_info__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(quilc_version_info__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(quilc_version_info__)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).unused as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(quilc_version_info__), + "::", + stringify!(unused) + ) + ); +} +pub type quilc_version_info = *mut quilc_version_info__; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct quilc_compilation_metadata__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_quilc_compilation_metadata__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(quilc_compilation_metadata__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(quilc_compilation_metadata__)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).unused as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(quilc_compilation_metadata__), + "::", + stringify!(unused) + ) + ); +} +pub type quilc_compilation_metadata = *mut quilc_compilation_metadata__; +extern "C" { + pub static mut quilc_get_version_info: ::std::option::Option< + unsafe extern "C" fn(result: *mut quilc_version_info) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_version_info_version: ::std::option::Option< + unsafe extern "C" fn( + version_info: quilc_version_info, + ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_version_info_githash: ::std::option::Option< + unsafe extern "C" fn( + version_info: quilc_version_info, + ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_parse_quil: ::std::option::Option< + unsafe extern "C" fn( + source: *mut ::std::os::raw::c_char, + result: *mut quil_program, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_print_program: + ::std::option::Option libquil_error_t>; +} +extern "C" { + pub static mut quilc_compile_quil: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + chip_spec: chip_specification, + result: *mut quil_program, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_len: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_final_rewiring: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + final_rewiring_ptr: *mut ::std::os::raw::c_void, + final_rewiring_len_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_gate_volume: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + gate_volume_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_gate_depth: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + gate_depth_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_multiqubit_gate_depth: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + gate_depth_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_topological_swaps: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + gate_depth_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_program_duration: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + duration_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_program_fidelity: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + fidelity_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compilation_metadata_get_qpu_runtime_estimation: ::std::option::Option< + unsafe extern "C" fn( + metadata: quilc_compilation_metadata, + runtime_ptr: *mut ::std::os::raw::c_void, + result: *mut ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_compile_protoquil: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + chip_spec: chip_specification, + metata_ptr: *mut ::std::os::raw::c_void, + result: *mut quil_program, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_build_nq_linear_chip: ::std::option::Option< + unsafe extern "C" fn( + n: ::std::os::raw::c_int, + result: *mut chip_specification, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_print_chip_spec: ::std::option::Option< + unsafe extern "C" fn(chip_spec: chip_specification) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_parse_chip_spec_isa_json: ::std::option::Option< + unsafe extern "C" fn( + isa_json: *mut ::std::os::raw::c_char, + result: *mut chip_specification, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_program_string: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_conjugate_pauli_by_clifford: ::std::option::Option< + unsafe extern "C" fn( + pauli_indices: *mut ::std::os::raw::c_void, + pauli_indices_len: ::std::os::raw::c_int, + pauli_terms: *mut ::std::os::raw::c_void, + pauli_terms_len: ::std::os::raw::c_int, + clifford: quil_program, + phase: *mut ::std::os::raw::c_void, + pauli: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut quilc_generate_rb_sequence: ::std::option::Option< + unsafe extern "C" fn( + depth: ::std::os::raw::c_int, + qubits: ::std::os::raw::c_int, + gateset_ptr: *mut ::std::os::raw::c_void, + gateset_len: ::std::os::raw::c_int, + seed_ptr: *mut ::std::os::raw::c_void, + interleaver: *mut ::std::os::raw::c_void, + results_ptr: *mut ::std::os::raw::c_void, + result_lens_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct qvm_multishot_addresses__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_qvm_multishot_addresses__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(qvm_multishot_addresses__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(qvm_multishot_addresses__)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).unused as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(qvm_multishot_addresses__), + "::", + stringify!(unused) + ) + ); +} +pub type qvm_multishot_addresses = *mut qvm_multishot_addresses__; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct qvm_multishot_result__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_qvm_multishot_result__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(qvm_multishot_result__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(qvm_multishot_result__)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).unused as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(qvm_multishot_result__), + "::", + stringify!(unused) + ) + ); +} +pub type qvm_multishot_result = *mut qvm_multishot_result__; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct qvm_version_info__ { + pub unused: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_qvm_version_info__() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(qvm_version_info__)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(qvm_version_info__)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).unused as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(qvm_version_info__), + "::", + stringify!(unused) + ) + ); +} +pub type qvm_version_info = *mut qvm_version_info__; +extern "C" { + pub static mut qvm_get_version_info: ::std::option::Option< + unsafe extern "C" fn(result: *mut qvm_version_info) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_version_info_version: ::std::option::Option< + unsafe extern "C" fn( + version_info: qvm_version_info, + result_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_version_info_githash: ::std::option::Option< + unsafe extern "C" fn( + version_info: qvm_version_info, + result_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot_addresses_new: ::std::option::Option< + unsafe extern "C" fn(result: *mut qvm_multishot_addresses) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot_addresses_set: ::std::option::Option< + unsafe extern "C" fn( + addresses: qvm_multishot_addresses, + name: *mut ::std::os::raw::c_char, + indices: *mut ::std::os::raw::c_void, + len: ::std::os::raw::c_int, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot_addresses_set_all: ::std::option::Option< + unsafe extern "C" fn( + addresses: qvm_multishot_addresses, + name: *mut ::std::os::raw::c_char, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + addresses: qvm_multishot_addresses, + trials: ::std::os::raw::c_int, + result: *mut qvm_multishot_result, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot_result_get: ::std::option::Option< + unsafe extern "C" fn( + qvm_result: qvm_multishot_result, + region_name: *mut ::std::os::raw::c_char, + region_index: ::std::os::raw::c_int, + result: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot_result_get_all: ::std::option::Option< + unsafe extern "C" fn( + qvm_result: qvm_multishot_result, + region_name: *mut ::std::os::raw::c_char, + shot_index: ::std::os::raw::c_int, + result: *mut ::std::os::raw::c_void, + result_len: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_multishot_measure: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + qubits: *mut ::std::os::raw::c_void, + n_qubits: ::std::os::raw::c_int, + trials: ::std::os::raw::c_int, + result: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_expectation: ::std::option::Option< + unsafe extern "C" fn( + state_prep: quil_program, + operators: *mut ::std::os::raw::c_void, + n_operators: ::std::os::raw::c_int, + results_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_wavefunction: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + results_ptr: *mut ::std::os::raw::c_void, + results_len_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut qvm_probabilities: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + results_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} +extern "C" { + pub static mut lisp_release_handle: + ::std::option::Option; +} +extern "C" { + pub static mut lisp_handle_eq: ::std::option::Option< + unsafe extern "C" fn( + a: *mut ::std::os::raw::c_void, + b: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, + >; +} +extern "C" { + pub fn init(core: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int; +} + diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 71b8016..550e48e 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -16,7 +16,7 @@ pub mod qvm; #[allow(dead_code)] pub(crate) mod bindings { - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/gen/bindings.rs")); } static START: Once = Once::new(); From 9d269a3fa2e978a6f71c4026efa1645eca10b739 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 15:43:53 +0000 Subject: [PATCH 2/9] debug LD_LIBRARY_PATH --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0806bc0..bdba74e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,7 @@ jobs: - name: Run tests run: | cd $GITHUB_WORKSPACE/lib + echo "paths: ${LD_LIBRARY_PATH}" cargo test test-macos: From 1f052e562cde9d6c5730f4899a57aca637cfb882 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 15:47:04 +0000 Subject: [PATCH 3/9] debug build failure location --- lib/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/build.rs b/lib/build.rs index 1efec19..e384d21 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -119,11 +119,15 @@ fn codegen() -> Result<(), Error> { } fn main() -> Result<(), Error> { + println!("adding search paths"); for path in get_lib_search_paths() { + println!("adding search path: {path}"); println!("cargo:rustc-link-search={}", path); } + println!("setting link"); println!("cargo:rustc-link-lib=quil"); + println!("finished setting link"); // If this isn't set on MacOS, memory allocation errors occur when trying to initialize the // library From 122d9cd0a5004f8ab819ca3e074383d7cb0764ae Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 15:53:53 +0000 Subject: [PATCH 4/9] use eprintln instead of println for debugging --- lib/build.rs | 6 +++--- python/build.rs | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/build.rs b/lib/build.rs index e384d21..c534dcb 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -119,15 +119,15 @@ fn codegen() -> Result<(), Error> { } fn main() -> Result<(), Error> { - println!("adding search paths"); + eprintln!("adding search paths"); for path in get_lib_search_paths() { println!("adding search path: {path}"); println!("cargo:rustc-link-search={}", path); } - println!("setting link"); + eprintln!("setting link"); println!("cargo:rustc-link-lib=quil"); - println!("finished setting link"); + eprintln!("finished setting link"); // If this isn't set on MacOS, memory allocation errors occur when trying to initialize the // library diff --git a/python/build.rs b/python/build.rs index dace4a9..34ff7f1 100644 --- a/python/build.rs +++ b/python/build.rs @@ -1,3 +1,5 @@ fn main() { + eprintln!("python build"); pyo3_build_config::add_extension_module_link_args(); + eprintln!("finished python build"); } From c69f22ab5fb6a6d19dda8ac0b03061c66209385d Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 15:57:02 +0000 Subject: [PATCH 5/9] use -vv for extra cargo build output --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bdba74e..b0419f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,6 +22,7 @@ jobs: run: | cd $GITHUB_WORKSPACE/lib echo "paths: ${LD_LIBRARY_PATH}" + cargo build -vv cargo test test-macos: From 45180d1b08b0286b7c017c5e25ca059935e2ce54 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 16:06:27 +0000 Subject: [PATCH 6/9] build: split search paths that include a colon --- lib/build.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/build.rs b/lib/build.rs index c534dcb..8fbba5c 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -1,5 +1,6 @@ use std::env; use std::path::PathBuf; +use std::str::FromStr; #[derive(Debug, thiserror::Error)] enum Error { @@ -32,6 +33,13 @@ fn get_header_path() -> Result { Err(Error::HeaderNotFound) } +fn split_lib_search_paths(paths: Vec) -> Vec { + paths + .into_iter() + .flat_map(|p| p.split(':').map(Into::into).collect::>()) + .collect() +} + fn get_lib_search_paths() -> Vec { let mut paths = vec!["/usr/local/lib".to_string(), "/usr/lib".to_string()]; @@ -45,7 +53,7 @@ fn get_lib_search_paths() -> Vec { paths.insert(0, ld_library_path.to_string()); } - paths + split_lib_search_paths(paths) } // #[cfg(feature = "codegen")] From 0582cea56dac6a6646e2a683d09836175a9d64b6 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 16:09:37 +0000 Subject: [PATCH 7/9] build: remove debug prints --- lib/build.rs | 11 +++-------- python/build.rs | 2 -- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/build.rs b/lib/build.rs index 8fbba5c..5030266 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -86,7 +86,6 @@ fn codegen() -> Result<(), Error> { // Write the bindings to the $OUT_DIR/bindings.rs file. let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - println!("Writing bindings to {}", out_path.display()); bindings .write_to_file(out_path.join("bindings.rs")) .expect("Should be able to write bindings to file."); @@ -111,9 +110,9 @@ fn codegen() -> Result<(), Error> { .create(true) .truncate(true) .open(dest.clone()) - .expect( - format!("Should open file '{}' for writing", dest.to_string_lossy()).as_str(), - ); + .unwrap_or_else(|_| { + panic!("Should open file '{}' for writing", dest.to_string_lossy()) + }); writeln!( file, "{}", @@ -127,15 +126,11 @@ fn codegen() -> Result<(), Error> { } fn main() -> Result<(), Error> { - eprintln!("adding search paths"); for path in get_lib_search_paths() { - println!("adding search path: {path}"); println!("cargo:rustc-link-search={}", path); } - eprintln!("setting link"); println!("cargo:rustc-link-lib=quil"); - eprintln!("finished setting link"); // If this isn't set on MacOS, memory allocation errors occur when trying to initialize the // library diff --git a/python/build.rs b/python/build.rs index 34ff7f1..dace4a9 100644 --- a/python/build.rs +++ b/python/build.rs @@ -1,5 +1,3 @@ fn main() { - eprintln!("python build"); pyo3_build_config::add_extension_module_link_args(); - eprintln!("finished python build"); } From 3ee8932e21c5322a7d44294f9972f11dffd6e706 Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 16:17:16 +0000 Subject: [PATCH 8/9] build: remove unused dependency --- lib/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Cargo.toml b/lib/Cargo.toml index d150270..00d7e1b 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -24,7 +24,6 @@ paste = "1.0.6" [build-dependencies] cc = { version = "1.0", features = ["parallel"] } -pkg-config = "0.3" bindgen = "0.53.1" thiserror = "1.0.44" From bbca7ba4e1de5fd995b284b3f178855b0e3269af Mon Sep 17 00:00:00 2001 From: Mark Skilbeck Date: Thu, 23 Nov 2023 16:40:54 +0000 Subject: [PATCH 9/9] build: commit bindings to repo --- lib/Cargo.toml | 6 +- lib/build.rs | 184 ++++++++++++++++++++-------------------- lib/src/gen/bindings.rs | 21 +++++ 3 files changed, 118 insertions(+), 93 deletions(-) diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 00d7e1b..0fabb43 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -11,8 +11,8 @@ build = "build.rs" categories = ["compilers", "api-bindings"] readme = "../README.md" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +codegen = ["bindgen"] [dependencies] libc = "0.2" @@ -24,7 +24,7 @@ paste = "1.0.6" [build-dependencies] cc = { version = "1.0", features = ["parallel"] } -bindgen = "0.53.1" +bindgen = { version = "0.53.1", optional = true } thiserror = "1.0.44" [dev-dependencies] diff --git a/lib/build.rs b/lib/build.rs index 5030266..ba346c5 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -1,38 +1,14 @@ use std::env; -use std::path::PathBuf; -use std::str::FromStr; #[derive(Debug, thiserror::Error)] enum Error { + #[allow(dead_code)] #[error("Could not find error in any of the standard locations. Try setting C_INCLUDE_PATH or LIBQUIL_SRC_PATH")] HeaderNotFound, #[error("Could not read environment variable: {0}")] InvalidEnvvar(#[from] env::VarError), } -fn get_header_path() -> Result { - let mut paths = vec!["/usr/local/include/libquil", "/usr/include/libquil"]; - - let libquil_src_path: Option<&'static str> = option_env!("LIBQUIL_SRC_PATH"); - if let Some(libquil_src_path) = libquil_src_path { - paths.insert(0, libquil_src_path); - } - - let c_include_path: Option<&'static str> = option_env!("C_INCLUDE_PATH"); - if let Some(c_include_path) = c_include_path { - paths.insert(0, c_include_path); - } - - for path in paths { - let path = PathBuf::from(path).join("libquil.h"); - if path.exists() { - return Ok(path); - } - } - - Err(Error::HeaderNotFound) -} - fn split_lib_search_paths(paths: Vec) -> Vec { paths .into_iter() @@ -56,73 +32,100 @@ fn get_lib_search_paths() -> Vec { split_lib_search_paths(paths) } -// #[cfg(feature = "codegen")] -fn codegen() -> Result<(), Error> { - use std::fs::OpenOptions; - use std::io::Write; - - let libquil_header_path = get_header_path()?; - - // Tell cargo to rerun if the libquil implementation has changed - println!( - "cargo:rustc-rerun-if-changed={}", - libquil_header_path.clone().display() - ); - - // The bindgen::Builder is the main entry point - // to bindgen, and lets you build up options for - // the resulting bindings. - let bindings = bindgen::Builder::default() - // The input header we would like to generate - // bindings for. - .header(libquil_header_path.to_string_lossy()) - // Tell cargo to invalidate the built crate whenever any of the - // included header files changed. - .parse_callbacks(Box::new(bindgen::CargoCallbacks)) - // Finish the builder and generate the bindings. - .generate() - // Unwrap the Result and panic on failure. - .expect("Bindings should be generated"); - - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Should be able to write bindings to file."); - - let gen_code_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("src") - .join("gen"); - - for entry in std::fs::read_dir(PathBuf::from(&out_path)) - .expect("OUT_DIR environment variable should point to a valid directory") - { - let src_path = entry.expect("OUT_DIR should contain files").path(); - if src_path.to_string_lossy().ends_with(".rs") { - let dest = gen_code_dir.join( - src_path - .file_name() - .expect("path should include a valid file name"), - ); - - let mut file = OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(dest.clone()) - .unwrap_or_else(|_| { - panic!("Should open file '{}' for writing", dest.to_string_lossy()) - }); - writeln!( - file, - "{}", - std::fs::read_to_string(src_path).expect("Should read file contents") - ) - .expect("Should write file contents"); +#[cfg(feature = "codegen")] +mod codegen { + use std::{env, path::PathBuf}; + + fn get_header_path() -> Result { + let mut paths = vec!["/usr/local/include/libquil", "/usr/include/libquil"]; + + let libquil_src_path: Option<&'static str> = option_env!("LIBQUIL_SRC_PATH"); + if let Some(libquil_src_path) = libquil_src_path { + paths.insert(0, libquil_src_path); + } + + let c_include_path: Option<&'static str> = option_env!("C_INCLUDE_PATH"); + if let Some(c_include_path) = c_include_path { + paths.insert(0, c_include_path); + } + + for path in paths { + let path = PathBuf::from(path).join("libquil.h"); + if path.exists() { + return Ok(path); + } } + + Err(super::Error::HeaderNotFound) } - Ok(()) + pub(crate) fn codegen() -> Result<(), super::Error> { + use std::fs::OpenOptions; + use std::io::Write; + + let libquil_header_path = get_header_path()?; + + // Tell cargo to rerun if the libquil implementation has changed + println!( + "cargo:rustc-rerun-if-changed={}", + libquil_header_path.clone().display() + ); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header(libquil_header_path.to_string_lossy()) + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Bindings should be generated"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Should be able to write bindings to file."); + + let gen_code_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("src") + .join("gen"); + + for entry in std::fs::read_dir(PathBuf::from(&out_path)) + .expect("OUT_DIR environment variable should point to a valid directory") + { + let src_path = entry.expect("OUT_DIR should contain files").path(); + if src_path.to_string_lossy().ends_with(".rs") { + let dest = gen_code_dir.join( + src_path + .file_name() + .expect("path should include a valid file name"), + ); + + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(dest.clone()) + .unwrap_or_else(|_| { + panic!("Should open file '{}' for writing", dest.to_string_lossy()) + }); + writeln!( + file, + "{}", + std::fs::read_to_string(src_path).expect("Should read file contents") + ) + .expect("Should write file contents"); + } + } + + Ok(()) + } } fn main() -> Result<(), Error> { @@ -138,7 +141,8 @@ fn main() -> Result<(), Error> { println!("cargo:rustc-link-arg=-pagezero_size 0x100000"); } - codegen()?; + #[cfg(feature = "codegen")] + codegen::codegen()?; Ok(()) } diff --git a/lib/src/gen/bindings.rs b/lib/src/gen/bindings.rs index 82a52f0..824f69c 100644 --- a/lib/src/gen/bindings.rs +++ b/lib/src/gen/bindings.rs @@ -8,6 +8,11 @@ extern "C" { unsafe extern "C" fn(result: *mut *mut ::std::os::raw::c_char) -> libquil_error_t, >; } +pub const program_memory_type_t_LIBQUIL_TYPE_BIT: program_memory_type_t = 0; +pub const program_memory_type_t_LIBQUIL_TYPE_OCTET: program_memory_type_t = 1; +pub const program_memory_type_t_LIBQUIL_TYPE_INTEGER: program_memory_type_t = 2; +pub const program_memory_type_t_LIBQUIL_TYPE_REAL: program_memory_type_t = 3; +pub type program_memory_type_t = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct quil_program__ { @@ -155,6 +160,15 @@ extern "C" { ) -> libquil_error_t, >; } +extern "C" { + pub static mut quilc_program_memory_type: ::std::option::Option< + unsafe extern "C" fn( + program: quil_program, + region_name: *mut ::std::os::raw::c_char, + region_type_ptr: *mut ::std::os::raw::c_void, + ) -> libquil_error_t, + >; +} extern "C" { pub static mut quilc_print_program: ::std::option::Option libquil_error_t>; @@ -453,6 +467,9 @@ extern "C" { program: quil_program, addresses: qvm_multishot_addresses, trials: ::std::os::raw::c_int, + gate_noise: *mut ::std::os::raw::c_void, + measurement_noise: *mut ::std::os::raw::c_void, + rng_seed: *mut ::std::os::raw::c_void, result: *mut qvm_multishot_result, ) -> libquil_error_t, >; @@ -485,6 +502,7 @@ extern "C" { qubits: *mut ::std::os::raw::c_void, n_qubits: ::std::os::raw::c_int, trials: ::std::os::raw::c_int, + rng_seed: *mut ::std::os::raw::c_void, result: *mut ::std::os::raw::c_void, ) -> libquil_error_t, >; @@ -495,6 +513,7 @@ extern "C" { state_prep: quil_program, operators: *mut ::std::os::raw::c_void, n_operators: ::std::os::raw::c_int, + rng_seed: *mut ::std::os::raw::c_void, results_ptr: *mut ::std::os::raw::c_void, ) -> libquil_error_t, >; @@ -503,6 +522,7 @@ extern "C" { pub static mut qvm_wavefunction: ::std::option::Option< unsafe extern "C" fn( program: quil_program, + rng_seed: *mut ::std::os::raw::c_void, results_ptr: *mut ::std::os::raw::c_void, results_len_ptr: *mut ::std::os::raw::c_void, ) -> libquil_error_t, @@ -512,6 +532,7 @@ extern "C" { pub static mut qvm_probabilities: ::std::option::Option< unsafe extern "C" fn( program: quil_program, + rng_seed: *mut ::std::os::raw::c_void, results_ptr: *mut ::std::os::raw::c_void, ) -> libquil_error_t, >;