I have a header (only) file constants.h, where I define all the constant variables, to be used later in the library. However, there is one variable, which I would like to define run-time in an implementation file. I tried to do something like this:
constant.hpp
extern const unsigned int numTests;
somewhere else in run.cpp
const unsigned int numTests = 10;
and, then yet another file tester.cpp uses
if ( n < numTests) {
// do something
}
Now, when I compile it, I get a linker error in tester.o as undefined symbol numTests. I sort of understand why this is happening: the tester.cpp includes constants.hpp and not the run.cpp and so, it can not find the constant numTests initialized in run.cpp.
Is there any better way to do it?
TIA,
Nikhil
Make sure you are compiling both run.cpp and tester.cpp when you compile your program and you won't get a linker error.
You need to link run.o when creating the executable:
g++ -o tester tester.cpp run.o ; for GNU C++
(Check your own compiler's command line switches if you're not using GNU C++)
Related
So let's say we have static library mylib.a, which contains compiled cpp files.
file1.cpp:
int do_stuff();
int func_unres()
{
int a = do_stuff();
return a;
}
file2.cpp:
int do_other_stuff();
int func_res()
{
int a = do_other_stuff();
return a;
}
file3.cpp:
int do_other_stuff()
{
return 42;
}
So, as we can see here, no file contains definition of do_stuff function.
Library created this way:
g++ -c file1.cpp -o file1.o
g++ -c file2.cpp -o file2.o
g++ -c file3.cpp -o file3.o
ar r mylib.a file1.o file2.o file3.o
Now we try to make some binary with this library. Simple example main file:
#include <iostream>
int func_res();
int main()
{
std::cout << func_res() << std::endl;
}
Compiling:
g++ main.cpp mylib.a -o my_bin
Everything works just fine.
Now consider case of main file like this:
#include <iostream>
int func_unres();
int main()
{
std::cout << func_unres() << std::endl;
}
In this case binary won't link, cause func_unres requires function do_stuff to be defined.
Is there a way to find out that static library requires symbol which no object file in the library contains before linking it with executable, which uses such symbol?
EDIT:
The question is not how to simple list such symbols, but to get an output with linker like error.
Like if i linked this library with executable using all of symbols it should contain.
It seems that as pointed in comments and in How to force gcc to link an unused static library, linker option --whole-archive is enough to force resolve all symbols and output linker error for all unresolved symbols in static library. So referring the question examples, compiling and linking this way first main file, which doesn't refer undefined symbol, will output linker error anyway:
g++ main.cpp -Wl,--whole-archive mylib.a -Wl,--no-whole-archive
Linking fails despite main doesn't use func_unres:
mylib.a(file1.o): In function func_unres(): file1.cpp:(.text+0x9):
undefined reference to do_stuff()
Second option --no-whole-archive is used so the rest of required libraries' symbols will not be force resolved like this.
I'm relatively new to gcc and I'm using 'gcc (tdm-1) 5.1.0'. I've come across a very peculiar circumstance by mistake. I've shrunk my concern down to a very small reproducible example...
main.cpp
extern int g;
int main(){
return g;
}
someOtherFile.cpp
#include<windows.h>
RECT g;
this I compile with
gcc -c someOtherFile.cpp
gcc main.cpp someOtherFile.o
and this will link without error.
Am I missing something here as to why this is allowed to link?
3.5/10:
After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given variable or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic.
That last sentence means the compiler and linker are not required to give you an error message. It's your job to get it straight.
In C++ it won't link as the types of g are non-matching between main.cpp and someOtherFile.cpp. You have to have int g in someOtherFile.cpp or opposite, extern RECT g; in main.cpp.
In C this will compile and link, but on in c++.
Com compile and link as c++:
g++ -c someOtherFile.cpp
g++ -c main.cpp
g++ main.o someOtherFile.o -o test
Alternatively, you may use functions for this:
main.cpp
int g();
int main{
return g();
}
someOtherFile.cpp
#include<windows.h>
RECT r;
int g()
{
return (int)r;
}
Obviously not recommended (as there isn't much point to cast RECT to int), but that would be similar in effect to what you were trying to do.
Variable g inside someOtherFile.cpp isn't related to the other extern int g declared in main.cpp. In effect, the int g simply isn't defined anywhere and linker will fail at the end for this reason.
Apparently, this will actually compile and link by g++, while microsoft linker will error on this type of mistake.
I have a header, core/types.hh, used by several different build targets. It has the following declaration:
core/types.hh
typedef std::size_t Size;
static const Size SZ_MAX = std::numeric_limits<Size>::max();
...
Some of the targets use this constant, some don't. So I get:
error: 'core::SZ_MAX' defined but not used"
I use scons with GCC 4.7.3 on Linux. I have -Wall set and want to keep it that way.
As far as I understand from the GCC documentation, this shouldn't give a warning:
-Wunused-variable
Warn whenever a local variable or non-constant static variable is unused aside from its declaration. This warning is enabled by -Wall.
So I don't see why I get a warning (which turns into an error).
On other answers, people were advised to make the declaration extern and to do the assignment in the file that uses the constant. This file is used by many other files, so it would loose its constant-ness if I do that. Furthermore, this file has header guards, so I think this should mean that the constant is actually created only once.
I'd appreciate any help!
Yuval
Possible duplicates:
How to use typed constants with “unused variable” warnings?
c++ static array declared in h file gives warning 'defined but not used'
It seems that this was not the error that halted compilation.
Rather, if GCC find another error, it would still report on this too.
I actually had another unused variable, and that's what caused this error in the first place.
For example, when creating the following files:
file1.cc
#include "head1.hh"
int main() {
int bad_unused_variable;
return my_ns::JUST_ANOTHER_CONST;
}
head1.hh
#ifndef HEAD1
#define HEAD1
#include <stdint.h>
#include <cstddef>
#include <limits>
namespace my_ns {
typedef std::size_t Size;
static const Size SZ_MAX = std::numeric_limits<Size>::max();
static const Size JUST_ANOTHER_CONST = 8;
}
#endif
You get:
> g++ -Wall -Werror file1.cc -O2 -std=c++98 -o file1
file1.cc: In function 'int main()':
file1.cc:4:6: error: unused variable 'bad_unused_variable' [-Werror=unused-variable]
In file included from file1.cc:1:0:
head1.hh: At global scope:
head1.hh:10:20: error: 'my_ns::SZ_MAX' defined but not used [-Werror=unused-variable]
cc1plus: all warnings being treated as errors
EDIT
This also seems to have been answered here: gcc warnings: defined but not used vs unused variable - there they mention the subtle differences between the two warning messages (unused variable vs defined but not used). Still, it doesn't really answer as to why GCC behaves this way...
I've just bought a new laptop for me on the travel, then on my free time, I've started to test MinGW on it by trying to compile my own OS that is written in C++, then I've created all the files needed and the kernel.cpp:
extern "C" void _main(struct multiboot_data* mbd, unsigned int magic);
void _main( struct multiboot_data* mbd, unsigned int magic )
{
char * boot_loader_name =(char*) ((long*)mbd)[16];
/* Print a letter to screen to see everything is working: */
unsigned char *videoram = (unsigned char *) 0xb8000;
videoram[0] = 65; /* character 'A' */
videoram[1] = 0x07; /* forground, background color. */
}
And tried to compile it with g++
G:> g++ -o C:\kernel.o -c kernel.cpp -Wall -Wextra -Werror -nostdlib -nostartfiles -nodefaultlibs
kernel.cpp: In function `void _main(multiboot_data*, unsigned int)':
kernel.cpp:8: warning: unused variable 'boot_loader_name'
kernel.cpp: At global scope:
kernel.cpp:4: warning: unused parameter 'magic'
G:>
But it don't create any binary file at C:/>.
What can I do?
It doesn't create the file because you have -Werror enabled. The warnings you're getting about unused variables are counting as errors, so compilation gets aborted. Just comment them out for the moment:
void _main( struct multiboot_data* mbd, unsigned int /* magic */ )
{
// char * boot_loader_name =(char*) ((long*)mbd)[16];
// ...
}
And it should build fine. Also, shouldn't _main() be declared as just main() and then allowed to be "mangled" into _main() by the compiler? Edit: You probably also want to be using -c to skip the linking phase, assuming you just want the object files.
Did you try creating the .o file in a local directory first? What result did you get?
C:\ is usually blocked for writing on Vista and 7, since it's considered a very sensitive location, and you have to run as administrator to be allowed to do that (as in, explicitly launching the command prompt or g++ with admin rights). The same should apply if you're running on a "regular" (non-admin) user account, even in XP.
Perhaps that's what's happening to you?
I'm compiling and linking a cpp file against a pre-compiled library, and I'm getting an "undefined reference" error.
Firstly, this is the command (the library in question is quicknet3, the program I'm compiling is trapper):
g++ -w -g -I. -g -O3 -pipe -Wall -I/home/install/x86_64/include/quicknet3 -L/home/install/x86_64/lib -lquicknet3 -lintvec -lfltvec -o trapper trapper.cpp CMyException.cpp
Here's the undefined reference error:
/tmp/ccFuVczF.o: In function 'main':
trapper.cpp:1731: undefined reference to 'QN_InFtrLabStream_PFile::QN_InFtrLabStream_PFile(int, char const*, _IO_FILE*, int)'
The call in trapper.cpp (line 1731) is:
IN_PFILE = new QN_InFtrLabStream_PFile(0, "", fp, 1);
where fp is a FILE *, assigned as the result of an fopen call beforehand.
The constructor being called is defined in the relevant header file (QN_Pfile.h), as follows:
class QN_InFtrLabStream_PFile : public
QN_InFtrLabStream
{
public:
QN_InFtrLabStream_PFile(int a_debug, const char* a_dbgname, FILE* a_file, int a_indexed);
(... other declarations ...)
}
The definition of the constructor is indeed given in QN_Pfile.cc:
QN_InFtrLabStream_PFile::QN_InFtrLabStream_PFile(int a_debug,const char* a_dbgname, FILE* a_file, int a_indexed) : log(a_debug, "QN_InFtrLabStream_PFile", a_dbgname),file(a_file),indexed(a_indexed),buffer(NULL),sentind(NULL)
{
(... the usual constructor stuff :P ...)
}
I compiled the quicknet3 library myself, without error, and installed it to /home/install/x86_64/lib/libquicknet3.a
So, I can't understand why the call from trapper.cpp is unable to find the reference to this constructor definition. The g++ arguments of -L/home/install/x86_64/lib -lquicknet3 should do the trick, right?
Any ideas?
Thanks,
Roy
I notice that you're mixing FILE* and _IO_FILE*. I'm not familiar with the latter, are you sure they're one and the same?
A quick workaround is to add /home/install/x86_64/lib/libquicknet3.a to g++ commandline.
I you want to investigate further, if g++ is picking another copy of libquicknet3, you can pass -v to g++ so it will output its searching paths.
FILE is a typedef of _IO_FILE. Your linker is treating it as a unique type.
You could try:
IN_PFILE = new QN_InFtrLabStream_PFile(0, "", (FILE *)fp, 1);
to see if this resolve your constructor.
(FILE is defined in stdio.h, _IO_FILE in libio.h if you're interested)