# Exporting renamed/multiple-named configs

**URL:** https://discourse.cmake.org/t/exporting-renamed-multiple-named-configs/2586
**Category:** Code
**Created:** [January 20, 2021, 9:50am UTC](https://discourse.cmake.org/t/exporting-renamed-multiple-named-configs/2586 "2021-01-20T09:50:11Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [January 20, 2021, 9:50am UTC](https://discourse.cmake.org/t/exporting-renamed-multiple-named-configs/2586/1 "2021-01-20T09:50:11Z")

</div>

I’m trying to find a way to rename an existing CMake project, but in a way that avoids disrupting existing users. Those users will (at least initially, and for a time) be expecting the project to define the options, targets, and output variables it previously used under the old name. That situation would continue, with deprecation warnings shown on any uses of the old name, for whatever transition period is deemed necessary. Then, the project would stop creating the configuration under the previous name, and only the new name would be recognized.

The `option()`s are easy enough to handle:

```cmake
option(NEW_NAME_FLAG1 "Description" ON/OFF)

foreach (_option _FLAG1 ... _FLAGn)
  if (DEFINED CACHE{OLD_NAME${_option}})
    message(WARNING "Deprecation notice")
    get_property(_help CACHE NEW_NAME${_option} PROPERTY HELPSTRING)
    set(NEW_NAME${_option} "${OLD_NAME${_option}}"
      CACHE BOOL "${_help}" FORCE)
    unset(OLD_NAME${_option} CACHE)
  endif()
endforeach()

```

It’s the exported config that’s proving trickier. Two basic approaches come to mind. But since I’m hitting snags with either of them, I’m curious if anyone has any recommendations or suggestions.

### Option 1: Export the full config under both names

- Generate a full set of `OldNameConfig.cmake`, `OldNameConfigVersion.cmake`, etc. to install in `lib/cmake/OldName/`
- Also generate a full set of `NewNameConfig.cmake`, `NewNameConfigVersion.cmake`, etc. to install in `lib/cmake/NewName/`
- `OldNameConfig.cmake` should export targets in namespace `OldName::`
- `NewNameConfig.cmake` should use namespace `NewName::`
- Target names _inside_ the namespace should remain unchanged. That is, the same targets should be exported in each config, just with different prefixing. However, results variables like `PackageName_INCLUDE_DIRECTORIES` should follow the config name, so `OldName_INCLUDE_DIRECTORIES` vs. `NewName_INCLUDE_DIRECTORIES`.
- All configuration _values_ should be identical in either config; they should be interchangeable except for the package name.

### Option 2: Create a “proxy” config under the old name

- Everything would be installed as `NewNameConfig.cmake`, `NewNameConfigVersion.cmake`, etc. using namespace `NewName::`, and installed to `lib/cmake/NewName/`.
- `OldNameConfig.cmake`, installed to `lib/cmake/OldName/`, would ideally display a deprecation message, then:
  - Perform a `find_package(NewName ...)` on behalf of the caller,
  - Define a set of `ALIAS` targets `OldName::target` for each `NewName::target`
  - Do a `set(OldName_RESULTn "${NewName_RESULTn}")` and `set(OLDNAME_RESULTn "${NEWNAME_RESULTn}")` for each result variable
  - End with:

```cmake
 find_package_handle_standard_args(OldName
   FOUND_VAR OldName_FOUND
   REQUIRED_VARS OldName_INCLUDE_DIRECTORY OldName_LIBRARY
   VERSION_VAR OldName_VERSION)

```

My strong preference would be the second option, primarily because the first one creates all sorts of squirrely issues, things like:

1. The package template file becomes a lot less clean; right now it outputs messages referring to the `@PACKAGE_PROJECT_NAME@::target` targets, and sets `@PACKAGE_PROJECT_NAME@_VAR` variables, all of which can no longer use `@PACKAGE_PROJECT_NAME@` unconditionally; it’ll depend on the _namespace_ I’m exporting under. But then other ones, the `@PACKAGE_PATH_VAR@` ones, remain unchanged.  
OK, yes, I could set a variable `EXPORT_NAMESPACE` for each run of `configure_package_config_file()` and change `@PACKAGE_PROJECT_NAME@ ` to `@PACKAGE_EXPORT_NAMESPACE@` easily enough, but…

2. Maintaining two namespaces/package-names becomes especially tricky, when initially creating the config files inside the build directory.  
In the existing (quite cleanly-written) tooling, each component is a target, or vice versa. Each target gets exported to its own `ComponentName.cmake` file, which `...Config.cmake` loads if that component is requested. Because the target names aren’t changing, I’d prefer to leave those files named the way they are. But there can’t be two `ComponentName.cmake` files configured to use different namespaces, and both exported to the same build directory.

The only tricky thing about option 2 is, I’d really like `OldNameConfig.cmake` to call the inner `find_package(NewName ...)` with all of the same arguments that the caller used when they called `find_package(OldName ...)`.

Thing is, there doesn’t seem to be a way to get at those args in their “raw” form. I’d have to process all of the various `OldName_FIND_REQUIRED*`, `OldName_FIND_QUIETLY`, `OldName_FIND_VERSION*`, `OldName_FIND_COMPONENTS`, etc. variables to reverse-engineer the calling arguments, if I wanted to call `find_package(NewName ...)` the same way.

Am I (hopefully) missing something? (Either a solution to one or the other set of issues, or a completely different approach I haven’t even considered. I’m not picky.)

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 20, 2021, 3:33pm UTC](https://discourse.cmake.org/t/exporting-renamed-multiple-named-configs/2586/2 "2021-01-20T15:33:36Z")

</div>

I would hand-code the `OldName` package to do forwarding. Something like this logic is used in VTK for [deprecated components](https://gitlab.kitware.com/vtk/vtk/-/blob/e310c3e9d19916a7d41412deea0240020179e928/CMake/vtk-config.cmake.in#L69-82) and [deprecating `VTK_USE_FILE`](https://gitlab.kitware.com/vtk/vtk/-/blob/e310c3e9d19916a7d41412deea0240020179e928/CMake/vtk-config.cmake.in#L313-320). So, basically:

- if there’s no minimum version requested, make deprecation warnings about the changes
- if a version before the change is requested, stay quiet (because they need to do that in order to keep their minimum there); an `AUTHOR_WARNING` may be appropriate to let the developers know that things are afoot though
- if a version with the new stuff is requested, error so that they migrate to the new names

Then I would provide targets under the old name:

```cmake
find_package(NewName) # Forward arguments like `QUIET`, components, and/or version requests too
if (NOT NewName_FOUND)
  set(OldName_FOUND 0)
  set(OldName_NOT_FOUND_MESSAGE "NewName not found: ${NewName_NOT_FOUND_MESSAGE}")
  return ()
endif ()

if (NOT TARGET OldName::OldTarget AND TARGET NewName::NewTarget)
  add_library(OldName::OldTarget IMPORTED INTERFACE)
  set_target_properties(OldName::OldTarget PROPERTIES INTERFACE_LINK_LIBRARIES "NewName::NewTarget")
endif ()

```

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [January 20, 2021, 10:16pm UTC](https://discourse.cmake.org/t/exporting-renamed-multiple-named-configs/2586/3 "2021-01-20T22:16:46Z")

</div>

> [@ben.boeckel](#):
>
> ```cmake
> if (NOT TARGET OldName::OldTarget AND TARGET NewName::NewTarget)
> add_library(OldName::OldTarget IMPORTED INTERFACE)
> set_target_properties(OldName::OldTarget PROPERTIES INTERFACE_LINK_LIBRARIES "NewName::NewTarget")
> endif ()
> 
> ```

Yeah, that’s the basic plan I was thinking, for option 2. (Now that you’ve shown code for that approach, I can see how `IMPORTED INTERFACE` proxy targets are a better way to go than `ALIAS` targets, tho — yeah.) The possibility of the user calling `find_package()` with (or without) a `VERSION` and/or any of the multiple `COMPONENT`s in any combination makes it a bit of a pain — well, not really, just a tedious _chore_ — to get the initial `find_package(NewName)` call right, but it’s far from impossible.

Still better than trying to export the targets two different ways. Which is probably _doable_, but I’m pretty sure NOT without making a complete **mess** of the code. And currently it’s clean and well-organized enough that I really don’t want to be the one who turns it into nasty spaghetti.

The best thing about option 2 is that it’s self-contained — I add the code to export as `OldNameConfig.cmake`, and in every _other_ way the code stays exactly the same as it is now except for the `PROJECT_NAME` change to `NewName`. Whenever the transition period is deemed complete, the bit of code that handles the `OldName` exports can be just as cleanly dropped, and it’s like it never happened.

> [@ben.boeckel](#):
>
> - if there’s no minimum version requested, make deprecation warnings about the changes
> - if a version before the change is requested, stay quiet (because they need to do that in order to keep their minimum there); an `AUTHOR_WARNING` may be appropriate to let the developers know that things are afoot though
> - if a version with the new stuff is requested, error so that they migrate to the new names

I _especially_ like that suggestion, thanks!
