The solution would be to throw away all target_link_libraries() calls in SFML's CMake scriptsYou meant the sfml_static_add_libraries calls, right?
You meant the sfml_static_add_libraries calls, right?Specially that one but the others aren't actually need either.
If you remove all target_link_libraries calls then dynamic SFML libraries will produce linker errors.That's not the case on Linux, it just builds fine. Also with MinGW on Windows. Maybe MSVC works different here, can't comment on that.
That's not the case on Linux, it just builds fine. Also with MinGW on Windows. Maybe MSVC works different here, can't comment on that.Wait... how can the linker produce a binary that uses xyz functions from a library, without linking to it? What you guys say doesn't make sense, but it's probably me missing something obvious or misunderstanding you ???
g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
would become something likeg++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system -lfreetype -lglew -ljpeg -lopenal32 -lsndfile
but I'm sure that's something that won't even bother newcomers.
Just try it: Write a source file that uses an external library's function (e.g. OpenGL) and compile and link it into a library, *without* linking to that external library. It won't produce any errorsHum ok, I never noticed that. I don't know why one would do that though, except adding more work for the final user. But that's another discussion... unless you also suggest that I remove dependencies from shared libraries (which I've never seen).
we need a reference to the GLEW code. This is already included in sfml-graphics but we can't access it under certain circumstancesCan you clarify this point? Since SFML embeds GLEW, you just don't have to (or "can't" :P) link your own version of it, but the result is the same, it gets included to the final executable.
I'm sure that's something that won't even bother newcomers.The Linux example is straight-forward of course, most dependencies are already installed and are in standard paths, so it's just a matter of adding a few -lxxx. On Windows things are worse: you need to add include and linker search paths (to those extra static libs), and you need to add them in your linker settings. It's not a big deal, but for beginners who can't even follow the getting started tutorial, it will be definitely too much. And be sure to see a lot of posts concerning this on the forum.
OK, imagine theoretically, SFGUI would remove all dependencies to SFML, which means SFML isn't needed to use SFGUI, SFGUI could use GLEW on it's own because we would link against it as already mentioned so many times. What would happen if someone wanted to use SFML and this new SFGUI together? It won't work because SFML includes GLEW in sfml-graphics and (just as an example) is linked dynamically. SFGUI is also linked dynamically but needs to link in GLEW at runtime. It won't work because there will be 2 GLEWs in the final executable, the one inside SFML and the dynamically linked one.Quotewe need a reference to the GLEW code. This is already included in sfml-graphics but we can't access it under certain circumstancesCan you clarify this point? Since SFML embeds GLEW, you just don't have to (or "can't" :P) link your own version of it, but the result is the same, it gets included to the final executable.
If the libs are in the same folder as the library files themselves and the headers in the SFML header folders there will be no extra overhead. Sure placing non-SFML headers in the SFML header folders is a bit unorthodox, but if it helps newcomers, why not. It is still less strange than including everything in the static library archive. The only extra work that has to be done is a copy from the extlibs folder into the library file destination and header folders. Since you would write the script for this the newcomer won't notice any file copying or extra compiler/linker search settings.QuoteI'm sure that's something that won't even bother newcomers.The Linux example is straight-forward of course, most dependencies are already installed and are in standard paths, so it's just a matter of adding a few -lxxx. On Windows things are worse: you need to add include and linker search paths (to those extra static libs), and you need to add them in your linker settings. It's not a big deal, but for beginners who can't even follow the getting started tutorial, it will be definitely too much. And be sure to see a lot of posts concerning this on the forum.
I'm not saying I'm against the idea of handling static libs the way they should be, but a lot of people will see the disadvantages, and only a few will see the benefits.
It won't work because there will be 2 GLEWs in the final executable, the one inside SFML and the dynamically linked one.I know that, but I was asking about the "we can't access it" part. So in fact it was just another way to refer to the "different versions linked together" problem? I thought you were talking about another problem.
If the libs are in the same folder as the library files themselves and the headers in the SFML header folders there will be no extra overhead.I don't like the idea of mixing SFML and external libraries in the same folder. But yes, that could be another option, which is probably not worse than the current one I guess.
I don't like the idea of mixing SFML and external libraries in the same folder. But yes, that could be another option, which is probably not worse than the current one I guess.Or you could also just copy the extlibs folder. Sure the users would then need to specify two paths but I guess this could work out...
I know that, but I was asking about the "we can't access it" part. So in fact it was just another way to refer to the "different versions linked together" problem?Yeah it's all one and the same problem with many different names.
I don't like the idea of mixing SFML and external libraries in the same folder. But yes, that could be another option, which is probably not worse than the current one I guess.Understandable, however it's already the same with the DLLs that have to be shipped with SFML in order for it to work, like sndfile and OpenAL. The user has to know that those must be copied to the final executable -- and I don't see a lot of postings on the forum asking why the program crashes with asking about a DLL.
Like binary said, the advantage of the .lib files is that those can be simply copied to SFML's lib directory, i.e. where the sfml-* libraries are saved to, and the user doesn't has to add any more linker and/or compiler search paths (considering that headers of external libraries also also added to SFML's include directory).But it automatically creates a conflict if the user has its own version of one library in another search path.
[...]in my opinion telling/teaching them the right way is better than going for an easy approach with accepting that fatal bugs might happen.
This is the famous /usr/local directory many Linux distros come with and make use of. AFAIR /usr/local is checked before /usr and as such it should work as expected.Correct, however afaik the most used distribution, our beloved Ubuntu, changed that. /usr/local/ isn't included in $PATH anymore. Cheers! ;)
Such a change would indeed require the end-user to link to all the deps himself, but in my opinion telling/teaching them the right way is better than going for an easy approach with accepting that fatal bugs might happen.I'd like this, personally. Is it possible for it to be a CMAKE option? To me that would be a win-win.
to see whether the extra configuration steps are reasonable or not.Keep in mind the modifications aren't for being pro, but eliminating serious problems. ;)
SFML is now in a state where it can't be built static with or without static runtime libraries on Windows with any MinGW versionAs in: can't be built static by MinGW at all?
Phew "wasted" 3 days to track this issue down...I'm giving you a considerable amount of brag-rights-currency for tracking that down.
As in: can't be built static by MinGW at all?You can build the lib, but once you try to link the window and the system module and invoke winmm calls in each library ld will crash.
But what exactly happens now? What is the error?There is no error, it simply crashes ld, i.e. the linker itself.
Making only sfml-system link to winmm, will resolve the crashingBut sfml-window does depend on winmm, I can't remove the dependency. It would get linked to it through sfml-system only in the case of static build.
True, so... :PQuoteMaking only sfml-system link to winmm, will resolve the crashingBut sfml-window does depend on winmm, I can't remove the dependency. It would get linked to it through sfml-system only in the case of static build.
a ticking time bomb if you willAnd it took only 1 year. Yaay. ;D
:'(That post made me lol, serious discussion and then suddenly post with just that from Laurent.
If we use the pre-compiled binaries, then...they're already compiled, and we don't have to link SFML's dependencies, just SFML itself. Right?No. After the change you'll have to link SFML dependencies as well when you link SFML statically. Because when you build a static library, there's no link step, it's just an archive of compiled files. Linking only happens in the user project, so that's the only place where all dependencies can be linked.
SFML Libraries:
+-----------+ +-----------+
| Library A | | Library B |
| | | |
| Depends: | | Depends: |
| opengl32 | | gdi32 | ...
| winmm | | winmm |
| ... | | ... |
| | | |
+-----------+ +-----------+
During building SFML statically, ar rcs does this:
+-----------+ +-----------+ +-----------+ +-----------+
| Library A | | winmm | | opengl32 | | Library A |
| | | | | | | |
| | | | | | | Lib A |
| symbols | + | symbols | + | symbols | = | symbols |
| | | | | | | |
| | | | | | | |
| | | | | | | |
+-----------+ +-----------+ +-----------+ + - - - - - +
| |
| |
| opengl32 |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| winmm |
| symbols |
| |
| |
| |
+-----------+
+-----------+ +-----------+ +-----------+ +-----------+
| Library B | | winmm | | gdi32 | | Library B |
| | | | | | | |
| | | | | | | Lib B |
| symbols | + | symbols | + | symbols | = | symbols |
| | | | | | | |
| | | | | | | |
| | | | | | | |
+-----------+ +-----------+ +-----------+ + - - - - - +
| |
| |
| gdi32 |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| winmm |
| symbols |
| |
| |
| |
+-----------+
When linking to both Library A and Library B statically ld does this:
+-----------+ +-----------+ +-----------+ +-----------+
| Program | | Library A | | Library B | | Program |
| | | | | | | |
| Program | | Lib A | | Lib B | | Program |
| symbols | + | symbols | + | symbols | = | symbols |
| | | | | | | |
| | | | | | | |
| | | | | | | |
+-----------+ + - - - - - + + - - - - - + + - - - - - +
| | | | | |
| | | | | |
| opengl32 | | gdi32 | | Lib A |
| symbols | | symbols | | symbols |
| | | | | |
| | | | | |
| | | | | |
+ - - - - - + + - - - - - + + - - - - - +
| | | | | |
| | | | | |
| winmm | | winmm | | Lib B |
| symbols | | symbols | | symbols |
| | | | | |
| | | | | |
| | | | | |
+-----------+ +-----------+ + - - - - - +
| |
| |
| opengl32 |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| gdi32 |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| |
| winmm | <-----+
| symbols | |
| | |
| | ld sends
+ - - - - - + it's regards
| | and crashes
| | |
| | |
| winmm | <-----+
| symbols |
| |
| |
+-----------+
We want this to happen when linking SFML libraries statically:
+-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+
| Program | | Library A | | Library B | | opengl32 | | gdi32 | | winmm | | Program |
| | | | | | | | | | | | | |
| Program | | Lib A | | Lib B | | opengl32 | | gdi32 | | winmm | | Program |
| symbols | + | symbols | + | symbols | + | symbols | + | symbols | + | symbols | = | symbols |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
+-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ + - - - - - +
| |
| |
| Lib A |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| Lib B |
| symbols |
| |
| |
| | ld is happy and gives us our executable
+ - - - - - +
| |
| |
| opengl32 |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| gdi32 |
| symbols |
| |
| |
| |
+ - - - - - +
| |
| |
| winmm |
| symbols |
| |
| |
| |
+-----------+
In static build, SFML does the linking of all it's dependencies for you, just for your convenience, at the expense of not conforming to convention. You could say it pretends to be GLEW, winmm and all those other libraries, so your linker won't complain when you don't link to them yourself. Now you can just include just the SFML libraries and your application will happily build. In the system we want, you will have to link to those libraries yourself, because SFML won't pretend to be them any more (this is overly simplified but I hope you get the point).Now my concern is purely practical. Sticking to Windows here (on Linux the precompiled binaries never worked for me anyway so I had to compile from source there), would the list of library names we have to tell Visual C++ to link against be a constant? Or would we have to worry about different lists of libraries depending on what iteration of Windows we have?It shouldn't change as long as SFML doesn't add/change dependencies.
P.S.: How do most C++ devs learn this stuff? Every textbook/tutorial/class/guide I've seen/used for people new to C++ says NOTHING about pragmatic linking issues (they define conceptually linking but never mention what's involved in linking to other people's code). So did you all have to learn this stuff through aimless googling and asking stupid questions on forums?Well I'm not sure if there are "C++ books" that teach such things in depth, but there are official documents of compilers and alike in the internet. Yes they are hard to read, but they'll teach you about anything you would ever want to know or even more.
This means in your project linker settings, you will need to specify opengl32 gdi32 winmm glew openal etc. But this is such wide-spread convention every C++ programmer is expected to know and understand how to do this already.I don't remember doing this all the time, for a lot of libraries it's fine to link a single target (but maybe it's because I linked dynamically). Specifying all the low-level libraries is annoying even for non-beginners, because you have to memorize implementation details (that may even change over versions).
So did you all have to learn this stuff through aimless googling and asking stupid questions on forums?MSDN is a good source for Windows-related development. I also learned a lot with Thor and its CMake configuration. But CMake itself was quite a pain to learn, because I hardly found clean, bigger examples...
I don't remember doing this all the time, for a lot of libraries it's fine to link a single target (but maybe it's because I linked dynamically). Specifying all the low-level libraries is annoying even for non-beginners, because you have to memorize implementation details (that may even change over versions).On Windows, for development of Windows applications that open up a window and do stuff interacting with the operating system, it doesn't matter what library you use, you will always need to link against winmm user32 gdi32 etc. So it isn't really a matter of memorizing implementation details (because it is always present regardless of library used), it's because the Windows executable loader doesn't do it for you automatically. On Linux and I guess OS X you need to do the same, randr X11 etc. So it's really just boilerplate, and has nothing specific to do with SFML. If you specify more than you need, the linker will just discard the superfluous stuff. But really... boilerplate project settings is something that I don't want to start complaining about ;) It is an O(1) operation after all. A simple solution to this would be to provide templates for the popular IDEs that SFML already has support for in its tutorials. It would be a welcome addition :).
Don't forget that on Windows, it's not unusual to make use of automatic linking. Boost does this for example, and it might also be something to consider for SFML.Correct me if I'm wrong, but this automatic linking you refer to, wouldn't be that #pragma lib directive we've all seen would it? If so, this isn't portable since it isn't supported by GCC. See the note here (http://www.boost.org/doc/libs/1_54_0/more/getting_started/windows.html#link-your-program-to-a-boost-library). Don't know if clang breaks tradition and has support for it or not.
Correct me if I'm wrong, but this automatic linking you refer to, wouldn't be that #pragma lib directive we've all seen would it? If so, this isn't portable since it isn't supported by GCC.Ok, then at least provide it for Visual Studio users. The g++ guys should finally introduce something like that, too :P
I don't remember doing this all the time, for a lot of libraries it's fine to link a single target (but maybe it's because I linked dynamically). Specifying all the low-level libraries is annoying even for non-beginners, because you have to memorize implementation details (that may even change over versions).As said before you still can do things as always with dynamic linking. Only static linking is affected by these changes.
Don't forget that on Windows, it's not unusual to make use of automatic linking. Boost does this for example, and it might also be something to consider for SFML.What do you mean with "automatic linking"?
What do you mean with "automatic linking"?#pragma comment(lib,"somelibyouwannadd.lib") probably, headers that have this pragma and add libs to libs list. Boost does that on visual so you don't have to type something that looks like boost_fs_vs10_hello_man_what_up_1_53_lib_static.lib all the time.
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib
They are under "inherited values" so I guess they are part of the default configuration Visual Studio applies to all projects. Who thought a simple Hello World application could tax the linker this much? ;)
Do you plan to update FindSFML.cmake, such that the SFML_LIBRARIES variable also contains the dependencies? Or maybe create a new variable?It seems like a good idea.
It compiles and runs just fine - but I might be doing too muchIf you link all SFML modules then the list seems to be the same as mine. ;)
2. FindSFML.cmake finds the dependencies and provides full paths -> what if user wants to use its own version of a library?This looks like the way to go.
We should definitely find a solution quickly, I'm currently stuck with CSFML which is exactly in this case: it links SFML statically and uses FindSFML.cmake ;DI've noticed, since I can't build my Nightly Builds for CSFML either. ;D