What is the correct way to customize the install output directory for each developer in CMake? - cmake

I've been working on an old game that I created CMake files for to get rid of a mix of Makefiles and visual studio projects. Everything is working well, but I'm having a hard time figuring out what the correct way to allow the developer to specify where the output files are copied to when install is run.
The issue is there are many DLLs and some custom targets that need their output copied into a directory structure that includes the game data (levels, art, sound, etc) before they can test the code.
My install commands currently uses a variable that I 'SET' at the top level CMakeLists.txt to specify the output directory. I've tried overriding it with -DD3_GAMEDIR on the cmake command line. That variable gets set in the CMakeCache, but the SET command appears to override it still.
Should I be checking the length of the variable before using SET to see if the user specified a value? That seems like a hack to me, but I'm having a hard time finding the correct way to do it.
Thanks!

The install target supports the DESTDIR parameter, so you could do something like:
make install DESTDIR="C:\RootGameDir"
The other option is to only set the variable if it isn't already set (if(myVar)), but I personally prefer the DESTDIR solution.

Here is the anwser, according your cmake version:
SET(CMAKE_VERSION "${CMAKE_CACHE_MAJOR_VERSION}.${CMAKE_CACHE_MINOR_VERSION}")
IF("${CMAKE_VERSION}" STRGREATER "2.4")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY /path/of/your/install/${CMAKE_BUILD_TYPE}/bin)
SET(CMAKE_LIBRARY_OUTPUT_PATH /path/of/your/install/${CMAKE_BUILD_TYPE}/lib)
ELSE("${CMAKE_VERSION}" STRGREATER "2.4")
SET(EXECUTABLE_OUTPUT_PATH /path/of/your/install/${CMAKE_BUILD_TYPE}/bin)
SET(LIBRARY_OUTPUT_PATH /path/of/your/install/${CMAKE_BUILD_TYPE}/lib)
ENDIF("${CMAKE_VERSION}" STRGREATER "2.4")

What about using the various CMAKE_INSTALL_PREFIX, PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR?

Related

Variable interpolation in -D option

As a package manager for a Linux distribution, I want to install docs into a separate prefix. With CMake projects, the docs installation location is controlled by CMAKE_INSTALL_DOCDIR from GNUInstallDirs module. Unfortunately, unlike the other directory variables, this one contains the project name so I cannot just use cmake "-DCMAKE_INSTALL_DOCDIR=$myDocPrefix/doc".
With GNU Make, I would run make "DOCDIR=$myDocPrefix/doc/\$(PROJECT_NAME)" and have Make interpolate it but the documentation of CMake’s -D option does not mention interpolation and I understand that CMake uses much more complex system of cache entries where interpolation might be problematic (especially if the referenced variable is not yet in cache).
I could pass tailor-made CMAKE_INSTALL_DOCDIR to each CMake project but would be bothersome as I would have to do that in every package definition manually; being able to define configureCmakeProject function and have it take care of everything automatically would be better. When setting it manually, I would also want to make sure it matches the PROJECT_NAME of the respective CMake project – well, I could resign on that and just use $packageName from the package definition instead but keeping packages as close to upstream as possible is preferred.
Alternately, I could try to grep CMakeLists.txt for project command but that seems fragile and might still result in misalignments. I doubt it is possible to extract it using some CMake API since the project is not configured at the time and we actually need the value to configure the project.
Is there a way I can configure CMAKE_INSTALL_DOCDIR to use custom prefix but still keep the project name set by the CMake project?

cmake always use my pc installed library instead of my target path

I get a project that was built for x86, and I am trying to make it work with mips. But I encounter problem when modifying the CMakelists.txt.
So here is the problem, the following code always use my PC's x86 library:
PKG_CHECK_MODULES(LIBCRYPTO REQUIRED libcrypto)
IF(LIBCRYPTO_FOUND)
INCLUDE_DIRECTORIES(${LIBCRYPTO_INCLUDE_DIRS})
LINK_DIRECTORIES(${LIBCRYPTO_LIB_DIRS})
ENDIF(LIBCRYPTO_FOUND)
I googled and found they always use system library first and can use find_package with NO_CMAKE_SYSTEM_PATH flag. But its not working and give me the following message. I don't know what its talking about..
Could not find a package configuration file provided by "libcrypto" with
any of the following names:
libcryptoConfig.cmake
libcrypto-config.cmake
Add the installation prefix of "libcrypto" to CMAKE_PREFIX_PATH or set
"libcrypto_DIR" to a directory containing one of the above files. If
"libcrypto" provides a separate development package or SDK, be sure it has
been installed.
My question is how to properly link a library to the path I assigned to and works like original piece of code?

How to add custom content to a CMake project?

We recently started switching over from using plain visual studio projects to using proper CMake files. Previously we would have the "Content" folder in the solution root folder to allow our executables to access content from it using a relative path like "../Tiles/tileset1.png".
How could we make sure CMake copies the files correctly, or in some other way makes sure that our executables are able to find the content folder while debugging from Visual Studio without manually setting the working directory?
I can think of a few different options:
Have CMake put all your executables in the same folder, as described in this question. Then you can use ../Tiles or ../../Tiles or whatever as you've been doing. Note, however, that you might want to consider setting this on a per-target basis instead of globally, e.g., using:
set_target_properties(
my_target
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/bin
)
Setting CMAKE_RUNTIME_OUTPUT_DIRECTORY works fine, but some people consider it to be the 'old' way of doing it. (Depending on your needs, you might also want to set LIBRARY_OUTPUT_DIRECTORY, and possibly ARCHIVE_OUTPUT_DIRECTORY.)
Use an environmental variable (e.g., CONTENT_ROOT or some-such) to locate the resources. Hard-code a default that makes sense for production, but let developers override it for their particular work flow.
Look into cross-platform resource libaries (something like Qt's QRC files, but perhaps not tied to Qt).
Try the CMake modules listed in this FAQ answer to change Visual Studio's working/debugging directory.
Actually, a combination of 1 and 2 is probably your best bet...

cmake suppress finding package and set path manually

I'm currently automating my the installation process for multiple instances of an application. This application uses cmake for building and uses some libraries for which no findModule.cmake files exist. Since I'm could find a good example how to generate a findModule.cmake file for existing libraries for example OpenCascade. When setting up the buildprocess manually one can easily adapt the include and lib path in ccmake. Since I want to automate this I'm looking for a way to do this by passing the options to cmake on the command line. Here is how I try to achieve this for OpenCascade:
cmake -DOCC_FOUND:INTERNAL=TRUE -DOCC_INCLUDE_DIR:PATH=/usr/include/opencascade -DOCC_LIBRARY:FILEPATH=/usr/lib/libTKernel.so -DCMAKE_BUILD_TYPE:STRING=Release ..
Unfortunately this doesn't work. Since the option for building are build-depended, passing a previously configured CMakeCache.txt file is not working.
Thanks for any suggestions to achieve what I'm trying to do.

Making my program compile on both windows and linux, what should I do about libraries?

I'm using CMake to generate my makefiles and VC solutions. I have my program running on linux just fine. I'm using a bunch of libraries, e.g. Lua. On my linux computer I just link to them and make sure in include the headers. All of the .so files are in some standard place. On Windows though I'm not sure what to do. Should I just include the entire Lua project into my own repository and link to that instead? Do I install Lua to some standard place like c:\program files\lua5.1 and link to that? Something else?
Your libraries can be in any place, you just need to say - where are they.
Before running cmake set up pathes of all your extern libs with some .bat file:
set LIBRARYPATH =path\to\your\library\
set include=%include%;%LIBRARYPATH%\include
set lib=%lib%;%LIBRARYPATH%\lib
Start cmd, run this .bat and then cmake should find all
I would provide a configuration field/variable for ccmake that the user can or must specify.
The mark_as_advanced can be used to make a custom variable only appear in the advanced mode. This would be suitable if you have a standard path (as you have mostly on windows). Yet, it still let's the user specify the value if needed.
Or you can simply set a variable the with the 'set' command if you don't want it in advanced.
Just make sure you check if the users entered a valid value.