Skip to content

draft proposal for the breaking changes to split public/private - #415

Draft
jacobmerson wants to merge 100 commits into
SCOREC:developfrom
jacobmerson:reorg/breaking-block
Draft

jacobmerson wants to merge 100 commits into
SCOREC:developfrom
jacobmerson:reorg/breaking-block

Conversation

@jacobmerson

Copy link
Copy Markdown
Collaborator

This is a monster PR that is supposed to capture all of the breaking changes needed to support a public/private API split. For most of the renaming, etc. AI was able to generate migration scripts that we can apply to the various PRs, other open work.

The headers are already installed through FILE_SET, which needs CMake 3.23;
the project and the external usage example declared 3.19. Raise both
minimums so that the declared requirement matches what is used. Consumers of
the exported targets also need 3.23 to import file sets.

This replaces PR SCOREC#410.

Verified: Minimal-static, Full-shared (build and ctest).
Records the process and API decisions agreed with the maintainer for the
reorganization, including where they deviate from the original plan:
interface-only public API with free-function factories, discretization-first
space construction, backends as directories/namespaces (pcms::backend::<name>)
compiled into the core targets, pcms::Mode replacing redev::Mode, and the
deferred FieldSource layer for multi-field sources. Also records the
decisions taken during the work: include guards instead of #pragma once,
the Phase 0 checkpoint (header classification), the Phase 3 backend
layout, and the Phase 5-9 notes.

Verified: Minimal-static, Full-shared (build and ctest).
…graphs

Records the baseline build/test results (including the full-static
baseline), the target dependency graph before the reorganization, after
Phase 2 and at the end (cmake --graphviz; raw .dot files next to it),
every installed header with its direct and transitive backend-library
includes, the declarations in installed headers that used Omega_h types,
the public / installed-detail / private classification with target
locations, the questions for the Phase 0 checkpoint, and the final list of
public headers.

Verified: Minimal-static, Full-shared (build and ctest).
Renames every .h / .h.in below the given directories with git mv and
rewrites #include directives (relative and pcms/-rooted) and CMake file
lists that refer to them. C API headers in src/pcms/capi are skipped.

Verified: Minimal-static, Full-shared (build and ctest).
Mechanical: renames every C++ header of utility, discretization,
localization, field, transfer, coupler and pythonapi, the generated
configuration/version headers (configuration.h.in and version.h.in become
.hpp.in) and the test support headers to .hpp, and updates all #include
directives, CMake header lists and configure_file calls that refer to them.
The C API headers in capi/ stay .h (the C API does not include the
generated headers). Two tests include <data/simple.h> through
pcms::field's include directory, which the script does not resolve; the
sed line updates them. No other changes.

Generated with (in this order):
    tools/reorg/rename_headers.py src/pcms/utility
    tools/reorg/rename_headers.py src/pcms/discretization
    tools/reorg/rename_headers.py src/pcms/localization
    tools/reorg/rename_headers.py src/pcms/field
    tools/reorg/rename_headers.py src/pcms/transfer
    tools/reorg/rename_headers.py src/pcms/coupler
    tools/reorg/rename_headers.py src/pcms/pythonapi
    tools/reorg/rename_headers.py src/pcms
    tools/reorg/rename_headers.py test
    sed -i 's|#include <data/simple.h>|#include <data/simple.hpp>|' \
        test/test_proxy_coupling_xgc_server.cpp \
        test/test_proxy_coupling_xgc_server_overlap.cpp

Verified: Full-shared (build and ctest).
Mechanical: the macro MAX_DIM defined in the installed header
transfer/linear_interpolant.hpp becomes PCMS_MAX_DIM. The only other use
of the macro is test_normalisation.cpp, which includes linear_interpolant.hpp
after mls_interpolation_impl.hpp, so its MAX_DIM resolves to the macro (10)
and is renamed too. test_mls_basis.cpp and mls_interpolation_impl.hpp use
an unrelated constexpr MAX_DIM (6) and are left unchanged.

Generated with:
    sed -i 's/\bMAX_DIM\b/PCMS_MAX_DIM/g' src/pcms/transfer/linear_interpolant.hpp test/test_normalisation.cpp

Verified: Full-shared (build and ctest).
Mechanical: the macro ACTIVE_GPU_EXECUTION defined in the installed header
utility/print.hpp becomes PCMS_ACTIVE_GPU_EXECUTION. It is used only in
that header.

Generated with:
    sed -i 's/\bACTIVE_GPU_EXECUTION\b/PCMS_ACTIVE_GPU_EXECUTION/g' src/pcms/utility/print.hpp

Verified: Full-shared (build and ctest).
R3D_USE_KOKKOS was a PUBLIC compile definition of pcms_transfer, so every
consumer of pcms::transfer had it, although only code that includes r3d
needs it. r3d is included only by transfer/mesh_intersection.hpp, which
in-tree tests also include and call from Kokkos kernels.

The definition is now PRIVATE, and mesh_intersection.hpp defines
R3D_USE_KOKKOS (if not already defined) right before including <r3d.hpp>,
so every translation unit that sees r3d still compiles it with the same
setting. No Omega_h header includes r3d.hpp, so the include order cannot
bypass this.

Verified: Minimal-static, Full-shared (build and ctest).
version.hpp.in used #pragma once, which is not standard C++; configuration.hpp.in
and pythonapi/numpy_array_transform.hpp had no guard at all. All three now use
#ifndef/#define/#endif guards. Normalizing the guard names of the remaining
headers is done once after the header moves (Phase 5), when paths are final.

Verified: Full-shared (build and ctest).
Mechanical: quoted includes that name a PCMS header relative to the
including file (e.g. "../field_data.hpp") are rewritten as "pcms/<path>"
in utility, localization, field, transfer, coupler, capi and pythonapi.
Two tests included <data/simple.hpp>, which only resolved through
pcms::field's extra include directory (src/pcms/field); they now include
<pcms/field/data/simple.hpp> like every other PCMS include. No other
changes.

Generated with (in this order):
    tools/reorg/absolute_includes.py src/pcms/utility
    tools/reorg/absolute_includes.py src/pcms/localization
    tools/reorg/absolute_includes.py src/pcms/field
    tools/reorg/absolute_includes.py src/pcms/transfer
    tools/reorg/absolute_includes.py src/pcms/coupler
    tools/reorg/absolute_includes.py src/pcms/capi
    tools/reorg/absolute_includes.py src/pcms/pythonapi
    sed -i 's|#include <data/simple.hpp>|#include <pcms/field/data/simple.hpp>|' \
        test/test_proxy_coupling_xgc_server.cpp \
        test/test_proxy_coupling_xgc_server_overlap.cpp

Verified: Full-shared (build and ctest).
Mechanical: PCMS_ENABLE_Python -> PCMS_ENABLE_PYTHON,
PCMS_ENABLE_Fortran -> PCMS_ENABLE_FORTRAN and
PETSC_LINK_STATIC -> PCMS_PETSC_LINK_STATIC everywhere they are used
(CMake, the package config, the generated configuration header, CI
workflows, the CDash script, pyproject.toml, Doxyfile and docs). All other
options already had the PCMS_ENABLE_<UPPERCASE> form. The old names are
mapped to the new ones in the following commit.

Generated with:
    sed -i -E 's/PCMS_ENABLE_Python\b/PCMS_ENABLE_PYTHON/g; s/PCMS_ENABLE_Fortran\b/PCMS_ENABLE_FORTRAN/g; s/(-D|^|[^A-Za-z0-9_])PETSC_LINK_STATIC\b/\1PCMS_PETSC_LINK_STATIC/g' \
        $(git grep -lE 'PCMS_ENABLE_(Python|Fortran)|PETSC_LINK_STATIC' -- ':!tools/reorg')

Verified: Minimal-static, Full-shared (build and ctest).
PCMS_ENABLE_Python, PCMS_ENABLE_Fortran and PETSC_LINK_STATIC were renamed
in the previous commit. cmake/PcmsRenamedOptions.cmake maps a value given
under an old name to the new name with a deprecation message and drops the
old cache entry, so existing build scripts and build directories keep
working. If both names are set to different values the new one wins, with
a warning. To be removed in the release after 0.4.

Tested: old name only, new name only, both (conflicting), neither, and
PETSC_LINK_STATIC, with a stand-alone project including the module.

Verified: Minimal-static, Full-shared (build and ctest).
MLSOptions only needs the RadialBasisFunction enum from
mls_interpolation.hpp, but including that header pulled in the whole MLS
implementation and Omega_h. The enum and its documentation move unchanged
into mls_options.hpp, and mls_interpolation.hpp includes mls_options.hpp
instead, so every existing user still sees the enum. This lets
mls_options.hpp move to the localization library without depending on
field (next commits).

Verified: Full-shared (build and ctest).
Moves files (or directories) with git mv according to a mapping file and
rewrites #include directives and CMake file lists that name them, so the
tree keeps building. Target membership in CMake is not changed.

- Files can be moved below src/ or include/; includes of moved files are
  written pcms/-rooted relative to either root.
- Quoted includes are looked up next to the including file and below the
  roots; angle-bracket includes only below the roots, so a library header
  such as <mfem.hpp> is never mistaken for a PCMS file of the same name.

Verified: Full-shared (build and ctest).
…localization

Mechanical moves so that localization no longer depends on field:

- coordinate_view.hpp, coordinate_system.{hpp,cpp} and coordinate_systems/
  move from field to utility (they only depend on utility; localization
  takes CoordinateView arguments);
- mls_options.hpp moves from field/evaluator to localization (the
  support-search parameters are used by localization);
- localization_path_selection.hpp and point_cloud_localization.hpp move from
  localization to field (they adapt field layouts to localization).

Includes and CMake paths are updated; CMake entries still belong to their
old targets, which are fixed in the next commit.

Generated with:
    tools/reorg/move_files.py tools/reorg/moves/02-localization-layering.txt

Verified: Minimal-static, Full-shared (build and ctest).
…rgets

Hand-written CMake follow-up to the previous move: the coordinate headers and
coordinate_system.cpp are now part of pcms::utility, mls_options.hpp of
pcms::localization, and point_cloud_localization.hpp of pcms::field.
pcms::localization no longer needs any field header.

Verified: Minimal-static, Full-shared (build and ctest).
pcms_transfer linked pcms::core, which is the coupler plus redev and ADIOS2,
although no transfer source uses the coupler. Its real dependencies are
pcms::field, pcms::localization and Omega_h (plus meshfields and PETSc
privately); the generated configuration header comes through
pcms::utility. pcms::transfer and everything it links no longer depend on
redev or ADIOS2.

Verified: Minimal-static, Full-shared (build and ctest).
src/pcms.cpp, the only source of pcms_core, contained static_asserts that
pcms::Real/LO/GO match redev's and Omega_h's types. The redev checks move to
coupler/coupler.cpp (the coupler is the only redev user) and the Omega_h
checks to the Omega_h discretization source, which is compiled under the
same PCMS_ENABLE_OMEGA_H condition as before. pcms.cpp is left without
code; pcms_core is replaced in a following commit.

Verified: Full-shared (build and ctest).
pcms::core was a library built from one file of static_asserts (moved out
in the previous commit) that linked the coupler, redev and every other
library, so it meant "coupler plus everything". It is removed:

- pcms::pcms (already exported as the umbrella target) now links every
  library that is built: utility, discretization, localization, field,
  coupler, transfer, and transient / capi / fortranapi when enabled. It
  has an in-tree alias pcms::pcms.
- pcms::core remains for one release as a deprecated INTERFACE target that
  links pcms::pcms. Its DEPRECATION property is exported (CMake does this
  natively), so consumers of the installed package get a warning.
- pcms.h and the generated version.hpp / configuration.hpp, previously
  installed as pcms_core's public headers, are installed to the same place
  (include/pcms) with install(FILES); in the build tree they are found
  through pcms::utility's include directories.
- The PCMS_HAS_ASAN compile options applied only to pcms.cpp and go away
  with it.
- In-tree users stop linking pcms::core (target-name changes only): the C
  API client library and the Python module link pcms::coupler, the
  narrowest target providing what they use; tests, test support, tools and
  the smoke test link pcms::pcms. This has to happen in the same commit:
  pcms::pcms links the C API, so a C API library still linking the
  pcms::core alias would form a dependency cycle.

Verified: Minimal-static, Full-shared (build and ctest).
Prepares for making the coupler optional (next commit). The tests that use
the coupler or redev (the multi-process coupling tests, test_support, the
smoke test, xgc_n0_server, test_mfem_coupling, the C/Fortran XGC client
tests, and the unit-test sources test_field_serializer, test_xgc_field_data,
test_field_exchange_planner and test_mfem_adapter) are now guarded by
if(TARGET pcms::coupler) / pcms::capi::core / pcms::fortranapi::core.

The coupler is still always built, so every test is still built and run;
the guards use TARGET checks rather than the new option so this commit is a
no-op on its own. No test source is changed. Agreed with the maintainer as
an exception to the 'target names only' rule for test CMake edits.

Verified: Minimal-static, Full-shared (build and ctest).
New option PCMS_ENABLE_COUPLER (default ON). When OFF:

- redev and ADIOS2 are not searched for and pcms::coupler is not built;
- the C API builds only its transfer part (pcms::capi::transfer), and the
  Fortran API only pcms::fortranapi::transfer, since the client parts wrap
  the coupler;
- the Python API is rejected with an error (its module binds the coupler);
- the package config skips redev/ADIOS2 and the coupler/client target
  files, and pcms::pcms does not link the coupler;
- coupler-dependent tests are skipped (guarded in the previous commit).

PCMS_ENABLE_COUPLER is also added to the generated configuration header.
The package config now finds perfstubs itself: pcms::utility links it, and
so far consumers only found it through redev's package config.

With the default (ON) nothing changes. This gives the 'Minimal'
configuration of the reorganization (Kokkos + Omega_h; field,
localization, transfer; no coupler).

Verified: Minimal-static, Full-shared (build and ctest).
Mechanical: the XGC discretization, reverse classification, layout, field
data and field factory move from discretization/ and field/ into
src/pcms/backends/xgc/. Includes and CMake paths are updated; the files
are still compiled into the same targets (pcms_discretization, pcms_field)
under the same conditions.

Generated with:
    tools/reorg/move_files.py tools/reorg/moves/03-xgc.txt

Verified: Minimal-static, Full-shared (build and ctest).
backend_namespace.py moves the code of one backend directory from pcms::
into pcms::backend::<name>: it rewrites the namespace blocks of the
backend's files (leaving the whitespace around namespace lines as it is)
and qualifies uses of the backend's symbols in the rest of the tree.
Inside pcms::backend, ::mfem is hidden by pcms::backend::mfem, so mfem::
is written ::mfem:: in backend code; other library namespaces (Kokkos,
Omega_h, ...) are not shadowed and are left as written.

Inside pcms::backend::<name>, detail::X finds the backend's own nested
detail namespace first if it has one, and then fails for names that live
in pcms::detail. The script collects the names a backend declares in its
own detail namespace and writes every other detail::X reference in the
backend as pcms::detail::X. Backends without a nested detail namespace are
unaffected. REORG_DEBUG=1 prints the collected names.

Verified: Minimal-static, Full-shared (build and ctest).
Mechanical: the XGC backend's declarations (XGCDiscretization,
ReverseClassificationVertex, DimID, ReadReverseClassificationVertex,
IndexBase, ConstructRCFromOmegaHMesh, XGCFieldLayout, XGCFieldData,
XGCFieldFactory) move from pcms:: to pcms::backend::xgc::, and the backend
refers to external library namespaces with a leading :: (::Kokkos,
::Omega_h). All users (C API, tests, tools) are updated to the qualified
names. No other changes.

Generated with:
    tools/reorg/backend_namespace.py xgc tools/reorg/namespaces/xgc.txt
Hand-written CMake for the move to backends/xgc: src/pcms/backends/ is a
new directory whose CMakeLists.txt adds each backend; backends/xgc adds its
sources and headers to the core targets that use them, under the same
conditions as before:

- discretization.cpp and reverse_classification.cpp (+ headers) to
  pcms_discretization, unconditionally;
- layout.cpp (+ layout, field data and field factory headers) to
  pcms_field when PCMS_ENABLE_XGC is on.

The entries are removed from the discretization and field lists. Headers
stay in the same FILE_SETs, so they are installed to
include/pcms/backends/xgc/ as in the previous commit.
Mechanical: the MFEM layout, field data and field factory move from
field/layout, field/data and field/function_space into
src/pcms/backends/mfem/. Includes and CMake paths are updated; the files are
still compiled into pcms_field under PCMS_ENABLE_MFEM.

Generated with:
    tools/reorg/move_files.py tools/reorg/moves/03-mfem.txt
…mfem

Mechanical: MFEMLayout, MFEMVertexFieldData and MFEMFieldFactory move from
pcms:: to pcms::backend::mfem::. Inside the backend, the MFEM and Kokkos
namespaces are written ::mfem / ::Kokkos so that pcms::backend::mfem cannot
shadow ::mfem. The MFEM tests are updated to the qualified names. No other
changes.

Generated with:
    tools/reorg/backend_namespace.py mfem tools/reorg/namespaces/mfem.txt
Hand-written CMake for the move to backends/mfem: backends/mfem (added when
PCMS_ENABLE_MFEM is on, as before) adds the MFEM sources and headers to
pcms_field and links MFEM, which is unchanged (PUBLIC). The entries and the
link are removed from field/CMakeLists.txt.
…_meshfields

Mechanical: the MeshFields layout, field data, evaluator and evaluator
backend move from field/{layout,data,evaluator} into
src/pcms/backends/omega_h_meshfields/. Every one of these files needs both
MeshFields and the Omega_h adapter (MeshFieldsAdapterLayout is built from an
OmegaHDiscretization), so they belong in the omega_h_meshfields bridge; no
MeshFields code is independent of Omega_h. Includes and CMake paths are
updated; the files are still compiled into pcms_field under
PCMS_ENABLE_MESHFIELDS.

Generated with:
    tools/reorg/move_files.py tools/reorg/moves/03-omega_h_meshfields.txt
…ga_h

Mechanical: Python tests and the flow example call
pcms.backend.omega_h.{create_uniform_grid_from_mesh,
compute_entity_centroids, map_entity_field_to_vertices_{average,mls}}
instead of the top-level names. Same arguments, same checks.

Generated with:
    tools/reorg/python_api_names.py $(git grep -lE 'pcms\.(create_uniform_grid_from_mesh|compute_entity_centroids|map_entity_field_to_vertices_)' -- '*.py' ':!tools')
pcms.create_uniform_grid_from_mesh, pcms.compute_entity_centroids and
pcms.map_entity_field_to_vertices_{average,mls} are only available as
pcms.backend.omega_h.*, matching C++ (pcms::backend::omega_h::
CreateUniformGridFromMesh) and the other Omega_h entry points. The
compute_entity_centroids_few alias is removed (identical to
compute_entity_centroids). No caller in the tree uses the old names; the
workflow guide is updated by hand. tools/reorg/python_api_names.py (run by
tools/migrate-pcms.sh) rewrites downstream callers.

Verified: Full-shared (build and ctest).
backend_namespace.py's core becomes move_namespace(ns, files, symbols,
external_prefix); sublib_namespace.py uses it with an explicit file list
for the sub-library namespaces (Phase 7). The backend mode now also treats
the backend's public headers under include/pcms/backends/<name>/ as its
own files (they moved there in Phase 5). Re-running the backend mode on
every backend leaves all backend files unchanged.

move_namespace() also handles the detail namespaces of the moved code:

- a compact `namespace pcms::detail` block (element_dispatch.hpp,
  localization_path_selection.hpp, omega_h_form_integrator_utils.hpp)
  becomes <ns>::detail, like a `namespace detail` nested in
  `namespace pcms` (detail namespaces stay nested under the new
  namespace);
- uses in other files of the names declared in the moved detail namespaces
  (written pcms::detail::X or detail::X) are qualified with <ns>::detail,
  except names that another file also declares in a detail namespace.

Verified: Full-shared (build and ctest).
mls_interpolation.hpp forward-declared pcms::SupportResults, which belongs to
localization (localization/support_results.hpp). It now includes that
header, so the declaration keeps referring to the right type when the
sub-libraries get their own namespaces.
…ility

Mechanical: the declarations of the private utility headers (array_mask,
mesh_geometry, mpi_type, omega_h_array_utils: ArrayMask,
EnsureClassification, GetMPIType, distance_squared,
flatten_to_omega_h_reals[_host], get_entity_centroids) move from pcms:: to
pcms::utility::, and their users (backends, localization, transfer, Python
bindings, tests) use the qualified names. Public utility types (arrays,
coordinate systems, UniformGrid, ...) stay in pcms::.

Generated with:
    tools/reorg/sublib_namespace.py utility tools/reorg/namespaces/sublib-utility.txt tools/reorg/namespaces/sublib-utility-files.txt
…space pcms::discretization

Mechanical: the declarations of the private discretization headers and the sources
implementing them move from pcms:: to pcms::discretization::, and their users use the
qualified names. Public discretization types stay in pcms::. Moved names: EmptyDiscretization

Generated with:
    tools/reorg/sublib_namespace.py discretization tools/reorg/namespaces/sublib-discretization.txt tools/reorg/namespaces/sublib-discretization-files.txt
…e pcms::localization

Mechanical: the declarations of the private localization headers and the sources
implementing them move from pcms:: to pcms::localization::, and their users use the
qualified names. Public localization types stay in pcms::. Moved names: AdjacencyLocalizationFactory BuildPointCloudSupports GetOwningElementId GridPointSearch2D GridPointSearch3D GridPointSearchVariant LocalizationFactory PointLocalizationSearch PointLocalizationSearch2D PointLocalizationSearch3D SupportResults adapt_radii minmax triangle_intersects_bbox within_number_of_support_range

Generated with:
    tools/reorg/sublib_namespace.py localization tools/reorg/namespaces/sublib-localization.txt tools/reorg/namespaces/sublib-localization-files.txt
Mechanical: the declarations of the private field headers and the sources
implementing them move from pcms:: to pcms::field::, and their users use the
qualified names. Public field types (Field, FunctionSpace, FieldLayout,
...) stay in pcms::. Moved names used elsewhere: AppendGidPermutation BuildSortedGidPermutation EmptyFieldLayout FieldEvaluatorFactory GidToIndexMaps LagrangeFunctionSpace MakeUnmappedPermutation PolynomialReconstructionFunctionSpace SplineFunctionSpace mls_interpolation

The private evaluator/interpolator_aliases.hpp keeps its generic type
aliases (member_type, ScratchMatView, ...) in pcms::, because other files
define unrelated local aliases with the same names.

Generated with:
    tools/reorg/sublib_namespace.py field tools/reorg/namespaces/sublib-field.txt tools/reorg/namespaces/sublib-field-files.txt
…transfer

Mechanical: the declarations of the private transfer headers (integrators,
projections, mesh intersection, MLS interpolation classes, PETSc helpers)
and the sources implementing them move from pcms:: to pcms::transfer::, and
their users (C API, projection factories, tests) use the qualified names.
Public transfer types (TransferOperator, Interpolator, Copy, the projection
factories and options) stay in pcms::. Moved names: BilinearFormIntegrator BuildOmegaHConservativeRHSIntegrator BuildOmegaHMassIntegrator FindIntersections GalerkinProjectionSolver InterpolationBase IntersectionResults LinearFormIntegrator MLSMeshInterpolation MLSPointCloudInterpolation MassMatrixIntegrator OmegaHConservativeProjection OmegaHControlVariateProjection OmegaHIntersectionRHSIntegrator OmegaHMassIntegrator OmegaHMonteCarloRHSIntegrator build_linear_triangle_coo_rows build_linear_triangle_coo_rows_cols copyHostScalarArrayView2HostWrite copyHostWrite2ScalarArrayView createSeqAIJMat createSeqVec intersectTargets

Generated with:
    tools/reorg/sublib_namespace.py transfer tools/reorg/namespaces/sublib-transfer.txt tools/reorg/namespaces/sublib-transfer-files.txt
…upler

Mechanical: the coupler's internal classes (the communicators, exchange
planners and field serializer of include/pcms/coupler/detail/, and the
private partition.hpp) and the sources implementing them move from pcms::
to pcms::coupler::, and their users (coupler.hpp, the C API, tests) use the
qualified names. The public coupler API (ApplicationComm, CouplerComm, the
handles, Mode, OverlapMask) stays in pcms::. Moved names: ExchangePlan FieldCommunicator FieldCommunicator2Ptr FieldCommunicator2PtrT FieldExchangePlanner FieldLayoutCommunicator FieldSerializer GenericFieldExchangePlanner GetRank GlobalCommunicator Partition

Generated with:
    tools/reorg/sublib_namespace.py coupler tools/reorg/namespaces/sublib-coupler.txt tools/reorg/namespaces/sublib-coupler-files.txt

Verified: Full-shared (build and ctest).
Phase 8.1: the CMake package files (pcms-config.cmake, its version file,
FindPETSc.cmake and every *-targets.cmake) were installed to
${CMAKE_INSTALL_LIBDIR}/cmake/pcms, which is lib64/cmake/pcms on some
platforms. They now go to the new cache variable PCMS_INSTALL_CMAKEDIR,
default lib/cmake/pcms on every platform (CI already expects that path).
Headers stay in include/pcms, libraries in ${CMAKE_INSTALL_LIBDIR}.
find_package(pcms) finds the package with either layout.
Phase 8.2: the package version file used AnyNewerVersion, so a project
asking for pcms 0.3 accepted any later release, including ones with
breaking changes such as 0.4. It now uses SameMinorVersion: a request for
X.Y is satisfied only by X.Y.z, matching the SOVERSION (next commit).
Phase 8.3: the project version becomes 0.4.0 (minor bump for this breaking
release). Every PCMS library gets VERSION 0.4.0 and SOVERSION 0.4: while
the major version is 0, any minor release may break the ABI, so the
SOVERSION follows major.minor, consistent with the SameMinorVersion check
of the package config.
Phase 8.4: src/pcms/external/flibhpc (SWIG .i files and their license and
README) was installed to include/pcms/external. No installed consumer uses
them: the Fortran wrappers are generated in-tree with
`swig -fortran` (see src/pcms/fortranapi/README.md) and installed as
compiled modules. They are no longer installed.

FindPETSc.cmake stays installed, because the package config calls
find_dependency(PETSc) when PETSc is enabled and needs that module.
Phase 8.5: pcms-config.cmake called find_dependency(<pkg> CONFIG HINTS
@<pkg>_DIR@) for redev, Kokkos, KokkosKernels, ADIOS2, perfstubs, meshfields,
Omega_h and MFEM, which baked the build machine's absolute paths into the
installed package. The HINTS are removed; consumers locate the dependencies
the usual way (CMAKE_PREFIX_PATH, <pkg>_ROOT or <pkg>_DIR), as for any CMake
package.

The PETSC_DIR / PETSC_ARCH defaults (used only when the consumer has not set
them, and needed by the installed FindPETSc.cmake) are kept.

Verified: Minimal-static, Full-shared (build and ctest).
Phase 9.3: tools/check-public-includes.py scans include/pcms and fails if
a header includes Omega_h, MFEM, MeshFields, PETSc, redev or ADIOS2, except
where allowed: backend headers may include their own library
(backends/omega_h: Omega_h; backends/mfem: MFEM; backends/xgc: Omega_h for
building the reverse classification from a mesh), and the coupler's headers
may include redev (agreed at the Phase 0 checkpoint). It runs as the ctest
public_header_includes and in CI.
detail/global_communicator.hpp uses Rank1View and HostMemorySpace without
including pcms/utility/arrays.hpp and pcms/utility/memory_spaces.hpp; it
compiled only because its includers had included them first. It now
includes them, so it compiles on its own (checked by the public header
self-containment test added in the next commit).
Phase 9.2: test/public_headers generates one translation unit per header
below include/pcms (#include <pcms/...> and nothing else) and compiles them
into an object library; the ctest public_headers_self_contained builds it.
Headers whose library is not part of the build (coupler, transient, C API,
the Omega_h / MFEM / XGC backends) are skipped in that configuration.
The external usage example only called pcms::printInfo. It now uses the
installed public API the way a downstream code would: pcms/pcms.hpp, the
discretization and space factories (CreateUniformGridDiscretization,
CreateLagrangeSpace), CreateFunction, Interpolator, and checks that
interpolating a constant field between two uniform grids reproduces it
exactly. It still includes a C API header to check that the installed C
headers are usable.
Phase 9.1: the existing installation step relied on the package config's
baked HINTS to find the dependencies, which are gone (Phase 8.5); it now
passes the dependency install prefixes in CMAKE_PREFIX_PATH and the MPI C++
compiler, builds examples/external-usage-example against the installed
pcms only, and runs it. A new step runs tools/check-public-includes.py.
Phase 9.4:

- tools/reorg/header-map.txt: every renamed or moved installed header (old
  include path -> new), marking the ones that are no longer installed;
  generated from git's rename detection between develop and this branch,
  with pcms.h, coupler_types, mls_options and adj_search added by hand
  (too much content change for rename detection).
- tools/reorg/symbol-map.txt: renamed CMake options and targets, renamed
  macros, C++ names that moved namespace (public or now internal), and the
  APIs that changed shape with their replacements.
- tools/migrate-pcms.sh <dir> [--dry-run]: rewrites includes, public names,
  macros, CMake options/targets and Python code (via
  tools/reorg/python_api_names.py) in a downstream tree, and lists every
  remaining use of a no-longer-public header or name with its replacement.

Tried on develop's own tests and examples: includes, CMake and Python are
migrated, and the uses of now-internal classes are all reported.
Phase 9.5: MIGRATION.md explains what changed (build and linking, headers,
the factory API with an old-to-new table, namespaces, coupler, macros,
Python) and how to migrate with tools/migrate-pcms.sh. CHANGELOG.md is new
and starts with the 0.4.0 entry.
Mechanical: include guards had mixed names (PCMS_COUPLING_*, COUPLER2_H_,
TEST_HELPERS_H, names of former paths, ...). Every header now uses
PCMS_<include path>_<HPP|H> (PCMS_TEST_<name>_HPP for test headers), with
the #endif comment matching. Done after the header moves (Phase 5) so the
names match the final paths. Guards stay #ifndef/#define/#endif; #pragma
once is not used (tools/reorg/decisions.md).

Generated with:
    tools/reorg/normalize_guards.py
Phase 10.1: formatting only, with the existing .clang-format and
clang-format 18 (the version the format-check workflow uses), over every
.c/.cpp/.h/.hpp/.cc/.cxx file. The changes come from the reorganization
(longer qualified names, moved includes); no generated file changes.

Generated with:
    find . -path ./.git -prune -o \( -name '*.cpp' -o -name '*.hpp' -o -name '*.c' \
      -o -name '*.h' -o -name '*.cc' -o -name '*.cxx' \) -type f -print | xargs clang-format-18 -i
Phase 10.2: adds the clang-format commit to .git-blame-ignore-revs.

Verified: Minimal-static, Full-shared, Full-static (build and ctest).
…cms.sh --in-tree

Porting SCOREC#399 with the recipe in MIGRATION.md showed two problems with
--in-tree:

- It rewrote PCMS's compatibility code in the PR's files: the deprecated
  pcms::core alias became a second pcms::pcms target (configure error), the
  renamed-option shims mapped the new names to themselves, and the MLS
  kernels' MAX_DIM constant (unrelated to the renamed macro) became
  PCMS_MAX_DIM. Symbol-map entries can now carry an "external" flag that
  --in-tree skips (pcms::core, MAX_DIM), and --in-tree leaves
  pcms_renamed_option() lines and CMake comments alone.
- It missed quoted includes relative to the including file
  ("numpy_view.h" in src/pcms/pythonapi/), which PCMS's sources use for
  their neighbors. Those are now resolved against the file's directory,
  both for rewriting and for the private-header report.

On the reorganized tree, --in-tree now changes only names in three
comments and test-case titles.
…ipe's merge-file step

The loop that keeps the branch's side of conflicting hunks ran on every
unmerged code file. For a file that one side deleted or moved (a
modify/delete conflict, only one of stages 2 and 3 present) git show
fails, merge-file runs against an empty file, and the result was staged:
porting SCOREC#345 staged an empty src/pcms/localization/point_search.hpp and
kept the branch's adj_search.hpp at its old path next to the moved one.
The loop now handles only files with all three stages; the others are
left unmerged for the by-hand step, which already describes them.
…a pull request

Porting SCOREC#345 (localization rework) showed that step 3 moves only the
files listed in tools/reorg/namespaces/: the PR's new
localization.hpp/uniform_grid_localization.* declare names that step 3
qualifies as pcms::localization::X elsewhere, but stayed in namespace
pcms themselves. Listing the new files and names before step 3 fixes it.

This branch is waiting to be deployed

1 waiting deployment
asics — 5ee6566b Waiting Nov 5, 2026 by jacobmerson via build_and_test #414
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant