-
Notifications
You must be signed in to change notification settings - Fork 453
Only add the uninstall target if the C driver is the top level project #1352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only add the uninstall target if the C driver is the top level project #1352
Conversation
Given this workaround is specific to the |
generate_uninstall/CMakeLists.txt
Outdated
# defining the uninstall target as a variable, the C++ driver is able to rename | ||
# this target in order to avoid the conflict. | ||
if (NOT DEFINED MONGOC_UNINSTALL_TARGET) | ||
set(MONGOC_UNINSTALL_TARGET uninstall) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the C++ driver renames the target, will running the uninstall target in the C++ driver only uninstall the C++ driver (and leave the C driver installed files)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this PR, make uninstall
will uninstall both the C and C++ drivers:
$ make install
$ tree -L 2 /tmp/cxxdriver/
/tmp/cxxdriver/
├── bin
│ └── mongoc-stat
├── include
│ ├── bsoncxx
│ ├── libbson-1.0
│ ├── libmongoc-1.0
│ └── mongocxx
├── lib
│ ├── cmake
│ ├── libbson-1.0.so -> libbson-1.0.so.0
│ ├── libbson-1.0.so.0 -> libbson-1.0.so.0.0.0
│ ├── libbson-1.0.so.0.0.0
│ ├── libbson-static-1.0.a
│ ├── libbsoncxx.so -> libbsoncxx.so._noabi
│ ├── libbsoncxx.so.0.0.0
│ ├── libbsoncxx.so._noabi -> libbsoncxx.so.0.0.0
│ ├── libmongoc-1.0.so -> libmongoc-1.0.so.0
│ ├── libmongoc-1.0.so.0 -> libmongoc-1.0.so.0.0.0
│ ├── libmongoc-1.0.so.0.0.0
│ ├── libmongoc-static-1.0.a
│ ├── libmongocxx.so -> libmongocxx.so._noabi
│ ├── libmongocxx.so.0.0.0
│ ├── libmongocxx.so._noabi -> libmongocxx.so.0.0.0
│ └── pkgconfig
└── share
├── mongo-c-driver
└── mongo-cxx-driver
12 directories, 15 files
$ make uninstall
$ tree -L 2 /tmp/cxxdriver/
/tmp/cxxdriver/ [error opening dir]
0 directories, 0 files
Setting this global variable instead of the current workaround results in this error:
|
@kkloberdanz Just confirming, this is a global property, not a variable. You need to use Edit: global properties != directory properties. |
generate_uninstall/CMakeLists.txt
Outdated
# the `uninstall` target causing the `make uninstall` command to fail. By | ||
# defining the uninstall target as a variable, the C++ driver is able to rename | ||
# this target in order to avoid the conflict. | ||
if (NOT DEFINED MONGOC_UNINSTALL_TARGET) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per https://gitlab.kitware.com/cmake/cmake/-/issues/23024#note_1098749, it may actually be more reasonable to simply not define the uninstall target at all if this project is not the top-level project (note: PROJECT_IS_TOP_LEVEL
is a CMake 3.21 feature). The top-level project (i.e. the CXX Driver) would be responsible for defining the uninstall
target behavior to include (or ignore) this project's files.
if ("${CMAKE_SOURCE_DIR}" STREQUALS "${PROJECT_SOURCE_DIR}")
add_custom_target(uninstall ...)
endif ()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to work too. I don't have an opinion on which one we go with.
Setting this as a property results in failures on Windows:
I set it like so in the top level
|
…r is the top level project
Co-authored-by: Kevin Albertson <[email protected]>
Co-authored-by: Kevin Albertson <[email protected]>
add_custom_target (uninstall | ||
COMMAND sh "${CMAKE_CURRENT_BINARY_DIR}/${UNINSTALL_PROG}" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest a different design:
if(NOT TARGET uninstall)
add_custom_target(uninstall)
endif()
add_custom_target(mongo-c-driver-uninstall COMMAND [do the uninstall])
add_dependencies(uninstall mongo-c-driver-uninstall)
This way, we "add" to an existing uninstall
target if it already defined (e.g. by a parent project).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be preferable to defer the responsibility of including C Driver files in the uninstall command to the CXX Driver (top-level project) rather than unconditionally hooking into it from the C Driver side? The CXX Driver may want to uninstall the C Driver as part of its uninstall command, but another top-level project (i.e. 3rd party that add_subdirectory()
's the C Driver) might not. As I understand, this would either unconditionally attach the C Driver to any existing uninstall
command regardless if the parent project actually wants to include it or not, or force the parent project to hook into the C Driver's uninstall
target instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's tricky, since the C driver unconditionally(?) adds its install rules, which the parent may not want, which would imply that it should also unconditionally(?) add its uninstall rules as well. It is possible to EXCLUDE_FROM_ALL
on the add_subdirectory()
, but I'm not sure if that affects the install()
commands (the documentation doesn't mention it, but one would intuit that it should).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A quick local test suggests that EXCLUDE_FROM_ALL
does exclude the subproject's install rules when running the install
target in the parent project. This is consistent with the GNU Make documentation for the install
target:
If possible, write the
install
target rule so that it does not modify anything in the directory where the program was built, provided ‘make all
’ has just been done. This is convenient for building the program under one user name and installing it under another.
combined with CMake documentation for EXCLUDE_FROM_ALL
:
If the
EXCLUDE_FROM_ALL
argument is provided then targets in the subdirectory will not be included in the ALL target of the parent directory by default, and will be excluded from IDE project files. Users must explicitly build targets in the subdirectory.
This is also consistent with this comment by a CMake maintainer, although their remarks are not as confident as I would have hoped:
Regarding the overarching theme of excluding things from the
ALL
target and then installing them, the thing to remember is that if a target is excluded fromALL
, then you the user are responsible for ensuring it is built if you then do something that wants to install that target. The documentation for theinstall()
command calls this undefined behavior, but that’s perhaps a bit strong. In reality, my preceding sentence is the real constraint, as far as I’m aware (but I haven’t checked how export sets affect the picture).
The documentation stating "undefined behavior" seems to have been changed from CMake 3.17 to CMake 3.18 (current wording):
If a target has
EXCLUDE_FROM_ALL
set to true, it may still be listed in aninstall(TARGETS)
command, but the user is responsible for ensuring that the target’s build artifacts are not missing or outdated when an install is performed.
Summary: there seems to be a lot more "should" qualifiers to this than one would expect or hope, but it should behave as expected (EXCLUDE_FROM_ALL
-> exclude from all
target -> also exclude from install
target).
Only add the
uninstall
target if the C driver is the top level project.The
uninstall
target was conflicting with the C++ driver'suninstall
target. This fixes the conflict.