5
« on: March 14, 2012, 12:36:26 pm »
Your problem is not really with SFML, in this case, your problem is that you don't seem to have a solid grasp of the compilation and linking process, so you don't know how to set things up.
This isn't really your fault. Compilation and linking is something I've never in my life seen a really good explanation of, and I think it's something that we don't learn early enough. So I'll attempt to do so here. I'll also try and explain the bugs you're encountering.
Enjoy.
----------------------------------------------------
Let's start abstract. What is a computer program?
A computer program is a file like any other. It's a string of data. Fundamentally, all computer files are exactly the same - There's no real difference between a text file and a music file and an executable file. Zeroes and ones are zeroes and ones. The distinction is in how that data is interpreted. Computer programs are strings of data designed to be interpreted as machine instructions. Data commands. Really raw instructions that your computer can follow. But it's not the code you write. The code you write is far, far different. If you've ever tried to open an executable in a text editor, this is something you can probably understand.
So, question. How does C++ code get converted into that raw binary machine code? How does hello_world.cpp become hello_world.exe?
The most common answer is "A program called a compiler turns your code into an executable". It's also, sadly, a misleading answer. It's not really a lie, it just leaves out a lot of important details. In some languages, you don't need to really know the details. C++, you do need to know the details.
First, I want to draw a distinction between an IDE and a Compiler Suite. An IDE is something like Code Blocks; Effectively little more than a glorified text editor. It has useful features like code highlighting and project management and all that jazz, but it doesn't make programs.
A Compiler Suite is something different. The keyword there is suite. Most people understand a compiler to be a single indivisible entity: A sort of black box where you put code in one end and executables pop out the other end. This is not how it actually works. Turning your source into a working binary is a multi-step process. The "correct" term for this is called the Build Process.
I'll try and break down the Build Process into its relevant steps.
The first step is called preprocessing. You know those #include lines? Those are preprocessor directives. An #include directive effectively copy-pastes code from one file into another. When you #include <iostream>, you could effectively take out that line and copy-paste the entire contents of the iostream header into your file, and it'd work exactly the same. The preprocessor is dumb. It's essentially a text filtering stage. But it's the first major step in the process.
The second major step is the actual compilation. This is where your preprocessed code actually gets converted into binary code. But that binary code, and this is the important part, is not actually your exe. What you get instead are object files, little packages of binary code. You generally get one for every source code file you have, every cpp file. But not header files. Header files exist purely to be copy-pasted into other files. They don't get compiled in and of themselves. Most of the errors you get when you build a program are in the compile stage. If you leave out a semicolon somewhere, it's the compiler that bitches at you.
Now, the final step is the most critical. It's called linking.
When you write a computer program, in 99.999% of cases, you're using code written by other people at some point. When you use cout, or vectors, or strings, or all of the other functions that "Come with" C++, you're making use of the "Standard Library". When you want to use SFML's functions for creating a window or drawing an image or (my personal favourite) sending data over a network, you're using the "Simple Fast Media Library". The key repeating word there is Library.
The binary code that your compiler outputs when it builds your program, that's the binary for the code you wrote. But what about the binary code for the stuff everybody else wrote?
The purpose of the linker is to gather up various bits of machine code, various object files and libraries, and stick them all together. This process is called linking, and the result is an executable file that you can actually run.
So you already know where your machine code is. It's the object file your compiler produces. So where is everybody else's machine code?
Well, that depends. Let me draw a distinction here between Dynamic Libraries and Static Libraries. A static library is object code (binary code) that's directly linked into your executable. When you link your program with a Static Library, all of that library's machine code is right there in the executable. SFML's static lib files are called lib-sfml-library.a, with "library" being replaced with "graphics" or "network" or "audio" or some such.
Dynamic Linking is different. See, programmers are smart. Once upon a time, somebody realized that, really, there's some machine code that's going to be used by a lot of people. When you print text on the screen, you're probably not the only program that needs that functionality. When you draw images on the screen, you're not the only program that needs that functionality. Indeed, there's a whole ton of functionality that's used by a lot of programs! A Dynamic Library is effectively this. It's a file which is actually a lot like an executable - It's binary code which is run when needed, and many programs can use it.
So where ARE these files? These are Dynamically Linked Library files. The acronym for that is DLL, and you're probably familiar with them. They're all over the place. The place you see them most is probably in your windows/system32 folder. That makes sense - There's certain binary code that a lot of windows programs use! It makes sense to put them all in one place. SFML's library files are sfml-library.dll, with, again, library usually being graphics or network or audio or system or what have you.
So now, let's steer back to your particular issue. Let's take your questions one by one.
The reason it says "your executable's directory" is because, if you link your program with dynamic libraries.. your program needs to know where those dynamic libraries are! It can't just go over your entire computer and look in every folder for sfml-system.dll. So it looks in a few key places. The first place it looks is in the folder with your executable. Actually, when you run the program from codeblocks, you're usually running the executable from your PROJECT'S folder, so that's where it'll look first. Incidentally, codeblocks has a special name for the location of your Project's folder - They call it your PATH variable. A path is another name for a string representing a folder on your computer. C:\ is a path. C:\Windows\system32 is a path. C:\Documents and Settings\VPellen\My Documents\Project Dream is a path. If that's confusing, let me know, I'll try and reiterate.
Oh, and, incidentally, there are certain folders which all the executables on your computer look in for DLLs, like your windows folder and your system32 and a few others. Those folders are defined in the Path environment variable on your computer - NOT to be confused with the Path environment variable in codeblocks, although they're called "path" for the same reason. You can modify your computer's Path environment variable in your computer's system properties, but DON'T DO THAT UNLESS YOU KNOW WHAT YOU'RE DOING - imagine what would happen if suddenly none of your programs could access all the DLLs in your system32 folder. It wouldn't be pretty.
Now, you're getting undefined reference errors. Those are linker errors. Effectively, your linker is saying "Hey, I was told to expect to find binary code for the function sf::Clock::GetElapsedTime() and a few other things, but I can't find them! That's not cool." So it spits out an error and tells you it can't link your program together.
My guess is that your search directories aren't defined properly.
When you list search directories, there are multiple tabs, for your compiler and your linker. Your compiler search directories should be the include directories for the libraries you want, because it's your compiler that uses the #include directive and such. Your linker search directories should be the lib directory, because that's where the libraries are contained.
Now there's another gotcha - Codeblocks has different "build targets". often, you want multiple "builds" of your program - a normal super fast build for when you publish your program, and a slower build called a "debug build" that lets you use debugging tools to help get rid of bugs in your program. When you're defining your include and lib directories, make sure you do it right for ALL THE BUILD TARGETS YOU NEED, not just one.
The only other thing that could be biting you in the ass is the -lsfml-system-s command - That SHOULD link your libraries, but again, make sure that it's in A: The linker options, and B: That it's set for the right target.
Tutorials are a lovely thing, but the problem is that they're often more concerned with results than education. I hope my rambling rant has been educational. If not, let me know and I'll try and clarify some things.
I'll probably go over this a few times and correct some typos, but I'll put it up now in case it's useful.
Good luck.