I have a bunch of arm assembly, C and C++ files. gcc is trying to link them, but these are for an embedded project.
I am not using any external libraries, all code that is being used was written by me. An error seems to happen because I have a function called int kernel_main(void) defined in main.c that is trying to call set_LED(int value) defined in mailbox.cpp which includes the header mailbox.h (I did include the header in the main.c file).
The exact error is:
undefined reference to `__aeabi_unwind_cpp_pr1'
The way I am making my project is:
-compile all source files (.s, .c, .cpp) into object files (.o) without linking (-c), then link them all together with the use of a custom linker script.
Edit: I am going to add some information to make things more clear.
First changing all files so that all of them are C files (no cpp extensions) yields:
undefined reference to `set_LED'
It is unlikely that the issue itself is name mangling an it probably has nothing to do with CPP and C differences.
The problem is very likely to be a linker issue
This is the build process:
Compile c files, Example:
arm-none-eabi-g++ -O0 -march=armv8-a source/MainFiles/mailbox.cpp -nostartfiles -c -o objects/MainFiles/mailbox.o
(Compiling a C++ file would be identical except for the use of g++ instead of gcc)
Link everything:
arm-none-eabi-ld object1 object2... -o build/kernel.elf -T ./source/kernel.ld -I include_directory_1 -I include_directory_2 -L include_directory_1 -L indlude_directory_2
Include directories are all directories under the current one
Edit:
The error came back. Ignore the parts of this question relevant to name mangling. The error I need to fix is:
./objects/Hardware/mailbox.o:(.ARM.exidx+0x18): undefined reference to `__aeabi_unwind_cpp_pr1'
So far all I know is that this has something to do with unwinding the stack and exceptions. It seems the function is defined in libgcc. However I have used -nostdlib, I have omitted it, and in both cases the error persists. I have tried changing file extensions to .c whenever possible and to .cpp whenever possible, alas the error is always there.
It got fixed only as long as I had exactly 1 cpp file and the rest of my files were C files (this is no longer true, I tried). What triggered the error again was that I was refactoring the code and I wanted to move a couple of functions to new files.
In other words, without deleting a single file, declaring a function named wait(uint32_t time) in mailbox.cpp works, declaring it in a file called time.c (or cpp) with it's respective header declaration and including the header in mailbox.cpp breaks things. Note I don't delete the files when moving the function I simply delete the function declaration inside each file.
Adding a stub like this:
void __aeabi_unwind_cpp_pr1()
{
}
Fixes the problem and the code works. But I don't like this solution. I don't want a useless stub being called mysteriously in my code. I don't need nor want this function in my current implementation, how can I tell the compiler or the linker that they are to omit whatever they are doing that requires this function?
The solution is very simple. As it turns out exceptions are enabled by default (which is what generates the code that calls __eabi_unwind_cpp_pr1). To disable them all that is needed is to pass:
-fno-exceptions as an argument to the gcc/g++ compiler and the problem is solved.
You have a reference to this function that belongs to the C++ runtime of GCC. It's part of the exception handling. Whatever you are doing, sounds a little crazy, but anyway you can do this if you really know what you are doing. You must link against the C++ runtime libraries. That's it. Link against "libstdc++".
About the set_LED I also believe it's just about the C++ mangling, just as Justin J mentioned in the other answer.
I have seen this when mixing C and C++. Because of name mangling, the symbols will have different names internally depending on the type of the source file.
If the source for 'set_LED'is a c file, use the following in the header around the prototype and see if it helps.
#ifdef __cplusplus
extern "C" {
#endif
// function prototypes here
#ifdef __cplusplus
}
#endif
Please also add prefix "-shared" without quotes to -fno-exceptions. I am using ARM GCC version
Related
I'm doing the "Hello World" in the GTKMM tutorial, the "app" uses three files, the main.cc, helloworld.h and helloworld.cc.
At the beginning I thought that compiling the main.cc :
g++ -o HW main.cc $(pkg-config ... )
would be enough, but gives an error (undefined reference to Helloworld::Helloworld), etc.
In other words, it compiles the main and the header, but not the HW class, and this makes sense because the header is included in Main but not the Helloworld.cc. The thing is I'm kinda scared of including it because I read in other question that "including everything was a bad practice".
That being said, when I compile using all the files in the same command:
g++ -o HW main.cc helloworld.cc $(pkg-config ... )
the "app" works without errors.
So, since using the last command works, is compiling in this way a good practice?
What happens if my app uses a big ton of classes?
Must I manually write them all down in the command?
If not, must I use #include?
Is it good practice using #include for all cc used files?
Is normal to list all the cpp/cc files when compiling with g++?
Yes, completely.
How else will it know what source code you want it to compile?
The thing is I'm kinda scared of including it because I read in other question that including everything was a bad practice.
#includeing excess headers is bad practice.
Passing your complete source code to the compiler is not.
Is it good practice using #include for all cc used files?
Absolutely not.
What happens if my app uses a big ton of classes? Must I manually write them all down in the command?
No. You should be using a build system that handles this for you. That could be an IDE which takes all the files in your project and passes them to the compiler in turn, or it could be a CMakeLists.txt/Makefile with a *.cpp wildcard in (although I actually recommend listing source files explicitly, one-by-one; it's not hard).
Invoking g++ manually on the command-line is fine for a quick test, but for real usage you don't want to be clowning around with such machinery.
is good practice using #include for all cc used files
It's not only bad practice, never do it.
In order to create an executable you actually have to do two things:
Compile all the source code files to object files or libraries.
Link all the object files and needed libraries into an executable.
You seem to be missing the point that the link phase is where symbols defined in separate source files are resolved or linked.
Must I manually write them all down in the command?
For the compiler to know about the DEFINTION of the symbols DECLARED in your headers, you must include all source files. Exceptions to this rule can be (but are not limited to) headers containing template metaprogramming (TMP) code that usually exist entirely in header files.
What happens if my app uses a big ton of classes?
Most of the large C++ projects utilize build configuration tools such as CMAKE to handle the generation of makefiles for them.
I am using SWIG to wrap C++ code in Ruby.
I have eight classes defined in eight separate files in a specific location. I had two approaches to wrapping them in Ruby.
In the first approach, I put all the classes in one file, placed that file in the same directory as the SWIG interface file and everything is okay.
I am, however, requested to link to the original location of the files, and have my interface file in a different directory. When I compile, I compile all the files in their directory plus the wrapper code and there are no errors produced. However, I get undefined symbols.
A part of my compile shell script is:
g++ -std=c++11 -fPIC -c ../../dir1/dir2/Class.cpp
g++ -std=c++11 -fPIC -c mymodule_wrap.cxx -I/usr/include/ruby-1.9.1 -I/usr/include/ruby-1.9.1/x86_64-linux
I compile all the other seven files in the same way as the "File.cpp" one. No compilation errors.
Then, when I try the following
require 'mymodule'
c = Mymodule::Class.new
I get an undefined symbol for the Class' constructor (I demangled the undefined symbol using c++filt), which is declared and defined.
Is there something wrong in the way I compile? Or are there some problems when it comes to different locations of the header/source files and the SWIG interface file? Because this is in no way different from when I have all the classes in one file, except for the location.
EDIT:
If i move the definitions of the declared functions in the header files I get no undefined symbols. That means that it actually doesn't even reach the definitions in the cpp files. But why? When I had all classes unseparated I still kept the definitions in a cpp files and the declarations in a header file...
When creating the shared library, it didn't know where the object files of the source code were, therefore it never knew the definitions of whatever was declared in the header files.
For me, all the object files were created in the same folder as the interface file where I was compiling everything, and I added this:
g++ -shared Class.o mymodule_wrap.o -o mymodule.so
to my compile shell script. Before I was using the extconf makefile creating script, and I am not sure where it searched for the object files.
For various reasons I have been trying to compile the FANN library myself. I'm on Windows 10 with MinGW. To keep things simple I was going for something like this to start with:
g++ mushroom.c -o shroom.exe -lm -I src\ -I src\include\ src\doublefann.c
(mushroom.c includes <stdio.h> and "fann.h".)
Using the -I src\ -I src\include\ src\doublefann.c allowed me to get rid of various undefined reference errors resulting from header files not being found, but it now keeps throwing the following undefined reference:
doublefann.c:(.text+0x4ee9): undefined reference to GetTickCount()
FYI, this appears in fann.h (line 54):
/* COMPAT_TIME REPLACEMENT */
#ifndef _WIN32
#include <sys/time.h>
#else /* _WIN32 */
#if !defined(_MSC_EXTENSIONS) && !defined(_INC_WINDOWS)
extern unsigned long __stdcall GetTickCount(void);
In short, this seems to be an error with linking windows libraries, and I don't really know how to proceed so as to find the relevant ones to link.
Here is the full fann.h and the full doublefann.c
DISCLAIMERS AND NOTES
EDIT: Since going to bed last night, I refined my approach so you don't have to edit the actual FANN source files. (For the record, my original approach worked and you can look at the edit history to see what that was if you really care).
Firstly, for anyone else stumbling across this question, I should note that it's not really necessary to use FANN this way. The website provides cmake files as well as Visual Studio Solutions that both work fine.
WHATS WRONG
Looking back at the question, the problem is obvious and I hate myself for not seeing it before the first of way too many hours. You'll notice that all of the files in that command have the *.c extension. Forgive me for treating you like a novice, but I can't assume you know anything or I risk giving a bad answer. *.c is the canonical file extension for C source files. The gnu toolchain is a fairly flexible piece of software, and you can compile C code with g++ without errors most of the time. But you shouldn't, because you'll get this error. Since your source file, mushroom.c, is a C source file, it'll work for you to just compile the code as C (in this case with gcc, not g++). If, however, you're using things in your program like iostream or string or classes or any other C++ code, you're right to compile it as C++ (by convention you would change the extension then to *.cpp for clarification, but I'm not sure the GNU toolchain cares). In that case, whenever you want to include C code in your C++ program, be sure to wrap it in an extern "C"{}, so that the compiler knows the calling conventions and labels are C standard, which isn't always the same as C++ standard. This means that not only does calling C code from C++ without extern "C" risk passing arguments to functions in the wrong way (good way to cause a segfault), but the way variables and functions are renamed when compiled to assembly is different between the two languages, which is why you get Undefined Reference in the linking stage, but not the compiling stage. In this case, not only is doublefann.c a C source file (which by itself links fine), but so is the library that contains the function declaration of GetTickCount(). Specifically, you're linking to %SYSTEMROOT%\System32\kernel32.dll (normally, but I believe MinGW uses PATH_TO_MinGW\lib\lib32k.a), which defines how programs can interact with the Windows Operating System at the machine-code level. The __stdcall utility is defined here to call things like GetTickCount() from the OS, which are assembly functions, within C code. Because this is in a *.dll, the compiler cannot change __stdcall to suit C++ coventions. This is due to the fact that "dll" stands for "Dynamically Linked Library". Essentially this means that these files were already compiled into machine code when Windows (or MinGW) was installed. So editing it is nonsensical, because you'd need to have intimate working knowledge of the opcodes for every x86_64 processor ever made. Thus, calling in C will do everything in a way that __stdcall expects, but calling in C++ requires the extern "C", or it'll mangle the names of your function declaration and possibly cause runtime errors.
tl;dr
FANN is written in C, C=/=C++, so don't expect a C++ compiler to always compile C code perfectly.
Solution
There are two ways to go about solving this problem.
1
If you're using C++ features/libraries, change the name of your source code to mushroom.cpp (if you want) and change the line (wherever it occurs in your program)
#include "doublefann.c"
to be wrapped like so:
extern "C"{
#include "doublefann.c"
}
If you read through fann.h, you might have noticed the lines:
#ifdef __cplusplus //line 65
extern "C"
{
#ifndef __cplusplus
} /* to fool automatic indention engines */
#endif
#endif /* __cplusplus */
Don't worry, these don't appear to conflict. Frankly, I'm not sure what these lines are meant to accomplish, but I'm sure they know what they're doing.
2
If mushroom.c really is just pure C, just compile using:
gcc -o shroom.exe mushroom.c -lm -I src\ -I src\ -I src\include\ src\doublefann.c -Wall
and that should work. I added -Wall because I love being able to make my code absolutely perfect, feel free to leave that out it just prints every warning you could have.
ALL,
I have a DLL from which I am exporting a function. There is only one C++ file with the source code.
It turns out that I need to add a function to that source C++ file and call this function from the exported function. Unfortunately MSVC 2010 throws an error:
extern "C" declspec(__dllexport) ExportedFunc()
{
int result = Foo();
}
int Foo();
Foo(): identifier not found.
I tried to export the Foo() function but it didn't change anything.
What is the best way to fix it?
Thank you.
I think #Captain has pointed the possible error. I will just add some points that might help you deal with linking better.
It is useful to know compiler and linker errors separately. You can compile client code with -c flag that will only give errors from the compiler which includes identifier not found. These errors have nothing to do with your library and does not require the library at all. Once you clear these errors, compile without the -c flag (you can use the .o object file generated with -c flag instead of .cpp) and your library to link and make an executable.
I came across this error trying to compile a shared object from 2 sets of objects. The first set contains one .os object compiled from one cpp file generated by SWIG. The second set is contains all of the .so files from the individual files that make up the interface to be wrapped.
$g++ -shared *.os -o Mathlibmodule.so
ld: duplicate symbol std::vector<int, std::allocator<int> >::size() constin Mathlib_wrap.o and Capsule.o
The swig c++ wrapper (Mathlib_wrap.o's source file) is machine generated and nasty to look at, with lots of #defines to make it extra hard to trace. It looks like the redefinition is present in all of the object files in the second set. I've traced through the headers included in all those files, and the seem to be #pragma once'd.
What advice do people have for tracking down what/where the problem is?
I'm going to assume that you've properly #ifndef/#define blocked all of the header files in your C++ library, after that I'd check your .i file to make sure you aren't actually duplicating some declaration there somehow. Maybe try importing a small small piece of the library first or something.
I have run into issues like this before, but its always turned out to be something silly I'd done. Nothing specific I'm afraid.
Post the .i file maybe, donno.
When in doubt, assume that the error means what it says: Actual code was generated for vector<T>::size within each of those object files. This of course seems very unusual because you would expect the function to be expanded inline in each file it was being used in.
If it weren't std::vector the first thing I would say is that a function defined in a header wasn't marked inline correctly. The compiler would generate the code in each source file that included that header. What version of g++ are you using, and are you using a custom standard library/vector implementation?
One thing to check is to compile with optimization on (-O2) and see if that causes it to inline the calls within creating an actual function.
Another possibility is that you're including two different versions of the vector include, and violating the one definition rule. At that point I wouldn't rule out a linker error such as you're seeing.