When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.
1 messages ยท Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.

What do you know about CMake already? So we can skip all that.
Okay no problem.
Do you know what a compiler and linker are?
Close enough. Compiler takes in source code (cpp file) and emits an object file, with stubs for stuff it doesn't know about (eg functions defined in another cpp file). Linker goes through all the generated object files and fills in all the stubs, to produce the final binary: this may be a library or an executable.
That's fine, you don't need to know too much, just "compiler and linker together take in source code and produce the final binary".
As shorthand it's even fine to say, "compiler takes in source code and produces binary", as long as you're aware that the linker is involved too.
Yup!
Next tool in the pipeline: build tool / make program / etc. Do you know what these do?
(With VS solutions this thing is MSBuild.)
It basically stores build configurations, the list of source files, flags to pass to the compiler, etc. in some form, and uses that to incrementally build the project: only compiles/links stuff that's out of date.
When you were editing the project to setup SFML headers, libraries, etc, you were effectively configuring the build tool: MSBuild, which uses sln and vcxproj files to store this stuff. Similarly, when you build/run that project, it kicks off MSBuild, which reads those project files, invokes the compiler, linker as needed, runs post build scripts if any, etc.
Yup, and kicks off such a compiler instance for each source file, ideally on its own thread.
Great, now we can start talking about the problems: a project that uses such a build tool will need to commit and push those sln and vcxproj files, and will only be usable through those. This has one major downside: despite your code being standard C++, the project is locked to a single platform + build tool (+ compiler).
If eg you wanted to also support MacOS, you'd have to repeat the same steps in Xcode, generate equivalent xcodeproj files, and keep both kinds of project files always in sync manually.
And then imagine wanting to support Linux. 
At this point you've got more project files than source code... and maintaining all of them by hand is a huge pain.
Ye (MSBuild).
Yeah, in the classic CS problem solving way: by adding another layer of indirection.
As a project author you only write source code and CMake scripts, and that's what gets committed and pushed: repo is totally platform agnostic (mostly).
As a project user (aka when you build/run/debug it), you use CMake and the scripts in the project to generate a build using whatever build tool + compiler you want. And then build it. (This generation step only needs to be done the first time.)
The author can also provide configure/build presets for users, which most IDEs pick up and support directly. Users can add their own presets on top as well.
Any questions so far?
Nice, ask anything that pops into your head, even if it seems stupid.
When you're ready to start experimenting, lemme know.
Probably not, maybe CMake standalone.
In VS, go to Get Tools and Features, and check if CMake Tools is installed? If not, you'll need that.
Writing a new CMake project.
Cool!
@lime tulip are we still doing this or not?
Ah okay no prob, the thread would disappear with no activity, just ping me in here when you're back.
Yoo

Just to remind myself, the goal is to use SFML via CMake in VS, right?
Gotcha, and we covered a bit of the tools involved.
Installer, and add it to PATH when it asks.
Check this ^ too?
It should install by default these days, but best to make sure. ๐
One more gotcha: do you have MinGW installed? It can interfere with VS CMake.
Let's hope it doesn't, but worst case you'll have to uninstall it.
All good haha
For any new project, start with creating a directory somewhere that will be the project root.
Add two text files:
/
CMakeLists.txt
main.cpp
You can do this on the explorer or terminal, best not to involve the IDE yet.
In main just write int main() {} for now. The CMake script will be a little more involved, but you'll probably understand what's going on pretty easily.
Let's modify this a bit to keep things more organized:
/
CMakeLists.txt
src/
main.cpp
In the (root) CMake script, start with this as the first line:
cmake_minimum_required(VERSION 3.24)
Yep!
You can leave main empty for now as well, just have it in the right subdirectory.
Yeah, that's why I'd said not to open VS yet, but those are ok.
If you want you can start from scratch, but it doesn't matter much.
Since we aren't sharing a screen, it's easier to keep things in sync, and let me know when something odd happens, like you did.
Sure, let's just keep going.
Done this much ^?
Cool, it lets CMake know (when it reads this file) that it expects at least version 3.24.
Nice, most of the stuff you'll write will be similarly intuitive.
Next line:
project(foo)
Or whatever name you want to give it. This is only a CMake thing, it's not the name of your executable, though if you want it could be.
After that:
add_executable(fubar)
Or foo or ${PROJECT_NAME}; whatever you like.
This will be the name of the exe by default.
Exactly!
Kinda like shell variables.
Well, in bash at least, not cmd.

An important thing to mention here: you've now declared a CMake target (which happens to be an executable, could be a library too). Everything we will do in the CMake script will be via targets.
Correct!
Next, give it some sources:
target_sources(${PROJECT_NAME} PRIVATE
src/main.cpp
)
Haha, sure, thanks!
Good question!
CMake has three kinds of "visibility" / scopes for such things:
PRIVATE: only applies to this target, does not propagate to targets that link to it.INTERFACE: only applies to targets that link to it.PUBLIC: applies to both.This is an exe target, so nothing will link to it, thus everything can just be PRIVATE.
Yes you can.
I would add a new line between every line you have so far.
Well, every command. The sources one spans multiple lines.
It gets a bit more complex: a library would separate headers into a FILE_SET of sources, which would be PUBLIC, and the normal list of cpp sources, which would be PRIVATE. Basically cpp sources are always private, you only want to compile them once.
You should now be able to configure, build, and debug/run on VS. The configure part is where CMake comes into the picture: it reads the script you wrote, takes some generator options to pick the build system, compiler, etc, and generates a build. VS takes care of the generator options part here for you, and invokes CMake itself.
To trigger a manual configure, use Project > Configure ... (Don't remember exactly what it's called.)
That's right, just int main() {} for now.
VS by default will trigger an auto configure every time you save the CMake script (in VS). And of course when you open the project in the IDE. First time configuration + generation takes longer as CMake has to build its cache, subsequent ones will be much faster, until you delete the cache (do this when it gets borked).
Were you able to configure + generate? Build and debug?
Share a screenshot?
Configure Cache is the one you want.
Delete Cache and Reconfigure is for when it's borked.
Press the green play button to debug, it will build anything that's out of date.
Actually, share a screenshot of the green button drop down first?
Hmm, that's not right, the configure step seems to have failed. What's the output at the bottom?

It should configure on its own when you save, but may not since it had errored last time.
BTW you can save as often as you like, if there's something that needs to be done all at once between two saves, I'll tell you.

Check the green drop down now.
Yes! Select your brand new executable target and run it.
Great, and it should say "exited with return code 0" or something similar somewhere.
Milestone 1 achieved.
You're now using CMake, congrats. 
My pleasure!
If you use git, this would be a good time to commit.
You want to ignore all the generated files/directories: .vs and out most likely.
It's also useful to know, but you can leave it for later.
If you want to do it now, that's also fine. ๐
You can even do it through VS itself.
All right.
Next milestone is to get SFML into the build tree, so back to the CMake script.
After project, add these lines:
include(FetchContent)
FetchContent_Declare(sfml
GIT_REPOSITORY https://github.com/SFML/SFML
GIT_TAG 2.6.0
SOURCE_DIR ext/sfml
)
FetchContent_MakeAvailable(sfml)
include(FetchContent) is as dumb as you think: there's a FetchContent file somewhere in the CMake install tree, and its path is built-in, so this "header" gets copy-pasted when CMake parses your script.
FetchContent_Declare declares a remote package using the arguments. FetchContent_MakeAvailable downloads the package if it hasn't already been downloaded, and adds it to the build tree (assuming it's got a CMakeLists.txt in its root, which SFML does).
It's all good!
Basically yes.
Before we proceed, make sure Configure Cache succeeds, and if you want, check that SFML has actually been downloaded into ext/sfml.
Correct, not yet, so far we've only added it to the build tree, but foo is unaware of it. Before we get to that, let's make sure the fetching is working.
You could even try building the project (after a successful configure), and notice that it will build 100+ source files as the SFML libraries (this will only happen once, next time they will not be rebuilt).
Aha, you need to install git.
It's pretty small, should be done in a few mins. You'll probably have to restart VS for it to pick it up.
I suppose so, but I'd recommend installing it standalone as well.
64 bit pls
Yup.
Noice!
Have you checked ext/sfml?
It should be in your project root.
Yes, something like this:
/
CMakeLists.txt
src/
main.cpp
ext/
sfml/
...
Strange, where did it clone SFML then? 
Put a log message in the CMake script to make sure you're running what you think:
FetchContent_Declare(sfml
...
)
message(STATUS "Fetching SFML...")
FetchContent_MakeAvailable()
Hmm, let's remove the SOURCE_DIR ext/sfml line for now.
There is way to "fix" the problem but it's not worth getting into, better to just let it remain defaulted.
Paste your whole CMake script so far? You should only need one more command to start using SFML.
You also want to move the FetchContent stuff before add_executable.
The next command will make sense why.
target_link_libraries(${PROJECT_NAME} PRIVATE
sfml-graphics
)
Now try using SFML in main.cpp.
#include <SFML/Graphics.hpp>
int main() {
auto window = sf::RenderWindow{...};
}
Show the CMake script.
It's probably the ordering of commands.
Paste text pls, then I can just copy and fix it.
cmake_minimum_required(VERSION 3.24)
project(foo)
# deal with external dependencies first
include(FetchContent)
FetchContent_Declare(sfml
GIT_REPOSITORY https://github.com/SFML/SFML
GIT_TAG 2.6.0
)
message(STATUS "Fetching SFML...")
FetchContent_MakeAvailable(sfml)
# add target
add_executable(${PROJECT_NAME})
# set sources
target_sources(${PROJECT_NAME} PRIVATE
src/main.cpp
)
# link to SFML
target_link_libraries(${PROJECT_NAME} PRIVATE
sfml-graphics
)
The mistake was calling target_sources before the target was declared with add_executable.
Does it work now?
Ah yes, I forgot one more thing.
cmake_minimum_required(VERSION 3.24)
project(foo)
# deal with external dependencies first
include(FetchContent)
FetchContent_Declare(sfml
GIT_REPOSITORY https://github.com/SFML/SFML
GIT_TAG 2.6.0
)
message(STATUS "Fetching SFML...")
set(BUILD_SHARED_LIBS OFF) # THIS LINE
FetchContent_MakeAvailable(sfml)
# add target
add_executable(${PROJECT_NAME})
# set sources
target_sources(${PROJECT_NAME} PRIVATE
src/main.cpp
)
# link to SFML
target_link_libraries(${PROJECT_NAME} PRIVATE
sfml-graphics
)
set(BUILD_SHARED_LIBS OFF) must happen before FetchContent_MakeAvailable.
By default SFML builds dynamic libraries, this tells it to build static ones instead.

They get archived, and can be hard to find after that.
Time to learn git. ๐
To recap, the process of creating a fresh project:
Once you get the hang of CMake basics, I hope you'll agree that this is not only more portable but also a lot easier than mucking about with solutions and project files.
Haha glad to hear it!
The basics of git are quite simple, it's a way to have "checkpoints" in your progress, and the ability to go back to any of those saved checkpoints at any time.
So if you mess up while working on a project, you don't have to start from scratch or spend hours/days fixing the issue, just go back to the last checkpoint and start from there again.
Now that you have git installed you could try it, either through VS or the command line. You have bash too BTW, sort of. (Search for "git bash" in the start menu.)
It's the shell (thing you interact with on a terminal) on Linux.
Git relies on it and many other Linux tools, so the Windows distribution offers them as Windows exes that do the same thing. It also offers bash through a mintty terminal.
@lime tulip Has your question been resolved? If so, run !solved :)
You're welcome!
It will only download it if it isn't already present (downloaded before and not deleted).
@karmic stirrup
so what was the TL DR of this thread
By default it goes into the build dir, you can try using SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/ext/sfml as the fix I'd mentioned before. Remember to ignore this directory in git.
Just getting into CMake and using it to build + link to SFML.
on which os, which compiler?
l need to learn cmake also
my os is windows
l installed cmake
but l dont know how to use it
Go through this thread. 
can i give a book recommendation? ๐ Well, I will anyway. I got it from this discord when i asked the same thing. Professional Cmake https://crascit.com/professional-cmake/ it's easy reading and while im new, it has already been plenty useful for me.