How can I force GCC to compile functions that are not used? - optimization

I am splitting off some of the code in my project into a separate library to be reused in another application. This new library has various functions defined but not implemented, and both my current project and the other application will implement their own versions of these functions.
I implemented these functions in my original project, but they are not called anywhere inside it. They are only called by this new library. As a result, the compiler optimizes them away, and I get linking failures. When I add a dummy call to these functions, the linking failures disappear.
Is there any way to tell GCC to compile these functions even if they're not being called?
I am compiling with gcc 4.2.2 using -O2 on SuSE linux (x86-64_linux_2.6.5_ImageSLES9SP3-3).

You could try __attribute__ ((used)) - see Declaring Attributes of Functions in the gcc manual.

Being a pragmatist, I would just put:
// Hopefully not a name collision :-)
void *xyzzy_plugh_zorkmid_3141592653589_2718281828459[] = {
&functionToForceIn,
&anotherFunction
};
at the file level of one of your source files (or even a brand new source file, something along the lines of forcedCompiledFunctions.c, so that it's obvious what it's for).
Because this is non-static, the compiler won't be able to take a chance that you won't need it elsewhere, so should compile it in.

Your question lacks a few details but I'll give it a shot...
GCC generally removes functions in very few cases:
If they are declared static
In some cases (like when using -fno-implement-inlines) if they are declared inline
Any others I missed
I suggest using 'nm' to see what symbols are actually exported in the resulting .o files to verify this is actually the issue, and then see about any stray 'static' keywords. Not necessarily in this order...
EDIT:
BTW, with the -Wall or -Wunused-function options GCC will warn about unused functions, which will then be prime targets for removal when optimising. Watch out for
warning: ‘xxx’ defined but not used
in your compile logs.

Be careful as the -Wunused-functions doesn't warn of unused functions as stated above. It warns of ununsed STATIC functions.
Here's what the man page for gcc says:
-Wunused-function
Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is
enabled by -Wall.
This would have been more appropriate as a comment but I can't comment on answers yet.

Related

CMake compiler independent flags

Are there any compiler independent flags that can be set? I'd like to be able to set single variable to e.g. OPTIMIZE_MOST and get -O3 on gcc and /O2 in MS C++ compiler. Is there something I can use or should flags be set for each compiler separately?
Simply spoken: No, there is no flag to directly set the optimization level independently for every compiler.
However, CMake provides so called build types. Those are independent of the compiler in use and each comes with a predefined selection of flags, one of which is the optimization flag.
Available build types are
Debug
Release
RelWithDebInfo
MinSizeRel
For a comprehensive explanation, I refer to this answer. It also provides some code that helps to identify the flags in question when included into the CMakeLists.txt file:
message("CMAKE_C_FLAGS_DEBUG is ${CMAKE_C_FLAGS_DEBUG}")
message("CMAKE_C_FLAGS_RELEASE is ${CMAKE_C_FLAGS_RELEASE}")
message("CMAKE_C_FLAGS_RELWITHDEBINFO is ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message("CMAKE_C_FLAGS_MINSIZEREL is ${CMAKE_C_FLAGS_MINSIZEREL}")
message("CMAKE_CXX_FLAGS_DEBUG is ${CMAKE_CXX_FLAGS_DEBUG}")
message("CMAKE_CXX_FLAGS_RELEASE is ${CMAKE_CXX_FLAGS_RELEASE}")
message("CMAKE_CXX_FLAGS_RELWITHDEBINFO is ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message("CMAKE_CXX_FLAGS_MINSIZEREL is ${CMAKE_CXX_FLAGS_MINSIZEREL}")
To a degree. For some concepts, CMake has support for specifying them in a compiler-agnostic manner, usually by setting properties on the target in question. Unfortunately, there is no one location where all such possibilities would be listed. I went through the current list of target properties and identified the following properties as "absrtacting away build-tool option syntax":
COMPILE_PDB_NAME
INCLUDE_DIRECTORIES
INSTALL_RPATH
INTERPROCEDURAL_OPTIMIZATION
LINK_DIRECTORIES
LINK_LIBRARIES
PDB_NAME
PDB_OUTPUT_DIRECTORY
(plus the properties for setting output name, path, etc.)
There is apparently nothing for handling optimisation flags other than IPO.
To the best of my knowledge, there is also no generic process for adding these — they are added to CMake as someone finds the need for them (and the time to implement them).

Compile-time warning about missing category method implementation

In our Xcode project we have multiple targets which share some common code. Each target includes only sources which are actually used by it. So when we use some category methods inside classes which are shared between targets we need to make sure that this category implementation is also included in all targets. Xcode doesn't show any warnings during compile time or link time if we forget to include category implementation to some of the targets. And it is troublesome to do it by hand.
Is there any automated way to ensure that category implementations are included to the targets which use them?
Categories are not automatically linked to the final binary.
They are linked if the linker finds the file where they are defined is used (which was a source of constant bug some times ago).
What you can do is use a special flag on the linker: '-all_load' and '-ObjC' in Build Settings/Linking/Other Linker flags
-ObjC Loads all members of static archive libraries that implement an Objective-C class or category.
And from this discussion:
-all_load and -force_load tell the linker to link the entire static archive in the final executable, even if the linker thinks that parts
of the archive are unused.
Another way I use to force link the module is to put a C function in the file:
void _linkWithNBLogClass(void)
{
NSLog(#"%s", __FUNCTION__);
}
and call it at the start of my application:
linkWithNBLogClass();
This way, by the console feedback, I'm sure my module is loaded and ready to be used.
The described behavior is as intended and much existing code would break, if it is changed.
Prior to formal protocols there was a need to declare methods without defining them. This was for optional methods, i. e. for declaring a delegate API. The usual technique was to declare a so-called informal protocol, consisting of a category on NSObject that is never implemented.
But if you have a category implementation, of course the completeness of it is checked against the category interface. (Otherwise you get a "Method definition for X is not found" error.) So you do not have a missing method in the category implementation, but a missing category implementation.
I do not think that this is a big deal. You will get a runtime error instead of a compile time error and simply add the category implementation to the target.

GTest not finding tests in separate compilation units

I've got a program written in C++, with some subfolders containing libraries linked in. There's a top level SConscript, which calls SConscript files in the subfolders/libraries.
Inside a library cpp, there is a GTest test function:
TEST(X, just_a_passing_test) {
EXPECT_EQ(true, true);
}
There is main() in the top level program source, which just calls GTests main, and has another GTest test within it:
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
TEST(Dummy, should_pass){
EXPECT_EQ(true, true);
}
Now the issue is that when I run the program, GTest only runs the test in the main.cpp source. Ignoring the test in the library. Now it gets bizarre when I reference an unrelated class in the same library cpp in main.cpp, in a no side-effect kind of way (eg. SomeClass foo;), the test magically appears. I've tried using -O0 and other tricks to force gcc to not optimize out code that isn't called. I've even tried Clang.
I suspect it's something to do with how GTest does test discovery during compilation, but I can't find any info on this issue. I believe it uses static initialization, so maybe there's some weird ordering going on there.
Any help/info is greatly appreciated!
Update: Found a section in the FAQ that sounds like this problem, despite it referring specifically to Visual C++. Which includes a trick/hack to force the compiler to not discard the library if not referenced.
It recommends not putting tests in libraries, but that leaves me wondering how else would you test libraries, without having an executable for every one, making quickly running them a pain and with bloated output.
https://code.google.com/p/googletest/wiki/Primer#Important_note_for_Visual_C++_users
From the scene-setting one gathers that the library whose gtest test case
goes missing is statically linked in the application build. Also that the
GNU toolchain is in use.
The cause of the problem behaviour is straightforward. The test
program contains no references to anything in the library that contains
TEST(X, just_a_passing_test). So the linker doesn't need to link any
object file from that library to link the program. So it doesn't. So the
gtest runtime doesn't find that test in the executable, because it's not there.
It helps to understand that a static library in GNU format is an archive
of object files, adorned with a house-keeping header block and a global symbol table.
The OP discovered that by coding in the program an ad hoc reference to
any public symbol in the problem library, he could "magically" compel its
test case into the program.
No magic. To satisfy the reference to that public symbol, the linker is
now obliged to link an object file from the library - the one that contains
the definition of the symbol. And the OP imparts that the library is made
from a .cpp. So there is only one object file in the library, and it
contains the definition of the test case, too. With that object file in the
linkage, the test case is in program.
The OP twiddled in vain with the compiler options, switching from GCC to clang,
in search of a more respectable way to achieve the same end. The compiler is
irrelevant. GCC or clang, it gets its linking done by the system linker, ld
(unless unusual measures have been taken to replace it).
Is there a more respectable way to get ld to link an object file from a
static library even when the program refers to no symbols in that object file?
There is. Say the problem program is app and the problem static library is
libcool.a
Then the usual GCC commandline that links app resembles this, in the relevant
points:
g++ -o app -L/path/to/the/libcool/archive -lcool
This delegates a commandline to ld, with additional linker options and
libraries that g++ deems to be defaults for the system where it finds itself.
When the linker comes to consider -lcool, it will figure out this is a request
for the archive /path/to/the/libcool/archive/libcool.a. Then it will figure
out whether at this point it has still got any unresolved symbol references in hand
whose definitions are compiled in object files in libcool.a. If there are
any, then it will link those object files into app. If not, then it links
nothing from libcool.a and passes on.
But we know there are symbol definitions in libcool.a that we want to
link, even though app does not refer to them. In that case, we can tell
the linker to link the object files from libcool.a even though they are
not referenced. More precisely, we can tell g++ to tell the linker to do that,
like so:
g++ -o app -L/path/to/the/libcool/archive -Wl,--whole-archive -lcool -Wl,-no-whole-archive
Those -Wl,... options tell g++ to pass the options ... to ld. The --whole-archive
option tells ld to link all object files from subsequent archives, whether they
are referenced or not, until further notice. The -no-whole-archive tells the
ld to stop doing that and resume business as usual.
It may look as if -Wl,-no-whole-archive is redundant, as it's the last thing on the
g++ commandline. But it's not. Remember that g++ appends system default libraries
to the commandline, behind the scenes, before passing it to the ld. You definitely
do not want --whole-archive to be in force when those default libraries are linked.
(The linkage will fail with multiple definition errors).
Apply this solution to the problem case and TEST(X, just_a_passing_test)
will be executed, without the hack of forcing the program to make some no-op
reference into the object file that defines that test.
There's an obvious downside to this solution in the general case. If it happens that the library from
which we want to force linkage of some unreferenced object file contains a
bunch of other unreferenced object files that we really don't need.
--whole-archive links them all of them too, and they're just bloat in the program.
The --whole-archive solution may be more respectable that the no-op reference
hack, but it's not respectable. It doesn't even look respectable.
The real solution here is just to do the reasonable thing. If you want the
linker to link the definition of something in your program, then don't keep that a secret from
the linker. At least declare the thing in each compilation unit where you
expect its definition to be used.
Doing the reasonable thing with gtest test-cases involves understanding that
a gtest macro like TEST(X, just_a_passing_test) expands to a class definition,
in this case:
class X_just_a_passing_test_Test : public ::testing::Test {
public:
X_just_a_passing_test_Test() {}
private:
virtual void TestBody();
static ::testing::TestInfo* const test_info_ __attribute__ ((unused));
X_just_a_passing_test_Test(X_just_a_passing_test_Test const &);
void operator=(X_just_a_passing_test_Test const &);
};
(plus a static initializer for test_info_ and a definition for TestBody()).
Likewise for the TEST_F, TEST_P variants. Consequently, you can deploy these
macros in your code with just the same constraints and expectations that would
apply to class definitions.
In this light, if you have a library libcool defined in cool.h, implemented in cool.cpp
and want gtest unit tests for it, to be executed by a test program tests
that is implemented in tests.cpp, the reasonable thing is:-
Write a header file, cool_test.h
#include "cool.h" in it
#include <gtest/gtest.h> in it.
Then define your libcool test cases in it
#include "cool_test.h" in tests.cpp,
Compile and link tests.cpp with libcool and libgtest
And it's obvious why you wouldn't do what the OP has done. You would not define
classes that are needed by tests.cpp, and not needed by cool.cpp, within cool.cpp
and not in tests.cpp.
The OP was averse to the advice against defining the test cases in the library
because:
how else would you test libraries, without having an executable for every one,
making quickly running them a pain.
As a rule of thumb I would recommend the practice of maintaining a gtest executable
per library to be unit-tested: running them quickly is painless with commonplace automation tools
such a make, and it's far better to get a pass/fail verdict per library than
just a verdict for a bunch of libraries. But if you don't want to do that there's still nothing to the
objection:
// tests.cpp
#include "cool_test.h"
#include "cooler_test.h"
#include "coolest_test.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Compile and link with libcool, libcooler, libcoolest and libgtest

Getting CMake to give an error/warning about unreferenced symbols

I'm wondering how I would go about making CMake produce an error, or at least a warning, when the linker cannot find symbols that are referenced in a source file?
For example, let's say I have foo.c:
#include "bar.h" //bar.h provides bar()
void foo(void)
{
bar()
return;
}
In the case that I am building a static library, if i am not smart about how i have used my add_library() directive, the default behavior seems to be to not even give a warning that bar is an unreferenced symbols in foo's object archive file (.a)
The CMAKE_SHARED_LINKER_FLAGS compiler flags for building shared libraries should get the compiler to do what you want.
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined")
On Unix systems, this will make the linker report any unresolved symbols from object files (which is quite typical when you compile many targets in CMake projects, but do not bother with linking target dependencies in proper order).
Source: http://www.cmake.org/Wiki/CMake_Useful_Variables
There's the -z now for the GCC linker these days, but yeah, this isn't CMake's problem.
The most fool-proof way I've found only works on shared libraries, but what you do is basically write a test for each shared library and it then just does dlopen(path, RTLD_NOW) (and similar for Windows) and then use its return value as the test return value. To get a list of all shared objects, I have a wrapper function around add_library which adds all shared libraries to a global property which then is used to generate the tests dynamically. I remember there being some way to tell if a target was shared or static, but I'm not finding it the docs right now.

Can the gcc static linker properly inline functions from a static library?

If we compile a number of source codes which makes uses of a static library named lib.a, would the inline functions in lib.a get properly inlined with the rest of binaries?
no, they would not. Inlining is an operation on the parse tree and requires access to the source code for both the host and donor sources of the inlined code.
Static libraries have already been compiled from source to binary at the point you use them, so inlining cannot happen.
However, code that is not inlined is also 'proper' and will function just fine (assuming it got compiled into the static library at all).
Well, since in order to even attempt to call an inline function its declaration must be visible at the call site. If it is then inline then the compiler will either inline it or completely ignore the request.
If you are wondering if functions NOT declared inline that were inlined in the library can then also be inlined when you link to the final product...this would depend on the implementation and, assuming it is already capable of LTO (since it did it to the library), it very well might be able to inline them again. You may be required to cause the implementation to include the definition even when it's been inlined everywhere though...all depends on the implementation.
http://crazyeddiecpp.blogspot.com/2010/12/inline-functions-and-you.html