-
Notifications
You must be signed in to change notification settings - Fork 22
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
DRAFT: Add Optional Config File Package Creation/Installation to Exemplar #115
base: main
Are you sure you want to change the base?
Conversation
…ion much more granular. Add config file package generation w/initial support for multiple target export variants. Still need to flesh out the logic to select the target export variant, but looking for feedback first.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Hey @chayden83 thanks for the contribution, you can apply linting suggestions by running Edit: Subsequent comment marked resolved is relating to this comment. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
None the less, thank you for your contribution! Package creation is definitely something we desperately need. This is out of my league to review, but I do like how configurable your implementation is. I will leave the review to @camio and @bretbrownjr . Just a note, beman usuals are at iso meetings right now, it might take a while for them to circle back and review your contribution. Edit: A while ~= One/ Two weeks. |
No, sorry, I wasn't clear. I rolled my own local image for beman dev.
👍 |
I've been setting up a python venv and pip installing the requirements for pre-commit, gcovr, etc, into that. There's enough C++ in the python ecosystem that most C++ tools have current versions available. The problem is, of course, yet another layer of tools. |
…mponent for various artifacts (headers, archives, libraries, etc). Add a helper function that implicitly uses these variables when installing targets.
…g on project settings.
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.
Note to maintainers: We should move this to infra repo in the future.
@chayden83 You can click on the "ready for review" button at the merge panel to update this PR to unset the draft state. |
… using a custom target export variant.
…h out body of config-file package.
…guration options.
…d relative to the project source directory, so I need to use strings instead.
|
… to CMake configuration options.
cmake/beman-utils.cmake
Outdated
VERSION ${PROJECT_VERSION} | ||
SOVERSION ${PROJECT_VERSION_MAJOR} |
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.
[pre-commit] reported by reviewdog 🐶
VERSION ${PROJECT_VERSION} | |
SOVERSION ${PROJECT_VERSION_MAJOR} | |
VERSION ${PROJECT_VERSION} | |
SOVERSION ${PROJECT_VERSION_MAJOR} |
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.
Hi @chayden83!
Nice CMake code. We really need changes in this space, and I'm excited to see you taking a crack at a lot of the problems here.
I think we need to downshift a bit, though. Can we iterate towards where we want to end up instead of doing it all at once? I'm OK hardcoding assumptions initially, for instance. And I'm OK on adding support for specific features (PIC, shared libs, etc.) in specific PRs.
Maybe this PR can focus on the task in its title? What's a reasonable sized PR for making sure cmake --install
workflows for beman.exemplar
produce files such that find_package(beman.exemplar REQUIRED)
works as expected? I'd be OK with a little beman_install_target
function that hardcodes the export install commands or even installing a set beman.exemplar-config.cmake
file that's reasonably portable.
- name: "Enable position-independent code?" | ||
arg: "-DBEMAN_EXEMPLAR_POSITION_INDEPENDENT_CODE=ON" |
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.
- name: "Enable position-independent code?" | |
arg: "-DBEMAN_EXEMPLAR_POSITION_INDEPENDENT_CODE=ON" |
I'd prefer just to support CMAKE_POSITION_INDEPENDENT_CODE
. As a general rule, I'd rather use standard CMake mechanisms whenever possible. Even if that means shoehorning more things into CMAKE_CXX_FLAGS
in .github
files.
- name: "Override default library install directory" | ||
arg: "-DBEMAN_EXEMPLAR_INSTALL_LIBDIR=local/lib" | ||
- name: "Override default executable installation directory" | ||
arg: "-DBEMAN_EXEMPLAR_INSTALL_BINDIR=local/bin" | ||
- name: "Override default include install directory" | ||
arg: "-DBEMAN_EXEMPLAR_INSTALL_INCLUDEDIR=local/include" | ||
- name: "Override default CMake config-file package install directory" | ||
arg: "-DBEMAN_EXEMPLAR_INSTALL_INCLUDEDIR=local/lib/cmake/beman.exemplar" |
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.
- name: "Override default library install directory" | |
arg: "-DBEMAN_EXEMPLAR_INSTALL_LIBDIR=local/lib" | |
- name: "Override default executable installation directory" | |
arg: "-DBEMAN_EXEMPLAR_INSTALL_BINDIR=local/bin" | |
- name: "Override default include install directory" | |
arg: "-DBEMAN_EXEMPLAR_INSTALL_INCLUDEDIR=local/include" | |
- name: "Override default CMake config-file package install directory" | |
arg: "-DBEMAN_EXEMPLAR_INSTALL_INCLUDEDIR=local/lib/cmake/beman.exemplar" |
I'd prefer just using the GNUInstallDirs
mechanisms as documented upstream. CMAKE_INSTALL_INCLUDEDIR
, etc. Though in most cases, we shouldn't need to reference those directly as defaults for HEADER
FILE_SETS
is documented to use those paths.
- name: "Enable config-file package creation?" | ||
arg: "-DBEMAN_EXEMPLAR_CONFIG_FILE_PACKAGE=OFF" | ||
- name: "Specify config-file package version compatibility" | ||
arg: "-DBEMAN_EXEMPLAR_CONFIG_FILE_PACKAGE_COMPATIBILITY=SameMajorVersion" | ||
- name: "Specify the name of the target export variant to create" | ||
arg: "-DBEMAN_EXEMPLAR_TARGET_EXPORT_VARIANT=custom" | ||
- name: "Specify the name of the development install component" | ||
arg: "-DBEMAN_EXEMPLAR_DEVELOPMENT_INSTALL_COMPONENT=development" | ||
- name: "Specify the name of the runtime install component" | ||
arg: "-DBEMAN_EXEMPLAR_RUNTIME_INSTALL_COMPONENT=runtime" |
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.
- name: "Enable config-file package creation?" | |
arg: "-DBEMAN_EXEMPLAR_CONFIG_FILE_PACKAGE=OFF" | |
- name: "Specify config-file package version compatibility" | |
arg: "-DBEMAN_EXEMPLAR_CONFIG_FILE_PACKAGE_COMPATIBILITY=SameMajorVersion" | |
- name: "Specify the name of the target export variant to create" | |
arg: "-DBEMAN_EXEMPLAR_TARGET_EXPORT_VARIANT=custom" | |
- name: "Specify the name of the development install component" | |
arg: "-DBEMAN_EXEMPLAR_DEVELOPMENT_INSTALL_COMPONENT=development" | |
- name: "Specify the name of the runtime install component" | |
arg: "-DBEMAN_EXEMPLAR_RUNTIME_INSTALL_COMPONENT=runtime" |
For these, I think we can just hardcode and document our APIs for now. We can come back with more targeted PRs when specific use cases arise.
- name: "Enable shared libs?" | ||
arg: "-DBEMAN_EXEMPLAR_SHARED_LIBS=ON" |
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.
- name: "Enable shared libs?" | |
arg: "-DBEMAN_EXEMPLAR_SHARED_LIBS=ON" |
Let's just use BUILD_SHARED_LIBS
as documented upstream.
- name: "Enable docs building" | ||
arg: "-DBEMAN_EXEMPLAR_BUILD_DOCS=OFF" |
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.
- name: "Enable docs building" | |
arg: "-DBEMAN_EXEMPLAR_BUILD_DOCS=OFF" |
I like supporting docs, though let's make that an entirely different PR please. Also note that we have been discussing options on this already. It's also not clear to me that we'd have CMake drive the documentation generation. The current discussion is centered around tools like mkdocs
that do not involve parsing C++ code, so there's no need to involve the C++ build system in the process.
@@ -182,6 +208,112 @@ jobs: | |||
cmake --install build --config Debug --prefix /opt/beman.exemplar | |||
ls -R /opt/beman.exemplar | |||
|
|||
target-export-variant-test: |
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.
I'll hold off on reviewing all this until we get on the same page about all the options being added to support this PR. I expect some obvious changes will be required after we sync up on the high level scope and design choices.
.github/workflows/ci_tests.yml
Outdated
test -f /opt/beman.exemplar/lib/libbeman.exemplar${{ matrix.cases.expected-library }} | ||
test -f /opt/beman.exemplar/lib/cmake/beman.exemplar/beman.exemplar-config.cmake | ||
test -f /opt/beman.exemplar/lib/cmake/beman.exemplar/beman.exemplar-version.cmake | ||
test -f /opt/beman.exemplar/lib/cmake/beman.exemplar/beman.exemplar-${{ matrix.cases.expected-variant }}-target-export.cmake | ||
test -f /opt/beman.exemplar/lib/cmake/beman.exemplar/beman.exemplar-${{ matrix.cases.expected-variant }}-target-export-release.cmake |
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.
Quick note: I like functional testing for this better. I'd rather do a full integration test in a subdir that includes a find_package(beman.exemplar REQUIRED)
in a CMakeLists.txt
and exercise that. Or use equivalent functionality in a Conan package test. Or have a vcpkg
arrangement that includes building at least one consumer package.
Those are more thorough test cases that actually represent what a user would do and ensure we didn't make any typos or whatnot while refactoring something.
I think it makes sense to have test
calls as an intermediate step I suppose. Maybe we compromise by speccing out an issue and reference the issue here?
@@ -7,27 +7,16 @@ project( | |||
# targets (e.g., library, executable, etc.). | |||
DESCRIPTION "A Beman library exemplar" | |||
LANGUAGES CXX | |||
VERSION 0.1.0 |
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.
I like having a properly set version. I'm a little out of the loop on how GitHub versioning works (or not) with respect to this kind of detail. I could see this actually being a cache variable set by a GitHub action based on a git tag?
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.
What use case are you asking here?
Do you mean substituting this field when we make a new release?
beman_install_targets( | ||
TARGETS beman.exemplar.headers beman.exemplar | ||
) | ||
|
||
beman_install_export() |
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.
beman_install_targets( | |
TARGETS beman.exemplar.headers beman.exemplar | |
) | |
beman_install_export() | |
beman_install_targets(TARGETS beman.exemplar) |
I've had a mind to introduce something like this myself, for what it's worth. I think it's a design gap in CMake upstream that there's not a clear design seam here.
That being said, I've had good luck elsewhere leaving it at only installing the library target and letting its properties and such speak for themselves. For instance the FILE_SET HEADERS
properties document that it has headers, that they are installed, where they are installed, and so on.
I would also expect that installing the beman.exemplar
module would be unconditional. It's phrased that way here since there's no if
statement! Similarly, we'll (in another PR) support pkg-config
and CPS files in the future.
… library suffix when using a custom target export variant.
This PR adds the ability to optionally create and install a config file package for the Beman exemplar project. Config file package creation and installation is enabled by default when the project is top-level. Basic usage is:
After this command, you should see the following files in
$PWD/build/cmake
.If you continue building like so, you should see the config file package and target export installed.
Notice that the target export variant name is
static
. This variant name was automatically determined based on the fact that the project was not configured to build shared libs or to use position independent code. If we configure the project to build shared libs, we get ashared
target export variant name.It's also possible to explicitly set the name of the target export variant using the
BEMAN_EXEMPLAR_TARGET_EXPORT_VARIANT
cache variable.I have not yet implemented the ability to select a specific variant when using the command
find_package(beman.exemplar)
because I wanted to get feedback on the direction up to this point. AFAIK, CMake doesn't really have explicit support for target export variants. I think there are a couple options, which are not necessarily mutually exclusive.COMPONENTS
argument offind_package
to select the desired target export variant. This is only viable if we don't want to useCOMPONENTS
for something else.BEMAN_EXEMPLAR_TARGET_EXPORT_VARIANT
BEMAN_TARGET_EXPORT_VARIANT
If the user requests a specific target export variant using either of the above methods and the specified target export variant doesn't exist, that's a hard error. If a user calls
find_package(beman.exemplar)
without doing either of the above, then the target export variant is determined as follows.beman.exemplar
.beman.exemplar
is directed to use shared libs, then the selected target export variant name isshared
.beman.exemplar
is directed to use static libs and position independent code, then the selected target export variant name isstatic-pic
.static
.We can add additional default target export names as we see fit. For example, we could add LTO variants that differ in name according to the toolchain since different compilers have incompatible LTO formats.
I designed all of this with a Beman super-build in mind. I think it's important that we be able to have a top-level
CMakeLists.txt
file that looks something like the following.