-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
334 additions
and
4 deletions.
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
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,86 @@ | ||
#!/usr/bin/env bash | ||
|
||
# This script was copied from the https://github.com/cross-rs/cross project at commit | ||
# ac4c11cedc97cd7c27faed36e55377a90e6ed618. The license for that project in its `Cargo.toml` file is | ||
# "MIT OR Apache-2.0". The copyright in the MIT license says: | ||
# | ||
# Copyright (c) 2017-2022 by the respective authors | ||
# Copyright (c) 2016 Jorge Aparicio | ||
# | ||
# The script was adjusted to get rid of the sysroot and arch parameters in favor of hardcoding the | ||
# paths for Ubuntu 22.04 and the x86-64 arch. | ||
|
||
# Create necessary symlinks for musl images to run | ||
# dynamically-linked binaries. | ||
# Just to be careful, we need this in a few locations, | ||
# relative to the musl sysroot. | ||
# /lib/ld-musl-armhf.so | ||
# /lib/ld-musl-armhf.so.1 | ||
# /usr/lib/ld.so | ||
# /usr/lib/ld.so.1 | ||
# /usr/lib/libc.so | ||
# /usr/lib/libc.so.1 | ||
|
||
set -x | ||
set -euo pipefail | ||
|
||
main() { | ||
apt-get --yes install libboost-dev | ||
|
||
local src | ||
local dst | ||
local dsts | ||
local libstdcpp_path | ||
local libstdcpp_basename | ||
|
||
# ignore any failures here | ||
src="/usr/lib/x86_64-linux-musl/libc.so" | ||
dsts=( | ||
"/usr/lib/ld-musl-x86_64.so" | ||
"/usr/lib/ld-musl-x86_64.so.1" | ||
"/usr/lib/ld.so" | ||
"/usr/lib/ld.so.6" | ||
"/usr/lib/libc.so" | ||
"/usr/lib/libc.so.6" | ||
) | ||
for dst in "${dsts[@]}"; do | ||
# force a link if the dst does not exist or is broken | ||
if [[ -L ${dst} ]] && [[ ! -e ${dst} ]]; then | ||
ln -sf "${src}" "${dst}" | ||
elif [[ ! -f ${dst} ]]; then | ||
ln -s "${src}" "${dst}" | ||
fi | ||
done | ||
|
||
libstdcpp_path=$(find /usr/lib/x86_64-linux-gnu/ -name 'libstdc++.so.6.0.*') | ||
libstdcpp_basename=$(basename "$libstdcpp_path") | ||
|
||
# ensure we statically link libstdc++, so avoid segfaults with c++ | ||
# https://github.com/cross-rs/cross/issues/902 | ||
find /usr -name 'libstdc++.so*' -exec rm -f {} \; | ||
|
||
# now, we create a linker script that adds all the required dependencies | ||
# because we link to a static libstdc++ to avoid runtime issues and | ||
# with the shared libstdc++, we can have missing symbols that are referenced | ||
# in libstdc++, such as those from libc like `setlocale` and `__cxa_atexit`, | ||
# as well as those from libgcc, like `__extendsftf2`. all musl targets | ||
# can require symbols from libc, however, only the following are known | ||
# to require symbols from libgcc: | ||
# - aarch64-unknown-linux-musl | ||
# - mips64-unknown-linux-muslabi64 | ||
# - mips64el-unknown-linux-muslabi64 | ||
echo '/* cross-rs linker script | ||
* this allows us to statically link libstdc++ to avoid segfaults | ||
* https://github.com/cross-rs/cross/issues/902 | ||
*/ | ||
GROUP ( libstdc++.a AS_NEEDED( -lgcc -lc -lm ) ) | ||
' >"$libstdcpp_path" | ||
ln -s "$libstdcpp_basename" /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | ||
ln -s "$libstdcpp_basename" /usr/lib/x86_64-linux-gnu/libstdc++.so | ||
|
||
echo /usr/lib/x86_64-linux-gnu >>/etc/ld-musl-x86_64.path | ||
|
||
ln -s /usr/bin/musl-gcc /usr/bin/musl-g++ | ||
} | ||
|
||
main |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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,15 @@ | ||
[package] | ||
name = "demo" | ||
version = "0.0.0" | ||
authors = ["David Tolnay <dtolnay@gmail.com>"] | ||
description = "Toy project from https://github.com/dtolnay/cxx" | ||
edition = "2021" | ||
license = "MIT OR Apache-2.0" | ||
publish = false | ||
repository = "https://github.com/dtolnay/cxx" | ||
|
||
[dependencies] | ||
cxx = "1.0" | ||
|
||
[build-dependencies] | ||
cxx-build = "1.0" |
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 @@ | ||
This was copied from https://github.com/dtolnay/cxx/tree/master/demo |
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,10 @@ | ||
fn main() { | ||
cxx_build::bridge("src/main.rs") | ||
.file("src/blobstore.cc") | ||
.std("c++14") | ||
.compile("cxxbridge-demo"); | ||
|
||
println!("cargo:rerun-if-changed=src/main.rs"); | ||
println!("cargo:rerun-if-changed=src/blobstore.cc"); | ||
println!("cargo:rerun-if-changed=include/blobstore.h"); | ||
} |
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,26 @@ | ||
#pragma once | ||
#include "rust/cxx.h" | ||
#include <memory> | ||
|
||
namespace org { | ||
namespace blobstore { | ||
|
||
struct MultiBuf; | ||
struct BlobMetadata; | ||
|
||
class BlobstoreClient { | ||
public: | ||
BlobstoreClient(); | ||
uint64_t put(MultiBuf &buf) const; | ||
void tag(uint64_t blobid, rust::Str tag) const; | ||
BlobMetadata metadata(uint64_t blobid) const; | ||
|
||
private: | ||
class impl; | ||
std::shared_ptr<impl> impl; | ||
}; | ||
|
||
std::unique_ptr<BlobstoreClient> new_blobstore_client(); | ||
|
||
} // namespace blobstore | ||
} // namespace org |
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,71 @@ | ||
#include "demo/include/blobstore.h" | ||
#include "demo/src/main.rs.h" | ||
#include <algorithm> | ||
#include <functional> | ||
#include <set> | ||
#include <string> | ||
#include <unordered_map> | ||
|
||
namespace org { | ||
namespace blobstore { | ||
|
||
// Toy implementation of an in-memory blobstore. | ||
// | ||
// In reality the implementation of BlobstoreClient could be a large complex C++ | ||
// library. | ||
class BlobstoreClient::impl { | ||
friend BlobstoreClient; | ||
using Blob = struct { | ||
std::string data; | ||
std::set<std::string> tags; | ||
}; | ||
std::unordered_map<uint64_t, Blob> blobs; | ||
}; | ||
|
||
BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {} | ||
|
||
// Upload a new blob and return a blobid that serves as a handle to the blob. | ||
uint64_t BlobstoreClient::put(MultiBuf &buf) const { | ||
std::string contents; | ||
|
||
// Traverse the caller's chunk iterator. | ||
// | ||
// In reality there might be sophisticated batching of chunks and/or parallel | ||
// upload implemented by the blobstore's C++ client. | ||
while (true) { | ||
auto chunk = next_chunk(buf); | ||
if (chunk.size() == 0) { | ||
break; | ||
} | ||
contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size()); | ||
} | ||
|
||
// Insert into map and provide caller the handle. | ||
auto blobid = std::hash<std::string>{}(contents); | ||
impl->blobs[blobid] = {std::move(contents), {}}; | ||
return blobid; | ||
} | ||
|
||
// Add tag to an existing blob. | ||
void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const { | ||
impl->blobs[blobid].tags.emplace(tag); | ||
} | ||
|
||
// Retrieve metadata about a blob. | ||
BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const { | ||
BlobMetadata metadata{}; | ||
auto blob = impl->blobs.find(blobid); | ||
if (blob != impl->blobs.end()) { | ||
metadata.size = blob->second.data.size(); | ||
std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(), | ||
[&](auto &t) { metadata.tags.emplace_back(t); }); | ||
} | ||
return metadata; | ||
} | ||
|
||
std::unique_ptr<BlobstoreClient> new_blobstore_client() { | ||
return std::make_unique<BlobstoreClient>(); | ||
} | ||
|
||
} // namespace blobstore | ||
} // namespace org |
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,59 @@ | ||
#[cxx::bridge(namespace = "org::blobstore")] | ||
mod ffi { | ||
// Shared structs with fields visible to both languages. | ||
struct BlobMetadata { | ||
size: usize, | ||
tags: Vec<String>, | ||
} | ||
|
||
// Rust types and signatures exposed to C++. | ||
extern "Rust" { | ||
type MultiBuf; | ||
|
||
fn next_chunk(buf: &mut MultiBuf) -> &[u8]; | ||
} | ||
|
||
// C++ types and signatures exposed to Rust. | ||
unsafe extern "C++" { | ||
include!("demo/include/blobstore.h"); | ||
|
||
type BlobstoreClient; | ||
|
||
fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; | ||
fn put(&self, parts: &mut MultiBuf) -> u64; | ||
fn tag(&self, blobid: u64, tag: &str); | ||
fn metadata(&self, blobid: u64) -> BlobMetadata; | ||
} | ||
} | ||
|
||
// An iterator over contiguous chunks of a discontiguous file object. | ||
// | ||
// Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating | ||
// over some more complex Rust data structure like a rope, or maybe loading | ||
// chunks lazily from somewhere. | ||
pub struct MultiBuf { | ||
chunks: Vec<Vec<u8>>, | ||
pos: usize, | ||
} | ||
pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { | ||
let next = buf.chunks.get(buf.pos); | ||
buf.pos += 1; | ||
next.map_or(&[], Vec::as_slice) | ||
} | ||
|
||
fn main() { | ||
let client = ffi::new_blobstore_client(); | ||
|
||
// Upload a blob. | ||
let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; | ||
let mut buf = MultiBuf { chunks, pos: 0 }; | ||
let blobid = client.put(&mut buf); | ||
println!("blobid = {}", blobid); | ||
|
||
// Add a tag. | ||
client.tag(blobid, "rust"); | ||
|
||
// Read back the tags. | ||
let metadata = client.metadata(blobid); | ||
println!("tags = {:?}", metadata.tags); | ||
} |