You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake自定义目标显式调用bash却似乎使用sh?

Fix: CMake Custom Target Using sh Instead of bash Despite Explicit bash Call

Let me walk you through what's going wrong here and how to fix it, plus clean up a couple of bugs in your current create_ros_target function.

Why This Is Happening

The core issue is xargs defaults to using /bin/sh to execute commands, even when you launch the parent process with bash -c. So when you pipe your setup scripts to xargs -r source, those source calls are running in a sh shell—not the bash you intended. That's why it looks like sh is being used.

On top of that, there's a bug in your target property lookup: you're assigning the dependency path to dep_path but then trying to use ${BUILD_PATH} (a non-existent variable) when building your ament_deps list.

Fixed Implementation

Here's the corrected function, with explanations of the changes:

function(create_ros_target NAME DIR DEPENDENCIES)
    set(ament_deps "")
    foreach(dep ${DEPENDENCIES})
        # Fixed: Reference the loop variable ${dep} instead of literal "dep"
        get_target_property(dep_path ${dep} BUILD_PATH)
        # Add safety check to skip dependencies without a valid BUILD_PATH
        if(dep_path)
            list(APPEND ament_deps "${dep_path}/install/local_setup.bash")
        endif()
    endforeach()

    add_custom_target(${NAME} 
        COMMAND bash -c "
            # Source each setup script in bash (no xargs to avoid sh fallback)
            for setup_script in ${ament_deps}; do
                if [ -f \"\${setup_script}\" ]; then
                    source \"\${setup_script}\"
                fi
            done
            # Run ament build in the same bash context to preserve environment
            ament build --symlink-install ${DIR}
        "
        COMMENT "Building ROS target ${NAME} in directory ${DIR}"
    )

    # Complete your target properties here (your original code was cut off)
    # set_target_properties(${NAME} PROPERTIES ...)
endfunction()

Key Changes Made

  1. Fixed target property lookup: Changed get_target_property(dep_path dep BUILD_PATH) to get_target_property(dep_path ${dep} BUILD_PATH) to correctly reference the loop's dependency target. Added a check to skip invalid paths.
  2. Replaced xargs with a bash loop: This eliminates xargs' sh fallback entirely. All source commands run in the same bash shell, ensuring your ROS setup scripts (which use bash-specific syntax) work as expected.
  3. Single bash context: The entire command runs in one bash process, so environment variables from the setup scripts are preserved when executing ament build.

Alternative: Force xargs to Use Bash

If you prefer to keep using xargs for some reason, you can explicitly tell it to use bash for each source call:

COMMAND bash -c "echo ${ament_deps} | xargs -r -I {} bash -c 'source {}' ; ament build --symlink-install ${DIR}"

But the bash loop approach is cleaner, more readable, and less prone to edge cases (like path names with spaces, though rare in ROS workspaces).

内容的提问来源于stack exchange,提问作者kutschkem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:12:37