Skip to content
Merged
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
14 changes: 4 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,10 @@ strata.lock
/.ost-ci/
/.ost-ci-home/

# Built plugin libraries are staged into each bundle's lib/ by the build, and
# tools into their own bin/.
/plugins/*/lib/
/tools/*/bin/

# Generated into bundle resources by the build: plugInfo.json names this
# platform's library suffix, and buildInfo.json varies per commit, toolchain
# and platform.
/plugins/*/plugin/resources/*/plugInfo.json
/plugins/*/plugin/resources/*/buildInfo.json
# Nothing the build produces lands in the source tree: bundles and tools are
# staged in the binary tree (cmake/UsdMotionStage.cmake), so a lib/, bin/ or
# plugInfo.json appearing under plugins/ or tools/ is a regression for
# `git status` to show, not to hide.

# --- CMake / MSVC generated ---
CMakeCache.txt
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ separate from the package version

### Changed

- **A build writes nothing into the source tree.** `execMotion`'s library and
its generated `plugInfo.json`, and the three CLIs, were built into
`plugins/execMotion/lib/`, `plugins/execMotion/plugin/resources/` and
`tools/*/bin/`, because `ost` packaged them from there. They are now staged in
each member's binary directory (`cmake/UsdMotionStage.cmake`), one stage per
configuration under a multi-config generator, so Debug and Release no longer
overwrite each other. `execMotion` gains install rules, which `ost plugin
build` (0.23.5 and later) installs into the bundle's target-local stage for
`ost plugin test` and `ost plugin package`; its package no longer carries
`plugInfo.json.in`. `motion_convert`'s build stages the profiles beside it,
so a converter run from the build tree still finds them with no flags. The
`.gitignore` entries that hid those outputs are gone: a checkout built before
this change can delete `plugins/execMotion/lib/`,
`plugins/execMotion/plugin/resources/execMotion/plugInfo.json` and
`tools/*/bin/`.
- **`ost` is pinned to 0.23.6**, in `openstrata.ci.yaml`, the rendered source
CI and the release lane. 0.23.5 and 0.23.6 stage an installable bundle and a
root-built tool per target and package from that stage, which is what moving
Expand Down
1 change: 1 addition & 0 deletions cmake/UsdMotionProject.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,4 @@ include("${CMAKE_CURRENT_LIST_DIR}/UsdMotionTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/UsdMotionUtf8CodePage.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/UsdMotionInstall.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/UsdMotionTesting.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/UsdMotionStage.cmake")
72 changes: 72 additions & 0 deletions cmake/UsdMotionStage.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# SPDX-License-Identifier: Apache-2.0
#
# UsdMotionStage.cmake -- where a build puts what it produces: the binary tree,
# never the source tree.
#
# A member's *stage* is its CMake binary directory, laid out the way the member
# is laid out: a tool's executable in `bin/`, a bundle's library in `lib/` and
# its registration under the `plugin/resources/...` path its manifest names. A
# multi-config generator gets one stage per configuration, `<binary>/<config>/`,
# so a Debug build and a Release build never overwrite each other's files.
#
# The stage is what the build's own tests run against. It is not what ships:
#
# * a bundle ships what its install rules install. `ost plugin build` (0.23.5
# and later) installs the bundle into its target-local bundle stage, and
# `ost plugin test` and `ost plugin package` read that;
# * a tool ships the executable `ost build` finds in the root build tree under
# the member's `bin/`, which is this stage under a single-config generator,
# the only kind `ost` configures.
#
# So the source tree stays an input only: a build writes nothing into it, and a
# Debug/Release pair, two targets or a parallel build cannot collide there.
include_guard(GLOBAL)

# usdmotion_member_stage(<out-var>)
#
# The current member's stage directory, as a path that may hold `$<CONFIG>`:
# usable in target properties, file(GENERATE), custom commands and test
# properties, which all evaluate generator expressions.
function(usdmotion_member_stage out_var)
get_property(_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(_multi_config)
set(${out_var} "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>" PARENT_SCOPE)
else()
set(${out_var} "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
endif()
endfunction()

# usdmotion_stage_tool(<target>)
#
# A tool's executable goes to `<stage>/bin/`, the directory its
# openstrata.tool.yaml declares. The path carries a generator expression under
# a multi-config generator, which also stops CMake appending a configuration
# directory of its own.
function(usdmotion_stage_tool target)
usdmotion_member_stage(_stage)
set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${_stage}/bin")
endfunction()

# usdmotion_stage_bundle(<target> PLUG_INFO <plugInfo.json> RESOURCES <dir>)
#
# A bundle's library goes to `<stage>/lib/`, and the registration PLUG_INFO
# names -- already configured -- to `<stage>/<RESOURCES>/plugInfo.json`, so the
# stage is a loadable bundle: its plugInfo.json finds the library by the same
# relative LibraryPath the installed bundle uses. Point PXR_PLUGINPATH_NAME at
# `$<TARGET_FILE_DIR:<target>>/../<RESOURCES>` to load it.
function(usdmotion_stage_bundle target)
cmake_parse_arguments(ARG "" "PLUG_INFO;RESOURCES" "" ${ARGN})
if(NOT ARG_PLUG_INFO OR NOT ARG_RESOURCES)
message(FATAL_ERROR "usdmotion_stage_bundle: PLUG_INFO and RESOURCES are required")
endif()
usdmotion_member_stage(_stage)
# RUNTIME is the DLL on Windows, LIBRARY the shared object elsewhere. A
# plugin is loaded rather than linked, so its import library, if any, stays
# out of the stage.
set_target_properties(${target} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${_stage}/lib"
LIBRARY_OUTPUT_DIRECTORY "${_stage}/lib")
file(GENERATE
OUTPUT "${_stage}/${ARG_RESOURCES}/plugInfo.json"
INPUT "${ARG_PLUG_INFO}")
endfunction()
15 changes: 12 additions & 3 deletions docs/architecture/WORKSPACE.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,18 @@ Code arrives from `usd-vrm-plugins` under that repository's moving rules
`UsdMotionOpenUsd.cmake` (the pin, OpenUSD's targets as
`usdmotion::pxr::<name>`, and the OpenExec probe), `UsdMotionTargets.cmake`
(a sibling package, and `/utf-8`), `UsdMotionInstall.cmake`,
`UsdMotionTesting.cmake` and `UsdMotionUtf8CodePage.cmake`. A component's
`CMakeLists.txt` keeps what is its own: its sources, its `PUBLIC` and
`PRIVATE` links, its definitions, its install and its tests.
`UsdMotionStage.cmake`, `UsdMotionTesting.cmake` and
`UsdMotionUtf8CodePage.cmake`. A component's `CMakeLists.txt` keeps what is
its own: its sources, its `PUBLIC` and `PRIVATE` links, its definitions, its
install and its tests.
- A build writes nothing into the source tree. Each member is staged in its
binary directory, laid out as the member is (a tool's `bin/`, a bundle's
`lib/` beside its `plugin/resources/`), one stage per configuration under a
multi-config generator; the build's tests run against that stage. What ships
is what the install rules install: `ost plugin build` installs the bundle
into its target-local stage, which `ost plugin test` and `ost plugin package`
read, and `ost build` takes each tool from its member's `bin/` in the root
build tree.

## 5. Invariants

Expand Down
6 changes: 3 additions & 3 deletions openstrata.ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
# rules, and a root-built tool, per target instead of reading them from the
# member's source tree (usd-mmd-plugins' ost report 01), and 0.23.6 packages a
# workspace bundle from that same stage (usd-vrm-plugins' ost report 47). That
# is the precondition for moving `execMotion`'s `lib/` and `plugInfo.json` and
# the CLIs' `bin/` out of the source tree; until they move, both versions read
# them where they are, as 0.23.4 did. 0.23.4 was re-pinned across the
# is what lets `execMotion`'s `lib/` and `plugInfo.json` and the CLIs' `bin/`
# live in the binary tree (cmake/UsdMotionStage.cmake) rather than the source
# tree: a build writes nothing into a checkout. 0.23.4 was re-pinned across the
# ecosystem together with usd-vrm-plugins, motion-connectors and
# usd-mmd-plugins, and lets a consumer pin a published bundle (`requires.bundles[].artifact`) and a published
# tool for its tests (`requires.tools[]`), which is what `execMotion` and the
Expand Down
36 changes: 24 additions & 12 deletions plugins/execMotion/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,24 +105,36 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE
usdmotion::pxr::exec
usdmotion::pxr::execUsd)

# The library is named lib<name> on every platform, which is the name
# plugInfo.json.in spells.
set(OPENSTRATA_PLUGIN_LIBRARY_PREFIX "lib")
set_target_properties(${PLUGIN_NAME} PROPERTIES
PREFIX "${OPENSTRATA_PLUGIN_LIBRARY_PREFIX}"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
foreach(_cfg DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
set_target_properties(${PLUGIN_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY_${_cfg} "${CMAKE_CURRENT_SOURCE_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY_${_cfg} "${CMAKE_CURRENT_SOURCE_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY_${_cfg} "${CMAKE_CURRENT_SOURCE_DIR}/lib")
endforeach()
PREFIX "${OPENSTRATA_PLUGIN_LIBRARY_PREFIX}")

# The registration names this platform's library suffix, so it is generated,
# into the binary tree; nothing here writes into the source tree.
set(_exec_motion_resources "plugin/resources/execMotion")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/plugin/resources/execMotion/plugInfo.json.in"
"${CMAKE_CURRENT_SOURCE_DIR}/plugin/resources/execMotion/plugInfo.json"
"${CMAKE_CURRENT_SOURCE_DIR}/${_exec_motion_resources}/plugInfo.json.in"
"${CMAKE_CURRENT_BINARY_DIR}/plugInfo.json"
@ONLY)

# The build's own stage, which the tests load (cmake/UsdMotionStage.cmake).
usdmotion_stage_bundle(${PLUGIN_NAME}
PLUG_INFO "${CMAKE_CURRENT_BINARY_DIR}/plugInfo.json"
RESOURCES "${_exec_motion_resources}")

# What ships: the library in lib/ beside the registration at the path
# openstrata.plugin.yaml's `usd.plug_info` names, so plugInfo.json's
# LibraryPath (../../../lib/...) holds in any prefix. `ost plugin build`
# installs this into the bundle's target-local stage, and `ost plugin test` and
# `ost plugin package` read it from there.
install(TARGETS ${PLUGIN_NAME}
RUNTIME DESTINATION lib
LIBRARY DESTINATION lib)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/plugInfo.json"
DESTINATION "${_exec_motion_resources}")

if(USDMOTION_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
enable_testing()
usdmotion_find_test_python()
Expand Down
13 changes: 7 additions & 6 deletions plugins/execMotion/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,14 @@ endif()
# ---------------------------------------------------------------------------
# Environment
# ---------------------------------------------------------------------------
# The bundle's own resource directory is what PXR_PLUGINPATH_NAME points at, and
# its plugInfo.json resolves LibraryPath relative to itself -- so the staged
# tree the bundle already produces is what the test loads, not a copy.
# The bundle's staged resource directory is what PXR_PLUGINPATH_NAME points at,
# and its plugInfo.json resolves LibraryPath relative to itself -- so the stage
# the build already produces in the binary tree is what the test loads, not a
# copy (cmake/UsdMotionStage.cmake).
usdmotion_openusd_root(_usd_root)

set(_bundle_dir "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(_plug_resources "${_bundle_dir}/plugin/resources/execMotion")
set(_bundle_lib "$<TARGET_FILE_DIR:${PLUGIN_NAME}>")
set(_plug_resources "${_bundle_lib}/../plugin/resources/execMotion")

# motionCore is static, so nothing of it is loaded at run time; OpenUSD is not,
# and on Windows a plain-CMake ctest run finds none of it without this. Same
Expand All @@ -329,7 +330,7 @@ set(_plug_resources "${_bundle_dir}/plugin/resources/execMotion")
set(_exec_motion_env
"PATH=path_list_prepend:${_usd_root}/bin"
"PATH=path_list_prepend:${_usd_root}/lib"
"PATH=path_list_prepend:${_bundle_dir}/lib"
"PATH=path_list_prepend:${_bundle_lib}"
"PXR_PLUGINPATH_NAME=path_list_prepend:${_plug_resources}")

set_tests_properties(execMotion_mechanism execMotion_sample execMotion_filter
Expand Down
11 changes: 3 additions & 8 deletions tools/motionBvhInspect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,9 @@ target_link_libraries(motion_bvh_inspect PRIVATE motionBvh::motionBvh)

usdmotion_target_utf8(motion_bvh_inspect PRIVATE)

# Staged into the member root's bin/: `ost plugin package` reads the
# directories openstrata.tool.yaml declares rather than a build tree.
set_target_properties(motion_bvh_inspect PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
foreach(_cfg DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
set_target_properties(motion_bvh_inspect PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_${_cfg} "${CMAKE_CURRENT_SOURCE_DIR}/bin")
endforeach()
# Staged into the member's binary-tree bin/, the directory openstrata.tool.yaml
# declares, where `ost build` finds it (cmake/UsdMotionStage.cmake).
usdmotion_stage_tool(motion_bvh_inspect)

usdmotion_install_tool(motion_bvh_inspect)

Expand Down
30 changes: 22 additions & 8 deletions tools/motionConvert/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,31 @@ if(MSVC)
target_compile_definitions(motion_convert PRIVATE NOMINMAX _USE_MATH_DEFINES)
endif()

# Staged into the member root's bin/: `ost plugin package` reads the
# directories openstrata.tool.yaml declares rather than a build tree.
set_target_properties(motion_convert PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
foreach(_cfg DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
set_target_properties(motion_convert PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_${_cfg} "${CMAKE_CURRENT_SOURCE_DIR}/bin")
endforeach()
# Staged into the member's binary-tree bin/, the directory openstrata.tool.yaml
# declares, where `ost build` finds it (cmake/UsdMotionStage.cmake).
usdmotion_stage_tool(motion_convert)

usdmotion_install_tool(motion_convert)

# The profiles are staged beside the tool as an install puts them, in
# <stage>/share/, so a converter run from the build tree finds them by the rule
# that finds them in an installed prefix: <exe>/../share/... (ProfileLocator.cpp).
# Copied only when they differ, and re-globbed when one is added.
file(GLOB _motion_convert_profiles CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/../../profiles/motion/*.yaml")
if(_motion_convert_profiles)
usdmotion_member_stage(_motion_convert_stage)
set(_motion_convert_profile_stage
"${_motion_convert_stage}/share/usd-motion-plugins/profiles/motion")
add_custom_target(motion_convert_profiles ALL
COMMAND "${CMAKE_COMMAND}" -E make_directory "${_motion_convert_profile_stage}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
${_motion_convert_profiles} "${_motion_convert_profile_stage}"
COMMENT "Staging the motion profiles beside motion_convert"
VERBATIM)
add_dependencies(motion_convert motion_convert_profiles)
endif()

# The profiles ship beside the tool, at the location ProfileLocator.cpp derives
# from the executable's own path: a converter with no profile available refuses
# every file it is given.
Expand Down
6 changes: 4 additions & 2 deletions tools/motionConvert/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,13 @@ first hit wins:
1. every `--profile-dir`, in the order given
2. `USDMOTION_PROFILE_PATH`, a list in the platform's PATH separator
3. `<exe>/../share/usd-motion-plugins/profiles/motion` — a `cmake --install`
prefix, where the tools land in `<prefix>/bin/`
prefix, where the tools land in `<prefix>/bin/`, and this repository's build
tree, which stages the profiles beside the tool the same way
4. `<exe>/../../../share/usd-motion-plugins/profiles/motion` — an installed
product, where `ost plugin product install` puts a tool member in
`<prefix>/tools/<member>/bin/` and the product's data in `<prefix>/share/`
5. `<exe>/../../../profiles/motion` — this repository
5. `<exe>/../../../profiles/motion` — a tool placed in this repository's own
`tools/<member>/bin/`, which no build does any more

The last two are offered only when the executable really is in a
`tools/<member>/bin/`; from anywhere else they would climb past a prefix
Expand Down
5 changes: 3 additions & 2 deletions tools/motionConvert/src/ProfileLocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,12 @@ ProfileSearchPath(const std::vector<std::string>& extraDirs)
if (!executableDir.empty())
{
// <prefix>/bin/<exe> -> <prefix>/share/... : a `cmake --install`
// prefix, and a member archive unpacked on its own.
// prefix, a member archive unpacked on its own, and this repository's
// build tree, which stages the profiles beside the tool.
directories.push_back(executableDir.parent_path() / "share" / "usd-motion-plugins" /
"profiles" / "motion");
// <prefix>/tools/<member>/bin/<exe> -> <prefix>/share/... : an
// installed product, and this repository's own build tree. The two
// installed product. The two
// installed layouts agree about where the data is relative to the
// prefix and disagree about how deep the tool sits inside it, so each
// needs its own rule.
Expand Down
11 changes: 3 additions & 8 deletions tools/motionRecord/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,9 @@ if(MSVC)
target_compile_definitions(motion_record PRIVATE NOMINMAX _USE_MATH_DEFINES)
endif()

# Staged into the member root's bin/: `ost plugin package` reads the
# directories openstrata.tool.yaml declares rather than a build tree.
set_target_properties(motion_record PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
foreach(_cfg DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
set_target_properties(motion_record PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_${_cfg} "${CMAKE_CURRENT_SOURCE_DIR}/bin")
endforeach()
# Staged into the member's binary-tree bin/, the directory openstrata.tool.yaml
# declares, where `ost build` finds it (cmake/UsdMotionStage.cmake).
usdmotion_stage_tool(motion_record)

usdmotion_install_tool(motion_record)

Expand Down
Loading