I been trying to create a custom command for dnf5 and following this guide exactly as is 1. DNF5 Command Template — dnf5 documentation . This is my tree structure . I didn’t modify the files at all they provided as example.
cmake_minimum_required(VERSION 3.20)
# Project name and version
project(MyDNF5Command
VERSION 1.0
DESCRIPTION "Custom DNF5 Command "
LANGUAGES CXX
)
# Set C++ standard and required features
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Set gettext domain for translations
add_definitions(-DGETTEXT_DOMAIN=\"dnf5_cmd_template\")
# Define sources and headers
set(SOURCES
main.cpp
command/template.cpp
command/template.hpp
command/arguments.hpp
)
# Add the library
add_library(template_cmd_plugin MODULE ${SOURCES})
# Disable the 'lib' prefix to create template_cmd_plugin.so
set_target_properties(template_cmd_plugin PROPERTIES PREFIX "")
# Find and link required packages
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBDNF5 REQUIRED libdnf5)
pkg_check_modules(LIBDNF5_CLI REQUIRED libdnf5-cli)
# Include directories
include_directories(${LIBDNF5_INCLUDE_DIRS} ${LIBDNF5_CLI_INCLUDE_DIRS})
# Link the default dnf libraries
target_link_libraries(template_cmd_plugin PRIVATE ${LIBDNF5_LIBRARIES} ${LIBDNF5_CLI_LIBRARIES})
# Install the plugin into the common dnf5-plugins location
install(TARGETS template_cmd_plugin LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/dnf5/plugins/)
When I build this is the Error :
-- The CXX compiler identification is GNU 14.2.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "2.3.0")
-- Checking for module 'libdnf5'
-- Found libdnf5, version 5.2.8.1
-- Checking for module 'libdnf5-cli'
-- Found libdnf5-cli, version 5.2.8.1
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: h2o/dnf5/build
❯ cmake --build .
[ 33%] Building CXX object CMakeFiles/template_cmd_plugin.dir/main.cpp.o
In file included from h2o/dnf5/command/template.hpp:3,
from h2o/dnf5/main.cpp:2:
h2o/dnf5/command/arguments.hpp:38:2: error: #endif without #if
38 | #endif // DNF_COMMANDS_DOWNLOAD_TEMPLATE_ARGUMENTS_HPP
| ^~~~~
h2o/dnf5/command/template.hpp:90:2: error: #endif without #if
90 | #endif // DNF5_COMMANDS_TEMPLATE_TEMPLATE_HPP
| ^~~~~
h2o/dnf5/command/template.hpp: In constructor ‘dnf5::TemplateCommand::TemplateCommand(dnf5::Command&)’:
h2o/dnf5/command/template.hpp:31:76: error: no matching function for call to ‘dnf5::Command::Command(dnf5::Command&, const char [9])’
31 | explicit TemplateCommand(Command & parent) : Command(parent, "template") {}
| ^
In file included from /home/mahalo/repos/dnf-purge-command/h2o/dnf5/command/arguments.hpp:4:
/usr/include/libdnf5-cli/session.hpp:91:14: note: candidate: ‘libdnf5::cli::session::Command::Command(libdnf5::cli::session::Session&, const std::string&)’
91 | explicit Command(Session & session, const std::string & name);
| ^~~~~~~
In file included from /home/mahalo/repos/dnf-purge-command/h2o/dnf5/command/template.hpp:5:
/usr/include/dnf5/context.hpp:183:43: note: inherited here
183 | using libdnf5::cli::session::Command::Command;
| ^~~~~~~
/usr/include/libdnf5-cli/session.hpp:91:32: note: no known conversion for argument 1 from ‘dnf5::Command’ to ‘libdnf5::cli::session::Session&’
91 | explicit Command(Session & session, const std::string & name);
| ~~~~~~~~~~^~~~~~~
/h2o/dnf5/main.cpp: At global scope:
/h2o/dnf5/main.cpp:5:38: error: ‘TemplateCommand’ was not declared in this scope; did you mean ‘dnf5::TemplateCommand’?
5 | register_subcommand(std::make_unique<TemplateCommand>(*this), software_management_commands_group);
| ^~~~~~~~~~~~~~~
| dnf5::TemplateCommand
h2o/dnf5/command/template.hpp:25:7: note: ‘dnf5::TemplateCommand’ declared here
25 | class TemplateCommand : public Command {
| ^~~~~~~~~~~~~~~
h2o/dnf5/main.cpp:5:20: error: expected constructor, destructor, or type conversion before ‘(’ token
5 | register_subcommand(std::make_unique<TemplateCommand>(*this), software_management_commands_group);
| ^
gmake[2]: *** [CMakeFiles/template_cmd_plugin.dir/build.make:76: CMakeFiles/template_cmd_plugin.dir/main.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/template_cmd_plugin.dir/all] Error 2
gmake: *** [Makefile:136: all] Error 2
If you’re using #pragma once, that would be at the top of each file, and there would be no#ifndef, #define, OR #endif to implement the guards.
It looks like, from those error messages, that the top of the file may have been converted to #pragma once, but the #endif at the bottom was left in.
If that’s the case (if there’s a #pragma once at the top of each header) just remove the line with the corresponding #endif (that’s even helpfully commented with the name of the guard symbol) at the bottom.
(And if that is [one of] the issue(s), and it’s present in the template, then submitting a PR to fix the template headers would surely be appreciated.)
Looking at this one, you may just need a #include <string> at the top of your template.hpp, in order for the conversion from a char* to std::string to be recognized. Or (if it’s already there), you could try being explicit about the string construction, by changing:
Oh, wait, no, never mind — my apologies, I misread the initial error. It’s not complaining about the std::string, it’s complaining about the other argument.
Your TemplateCommand constructor takes a Command & parent and passes it to libdnf5::cli::session::Command::Command, but that constructor expects a Session & as its first argument, not a Command &.
(I strongly suspect it’s the first one, because otherwise you’re effectively losing the value of parent by not storing it anywhere, which seems… unlikely. So I think the TemplateCommand(Command & parent) constructor would have to be more complex, in that case. But we’re kind of veering into guesswork now.)
For the second, I think we’d have to see the full contents of your main.cpp. The first of the two errors there was eliminated, but the second one is impossible to diagnose without context.
in the add_commands(Context & context) function, after adding a #include for your new command’s header at the top of the file.
…I’ll put together a PR to try and shore up the documentation, since this stated goal is not being met at all:
Note
This code is thought to be self explanatory. You should be able to copy the snippets, following the directory structure and naming shown above each one.
…It’s also worth pointing out: The documentation as written there is for adding a command to dnf5 itself, meaning it would be in the dnf5 repo itself. If you’re looking to write an external command defined in a plugin, that’s an entirely different beastie (and is documented in the next set of templates at 2. DNF5 Plugin Template — dnf5 documentation)
…That documentation may also be wrong/outdated, but the point is that main.cpp as discussed in the first set of templates is the actual DNF5 main.cpp, not a separate file for an external plugin. Plugins don’t use register_subcommand or context.add_and_initialize_command or anything like that, as they’re not part of the dnf5 codebase itself.
Note that for plugin purposes, we don’t want to register new commands in the dnf5/main.cpp file. Instead, we will implement the dnf5::IPlugin interface by reusing the existing boilerplate code
For how to write a plugin, a good approach is to use the source of an existing plugin (that’s built as part of dnf5 and still works, meaning the code is up to date) as a template — like dnf5-plugins/builddep_plugin.