Home > OS >  How to add command line option to ELF binary using cmake and gcc?
How to add command line option to ELF binary using cmake and gcc?

Time:06-16

I have a C based application and building the binary for it using cmake and make. Now, I want to show the version of my binary with something like --version flag. In the end I want to achieve ex_app -v should show the binary version. In one of the header files I could see a #define APP_VERSION "1.0" and this version number is displayed when the binary is executed. Now, I want to display this version number with -v command line option. In the existing source files there is no code for "command line options". And I am looking ways to introduce command line arguments for the binary. The binary is of ELF format compiled for GNU/Linux. I want to know if this is possible to accomplish without majorly modifying source files. Does GCC provide any option to insert version info to ELF binary file?

Thanks in advance.

P.S: I understand that this is more of discussion type post and I am looking for some hint to get started.

CodePudding user response:

You can use the CMake configure_file directive to generate a header file with APP_VERSION macro.

CMakeLists.txt:

...
configure_file(${CMAKE_SOURCE_DIR}/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h)
...

version.h.cmake:

...
#define APP_VERSION "@PROJECT_VERSION@"
...

This will take version.h.cmake (template) from your source directory, substitute @PROJECT_VERSION@ with VERSION value you set in project(...) in CMakeLists.txt and dump it into version.h file in build directory.

This is not limited to the project version, you can do this with any CMake variable. For list of CMake defined ones see cmake-variables(7).

version.h can be then included in your codebase and macro APP_VERSION used to display version with --version without need of modifying any source files (you just need to bump version in a single central place - CMakeLists.txt).

Command line arguments are passed to the program through its main() entrypoint as arguments argc (count of given arguments) and argv (array of C strings representing each argument). First argument is always the command itself. Very naive command line argument processing code example:

#include <string>
#include <iostream>
#include "version.h"
...
int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i  ) {
        std::string_view a(argv[i]);
        if (a == "-v" || a == "--version") {
            std::cout << APP_VERSION << std::endl;
        } else {
            std::cout << "unknown argument: " << a << std::endl;
        }
    }
    return 0;
}

For more complicated CLI interfaces (such as some arguments taking a value, value validation, formatting, mutual exclusion etc.) I recommend using some existing library such as CLI11.

  • Related