Search code examples
cmakecmake-gui

cmake - preset settings for entries from ini file


I have a project that uses some third party libraries. So each time I setup this project with CMake, I have to set each entry (path of the third party library) on the GUI of CMake. I improve this by making CMake script guess the path by this script (learn this technique from OGRE):

# Guess the paths.
set( OGRE_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/Dependencies/Ogre" CACHE STRING "Path to OGRE source code (see http://www.ogre3d.org/tikiwiki/tiki-index.php?page=CMake+Quick+Start+Guide)" )

So each time I setup with CMake, it will automatic fill the entry OGRE_SOURCE. But that doesn't enough. If the Ogre source is not in the path

"${CMAKE_CURRENT_SOURCE_DIR}/Dependencies/Ogre"

, then I have to open and edit the CMake script or I have to edit the entry on the GUI of CMake. I find that pretty inconvenient, especially when you link to a lot of third party libraries.

So I want to use another technique: preset settings for entries from file - CMake reads the presets from file PresetEntries.txt (that I make) and apply the these presets on the entries (It's a lot quicker to edit the path in text file than on the GUI of CMake).

Here my idea about this preset file: PresetEntries.txt

OGRE_SOURCE=E:/Source/ogre

I found that CMake can read a text file, but if I use this, I have to do string manipulations.

CMake has the file CMakeCache.txt to save the settings on the CMake GUI, but I want it to be simple: it should only has the preset settings that need to be pre-set.

So I wonder if CMake support this preset settings for entries from file.

Edit: So I read this question and see that CMake can set config from file, but this require to fire cmake with the -C mysettings.cmake, but I wanna it to be automatically with CMake GUI - just edit the file and hit generate button in CMake GUI. So I wanna make this question more specific: In my CMakeLists.txt should have script like this:

# Guess the paths.
#I wanna have this function from C++
#https://msdn.microsoft.com/en-us/library/windows/desktop/ms724353%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
GetPrivateProfileString("OGRE",         #lpAppName
                        "OGRE_SOURCE",  #lpKeyName
                        "${CMAKE_CURRENT_SOURCE_DIR}/Dependencies/Ogre", #lpDefault
                        OGRE_SOURCE_VAR,#lpReturnedString
                        MAX_PATH,       #nSize, may be can reduce this variable
                        "LibPath.ini")  #lpFileName

set( OGRE_SOURCE "${OGRE_SOURCE_VAR}" CACHE STRING "Path to OGRE source code" )

In the file LibPath.ini

[OGRE]
OGRE_SOURCE = "E:/Source/ogre"

So the user can choose to either use the ini file or not.

I don't know if there any way I can use a function that similar to function GetPrivateProfileString (of C++) in CMake.

Thanks for reading


Solution

  • I can't find the function to read the ini file, so what I can do is create a simple function that read simple txt file for myself.

    1. I declare the function in 1 file for other file use it

    "\CMake\Dependencies\CommonFunc.cmake"

    #------------Define function Read file------------
    macro( readSettingFile KEY DEFAULT_RESULT STRING_RESULT_OUT)
    
        unset(STRING_RESULT)
        # Read the file
        file( READ "${CMAKE_SOURCE_DIR}/LibPath.txt" LIB_PATH_STR )
    
        # Set the variable "Esc" to the ASCII value 27 - basically something
        # which is unlikely to conflict with anything in the file contents.
        string(ASCII 27 Esc)
    
        # Turn the contents into a list of strings, each ending with an Esc.
        # This allows us to preserve blank lines in the file since CMake
        # automatically prunes empty list items during a foreach loop.
        string(REGEX REPLACE "\n" "${Esc};" LIB_PATH_LINES "${LIB_PATH_STR}")
    
        foreach(LINE ${LIB_PATH_LINES})
            if("${LINE}" MATCHES "${KEY}")
                #remove the key, leave the content untouch
                string(REPLACE "${KEY}" "" STRING_RESULT ${LINE})
                # Swap the appended Esc character back out in favour of a line feed
                string(REGEX REPLACE "${Esc}" "" STRING_RESULT ${STRING_RESULT})
            endif()
        endforeach()
    
        if("${STRING_RESULT}" STREQUAL "")
            set( STRING_RESULT ${DEFAULT_RESULT} )
        endif()
    
    
        #message( STATIC "---GTA Sa-----" "[${STRING_RESULT}]" )
    endmacro()
    

    (I need the help from this answer to write this function :p)

    1. Here is how I use

    For example: "\CMake\Dependencies\Ogre.cmake"

    #include common functions
    include( CMake/Dependencies/CommonFunc.cmake )
    #---------------Guess the paths.----------------------
    #----Set OGRE_SOURCE
    readSettingFile(    "OGRE_SOURCE="
                        "E:/Source/ogre"
                        STRING_RESULT
                    )
    set( OGRE_SOURCE "${STRING_RESULT}" CACHE STRING "Path to OGRE Source" )
    #----Set OGRE_BINARIES
    readSettingFile(    "OGRE_BINARIES="
                        "E:/Source/_build/ogre"
                        STRING_RESULT
                    )
    set( OGRE_BINARIES "${STRING_RESULT}" CACHE STRING "Path to OGRE's build folder generated by CMake" )
    
    1. Here is the setting file

    "\LibPath.txt"

    OGRE_SOURCE=E:/Source/ogre
    OGRE_BINARIES=E:/Source/_build/ogre