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

Author Topic: FindSFML.cmake update suggestion  (Read 6613 times)

0 Members and 1 Guest are viewing this topic.

Dúthomhas

  • Newbie
  • *
  • Posts: 6
    • View Profile
FindSFML.cmake update suggestion
« on: August 25, 2013, 07:48:37 am »
Hello everyone! First time poster here, so here goes.

...rambling about why I'm doing this goes here, but thoughtfully omitted for your viewing pleasure...

Description of Problem
I've been trying to use cmake to compile a little project of mine on both Windows 7 and Fedora 19... and I have run into an apparently common problem:

Quote
CMake Error at /usr/share/cmake/Modules/FindSFML.cmake:199 (message):
  Could NOT find SFML (missing: SFML_GRAPHICS_LIBRARY SFML_WINDOW_LIBRARY
  SFML_SYSTEM_LIBRARY)
Call Stack (most recent call first):
  CMakeLists.txt:6 (find_package)

The common answer is that the libs are installed in some non-standard location. But I had already taken extra pains to make sure that they were exactly where they belonged... so something else was wrong.

After inspecting Laurent's FindSFML.cmake plugin, and considering why it wasn't finding my libraries, I discovered the problem. Here's a hint: the libraries that yum installed for me are these:

Code: [Select]
/usr/lib/libsfml-audio-2.0.so@     /usr/lib/libsfml-graphics.so.2.0*  /usr/lib/libsfml-system.so.2@
/usr/lib/libsfml-audio.so.2@       /usr/lib/libsfml-network-2.0.so@   /usr/lib/libsfml-system.so.2.0*
/usr/lib/libsfml-audio.so.2.0*     /usr/lib/libsfml-network.so.2@     /usr/lib/libsfml-window-2.0.so@
/usr/lib/libsfml-graphics-2.0.so@  /usr/lib/libsfml-network.so.2.0*   /usr/lib/libsfml-window.so.2@
/usr/lib/libsfml-graphics.so.2@    /usr/lib/libsfml-system-2.0.so@    /usr/lib/libsfml-window.so.2.0*
Do you see what is unusual and/or missing about them?

Answer: there is no, eg. "libsfml-audio.so". They all have some version information attached to them. I suspect this is the common cause of a lot of problems people are reporting about cmake.

The Fix
The issue is on lines 139 and 145 of FindSFML.cmake. There is only one name given in the NAMES list, and it does not have any version information attached. This may be correct, but as people may have naming stuff added to their default installs (as I did on Fedora), and as is reasonable for SFML 2.x stuff, the fix is to add in names for any possible match. Stuff I considered possible are things like

  sfml-audio
  sfml-audio-2    sfml-audio2
  sfml-audio-2.0  sfml-audio2.0
  sfml-audio-20   sfml-audio20

I do not know how to apply for stuff appearing after .so (nothing should ever appear after .dll or .lib on Windows), but I suspect that ought to cover all cases... though I don't really know enough to say for sure.

In any case, here's the updated portions, starting with line 137:

Code: [Select]
    # debug library
    find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
                 NAMES ${FIND_SFML_COMPONENT_NAME}-d
                       ${FIND_SFML_COMPONENT_NAME}-d-${SFML_VERSION_MAJOR}
                       ${FIND_SFML_COMPONENT_NAME}-d-${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
                       ${FIND_SFML_COMPONENT_NAME}-d-${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
                       ${FIND_SFML_COMPONENT_NAME}-d${SFML_VERSION_MAJOR}
                       ${FIND_SFML_COMPONENT_NAME}-d${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
                       ${FIND_SFML_COMPONENT_NAME}-d${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
                 PATH_SUFFIXES lib64 lib
                 PATHS ${FIND_SFML_LIB_PATHS})

    # release library
    find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
                 NAMES ${FIND_SFML_COMPONENT_NAME}
                       ${FIND_SFML_COMPONENT_NAME}-${SFML_VERSION_MAJOR}
                       ${FIND_SFML_COMPONENT_NAME}-${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
                       ${FIND_SFML_COMPONENT_NAME}-${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
                       ${FIND_SFML_COMPONENT_NAME}${SFML_VERSION_MAJOR}
                       ${FIND_SFML_COMPONENT_NAME}${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
                       ${FIND_SFML_COMPONENT_NAME}${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
                 PATH_SUFFIXES lib64 lib
                 PATHS ${FIND_SFML_LIB_PATHS})

Now cmake finds everything for me properly. Please update the SFML sources with this. And...

Hope this helps.

Sonkun

  • Full Member
  • ***
  • Posts: 241
    • View Profile
Re: FindSFML.cmake update suggestion
« Reply #1 on: August 25, 2013, 11:07:06 am »
I don't know why you're having your libraries ending in @. Which arch do you have? x86 or x64 ?

If you environement was clean, you should have ran into another issue: the inability for you system to find SFML headers (since they've been messy and have renamed SFML/ to SFML-2.0/ in order to keep SFML 1.6, which was a stupid idea).

Without any more information, the only thing I can advise is, clean your environement and install SFML from source... or wait for the packages to be fixed.

Clean your environement:
sudo yum remove SFML* compat-SFML*

sudo rm -r /usr/include/SFML/*
sudo rm -r /usr/local/include/SFML/*

sudo rm /usr/lib/libsfml-*
sudo rm /usr/lib64/libsfml-*
sudo rm /usr/local/lib/libsfml-*
sudo rm /usr/local/lib64/libsfml-*
« Last Edit: August 25, 2013, 12:13:43 pm by Sonkun »
Interested in using SFML with Python ? Try out its Python binding!

Dúthomhas

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: FindSFML.cmake update suggestion
« Reply #2 on: August 25, 2013, 04:56:45 pm »
The @, *, and / are all standard *nix stuff when you ask for a directory listing with ls -CF.

And I told you, I took extra pains to make sure that things were where they belonged to be -- meaning I have a symlink at /usr/include/SFML/ --> /usr/include/SFML-2.0/SFML/.

I actually forgot about that... hmm. The stuff that finds the headers should also be fixed then...

Sonkun

  • Full Member
  • ***
  • Posts: 241
    • View Profile
Re: FindSFML.cmake update suggestion
« Reply #3 on: August 25, 2013, 05:30:26 pm »
Quote
The @, *, and / are all standard *nix stuff when you ask for a directory listing with ls -CF.
Alright, I didn't know that but if you use a regular ls, *.so files will show up, so they do exist. And I had no problem using FindSFML.cmake to compile CSFML  so I guess you set up something wrong.

The only mistake is CMake which doesn't install SFML libraries in the right directory on x64 systems. So, on Fedora x86_64, there's an extra step:
cd SFML-2.1
cmake
make
sudo make install
sudo mv /usr/local/lib/libsfml-* /usr/local/lib64
sudo ldconfig
Interested in using SFML with Python ? Try out its Python binding!

Dúthomhas

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: FindSFML.cmake update suggestion
« Reply #4 on: August 25, 2013, 06:17:20 pm »
And I had no problem using FindSFML.cmake to compile CSFML  so I guess you set up something wrong.
I don't wish to be rude, but again you assume.

The way I installed SFML is with the official repositories
yum install SFML-devel

This placed all the headers in /usr/include/SFML-2.0/SFML, and all the shared libs in /usr/lib (i686) and /usr/lib64 (x32_64). Once installed, pkg-config works correctly on both systems.

So my system is not misconfigured. So can we get past this point? The issue is with FindSFML.cmake.

Here's the current version I am using. I am still a little bewildered by CMake (I haven't needed it on Windows), so I don't know if this correct enough to find a requested version over some other version first. You'll notice the two major changes are
  • finding the include directory and adding it to the compiler's path
  • finding the library libs
Yum does not install static SFML libs, so I haven't played with static linkage. (Though I probably will on Windows, since the whole point is that I'm using this to compile my own programs cross-platform now.)

Code: [Select]
# This script locates the SFML library
# ------------------------------------
#
# Usage
# -----
#
# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main).
# If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing.
# example:
#   find_package(SFML COMPONENTS graphics window system) // find the graphics, window and system modules
#
# You can enforce a specific version, either MAJOR.MINOR or only MAJOR.
# If nothing is specified, the version won't be checked (ie. any version will be accepted).
# example:
#   find_package(SFML COMPONENTS ...)     // no specific version required
#   find_package(SFML 2 COMPONENTS ...)   // any 2.x version
#   find_package(SFML 2.4 COMPONENTS ...) // version 2.4 or greater
#
# By default, the dynamic libraries of SFML will be found. To find the static ones instead,
# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...).
# In case of static linking, the SFML_STATIC macro will also be defined by this script.
# example:
#   set(SFML_STATIC_LIBRARIES TRUE)
#   find_package(SFML 2 COMPONENTS network system)
#
# On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless
# CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details.
# Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which
# are available for both release and debug modes.
#
# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable
# to tell CMake where SFML is.
#
# Output
# ------
#
# This script defines the following variables:
# - For each specified module XXX (system, window, graphics, network, audio, main):
#   - SFML_XXX_LIBRARY_DEBUG:   the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found)
#   - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found)
#   - SFML_XXX_LIBRARY:         the name of the library to link to for the xxx module (includes both debug and optimized names if necessary)
#   - SFML_XXX_FOUND:           true if either the debug or release library of the xxx module is found
# - SFML_LIBRARIES:   the list of all libraries corresponding to the required modules
# - SFML_FOUND:       true if all the required modules are found
# - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file)
#
# example:
#   find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED)
#   include_directories(${SFML_INCLUDE_DIR})
#   add_executable(myapp ...)
#   target_link_libraries(myapp ${SFML_LIBRARIES})

# define the SFML_STATIC macro if static build was chosen
if(SFML_STATIC_LIBRARIES)
    add_definitions(-DSFML_STATIC)
endif()

# deduce the libraries suffix from the options
set(FIND_SFML_LIB_SUFFIX "")
if(SFML_STATIC_LIBRARIES)
    set(FIND_SFML_LIB_SUFFIX "${FIND_SFML_LIB_SUFFIX}-s")
endif()

# find the SFML include directory
# (Due to non-relative paths in the SFML source itself, the only
#  potential SFML path version number variations are as follows...)
find_path(SFML_INCLUDE_DIR /SFML/Config.hpp
          PATH_SUFFIXES include/SFML-${SFML_FIND_VERSION_MAJOR}
                        include/SFML-${SFML_FIND_VERSION_MAJOR}.${SFML_FIND_VERSION_MINOR}
                        include/SFML-${SFML_FIND_VERSION_MAJOR}${SFML_FIND_VERSION_MINOR}
                        include/SFML${SFML_FIND_VERSION_MAJOR}
                        include/SFML${SFML_FIND_VERSION_MAJOR}.${SFML_FIND_VERSION_MINOR}
                        include/SFML${SFML_FIND_VERSION_MAJOR}${SFML_FIND_VERSION_MINOR}
                        include
          PATHS
          ${SFML_ROOT}
          $ENV{SFML_ROOT}
          ~/Library/Frameworks
          /Library/Frameworks
          /usr/local/
          /usr/
          /sw          # Fink
          /opt/local/  # DarwinPorts
          /opt/csw/    # Blastwave
          /opt/)
         
# make sure that the found path is in the compiler's path
include_directories("${SFML_INCLUDE_DIR}")

# check the version number
set(SFML_VERSION_OK TRUE)
if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
    # extract the major and minor version numbers from SFML/Config.hpp
    # we have to handle framework a little bit differently :
    if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework")
        set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp")
    else()
        set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp")
    endif()
    FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS)
    STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}")
    STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}")
    STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}")
    math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10 + ${SFML_FIND_VERSION_MINOR}")

    # if we could extract them, compare with the requested version number
    if (SFML_VERSION_MAJOR)
        # transform version numbers to an integer
        math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10 + ${SFML_VERSION_MINOR}")

        # compare them
        if(SFML_VERSION LESS SFML_REQUESTED_VERSION)
            set(SFML_VERSION_OK FALSE)
        endif()
    else()
        # SFML version is < 2.0
        if (SFML_REQUESTED_VERSION GREATER 19)
            set(SFML_VERSION_OK FALSE)
            set(SFML_VERSION_MAJOR 1)
            set(SFML_VERSION_MINOR x)
        endif()
    endif()
endif()

# find the requested modules
set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found
set(FIND_SFML_LIB_PATHS
    ${SFML_ROOT}
    $ENV{SFML_ROOT}
    ~/Library/Frameworks
    /Library/Frameworks
    /usr/local
    /usr
    /sw
    /opt/local
    /opt/csw
    /opt)
foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS})
    string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER)
    string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER)
    set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER}${FIND_SFML_LIB_SUFFIX})

    # no suffix for sfml-main, it is always a static library
    if(FIND_SFML_COMPONENT_LOWER STREQUAL "main")
        set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER})
    endif()

    # debug library
    find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
                 NAMES ${FIND_SFML_COMPONENT_NAME}-d
       ${FIND_SFML_COMPONENT_NAME}-d-${SFML_VERSION_MAJOR}
       ${FIND_SFML_COMPONENT_NAME}-d-${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
       ${FIND_SFML_COMPONENT_NAME}-d-${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
       ${FIND_SFML_COMPONENT_NAME}-d${SFML_VERSION_MAJOR}
       ${FIND_SFML_COMPONENT_NAME}-d${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
       ${FIND_SFML_COMPONENT_NAME}-d${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
                 PATH_SUFFIXES lib64 lib
                 PATHS ${FIND_SFML_LIB_PATHS})

    # release library
    find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
                 NAMES ${FIND_SFML_COMPONENT_NAME}
       ${FIND_SFML_COMPONENT_NAME}-${SFML_VERSION_MAJOR}
       ${FIND_SFML_COMPONENT_NAME}-${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
       ${FIND_SFML_COMPONENT_NAME}-${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
       ${FIND_SFML_COMPONENT_NAME}${SFML_VERSION_MAJOR}
       ${FIND_SFML_COMPONENT_NAME}${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}
       ${FIND_SFML_COMPONENT_NAME}${SFML_VERSION_MAJOR}${SFML_VERSION_MINOR}
                 PATH_SUFFIXES lib64 lib
                 PATHS ${FIND_SFML_LIB_PATHS})

    if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
        # library found
        set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE)
       
        # if both are found, set SFML_XXX_LIBRARY to contain both
        if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
            set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug     ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}
                                                          optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
        endif()

        # if only one debug/release variant is found, set the other to be equal to the found one
        if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
            # debug and not release
            set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
            set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY         ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
        endif()
        if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG)
            # release and not debug
            set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
            set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY       ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
        endif()
    else()
        # library not found
        set(SFML_FOUND FALSE)
        set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE)
        set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "")
        set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY")
    endif()

    # mark as advanced
    MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY
                     SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
                     SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG)

    # add to the global list of libraries
    set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}")
endforeach()

# handle errors
if(NOT SFML_VERSION_OK)
    # SFML version not ok
    set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR})")
    set(SFML_FOUND FALSE)
elseif(NOT SFML_FOUND)
    # include directory or library not found
    set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})")
endif()
if (NOT SFML_FOUND)
    if(SFML_FIND_REQUIRED)
        # fatal error
        message(FATAL_ERROR ${FIND_SFML_ERROR})
    elseif(NOT SFML_FIND_QUIETLY)
        # error but continue
        message("${FIND_SFML_ERROR}")
    endif()
endif()

# handle success
if(SFML_FOUND)
    message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR} in ${SFML_INCLUDE_DIR}")
endif()
I do appreciate your time.

Sonkun

  • Full Member
  • ***
  • Posts: 241
    • View Profile
Re: FindSFML.cmake update suggestion
« Reply #5 on: August 26, 2013, 10:19:06 am »
Ok, I could reproduce this problem and I solved it with your changes, but I could also reinstall CSFML 2.0 which relies on FindSFML.cmake (unmodified) without any problem. :/

I compared the usage of find_library() in several FindXXX.cmake scrips found in /usr/share/cmake/Modules/* and this seems not to be a common practice. So I guess it should be okay without these extra lines.

Anyway, I need to figure that out, and thank you for reporting it! :)
Interested in using SFML with Python ? Try out its Python binding!

Dúthomhas

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: FindSFML.cmake update suggestion
« Reply #6 on: August 26, 2013, 06:12:44 pm »
Thank you for taking your time with this.

 

anything