Pep wrote: > Using g++ 3.3.6 on various linux distro's. > > I have a namespace spread over 4 source files called file1.h file1.cc > file2.h file2.cc, which are built in to a static library. My problem > is that I cannot link against the library I create. The symbols from > the library used in the main routine are rejected as undefined. I have > checked the mangled names in both the main routine and the library and > they match. > > g++ -I. -L. -ltest -o test-main main.cc > /tmp/ccuB5As0.o: In function `main': > main.cc:(.text+0x19): undefined reference to > `ns1::derived_class::derived_class()' > main.cc:(.text+0x29): undefined reference to > `ns1::derived_class::~derived_class()' > collect2: ld returned 1 exit status > > Yet if I compile and link the objects in one unit, everything is fine, > as shown by the following > > g++ -I. -o test-main main.cc file1.cc file2.cc > > ./test-main > ns1::base_class::base_class() > ns1::derived_class::derived_class() > ns1::derived_class::~derived_class() > ns1::base_class::~base_class() > > Here's the working source files that demonstrate the problem, with the > output of the build steps at the end > > // file1.h > #ifndef X__FILE1_H__X > #define X__FILE1_H__X > > namespace ns1 > { > class base_class > { > public: > base_class(); > ~base_class(); > }; > } > #endif // X__FILE1_H__X > > // file 1.cc > #include <file1.h> > > #include <iostream> > > ns1::base_class::base_class() > { > std::cout << "ns1::base_class::base_class()" << std::endl; > } > > ns1::base_class::~base_class() > { > std::cout << "ns1::base_class::~base_class()" << std::endl; > } > > // file2.h > #ifndef X__FILE2_H__X > #define X__FILE2_H__X > > #include <file1.h> > > namespace ns1 > { > class derived_class > : public base_class > { > public: > derived_class(); > ~derived_class(); > }; > } > #endif // X__FILE2_H_X > > // file2.cc > #include <file2.h> > > #include <iostream> > > ns1::derived_class::derived_class() > { > std::cout << "ns1::derived_class::derived_class()" << > std::endl; > } > > ns1::derived_class::~derived_class() > { > std::cout << "ns1::derived_class::~derived_class()" << > std::endl; > } > > // file main.cc > #include <file2.h> > > int main(int argc, char** argv) > { > ns1::derived_class object; > > return(1); > } > > file1 contains a base class called base_class which is derived in to a > class called derived_class in file2. > > main.cc contains a simple test for the problem that only instantiates > an object of derived_class. > > Here's the output of the library build step with output from nm > > g++ -c -I./ file1.cc file2.cc && ar cqsv libtest.a *.o && nm --print- > armap libtest.a > a - file1.o > a - file2.o > > Archive index: > _ZN3ns110base_classD1Ev in file1.o > _ZN3ns110base_classD2Ev in file1.o > _ZN3ns110base_classC1Ev in file1.o > _ZN3ns110base_classC2Ev in file1.o > _ZN3ns113derived_classD1Ev in file2.o > _ZN3ns113derived_classD2Ev in file2.o > _ZN3ns113derived_classC1Ev in file2.o > _ZN3ns113derived_classC2Ev in file2.o > > file1.o: > 00000046 t _GLOBAL__I__ZN3ns110base_classC2Ev > 00000000 t _Z41__static_initialization_and_destruction_0ii > 000000ca T _ZN3ns110base_classC1Ev > 000000f6 T _ZN3ns110base_classC2Ev > 00000072 T _ZN3ns110base_classD1Ev > 0000009e T _ZN3ns110base_classD2Ev > U _ZNSolsEPFRSoS_E > U _ZNSt8ios_base4InitC1Ev > U _ZNSt8ios_base4InitD1Ev > U _ZSt4cout > U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ > 00000000 b _ZSt8__ioinit > U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc > U __cxa_atexit > U __dso_handle > U __gxx_personality_v0 > 0000005e t __tcf_0 > > file2.o: > 00000046 t _GLOBAL__I__ZN3ns113derived_classC2Ev > U _Unwind_Resume > 00000000 t _Z41__static_initialization_and_destruction_0ii > U _ZN3ns110base_classC2Ev > U _ZN3ns110base_classD2Ev > 00000146 T _ZN3ns113derived_classC1Ev > 000001a4 T _ZN3ns113derived_classC2Ev > 00000072 T _ZN3ns113derived_classD1Ev > 000000dc T _ZN3ns113derived_classD2Ev > U _ZNSolsEPFRSoS_E > U _ZNSt8ios_base4InitC1Ev > U _ZNSt8ios_base4InitD1Ev > U _ZSt4cout > U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ > 00000000 b _ZSt8__ioinit > U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc > U __cxa_atexit > U __dso_handle > U __gxx_personality_v0 > 0000005e t __tcf_0 > > Here's the output of the main.cc build step with output from nm > > g++ -c -I. -o main.o main.cc && nm --print-armap main.o > U _ZN3ns113derived_classC1Ev > U _ZN3ns113derived_classD1Ev > U __gxx_personality_v0 > 00000000 T main > > I've been looking at this for some time now and am frankly stumped by > what I know must be a simple case of me not doing something I should > have but I don't know what. I blame all these RAD tools and things > like autoconf, etc because I've been so embedded in them for years > that I can't do a simple thing on the comand line, lol. > > TIA, > Pep.
Here is the "makefile" I used to build your example: ---------- # GNU Make makefile # how to make a '.o' from a '.cc'. # make will use this rule to build main.o, file1.o, and file2.o %.o: %.cc g++ -c -o $@ -I. $< # how to make 'test-main' # the pre-reqs libtest.a and main.o will be built first test-main : libtest.a main.o g++ -o $@ main.o -L. -ltest # how to make libtest.a # the pre-reqs file1.o and file2.o will be built first libtest.a : file1.o file2.o ar -rvs $@ $^ # clean up the files created by 'make' clean : -rm main.o file1.o file2.o libtest.a test-main ------------ Here is the output from the command "make": ~/x/pep> make g++ -c -o file1.o -I. file1.cc g++ -c -o file2.o -I. file2.cc ar -rvs libtest.a file1.o file2.o ar: creating libtest.a a - file1.o a - file2.o g++ -c -o main.o -I. main.cc g++ -o test-main main.o -L. -ltest Here is the output from executing "test-main": ~/x/pep> ./test-main ns1::base_class::base_class() ns1::derived_class::derived_class() ns1::derived_class::~derived_class() ns1::base_class::~base_class() So, it works for me (openSUSE 10.3, g++ v4.2.1) _______________________________________________ help-gplusplus mailing list help-gplusplus@gnu.org http://lists.gnu.org/mailman/listinfo/help-gplusplus