diff --git a/.github/workflows/bundled-lint-and-test.yaml b/.github/workflows/bundled-lint-and-test.yaml index 6ee28d45..771c0390 100644 --- a/.github/workflows/bundled-lint-and-test.yaml +++ b/.github/workflows/bundled-lint-and-test.yaml @@ -15,8 +15,6 @@ name: Lint and Test - Bundled env: VSOMEIP_INSTALL_PATH: vsomeip-install - GENERIC_CPP_STDLIB_PATH: /usr/include/c++/11 - ARCH_SPECIFIC_CPP_STDLIB_PATH: /usr/include/x86_64-linux-gnu/c++/11 on: push: @@ -27,6 +25,7 @@ on: - "**/include/**" - "**/src/**" - "**/Cargo.*" + - "build/**" workflow_call: workflow_dispatch: @@ -36,9 +35,35 @@ concurrency: jobs: + set-env: + name: Set environment variables + runs-on: ubuntu-latest + + outputs: + arch_specific_cpp_stdlib_path: ${{ steps.set_env.outputs.arch_specific_cpp_stdlib_path }} + generic_cpp_stdlib_path: ${{ steps.set_env.outputs.generic_cpp_stdlib_path }} + + steps: + - uses: actions/checkout@v4 + + - name: Add execute permissions for envsetup + run: chmod +x build/envsetup.sh + + - name: Set stdlib paths dynamically + id: set_env + run: | + source ./build/envsetup.sh highest + echo "arch_specific_cpp_stdlib_path=$ARCH_SPECIFIC_CPP_STDLIB_PATH" >> $GITHUB_OUTPUT + echo "generic_cpp_stdlib_path=$GENERIC_CPP_STDLIB_PATH" >> $GITHUB_OUTPUT + lint: name: Lint runs-on: ubuntu-latest + needs: set-env + + env: + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} steps: - uses: actions/checkout@v4 @@ -49,10 +74,14 @@ jobs: - name: Set environment variables run: | echo "VSOMEIP_INSTALL_PATH=${{ github.workspace }}/${{ env.VSOMEIP_INSTALL_PATH }}" >> $GITHUB_ENV + env - name: Print environment variables for debugging run: | echo "VSOMEIP_INSTALL_PATH: ${{ env.VSOMEIP_INSTALL_PATH }}" + echo "GENERIC_CPP_STDLIB_PATH: ${{ env.GENERIC_CPP_STDLIB_PATH }}" + echo "ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ env.ARCH_SPECIFIC_CPP_STDLIB_PATH }}" + env - name: Ensure vsomeip install path exists run: | @@ -77,6 +106,11 @@ jobs: test: name: Test runs-on: ubuntu-latest + needs: set-env + + env: + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} steps: - uses: actions/checkout@v4 @@ -92,6 +126,7 @@ jobs: - name: Print environment variables for debugging run: | echo "VSOMEIP_INSTALL_PATH: ${{ env.VSOMEIP_INSTALL_PATH }}" + env - name: Ensure vsomeip install path exists run: | @@ -113,7 +148,9 @@ jobs: - name: Run tests and report code coverage run: | # enable nightly features so that we can also include Doctests - LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${VSOMEIP_INSTALL_PATH}/lib RUSTC_BOOTSTRAP=1 cargo tarpaulin -o xml -o lcov -o html --doc --tests -- --test-threads 1 + # TODO: tarpaulin fails silently. Possible version issue + # LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${VSOMEIP_INSTALL_PATH}/lib RUSTC_BOOTSTRAP=1 cargo tarpaulin -o xml -o lcov -o html --doc --tests -- --test-threads 1 + LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${VSOMEIP_INSTALL_PATH}/lib cargo test -- --test-threads 1 - name: Upload coverage report (xml) uses: actions/upload-artifact@v4 @@ -142,6 +179,11 @@ jobs: build-docs: name: Build documentation runs-on: ubuntu-latest + needs: set-env + + env: + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/unbundled-lint-and-test.yaml b/.github/workflows/unbundled-lint-and-test.yaml index 7b4630a6..3995ba89 100644 --- a/.github/workflows/unbundled-lint-and-test.yaml +++ b/.github/workflows/unbundled-lint-and-test.yaml @@ -19,9 +19,6 @@ env: VSOMEIP_SOURCE_PATH: vsomeip-src VSOMEIP_INSTALL_PATH: vsomeip-install - GENERIC_CPP_STDLIB_PATH: /usr/include/c++/11 - ARCH_SPECIFIC_CPP_STDLIB_PATH: /usr/include/x86_64-linux-gnu/c++/11 - on: push: branches: [ main ] @@ -31,6 +28,7 @@ on: - "**/include/**" - "**/src/**" - "**/Cargo.*" + - "build/**" workflow_call: workflow_dispatch: @@ -39,10 +37,39 @@ concurrency: cancel-in-progress: true jobs: + + set-env: + name: Set environment variables + runs-on: ubuntu-latest + + outputs: + arch_specific_cpp_stdlib_path: ${{ steps.set_env.outputs.arch_specific_cpp_stdlib_path }} + generic_cpp_stdlib_path: ${{ steps.set_env.outputs.generic_cpp_stdlib_path }} + + steps: + - uses: actions/checkout@v4 + + - name: Add execute permissions for envsetup + run: chmod +x build/envsetup.sh + + - name: Set stdlib paths dynamically + id: set_env + run: | + source ./build/envsetup.sh highest + echo "arch_specific_cpp_stdlib_path=$ARCH_SPECIFIC_CPP_STDLIB_PATH" >> $GITHUB_OUTPUT + echo "generic_cpp_stdlib_path=$GENERIC_CPP_STDLIB_PATH" >> $GITHUB_OUTPUT + obtain_and_build_vsomeip: runs-on: ubuntu-latest + needs: set-env + outputs: cache_key: ${{ steps.generate_cache_key.outputs.CACHE_KEY }} + + env: + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -53,6 +80,7 @@ jobs: echo "VSOMEIP_SOURCE_PATH=${{ github.workspace }}/${{ env.VSOMEIP_SOURCE_PATH }}" >> $GITHUB_ENV echo "VSOMEIP_INSTALL_PATH=${{ github.workspace }}/${{ env.VSOMEIP_INSTALL_PATH }}" >> $GITHUB_ENV echo "VSOMEIP_SOURCE_PATH_WITH_WILDCARD=${{ github.workspace }}/${{ env.VSOMEIP_SOURCE_PATH }}/*" >> $GITHUB_ENV + env - name: Print environment variables for debugging run: | @@ -60,7 +88,10 @@ jobs: echo "VSOMEIP_SOURCE_PATH: ${{ env.VSOMEIP_SOURCE_PATH }}" echo "VSOMEIP_INSTALL_PATH: ${{ env.VSOMEIP_INSTALL_PATH }}" echo "VSOMEIP_SOURCE_PATH_WITH_WILDCARD: ${{ env.VSOMEIP_SOURCE_PATH_WITH_WILDCARD }}" - + echo "GENERIC_CPP_STDLIB_PATH: ${{ env.GENERIC_CPP_STDLIB_PATH }}" + echo "ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ env.ARCH_SPECIFIC_CPP_STDLIB_PATH }}" + env + - name: Download tarball run: | wget -O vsomeip-source.tar.gz $VSOMEIP_SOURCE_TARBALL @@ -120,9 +151,14 @@ jobs: lint: name: Lint - needs: obtain_and_build_vsomeip + needs: + - obtain_and_build_vsomeip + - set-env runs-on: ubuntu-latest + env: + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} CACHE_KEY: ${{ needs.obtain_and_build_vsomeip.outputs.cache_key }} steps: @@ -170,10 +206,15 @@ jobs: test: name: Test - needs: obtain_and_build_vsomeip + needs: + - obtain_and_build_vsomeip + - set-env runs-on: ubuntu-latest + env: CACHE_KEY: ${{ needs.obtain_and_build_vsomeip.outputs.cache_key }} + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} steps: - uses: actions/checkout@v4 @@ -221,7 +262,9 @@ jobs: - name: Run tests and report code coverage run: | # enable nightly features so that we can also include Doctests - LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${VSOMEIP_INSTALL_PATH}/lib RUSTC_BOOTSTRAP=1 cargo tarpaulin --no-default-features -o xml -o lcov -o html --doc --tests -- --test-threads 1 + # TODO: tarpaulin fails silently. Possible version issue + # LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${VSOMEIP_INSTALL_PATH}/lib RUSTC_BOOTSTRAP=1 cargo tarpaulin --no-default-features -o xml -o lcov -o html --doc --tests -- --test-threads 1 + LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${VSOMEIP_INSTALL_PATH}/lib cargo test -- --test-threads 1 - name: Upload coverage report (xml) uses: actions/upload-artifact@v4 @@ -249,10 +292,14 @@ jobs: build-docs: name: Build documentation - needs: obtain_and_build_vsomeip + needs: + - obtain_and_build_vsomeip + - set-env runs-on: ubuntu-latest env: CACHE_KEY: ${{ needs.obtain_and_build_vsomeip.outputs.cache_key }} + ARCH_SPECIFIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.arch_specific_cpp_stdlib_path }} + GENERIC_CPP_STDLIB_PATH: ${{ needs.set-env.outputs.generic_cpp_stdlib_path }} steps: - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 07b848bb..49d0d8f0 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,15 @@ This library implements a uTransport client for vsomeip in Rust following the uP ### Building the Library -To build the library, run: +To build the library, setup the environment + +``` bash +source build/env_setup.sh +``` + +then run: ```bash -VSOMEIP_INSTALL_PATH= GENERIC_CPP_STDLIB_PATH= ARCH_SPECIFIC_CPP_STDLIB_PATH= cargo build +VSOMEIP_INSTALL_PATH= cargo build ``` in the project root directory. @@ -23,7 +29,7 @@ This library leverages the [up-rust](https://github.com/eclipse-uprotocol/up-rus To run the tests, run ```bash - VSOMEIP_INSTALL_PATH= LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib GENERIC_CPP_STDLIB_PATH= ARCH_SPECIFIC_CPP_STDLIB_PATH= cargo test -- --test-threads 1 + VSOMEIP_INSTALL_PATH= LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib cargo test -- --test-threads 1 ``` Breaking this down: diff --git a/build/envsetup.sh b/build/envsetup.sh new file mode 100755 index 00000000..28a364e5 --- /dev/null +++ b/build/envsetup.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# +# to set environment variables for c++ stdlib paths: +# $ source build/envsetup.sh +# +# to automatically select the highest version of the c++ stdlib: +# $ source build/envsetup.sh highest + +# console colors +RED='\033[0;31m' +GRN='\033[0;32m' +ORNG='\033[0;33m' +NC='\033[0;0m' +USE_HIGHEST=0 +if [ "$1" == "highest" ]; then + USE_HIGHEST=1 +fi + +# find the highest number in an array +select_highest_number() { + local numbers=("$@") + local highest_number=0 + + for number in "${numbers[@]}"; do + if [ "$number" -gt "$highest_number" ]; then + highest_number=$number + fi + done + + echo "$highest_number" +} + +# Select a directory from a list of directories +select_directory() { + local directories=("$@") + local selected_path="" + # Check if the directory array contains numbers or strings + is_number=0 + if [[ "${directories[0]}" =~ ^[0-9]+$ ]]; then + is_number=1 + fi + + # Check the number of directories + if [ "${#directories[@]}" -eq 1 ]; then + # If only one directory is found, set MY_PATH to it + selected_path="${directories[0]}" + + elif [ "$USE_HIGHEST" -eq 1 ] && [ "$is_number" -eq 1 ]; then + highest_version=$(select_highest_number "${directories[@]}") + selected_path="$highest_version" + + else + # Display directories to the user if more than one exists + printf "Select a directory: \n" 1>&2 + for i in "${!directories[@]}"; do + printf "%d) %s\n" "$((i + 1))" "${directories[i]}" 1>&2 + done + + # Prompt the user to enter a choice + read -p "Enter the number of your choice: " choice + + # Validate the user’s input + if [[ "$choice" -ge 1 && "$choice" -le "${#directories[@]}" ]]; then + selected_path="${directories[choice - 1]}" + else + printf "${RED}Invalid selection ${NC}\n" 1>&2 + return 1 + fi + fi + + # Return the selected path + echo "$selected_path" +} + +# find c++ include +if [ -d "/usr/include/c++/" ]; then + CPP_DIRS=$( ls /usr/include/c++/ ) + CPP_ARRAY=($CPP_DIRS) + STDLIB_DIR=$(select_directory "${CPP_ARRAY[@]}") + if [ -z "$STDLIB_DIR" ]; then + return 1 + fi + STDLIB_PATH="/usr/include/c++/${STDLIB_DIR}" +else + # Print warning if the directory doesn't exist + echo -e "${RED}/usr/include/c++/ does not exist.${NC}" + return +fi + +# find machine dir +MACHINE_NAME=$(uname -m) +MACHINE_DIRS=$( ls /usr/include/ | grep "${MACHINE_NAME}" ) +MACHINE_ARRAY=($MACHINE_DIRS) +ARCH_DIR=$(select_directory "${MACHINE_ARRAY[@]}") +if [ -z "$ARCH_DIR" ]; then + return 1 +fi +ARCH_PATH="/usr/include/${ARCH_DIR}" + +# find arch c++ include +if [ -d "$ARCH_PATH/c++/" ]; then + CPP_DIRS=$( ls ${ARCH_PATH}/c++/ ) + CPP_ARRAY=($CPP_DIRS) + STDLIB_DIR=$(select_directory "${CPP_ARRAY[@]}") + if [ -z "$STDLIB_DIR" ]; then + return 1 + fi + ARCH_STDLIB_PATH="${ARCH_PATH}/c++/${STDLIB_DIR}" +else + # Print warning if the directory doesn't exist + echo -e "${RED}$ARCH_PATH/c++/ does not exist.${NC}" + return +fi + +# export the variables +export GENERIC_CPP_STDLIB_PATH=$STDLIB_PATH +export ARCH_SPECIFIC_CPP_STDLIB_PATH=$ARCH_STDLIB_PATH + +echo -e "${ORNG}Set GENERIC_CPP_STDLIB_PATH=${GRN}$GENERIC_CPP_STDLIB_PATH${NC}" +echo -e "${ORNG}Set ARCH_SPECIFIC_CPP_STDLIB_PATH=${GRN}$ARCH_SPECIFIC_CPP_STDLIB_PATH${NC}" diff --git a/up-transport-vsomeip/src/vsomeip_config.rs b/up-transport-vsomeip/src/vsomeip_config.rs index b5ebb42a..297e5b9b 100644 --- a/up-transport-vsomeip/src/vsomeip_config.rs +++ b/up-transport-vsomeip/src/vsomeip_config.rs @@ -73,7 +73,7 @@ fn read_json_file(file_path: &Path) -> Result { pub(crate) fn extract_application(file_path: &Path) -> Result { let file_content = read_json_file(file_path); - return match file_content { + match file_content { Ok(json_data) => { if let Some(applications_value) = json_data.get("applications").and_then(|v| v.as_array()) @@ -103,13 +103,13 @@ pub(crate) fn extract_application(file_path: &Path) -> Result Result, UStatus> { let file_content = read_json_file(file_path); - return match file_content { + match file_content { Ok(json_data) => { if let Some(services_value) = json_data.get("services").and_then(|v| v.as_array()) { match serde_json::from_value::>(Value::from( @@ -130,7 +130,7 @@ pub(crate) fn extract_services(file_path: &Path) -> Result, U let err_msg = format!("Error reading JSON file: {:?}", e); Err(UStatus::fail_with_code(UCode::INVALID_ARGUMENT, err_msg)) } - }; + } } // TODO: Add unit tests diff --git a/up-transport-vsomeip/tests/client_service.rs b/up-transport-vsomeip/tests/client_service.rs index c759a916..6f7001ac 100644 --- a/up-transport-vsomeip/tests/client_service.rs +++ b/up-transport-vsomeip/tests/client_service.rs @@ -21,6 +21,7 @@ use up_rust::{UCode, UListener, UMessage, UMessageBuilder, UPayloadFormat, UTran use up_transport_vsomeip::UPTransportVsomeip; const TEST_DURATION: u64 = 1000; +const MAX_ITERATIONS: usize = 100; pub struct ResponseListener { received_response: AtomicUsize, @@ -246,7 +247,7 @@ async fn client_service() { // let iterations_to_run = 1; let mut i = 20; // while iterations < iterations_to_run { - while Instant::now().duration_since(start_time) < duration { + while (Instant::now().duration_since(start_time) < duration) && (iterations < MAX_ITERATIONS) { let payload_string = format!("request@i={i}"); let payload = payload_string.into_bytes(); let request_msg_res_1_a = diff --git a/up-transport-vsomeip/tests/point_to_point.rs b/up-transport-vsomeip/tests/point_to_point.rs index 36d4da1d..7b081bd4 100644 --- a/up-transport-vsomeip/tests/point_to_point.rs +++ b/up-transport-vsomeip/tests/point_to_point.rs @@ -25,7 +25,7 @@ use up_rust::{UCode, UListener, UMessage, UMessageBuilder, UMessageType, UTransp use up_transport_vsomeip::UPTransportVsomeip; const TEST_DURATION: u64 = 500; - +const MAX_ITERATIONS: usize = 100; const STREAMER_UE_ID: u32 = 0x9876; const CLIENT_AUTHORITY_NAME: &str = "foo"; @@ -453,7 +453,7 @@ async fn point_to_point() { let start_time = Instant::now(); let mut iterations = 0; - while Instant::now().duration_since(start_time) < duration { + while (Instant::now().duration_since(start_time) < duration) && (iterations < MAX_ITERATIONS) { let request_msg_res = UMessageBuilder::request(ptp_method_uuri(), client_reply_uuri(), 10000) .build() diff --git a/up-transport-vsomeip/tests/publisher_subscriber.rs b/up-transport-vsomeip/tests/publisher_subscriber.rs index b6781efb..ed461851 100644 --- a/up-transport-vsomeip/tests/publisher_subscriber.rs +++ b/up-transport-vsomeip/tests/publisher_subscriber.rs @@ -20,6 +20,7 @@ use up_rust::{UListener, UMessage, UMessageBuilder, UPayloadFormat, UTransport, use up_transport_vsomeip::{UPTransportVsomeip, VsomeipApplicationConfig}; const TEST_DURATION: u64 = 1000; +const MAX_ITERATIONS: usize = 100; pub struct SubscriberListener { received_publish: AtomicUsize, @@ -120,7 +121,7 @@ async fn publisher_subscriber() { let start_time = Instant::now(); let mut iterations = 0; - while Instant::now().duration_since(start_time) < duration { + while (Instant::now().duration_since(start_time) < duration) && (iterations < MAX_ITERATIONS) { let publish_payload_string = format!("publish_message@i={iterations}"); let publish_payload = publish_payload_string.into_bytes(); diff --git a/vsomeip-sys/README.md b/vsomeip-sys/README.md index 02d74c54..23a8c49f 100644 --- a/vsomeip-sys/README.md +++ b/vsomeip-sys/README.md @@ -13,18 +13,16 @@ We currently support vsomeip **3.4.10** as released [here](https://github.com/CO 1. Ensure you have a Rust toolchain installed 2. Ensure you have the vsomeip library installed (optional, see features in `Cargo.toml`) 3. Ensure that you have the [requirements](https://github.com/COVESA/vsomeip?tab=readme-ov-file#build-instructions-for-linux) of the vsomeip project install +4. Run env_setup.sh in parent directory -Then, - -```bash -VSOMEIP_INSTALL_PATH= GENERIC_CPP_STDLIB_PATH= ARCH_SPECIFIC_CPP_STDLIB_PATH= cargo build +``` bash +source ../build/env_setup.sh ``` -If you are running a Linux-based OS on x86_64, it's possible these look like: +Then, -``` -GENERIC_CPP_STDLIB_PATH=/usr/include/c++/11 -ARCH_SPECIFIC_CPP_STDLIB_PATH=/usr/include/x86_64-linux-gnu/c++/11 +```bash +VSOMEIP_INSTALL_PATH= cargo build ``` ## Running a binary built with vsomeip-sys @@ -61,7 +59,7 @@ The `VSOMEIP_INSTALL_PATH` then becomes _required_ and must point to the install You may do the following (note `--no-default-features`): ```bash -VSOMEIP_INSTALL_PATH= GENERIC_CPP_STDLIB_PATH= ARCH_SPECIFIC_CPP_STDLIB_PATH= cargo build --no-default-features +VSOMEIP_INSTALL_PATH= cargo build --no-default-features ``` ## My build and deployment environments differ