Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ jobs:
env: { GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" }
run: ./ci/deps.sh
- name: 构建
env: { KVSPACE_BACKEND_PATH: /usr/lib/kvspace }
run: make shm
- name: rwir 合同测试
env: { KVSPACE_BACKEND_PATH: /usr/lib/kvspace }
run: make test-rwir
- name: 测试
env: { KVSPACE: "shm:///tmp/kvlang_ci" }
env:
KVSPACE: "shm:///tmp/kvlang_ci"
KVSPACE_BACKEND_PATH: /usr/lib/kvspace
run: python3 tutorial/test.py
17 changes: 14 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,27 @@

BIN := bin

.PHONY: all runtime term layout json oldhero test install clean
.PHONY: all shm runtime term layout json oldhero test test-rwir install clean

all: runtime term layout json
shm: all

test: all
test: all test-rwir
python3 tutorial/test.py --no-build

runtime:
cmake -S runtime -B build/runtime -DCMAKE_BUILD_TYPE=Release
cmake --build build/runtime --target kvlang_runtime -j
cmake --build build/runtime --target kvlang_runtime \
kvlang_delegate_test kvlang_notify_test kvlang_incr_test \
kvlang_expire_test kvlang_watchany_test -j

test-rwir:
./$(BIN)/kvlang_delegate_test
./$(BIN)/kvlang_notify_test
./$(BIN)/kvlang_incr_test
./$(BIN)/kvlang_expire_test
./$(BIN)/kvlang_watchany_test
cargo test --manifest-path layout/Cargo.toml --test pipeline_test refuse_rwir_and_rwfunc -- --nocapture

term:
cargo build --release --manifest-path runtime-rwirext_example/rust/term/Cargo.toml
Expand Down
29 changes: 23 additions & 6 deletions ci/deps.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
#!/usr/bin/env bash
# 下载 ABI 依赖(deps.json: repo → tag),安装到 /usr/lib + /usr/include。本地与 CI 共用。
# 下载 ABI 依赖(deps.json: repo → tag 或 owner/repo@tag),安装到 PREFIX。
# 本地与 CI 共用。PREFIX 默认 /usr;非 /usr 不使用 sudo。
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
PREFIX="${KVSPACE_ABI_PREFIX:-/usr}"
if [ "$PREFIX" = /usr ]; then SUDO=sudo; else SUDO=; fi
$SUDO mkdir -p "$PREFIX/lib" "$PREFIX/include" "$PREFIX/lib/kvspace"
for repo in $(jq -r 'keys[]' "$ROOT/deps.json"); do
ver=$(jq -r ".\"$repo\"" "$ROOT/deps.json")
spec=$(jq -r --arg r "$repo" '.[$r]' "$ROOT/deps.json")
if [[ "$spec" == *@* ]]; then
owner_repo="${spec%@*}"
ver="${spec##*@}"
else
owner_repo="array2d/$repo"
ver="$spec"
fi
tmp="$(mktemp -d)"
gh release download "$ver" -R "array2d/$repo" -p "${repo}-abi-*-linux-x86_64.tar.gz" -D "$tmp"
gh release download "$ver" -R "$owner_repo" -p "${repo}-abi-*-linux-x86_64.tar.gz" -D "$tmp"
tar xzf "$tmp"/*.tar.gz -C "$tmp" --strip-components=1
if [ -d "$tmp/include" ]; then sudo cp -r "$tmp/include/"* /usr/include/; fi
sudo cp "$tmp/lib/"*.so* /usr/lib/
if [ -d "$tmp/include" ]; then $SUDO cp -r "$tmp/include/"* "$PREFIX/include/"; fi
$SUDO cp "$tmp/lib/"*.so* "$PREFIX/lib/"
# dispatch 前端默认 dlopen $PREFIX/lib/kvspace/<soname>
$SUDO cp "$tmp/lib/"*.so* "$PREFIX/lib/kvspace/"
# durable v0.2.1 ships libkvspace_durable.so without SONAME .1
if [ -e "$PREFIX/lib/kvspace/libkvspace_durable.so" ] && [ ! -e "$PREFIX/lib/kvspace/libkvspace_durable.so.1" ]; then
$SUDO ln -s libkvspace_durable.so "$PREFIX/lib/kvspace/libkvspace_durable.so.1"
fi
rm -rf "$tmp"
done
echo "✅ ABI deps → /usr/lib + /usr/include"
echo "✅ ABI deps → $PREFIX/lib + $PREFIX/include"
3 changes: 2 additions & 1 deletion deps.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"kvspace-c": "v0.2.1",
"kvspace": "carsontung666/kvspace@v0.1.0",
"kvspace-c": "carsontung666/kvspace-c@v0.2.2",
"kvspace-durable": "v0.2.1",
"blockmalloc": "v0.1.4",
"slotsboxmalloc": "v0.1.4"
Expand Down
31 changes: 25 additions & 6 deletions layout/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ pub fn compile(kv: &mut Kv, src: &str) -> Result<(), String> {
for func in &file.funcs {
let pkg = if func.pkg.is_empty() { file.package.clone() } else { func.pkg.clone() };
let mut lowered = lower::lower_func(func);
write_func(kv, &pkg, &mut lowered);
write_func(kv, &pkg, &mut lowered)?;
any_code = true;
}
for decl in &file.rwir_decls {
write_rwir_decl(kv, decl);
write_rwir_decl(kv, decl)?;
any_code = true;
}

let mut body = file.init_body.clone();
Expand All @@ -53,7 +54,7 @@ pub fn compile(kv: &mut Kv, src: &str) -> Result<(), String> {
pkg: String::new(),
};
let mut lowered = lower::lower_func(&init_fn);
write_func(kv, "", &mut lowered);
write_func(kv, "", &mut lowered)?;
any_code = true;
}

Expand Down Expand Up @@ -100,10 +101,21 @@ pub fn vet(src: &str) -> Result<(), String> {
}

/// 写函数到 /lib/:签名(rwfunc)、源码、参数 Ptr、指令体。
pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) -> Result<(), String> {
let mut type_map = lower::infer_types(fn_);
lower::specialize(fn_, &type_map);
let func_dir = keytree::lib_func(pkg, &fn_.sig.name);
let opcode = if pkg.is_empty() {
fn_.sig.name.clone()
} else {
format!("{}{}{}", pkg, keytree::MEMBER_SEP, fn_.sig.name)
};
let existing = kv.get_one(&keytree::rwir(&opcode));
if kvkind::kind(&existing) == kvkind::KIND_DEF_RWIR {
return Err(format!(
"{opcode}: rwir declaration and rwfunc body both define it; one opcode, one definition"
));
}

// 按函数覆盖(文件夹复制式合并):只 del_tree 本函数子树,不动 /lib 下其它函数。
// 禁止整库删除——layoutcode 必须可增量:多次 layout 各自覆盖其函数,不误删先前的函数。
Expand Down Expand Up @@ -134,16 +146,23 @@ pub fn write_func(kv: &mut Kv, pkg: &str, fn_: &mut Func) {
let _ = kv.set(&pairs);

write_body(kv, pkg, &fn_.sig.name, &fn_.body, &mut type_map, 1);
Ok(())
}

/// 写用户声明的 rwir(无体)到 /lib/<opcode>。
pub fn write_rwir_decl(kv: &mut Kv, decl: &RwirDecl) {
pub fn write_rwir_decl(kv: &mut Kv, decl: &RwirDecl) -> Result<(), String> {
let mut opcode = decl.sig.name.clone();
if !decl.pkg.is_empty() {
opcode = format!("{}{}{opcode}", decl.pkg, keytree::MEMBER_SEP);
}
let sig = kv.get_one(&format!("{}/[0,0]", keytree::lib_func("", &opcode)));
if kvkind::kind(&sig) == kvkind::KIND_DEF_RWFUNC {
return Err(format!(
"{opcode}: rwir declaration and rwfunc body both define it; one opcode, one definition"
));
}
let v = kvkind::new_defrwir(decl.sig.num_reads(), decl.sig.num_writes(), &decl.sig.kindexp_list().join("\n"));
let _ = kv.set(&[(keytree::rwir(&opcode), v)]);
kv.set(&[(keytree::rwir(&opcode), v)])
}

/// 将 body 写入 /lib/<pkg>/<name>/ 下。offset 起始 idx(顶层函数=1)。
Expand Down
10 changes: 9 additions & 1 deletion layout/tests/pipeline_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@ fn sig(data: &[u8]) -> String {
}

fn fresh_kv() -> Kv {
let dsn = format!("fs:///tmp/kvlang_layout_test_{}", std::process::id());
let dsn = format!("shm:///tmp/kvlang_layout_test_{}", std::process::id());
let mut kv = Kv::conn(&dsn);
init_dirs(&mut kv).unwrap();
kv
}

#[test]
fn refuse_rwir_and_rwfunc() {
let mut kv = fresh_kv();
compile(&mut kv, "rwfunc dup() -> () {\n 1 -> _\n}\n").unwrap();
let err = compile(&mut kv, "rwir dup() -> ()\n").unwrap_err();
assert!(err.contains("one opcode, one definition"), "{err}");
}

#[test]
fn compile_simple_func() {
let mut kv = fresh_kv();
Expand Down
15 changes: 14 additions & 1 deletion runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}")
add_library(kvlang_runtime SHARED
src/strbuf.c src/xvalue.c src/kv.c src/keytree.c src/rwir.c
src/vthread.c src/logx.c src/builtin.c src/kvcpu.c src/runtime.c src/rwirext.c
src/kindexpr.c)
src/kindexpr.c src/dispatch.c)
target_include_directories(kvlang_runtime PUBLIC include src)
target_compile_definitions(kvlang_runtime PRIVATE _GNU_SOURCE)

Expand All @@ -22,3 +22,16 @@ target_link_libraries(kvlang_runtime PRIVATE kvspace m pthread)

# --export-dynamic 供 kvlang(term 扩展)找符号;--disable-new-dtags 使 rpath 转 DT_RPATH(传递)。
set_target_properties(kvlang_runtime PROPERTIES LINK_FLAGS "-Wl,--export-dynamic -Wl,--disable-new-dtags")

function(kvlang_runtime_test name src)
add_executable(${name} ${src})
target_link_libraries(${name} PRIVATE kvlang_runtime pthread)
target_include_directories(${name} PRIVATE include src)
set_target_properties(${name} PROPERTIES BUILD_RPATH "${BIN_DIR}")
endfunction()

kvlang_runtime_test(kvlang_delegate_test tests/delegate_test.c)
kvlang_runtime_test(kvlang_notify_test tests/notify_contract_test.c)
kvlang_runtime_test(kvlang_incr_test tests/incr_test.c)
kvlang_runtime_test(kvlang_expire_test tests/expire_test.c)
kvlang_runtime_test(kvlang_watchany_test tests/watchany_test.c)
Loading
Loading