-
January 7th, 2011, 12:38 AM
#1
Can't compile; two source files
I'm learning c++ from a guidebook, and one of the exercises has me build and run a project with two source files. I'm using Code::Blocks on mac 10.6. When I try to build and run, it says there are no errors, but doesn't run.
The first (main.cpp) is:
Code:
#include <iostream>
using namespace std;
void ProgRun(int choice);
int main()
{
ProgRun(3);
return 0;
}
The second (othersource.cpp) is:
Code:
#include <iostream>
using namespace std;
void ProgRun(int choice)
{
cout << "You chose: " << choice << endl;
}
I click build and run (F9), and a dialog pops up, saying "This project has not yet been built," (what!?) "Do you want to build it?"
I click yes, and nothing happens. The build log says this:
-------------- Build: Debug in MultipleSource ---------------
Linking console executable: bin/Debug/MultipleSource
Undefined symbols:
"ProgRun(int)", referenced from:
_main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings
Not sure if this is a Code::Blocks issue or not (the mac build is apparently more buggy), but their message board specifically says not to ask questions about errors during build time, so I thought it best to ask here.
(Kind of reminds me of when I had problems running xp on my mac mini; Apple wouldn't help me because it was Microsoft software, and Microsoft wouldn't help me because it was Apple hardware.)
I googled the problem as any good person would and found many results, but I'm just fresh into the c++ world, and I couldn't understand anything I found. A little help in "beginner" language would be appreciated.
Thanks in advance.
-
January 7th, 2011, 12:59 AM
#2
Re: Can't compile; two source files
The main problem is that you have not told main.cpp where to look for the function ProgRun. You've only declared it, but you haven't defined it. You would need to include the other file in main to tell it where to find that function (I'd probably just remove the:
Code:
void ProgRun(int choice);
line from main. In addition you typically include header files, not .cpp files. So, what you could do is create a header file for othersource.cpp and just put the function declaration there. Then you'd include that header file in both .cpp files.
Last edited by Alterah; January 7th, 2011 at 01:03 AM.
-
January 7th, 2011, 02:10 AM
#3
Re: Can't compile; two source files
Originally Posted by Alterah
...
Including files only tells the compiler the signature of functions so it can generate compiled code, even if it doesn't know the definition. It is the linker that then looks for the implementation, and it does not need includes.
Your recommendations are correct, but the OP's code IS well built, and should run perfectly fine.
Did you make ProgRun.cpp an actual file in your project? The file is probably open in your editor, but did you add it to the project? Your log is leading me to think that it is being ignored, hence the link error.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
January 7th, 2011, 04:35 PM
#4
Re: Can't compile; two source files
@Alterah:
In the guidebook, it shows how to make header files in the following exercise, so I assumed it would work fine without one. Just to be on the safe side, however, I skipped ahead and made a header file, linking it in both .cpp files. The result was exactly the same.
@monarch_dodra:
I checked in the folder, and the file does actually exist.
Just on a lark, I tried the exact same project on Code::Blocks under Windows 7. It worked perfectly. Clearly, a Code::Blocks issue. As for what the issue is, I don't really care right now, I just want to get back to learning. Thanks for the help anyway, though.
-
January 7th, 2011, 08:26 PM
#5
Re: Can't compile; two source files
No, it's not a Code::Blocks issue, it's a compiler/linker (gcc/ld) error.
-
January 8th, 2011, 10:37 AM
#6
Re: Can't compile; two source files
The error means that the linker cannot find the actual compiled function to run. You did not include the object file in your build. At risk of sounding harsh, it's not a Code::Blocks problem, it's a you not understanding what the linker is for and how to work it problem.
There's no shame in not understanding how something works, and now that you know what you don't understand here you can do something about it.
-
January 8th, 2011, 09:08 PM
#7
Re: Can't compile; two source files
Originally Posted by Moschops
There's no shame in not understanding how something works, and now that you know what you don't understand here you can do something about it.
Care to share what exactly it is that I should do? Am I missing a file or something?
-
January 8th, 2011, 09:52 PM
#8
Re: Can't compile; two source files
No, you're not missing any files.
Here's how it works. The preprocessor runs and in every file swaps
"#include someFile"
with the entire contents of someFile.
Then, each resulting file is compiled into object code, by the compiler. This will create a number of new files; object files.
Then, each object file is linked into the built executable or library, by the linker.
This is what enables you to call ProgRun; the actual machine code for that is in the object file built from othersource.cpp. To use ProgRun the linker must link in an object file containing this code. It is complaining that it can't find an object file containing this function. You will need to examine your tools and discover how to specify what files should be linked to, and double check that you are building the object file.
For example, if you were doing this with the ubiquitous gcc, your command line would be something like:
g++ main.cpp othersource.cpp
This works perfectly with the two files you gave in your original post. I can also do it this way, which demonstrates the complete build chain, and I also included the same error you must have made to get the error regards undefined ProgRun. The commands I typed are in bold.
Code:
j@j-desktop:~/temp/temp01$ l
total 8
-rw-r--r-- 1 j j 116 2011-01-09 02:28 main.cpp
-rw-r--r-- 1 j j 118 2011-01-09 02:26 otherSource.cpp
j@j-desktop:~/temp/temp01$ g++ -c main.cpp otherSource.cpp
j@j-desktop:~/temp/temp01$ l
total 16
-rw-r--r-- 1 j j 116 2011-01-09 02:28 main.cpp
-rw-r--r-- 1 j j 2288 2011-01-09 02:30 main.o
-rw-r--r-- 1 j j 118 2011-01-09 02:26 otherSource.cpp
-rw-r--r-- 1 j j 2800 2011-01-09 02:30 otherSource.o
j@j-desktop:~/temp/temp01$ g++ main.o -o theOutputExecutable
main.o: In function `main':
main.cpp:(.text+0xa): undefined reference to `ProgRun(int)'
collect2: ld returned 1 exit status
j@j-desktop:~/temp/temp01$ g++ main.o otherSource.o -o theOutputExecutable
j@j-desktop:~/temp/temp01$ l
total 28
-rw-r--r-- 1 j j 116 2011-01-09 02:28 main.cpp
-rw-r--r-- 1 j j 2288 2011-01-09 02:30 main.o
-rw-r--r-- 1 j j 118 2011-01-09 02:26 otherSource.cpp
-rw-r--r-- 1 j j 2800 2011-01-09 02:30 otherSource.o
-rwxr-xr-x 1 j j 9368 2011-01-09 02:31 theOutputExecutable*
j@j-desktop:~/temp/temp01$ ./theOutputExecutable
You chose: 3
You can see there that I start with the two cpp files, then I compile them both into object files, then I ask the linker to build me an executable; I did it using g++ both times, because there are a large number of standard libraries that I didn't want to have to specify by hand. The only objects I did have to specify by hand were the two I'd made myself.
To give an idea of what's going on behind the scenes when the linker does it's job, here's the path and standard library details that get used every time I run a build:
Code:
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.4.3/:/usr/lib/gcc/x86_64-linux-gnu/4.4.3/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.4.3/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.4.3/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.4.3/:/usr/lib/gcc/x86_64-linux-gnu/4.4.3/:/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../:/lib/:/usr/lib/:/usr/lib/x86_64-linux-gnu/
COLLECT_GCC_OPTIONS='-v' '-o' 'theOutputExecutable' '-shared-libgcc' '-mtune=generic'
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/collect2 --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o theOutputExecutable -z relro /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../.. -L/usr/lib/x86_64-linux-gnu main.o otherSource.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.4.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crtn.o
An awful lot of extra libraries being linked to there!
-
January 9th, 2011, 02:52 PM
#9
Re: Can't compile; two source files
Originally Posted by code:9999
I checked in the folder, and the file does actually exist.
That's what I told you, it does not matter if the file actually exits, if you don't tell your compiler to compile it. By adding the file to the project, it will be correctly compiled, and you won't have link problems.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|