I have several source files, which are compiled and linked into several executables. Some executables don't link some of the files.
I'm getting undefined reference
errors, because the calls to the missing functions are still present in the code, even though they will never happen at runtime. I'm looking for a way to disable those errors (and if the call actually happens, crashing is fine).
Ultimately, this boils down to following: (I want this code to build and run)
1.h
#pragma once
struct A
{
/*??*/ void foo();
/*??*/ void bar();
};
1.cpp
#include "1.h"
int main()
{
A a;
a.foo(); // foo!
volatile bool f = false;
if (f)
a.bar();
}
2.cpp
#include <iostream>
#include "1.h"
void A::foo() {std::cout << "foo\n";}
This obviously gives me undefined reference
errors.
I want to support MSVC, MinGW, Linux, and Emscripten.
For Linux and Emscripten, I found that adding __attribute__((__weak__))
to the declarations (at /**/
) does exactly what I want (no linker errors, calling an undefined function crashes at runtime).
For MSVC, I found this pragma: _Pragma("comment(linker, \"/alternatename:??=fallback\")")
, where ??
is the mangled name of such a function, and fallback
is the name of the fallback symbol, which can be something like extern "C" const std::nullptr_t fallback = nullptr;
.
I can use a macro to insert the function name into the pragma, so I end up with:
struct A
{
MAYBE_UNDEFINED(mangled_name_of_foo) void foo();
MAYBE_UNDEFINED(mangled_name_of_bar) void bar();
};
, which expands to the pragma on MSVC, and to __attribute__((__weak__))
otherwise.
But I'm still having issues with MinGW. Adding __attribute__((__weak__))
like on Linux doesn't work, the resulting application segfaults on a.foo();
(bug report).
It starts working if the definitions don't see __attribute__((__weak__))
(so it needs to be conditionally disabled with macros), but I really don't like the syntax.
Having to define a unique macro per source file to conditionally add __weak__
is annoying, so I'm looking for a more bearable syntax to do the same thing. Ideally just a macro I can just add to the declarations and/or definitions.
I also tried "weak aliases" on MinGW, but no cigar:
#ifndef FOO
#define FOO
#endif
struct A
{
FOO void foo();
FOO void bar();
};
Then, in a separate source file:
extern "C" void fallback() {}
#define FOO __attribute__((__weak__, __alias__("fallback")))
#include "1.h"
This still gives me undefined references, unless I add __weak__
to the declarations as well, at which point the code links, but crashes at a.foo();
(which makes it no different to not having weak aliases at all, and just leaving weak functions undefined).