install(TARGETS ...) CONFIGURATIONS documentation is confusing and/or the behavior is buggy
The install(TARGETS ...) documentation about the CONFIGURATIONS does not seem to be adequate or inline with how it actually works.
First off the docs state that:
CONFIGURATIONS: ... Note that the values specified for this option only apply to options listed AFTER the CONFIGURATIONS option. ...
That does not seem to be inline with the behavior what I observe. Given the following hypothetical self-contained example building a Windows DLL:
cmake_minimum_required(VERSION 3.25)
project(test LANGUAGES C)
file(WRITE main.c "__declspec(dllexport) void func() {}")
add_library(test SHARED main.c)
install(TARGETS test
CONFIGURATIONS DEBUG RUNTIME DESTINATION debug # RUNTIME
CONFIGURATIONS RELEASE ARCHIVE DESTINATION release # yes, ARCHIVE, not a typo!
)
After building, install does the exact opposite what the docs imply:
>cmake --install build --config Release
-- Installing: D:/dev/_cmake_issues/install/debug/test.dll
>cmake --install build --config Debug
-- Installing: D:/dev/_cmake_issues/install/release/test.lib
Apparently the install() rule seems to be interpreted the following way:
install(TARGETS test
CONFIGURATIONS DEBUG # <-- global for the whole install()
RUNTIME DESTINATION debug CONFIGURATIONS RELEASE # <-- applies to file type BEFORE
ARCHIVE DESTINATION release # <-- no config, so global applies, ie. DEBUG
)
This seems to be inline with the synopsis of the command in the documentation:
install(TARGETS targets... [EXPORT <export-name>]
[RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>|CXX_MODULES_BMI]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[NAMELINK_COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
[NAMELINK_ONLY|NAMELINK_SKIP]
] [...]
[INCLUDES DESTINATION [<dir> ...]]
)
The above seems to indicate that CONFIGURATIONS is part of a group, and it is listed after RUNTIME|ARCHIVE|... DESTINATION.
[Issue no.2] Furthermore, the above synopsis seems to imply that I should be able to write the following rule:
install(TARGETS test
RUNTIME DESTINATION release CONFIGURATIONS RELEASE
RUNTIME DESTINATION debug CONFIGURATIONS DEBUG
)
Yet only the last rule wins, and weirdly for BOTH configurations, ie. it installs to the "debug" dir for both Release and Debug builds. If I change it to the following, it works as expected (except for the fact that CONFIGURATIONS appear AFTER the type, yet it works still):
install(TARGETS test
RUNTIME DESTINATION debug CONFIGURATIONS DEBUG
)
install(TARGETS test
RUNTIME DESTINATION release CONFIGURATIONS RELEASE
)
There is no mention in the docs that a given file type can only appear once. If there is such a restriction, then the install() command should fail with an error.
Further trial and error with various combinations of multiple "RUNTIME DESTINATION", "DESTINATION" (without any type) and "CONFIGURATIONS" result in further weird behavior which would simply be too long to list them all here (there's just too many permutations, most of which behave unexpectedly).
So the docs statement about the placement of CONFIGURATIONS is not inline with the command synopsis, and neither is inline with observed behavior always. I suggest to either fully document the behavior as it is now, or better yet make install() fail in situations similar to the ones listed above.