Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: CMake: Link to debug/release libraries in VS 2010  (Read 20808 times)

0 Members and 3 Guests are viewing this topic.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« on: April 11, 2011, 03:30:14 pm »
Hello, I try to link the SFML libraries in an executable I build with CMake. My problem is to choose the right configuration (debug/release) of the libraries. Normally, I could check CMAKE_BUILD_TYPE for this purpose.

However, Visual Studio (and maybe other IDEs) internally use both Release/Debug configurations independently of CMAKE_BUILD_TYPE. How is it possible to link "sfml-xy.lib" in Release and "sfml-xy-d.lib" in Debug mode? What do I have to pass to target_link_libraries()?

I have already looked at the SFML examples, but I haven't found out a lot. I am not used to macros, besides I don't know if the libraries are handled differently because they are built in the same CMake project as SFML itself. And is it correct that the FindSFML variable SFML_LIBRARIES always lists the Release libraries?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #1 on: April 11, 2011, 03:50:10 pm »
You can give both debug and release libraries to target_link_libraries, with the "debug" and "optimized" flags:
Code: [Select]
target_link_libraries(debug <debug libs> optimized <release libs>)

Quote
And is it correct that the FindSFML variable SFML_LIBRARIES always lists the Release libraries?

True. I guess I should add SFML_LIBRARIES_DEBUG :)
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #2 on: April 11, 2011, 04:19:17 pm »
Thanks a lot for the fast answer.

I wonder why one has to specify "debug" or "optimized" in front of each library, why they don't use "release" like everywhere else and why they don't use capital letters like everywhere else. Sometimes, CMake is a really inconsistent pain :D

Ok, I'm now trying to find out how to put the "debug"/"optimized" keyword before each library, probably foreach() and some string manipulations are necessary. But I guess it is easier if I just compose the single SFML libraries in a set() command, for debug libraries this is the only option anyway.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #3 on: April 11, 2011, 04:32:49 pm »
Quote
I wonder why one has to specify "debug" or "optimized" in front of each library

You don't have to do that ;)

Quote
why they don't use "release" like everywhere else

I guess that's because there are multiple release configurations, not all named "release", and this flag applies to all of them.

Quote
why they don't use capital letters like everywhere else

They don't, in fact you can write CMake files entirely in lower case if you want.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #4 on: April 11, 2011, 05:04:13 pm »
Quote from: "Laurent"
You don't have to do that ;)
I think I do, with only one keyword the release libs except the first one also appear at the debug linker dependencies (because they're considered "general" by default). The documentation also says:
Code: [Select]
A "debug", "optimized", or "general" keyword indicates that the library immediately following it is to be used only for the corresponding build configuration.

Quote from: "Laurent"
They don't, in fact you can write CMake files entirely in lower case if you want.
I thought only the commands are case-insensitive, but not keywords inside the commands. A capital "DEBUG" inside target_link_libraries() is interpreted as library "DEBUG.lib", but it's possible that lowercase letters are always (or mostly) allowed.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #5 on: April 11, 2011, 05:23:41 pm »
Quote
I think I do, with only one keyword the release libs except the first one also appear at the debug linker dependencies (because they're considered "general" by default).

Oh, I really thought "debug" and "optimized" were kind of switches. They should have made it like that.

Anyway, I'll improve FindSFML.CMake to provide variables that work out of the box.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #6 on: April 12, 2011, 07:02:17 pm »
Unfortunately, that's not the end of the story. I can't just assume either none or both Debug and Release configurations of the SFML libraries are available, maybe only configuration has been compiled. So I cannot list all "debug" and "optimized" libraries in target_link_libraries(), since CMake would raise an error when one library is missing.

I currently don't see an easy and proper way to address this issue. I have written the following case differentiation. Are there any problems, or is there a much better way?
Code: [Select]
# Check if library found (check sfml-system)
# Maybe I should rather use "EXISTS" here...
if(SFML_SYSTEM_LIBRARY_DEBUG STREQUAL "SFML_SYSTEM_LIBRARY_DEBUG-NOTFOUND")

# CMAKE_CONFIGURATION_TYPES is defined when generator
# can switch between configurations, like Visual Studio
if((CMAKE_BUILD_TYPE STREQUAL "Debug") AND (NOT CMAKE_CONFIGURATION_TYPES))
message(FATAL_ERROR "SFML debug libraries not found.")
endif()

else()

set(SFML_LIBS_DEBUG
debug ${SFML_SYSTEM_LIBRARY_DEBUG}
debug ${SFML_WINDOW_LIBRARY_DEBUG}
debug ${SFML_GRAPHICS_LIBRARY_DEBUG}
debug ${SFML_AUDIO_LIBRARY_DEBUG})

endif()

... # same with Release

target_link_libraries(${PROJECT_NAME} ${SFML_LIBS_DEBUG} ${SFML_LIBS_RELEASE})
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #7 on: April 12, 2011, 09:59:35 pm »
Quote
is there a much better way?

There are several options (all of them are modifications to FindSFML.cmake):
- define SFML_XXX_DEBUG = SFML_XXX if the debug version is not found (and vice versa)
- define additional variables such as SFML_DEBUG_FOUND
- define flags before invoking FindSFML.cmake to tell it what to find or not

I'll take a look at other FindXXX.cmake files to see how they handle this problem.

You should add an issue in the task tracker for this, something like "improve FindSFML.cmake to handle configurations in a better way". Or I can do it later if you prefer.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #8 on: April 12, 2011, 10:29:14 pm »
Thanks for the advice, I am going to try the mentioned points.

I added the issue to the task tracker.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #9 on: April 13, 2011, 07:54:50 am »
Thanks :)

Quote
I am going to try the mentioned points

Let me know if you find something that works well.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #10 on: April 13, 2011, 11:17:54 pm »
I have expanded FindSFML.cmake a little bit. I have added the variables SFML_RELEASE_FOUND and SFML_DEBUG_FOUND which are only true if all components of the respective configuration are found. Furthermore, I have introduced SFML_LIBRARIES_DEBUG that lists the debug libraries, and added "optimized" and "debug" keywords.
Code: [Select]
...
set(SFML_RELEASE_FOUND TRUE)
set(SFML_DEBUG_FOUND TRUE)
foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS})
    ...
    find_library(${FIND_SFML_COMPONENT_VAR}
                 NAMES ${FIND_SFML_COMPONENT_NAME}
                 PATH_SUFFIXES lib64 lib
                 PATHS ${FIND_SFML_LIB_PATHS})

    if(${FIND_SFML_COMPONENT_VAR} STREQUAL "${FIND_SFML_COMPONENT_VAR}-NOTFOUND")
        set(SFML_RELEASE_FOUND FALSE)
    endif()
   
    # debug library
    find_library(${FIND_SFML_COMPONENT_VAR}_DEBUG
                 NAMES ${FIND_SFML_COMPONENT_NAME}-d
                 PATH_SUFFIXES lib64 lib
                 PATHS ${FIND_SFML_LIB_PATHS})

    if(${FIND_SFML_COMPONENT_VAR}_DEBUG STREQUAL "${FIND_SFML_COMPONENT_VAR}_DEBUG-NOTFOUND")
        set(SFML_DEBUG_FOUND FALSE)
    endif()

    set(SFML_LIBRARIES_NAMES ${SFML_LIBRARIES_NAMES} ${FIND_SFML_COMPONENT_VAR})
    set(SFML_LIBRARIES ${SFML_LIBRARIES} ${${FIND_SFML_COMPONENT_VAR}})

    set(SFML_LIBRARIES_DEBUG_NAMES ${SFML_LIBRARIES_DEBUG_NAMES} ${FIND_SFML_COMPONENT_VAR}_DEBUG)
    set(SFML_LIBRARIES_DEBUG ${SFML_LIBRARIES_DEBUG} debug ${${FIND_SFML_COMPONENT_VAR}_DEBUG})
endforeach()

...
    FIND_PACKAGE_HANDLE_STANDARD_ARGS(SFML DEFAULT_MSG SFML_INCLUDE_DIR ${SFML_LIBRARIES_NAMES} ${SFML_LIBRARIES_DEBUG_NAMES})
...

There is a problem with the last line: At the moment, all libraries have to be found in order to set SFML_FOUND to true. I think it should be true if either the debug or the release libraries are found (and of course all other stuff like include directory).

The code on the user-side could look like the following (I didn't test it a lot, though). I haven't come across a better way to differentiate between generators allowing more than one configuration and ones that don't yet. With this code, multi-configuration generators must have access to both library types, this is hardly the best option. What behavior do you recommend?
Code: [Select]
if((NOT SFML_DEBUG_FOUND) AND (CMAKE_BUILD_TYPE STREQUAL "Debug") AND (NOT CMAKE_CONFIGURATION_TYPES))
message(FATAL_ERROR "SFML debug libraries not found.")
endif()

if((NOT SFML_RELEASE_FOUND) AND (CMAKE_BUILD_TYPE STREQUAL "Release") AND (NOT CMAKE_CONFIGURATION_TYPES))
message(FATAL_ERROR "SFML release libraries not found.")
endif()

target_link_libraries(${PROJECT_NAME} ${SFML_LIBRARIES_DEBUG} ${SFML_LIBRARIES})

I am not sure either if it is a good idea to outsource this differentiation or parts of it into the FindSFML module.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #11 on: April 14, 2011, 12:06:08 am »
I had a look at FindQt4.cmake and I like the way they handle this stuff, so I'm writing the same kind of code in FindSFML.cmake.

Basically:
- SFML_XXX_LIBRARY_DEBUG contains the debug library, or the release one if no debug version is found
- SFML_XXX_LIBRARY_RELEASE contains the release library, or the debug one if no release version is found
- SFML_XXX_LIBRARY contains both, using the "debug" and "optimized" keywords, or only one library is the other is not found
- SFML_XXX_FOUND is true if at least one of the debug/release libraries of the module is found
- SFML_LIBRARIES is the list of all SFML_XXX_LIBRARY
- SFML_FOUND is true if all SFML_XXX_FOUND are true

What do you think about it?
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #12 on: April 14, 2011, 12:26:07 am »
Quote from: "Laurent"
- SFML_XXX_LIBRARY_DEBUG contains the debug library, or the release one if no debug version is found
Why the release if no debug is found? I think when the user explicitly writes "DEBUG" he also wants the debug libraries, giving him the release ones is likely to raise errors at link, load or run time. The same applies to the RELEASE equivalent.

Quote from: "Laurent"
- SFML_XXX_FOUND is true if at least one of the debug/release libraries of the module is found
Hm... Is that often used? Doesn't the user want to know whether the library of the desired configuration is found (since sfml-window-d helps nothing for a release application)? See also the last one of the points below.

The others look okay. What about the following (with analogue DEBUG variables)?
  • SFML_LIBRARIES_RELEASE as a list of SFML_XXX_LIBRARY_RELEASE (possibly empty), with the "optimized" keyword.
  • SFML_RELEASE_FOUND maybe. But if there is an easy way to check whether SFML_LIBRARIES_RELEASE is empty, there is no need for that.
  • SFML_XXX_RELEASE_FOUND maybe if the XXX component in release configuration is found.
And concerning the multi-configuration generators, I really can't believe this is the default approach to link a library in a portable way. What is a SFML user supposed to type in his CMake file to achieve this? In my opinion, it is important to keep the user code as simple as possible. Is there a fundamental CMake mechanism I've overlooked?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CMake: Link to debug/release libraries in VS 2010
« Reply #13 on: April 14, 2011, 08:01:42 am »
Quote
Why the release if no debug is found? I think when the user explicitly writes "DEBUG" he also wants the debug libraries, giving him the release ones is likely to raise errors at link, load or run time. The same applies to the RELEASE equivalent

On Linux for example, you'll have only the release libraries installed, so you'll use them in debug mode (which is perfectly fine, unlike on Windows).

Quote
Hm... Is that often used? Doesn't the user want to know whether the library of the desired configuration is found (since sfml-window-d helps nothing for a release application)? See also the last one of the points below.

It's consistent with the rules that define the _DEBUG and _RELEASE variables, it's used when you don't care about which variant(s) of the SFML libraries are installed, as long as you've got at least one.

Quote
The others look okay. What about the following (with analogue DEBUG variables)?
- SFML_LIBRARIES_RELEASE as a list of SFML_XXX_LIBRARY_RELEASE (possibly empty), with the "optimized" keyword.
- SFML_RELEASE_FOUND maybe. But if there is an easy way to check whether SFML_LIBRARIES_RELEASE is empty, there is no need for that.
- SFML_XXX_RELEASE_FOUND maybe if the XXX component in release configuration is found.

Well, my point is: can you really check for the DEBUG libraries?
If you distribute your sources you can't require that developers compile in debug mode, or link to debug libraries in debug mode. Linking to release libraries in debug mode is an error on Windows with most compilers, but on other systems the default behaviour is often to have and use only the release libraries. It's even worse on Linux: there are no debug libraries, only debug symbols that live in a separate file.
If you explicitely handle the DEBUG libraries in your CMakeLists.txt file I think you'll make a lot of developers unhappy.
That's why I thought that Qt's strategy (using the library that is available if not both are there) is a good one.

Quote
And concerning the multi-configuration generators, I really can't believe this is the default approach to link a library in a portable way. What is a SFML user supposed to type in his CMake file to achieve this? In my opinion, it is important to keep the user code as simple as possible. Is there a fundamental CMake mechanism I've overlooked?

What are you talking about? Using the new rules I described, users would only have to link to ${SFML_LIBRARIES}.
For multi-configurations generators, the right libraries will be chosen for each config thanks to the "optimized" and "debug" flags, and for single-configuration generators... it's the same actually, CMake will pick the right one according to these flags.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
CMake: Link to debug/release libraries in VS 2010
« Reply #14 on: April 14, 2011, 06:02:14 pm »
Quote from: "Laurent"
If you explicitely handle the DEBUG libraries in your CMakeLists.txt file I think you'll make a lot of developers unhappy.
That's why I thought that Qt's strategy (using the library that is available if not both are there) is a good one.
Thanks for the explanation, as a Windows developer I'm not very experienced with this stuff on Linux.

As I see this, the problem effectively boils down to two options, of which none really satisfies all users:
[list=1]
  • Make it intuitive for Linux developers and choose the desired configuration if possible, and the other if not. This however doesn't allow a Windows developer to enforce the desired configuration. But worse is the fact that if the configuration is missing, there will occur a silent error on Windows.
  • Prevent errors on Windows and provide either the right configuration or nothing. But this makes the life of Linux users more complicated, since they need to manually check for an alternative in case of missing libraries.[/list:o]
    Quote from: "Laurent"
    What are you talking about? Using the new rules I described, users would only have to link to ${SFML_LIBRARIES}.
    Ah yes, I confused this with the current meaning of SFML_LIBRARIES and thought it would be a problem because of "-NOTFOUND" libraries in the list. But according to your post, this variable only contains the libraries of the found configuration (or both).

    By the way, how is a single missing component (e.g. sfml-window) handled, when the rest of the same configuration is available? Is the library just missing in the list, or does the variable contain the "-NOTFOUND" postfix? The latter would probably be the better choice because the error is immediately recognized.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: