2

Is there any way to make a substring at compile time, and NOT store the original string in the binary ?

I'm using std::experimental::source_location, and really only need the filename, and not the full path, which ends up taking lots of space in the binary

Here's an example:

#include <iostream>
#include <experimental/source_location>

consteval std::string_view filename_only(
    std::experimental::source_location location = std::experimental::source_location::current())
{
    std::string_view s = location.file_name();
    return s.substr(s.find_last_of('/')+1);
}

int main()
{
    std::cout << "File: " << filename_only() << '\n';
}

https://godbolt.org/z/TqE7T87j3

The full string "/app/example.cpp" is stored, but only the file name is needed, so "/app/" is wasted memory.

Nebular Noise
  • 388
  • 3
  • 15
  • Although not really relevant to your question, what compiler are you using? – prapin Sep 26 '22 at 13:25
  • gcc-arm-none-eabi 11.2 – Nebular Noise Sep 26 '22 at 13:28
  • My guess would be that as you're using `std::string_view` which is only a reference to some original string the compiler can't get rid of the original string. If you use `std::string` instead the compiler might be able to do what you want (assuming your standard library supports constexpr std::string) – Alan Birtles Sep 26 '22 at 13:31
  • When I try to use `std::string`, I run into this error: `'location' is not a constant expression` – Nebular Noise Sep 26 '22 at 13:37
  • If you just really need to *get this done* — and it's okay to inject another tool in your toolchain — you could run the C preprocessor against your file, then post-process that output to rework the offending strings (I'd use Python, or sed, or awk, or whatever you find suitable as a post-pre-processor), then continue the rest of the compiling, assembling, and linking of the toolchain. It's an outside-the-box Big Hammer™. – Eljay Sep 26 '22 at 15:35
  • This C++ feature is still quite poorly supported, so would use it only for toy code. – Marek R Sep 27 '22 at 14:41

1 Answers1

0

Based on this, I ended up using the __FILE__ macro combined with the -fmacro-prefix-map compiler option, instead of source_location.

So I essentially use the following code

#include <cstdio>
#include <cstdint>
#define ERROR_LOG(s) log_impl(s, __FILE__, __LINE__);

void log_impl(const char* s, const char* file_name, uint16_t line)
{
    printf("%s:%i\t\t%s", file_name, line, s);
}

int main()
{
    ERROR_LOG("Uh-oh.")
}

with the following compiler option:

-fmacro-prefix-map=${SOURCE_DIR}/=/

I can verify that the constant strings stored in the binary do not include the full file path, as they did before, which was my objective.

Note that starting from GCC12, the macro __FILE_NAME__ should be available, making the use of the -fmacro-prefix-map option redundant. I'm not using gcc 12 just yet, so the solution above is adequate.

Nebular Noise
  • 388
  • 3
  • 15