Skip to content
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

Feature/599 provide and use c service in rust #627

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2c8d89a
#599: Add rust (mini) example impl for context, activator and log hel…
pnoltes Aug 19, 2023
2f37f72
#599: Add initial setup for rust shell tui
pnoltes Aug 19, 2023
3b4ccb9
#599: Refactor rust api into modules
pnoltes Aug 20, 2023
4c14d8c
#599: Move Celix rust api to a separate rust lib
pnoltes Aug 20, 2023
21b0027
#599: Refactor rust celix lib and add LogHelper to rust celix lib
pnoltes Aug 20, 2023
1654e21
#599: Refactor bundle context for service registration builder
pnoltes Aug 22, 2023
dd13817
#599: Refactor rust log helper
pnoltes Aug 22, 2023
99717a6
Add registration of rust trait
pnoltes Aug 23, 2023
3ef7b52
Add use_service poc for Rust experiment
pnoltes Aug 25, 2023
b2e8657
#599: Remove BundleContext trait so that generic method are possible
pnoltes Aug 25, 2023
5329420
#599: Add poc svc tracker to rust experimental
pnoltes Aug 28, 2023
8b3f943
#599: Remove unused poc rust bundle example
pnoltes Aug 28, 2023
53654a3
#599: Add support for CELIX_RUST_INCLUDE_PATHS_FILE env in rust poc
pnoltes Aug 29, 2023
88deb83
#599: Rename RustShellCommandTrait in rust poc
pnoltes Aug 29, 2023
bf01a26
#632: Update changes.md for coming Apache Celix 2.4.0
pnoltes Sep 4, 2023
f227191
Update CMake to 3.19 to meet Corrosion's need.
PengZheng Sep 6, 2023
e3aa83a
#599: Add CMake 3.19 requirement for Rust PoC
pnoltes Sep 6, 2023
e0f3c4c
Revert " #599: Add CMake 3.19 requirement for Rust PoC"
pnoltes Sep 6, 2023
c89893f
Merge branch 'feature/632-update-changes' into feature/599-provide-an…
pnoltes Sep 6, 2023
9fd6da5
Fix rustc warning.
PengZheng Sep 16, 2023
766ee3b
Merge remote-tracking branch 'apache/feature/599-provide-and-use-c-se…
PengZheng Sep 16, 2023
dc81c7a
Update Rust edition, remove extern crates
PengZheng Sep 17, 2023
4e91216
Added resolver in workspace to version 2
PengZheng Sep 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 33 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@ See the License for the specific language governing permissions and
limitations under the License.
-->

# Noteworthy Changes for 2.4.0 (TBD)

## New Features

- V2 Shared memory for remote service admin.
- Zeroconf discovery of remote services.
- Symbol visibility support: Bundle symbols are now hidden by default, except for the bundle activator.
- Error injection library (for testing).
- Coding convention documentation.
- Celix error library for printing errors when no framework is available.
- Scope-based Resource Management (RAII-light for C).
- Rust Proof of Concept (PoC) for Apache Celix.

## Improvements

- Support for Conan 2.
- Support for uclibc (not tested in CI yet).
- Support for C++14 in addition to C++17.
- Deprecated `snprintf` usage; transitioned to `snprintf` or `aprintf`.
- Refactored the bundle cache to support retention of unchanged bundles on disk.
- Automatic scan for project build options using CMake.
- Use of upstream `civetweb` dependency instead of embedded sources.
- Applied attribute format for printf-like functions.
- Removed the busy loop mechanism from the pubsub admin websocket.
- Improved cleanup procedures during bundle uninstallation to conform to the OSGi specification.
- Improved `INSTALL_RPATH` to use `$ORIGIN` during installation.
- Corrected bundle update behavior when updating bundles from different sources.
- Enhanced `libcurl` initialization procedures and made `libcurl` optional.

## Fixes

- Numerous minor fixes, especially concerning multi-threading issues and error handling.

# Noteworthy changes for 2.3.0 (2022-07-10)

## New Features
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.

cmake_minimum_required (VERSION 3.18)
cmake_minimum_required (VERSION 3.19)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0042 NEW)
cmake_policy(SET CMP0068 NEW)
Expand Down
33 changes: 24 additions & 9 deletions misc/experimental/rust/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# under the License.

option(CELIX_RUST_EXPERIMENTAL "Enable experimental rust bundle" OFF)
if (CELIX_RUST_EXPERIMENTAL)
if (CELIX_RUST_EXPERIMENTAL AND TARGET Celix::shell_tui AND TARGET Celix::shell AND TARGET Celix::log_admin)
include(FetchContent)
FetchContent_Declare(
Corrosion
Expand All @@ -26,13 +26,12 @@ if (CELIX_RUST_EXPERIMENTAL)
FetchContent_MakeAvailable(Corrosion)
PengZheng marked this conversation as resolved.
Show resolved Hide resolved

#Prepare a list of include paths needed to generating bindings for the Apache Celix C API
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include_paths.txt"
CONTENT "$<TARGET_PROPERTY:framework,INTERFACE_INCLUDE_DIRECTORIES>;$<TARGET_PROPERTY:utils,INTERFACE_INCLUDE_DIRECTORIES>"
)
#Note for now this includes framework, utils and shell_api maybe this should be separated in the future.
file(GENERATE OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/include_paths.txt" CONTENT
"$<TARGET_PROPERTY:framework,INTERFACE_INCLUDE_DIRECTORIES>;$<TARGET_PROPERTY:utils,INTERFACE_INCLUDE_DIRECTORIES>;$<TARGET_PROPERTY:shell_api,INTERFACE_INCLUDE_DIRECTORIES>;$<TARGET_PROPERTY:Celix::log_service_api,INTERFACE_INCLUDE_DIRECTORIES>")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

INCLUDE_DIRECTORIES alone is not enough, we shall also have COMPILE_DEFINITIONS and COMPILE_OPTIONS.


corrosion_import_crate(MANIFEST_PATH Cargo.toml)

corrosion_add_target_local_rustflags(rust_bundle_activator "-Cprefer-dynamic")
corrosion_link_libraries(rust_bundle_activator Celix::framework)

Expand All @@ -41,12 +40,28 @@ if (CELIX_RUST_EXPERIMENTAL)
get_target_property(ACTUAL_LIB_TARGET rust_bundle_activator INTERFACE_LINK_LIBRARIES)
add_celix_bundle(rust_bundle ACTIVATOR ${ACTUAL_LIB_TARGET})
add_dependencies(rust_bundle rust_bundle_activator)
corrosion_add_target_local_rustflags(rust_shell_command_activator "-Cprefer-dynamic")
corrosion_link_libraries(rust_shell_command_activator
Celix::framework
)

add_celix_container(rust_container
NO_COPY
get_target_property(ACTUAL_LIB_TARGET rust_shell_command_activator INTERFACE_LINK_LIBRARIES)
add_celix_bundle(rust_shell_command ACTIVATOR ${ACTUAL_LIB_TARGET})
add_dependencies(rust_shell_command rust_shell_command_activator)

add_celix_container(rust_container NO_COPY
BUNDLES
Celix::shell
Celix::shell_tui
rust_bundle
)
endif ()

add_celix_container(rust_shell_cnt NO_COPY
BUNDLES
Celix::shell
Celix::shell_tui
Celix::log_admin
rust_shell_command
)

endif()
3 changes: 3 additions & 0 deletions misc/experimental/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
[workspace]
members = [
"celix_bindings",
"celix",
"hello_world_activator",
"rust_shell_api",
"shell_command_bundle",
]
28 changes: 28 additions & 0 deletions misc/experimental/rust/celix/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

[package]
name = "celix"
version = "0.0.1"

[dependencies]
celix_bindings = { path = "../celix_bindings" }

[lib]
name = "celix"
path = "src/lib.rs"
crate-type = ["rlib"]
Copy link
Contributor

@PengZheng PengZheng Sep 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it's OK to have static libcelix.

Considering its size, 200KB for x64 release build, it might be preferable to built as shared object.
But unfortunately I've not found any way to make BUILD_RPATH work for Corrosion, without which it is quite inconvenient to run the resulting binary in the build tree.

Even if we can add BUILD_RPATH via build.rs, I don't know how to make RPATH rewrite work.

88 changes: 88 additions & 0 deletions misc/experimental/rust/celix/src/bundle_activator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

use std::sync::Arc;

use super::BundleContext;
use super::Error;

pub trait BundleActivator {
fn new(ctx: Arc<BundleContext>) -> Self;
fn start(&mut self) -> Result<(), Error> {
/* Default implementation */
Ok(())
}
fn stop(&mut self) -> Result<(), Error> {
/* Default implementation */
Ok(())
}
}

#[macro_export]
macro_rules! generate_bundle_activator {
($activator:ty) => {
#[no_mangle]
pub unsafe extern "C" fn celix_bundleActivator_create(
ctx: *mut $crate::details::CBundleContext,
out: *mut *mut ::std::ffi::c_void,
) -> $crate::details::CStatus {
let boxed_context = $crate::bundle_context_new(ctx);
let mut arc_context = Arc::from(boxed_context);
let activator = <$activator>::new(arc_context);
*out = Box::into_raw(Box::new(activator)) as *mut ::std::ffi::c_void;
$crate::CELIX_SUCCESS
}

#[no_mangle]
pub unsafe extern "C" fn celix_bundleActivator_start(
handle: *mut ::std::ffi::c_void,
ctx: *mut $crate::details::CBundleContext,
) -> $crate::details::CStatus {
let activator = &mut *(handle as *mut $activator);
let result = activator.start();
match result {
Ok(_) => $crate::CELIX_SUCCESS,
Err(e) => e.into(),
}
}

#[no_mangle]
pub unsafe extern "C" fn celix_bundleActivator_stop(
handle: *mut ::std::ffi::c_void,
ctx: *mut $crate::details::CBundleContext,
) -> $crate::details::CStatus {
let activator = &mut *(handle as *mut $activator);
let result = activator.stop();
match result {
Ok(_) => $crate::CELIX_SUCCESS,
Err(e) => e.into(),
}
}

#[no_mangle]
pub unsafe extern "C" fn celix_bundleActivator_destroy(
handle: *mut ::std::ffi::c_void,
_ctx: *mut $crate::details::CBundleContext,
) -> $crate::details::CStatus {
let reclaimed_activator = Box::from_raw(handle as *mut $activator);
Copy link
Contributor

@PengZheng PengZheng Sep 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not feel right. In the C version, activator is dropped after celix_bundleContext_waitForEvents(ctx).

IMHO, the best fix is to change the corresponding logic in celix_framework_stopBundleEntryInternal:

From

        status = CELIX_DO_IF(status, bundle_getContext(bndEntry->bnd, &context));
        if (status == CELIX_SUCCESS) {
            if (activator->stop != NULL) {
                status = CELIX_DO_IF(status, activator->stop(activator->userData, context));
                if (status == CELIX_SUCCESS) {
                    celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(context);
                    celix_dependencyManager_removeAllComponents(mng);
                }
            }
        }
        if (status == CELIX_SUCCESS) {
            if (activator->destroy != NULL) {
                status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
            }
        }

        if (bndEntry->bndId >= CELIX_FRAMEWORK_BUNDLE_ID) {
            //framework and "normal" bundle
            celix_framework_waitUntilNoEventsForBnd(framework, bndEntry->bndId);
            celix_bundleContext_cleanup(bndEntry->bnd->context);
        }

To

        status = CELIX_DO_IF(status, bundle_getContext(bndEntry->bnd, &context));
        if (status == CELIX_SUCCESS) {
            if (activator->stop != NULL) {
                status = CELIX_DO_IF(status, activator->stop(activator->userData, context));
                if (status == CELIX_SUCCESS) {
                    celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(context);
                    celix_dependencyManager_removeAllComponents(mng);
                }
            }
        }

        if (bndEntry->bndId >= CELIX_FRAMEWORK_BUNDLE_ID) {
            //framework and "normal" bundle
            celix_framework_waitUntilNoEventsForBnd(framework, bndEntry->bndId);
            celix_bundleContext_cleanup(bndEntry->bnd->context);
        }
        if (status == CELIX_SUCCESS) {
            if (activator->destroy != NULL) {
                status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
            }
        }

So that we can remove celix_bundleContext_waitForEvents(ctx) from the generated celix_bundleActivator_destroy. Also we re-promote usage of create/start/stop/destroy rather than CELIX_GEN_BUNDLE_ACTIVATOR.

drop(reclaimed_activator);
$crate::CELIX_SUCCESS
}
};
}