[CMake] Project initialization file path

Michael Hertling mhertling at online.de
Thu Jun 10 15:52:26 EDT 2010


On 06/10/2010 10:51 AM, Eric Noulard wrote:
> 2010/6/9 Aby Louw <jalouw at csir.co.za>:
>> Hi,
>>
>> I have a Linux project that reads an initialization file on startup to
>> get some file names and variables.
>>
>> When doing an in-source or out of source build, I generate the
>> initialization file in the CMAKE_BINARY_DIR and then also generate the C
>> file that reads this file so that I know the correct path.
>>
>> Now when doing a "make install" I want to install the initialization
>> file on the /etc path. Therefore the initialization file path in the C
>> file needs to be updated. However I do not know how to recompile the C
>> target before installation happens.
> 
> Looks odd to bury some config into a compiled C-file.
> If the C file contains some "actual installation path" It may be easier for this
> executable/function to lookup **at runtime** its actual install path...
> 
> If this C file is "reading" some config file may be you can add
> some primitive search path mechanism,
> 
>  1) look in "."
>  2) look in "${CMAKE_INSTALL_PREFIX}/...." --> you must be doing
> something like that now
>  3) use some environment var prefix
>       getenv(HOME)/... --> using HOME env var
>       getenv(MYSW_PATH)/.... --> using specific env var
> 
> then during devel you may setup MYSW_PATH as you want
> and then when installed ${CMAKE_INSTALL_PREFIX}/ will be used
> provided 3) as a higher priority than 2)
> 
>> I need something like a pre install or, add_dependency to install
>> target, but as far as I know this is not possible. Does anybody know of
>> a workaround to this problem?
> 
> install(CODE  ...
> or
> install(SCRIPT ...
> 
> may help you to execute extra CMake action at install time.
> However I would rather use some "search path" mechanism.

The following CMakeLists.txt provides a somewhat weird approach:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(REINSTALL C)
FILE(WRITE f.c "void f(void){}\n")
FILE(WRITE reinstall.cmake
    "IF(NOT INSTALLED)\n"
    "    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E touch
${CMAKE_SOURCE_DIR}/f.c)\n"
    "    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} --build
${CMAKE_BINARY_DIR})\n"
    "    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -DINSTALLED=TRUE -P
cmake_install.cmake)\n"
    "ENDIF()\n"
)
ADD_LIBRARY(f STATIC f.c)
INSTALL(
    TARGETS f
    RUNTIME DESTINATION bin
    ARCHIVE DESTINATION lib
    LIBRARY DESTINATION lib
)
INSTALL(SCRIPT reinstall.cmake)

The reinstall.cmake script is executed by INSTALL(SCRIPT ..), i.e. after
the targets are checked for being up to date and after being installed;
it touches a source file, rebuilds by "cmake --build ..." and reinstalls
by "cmake -P cmake_install.cmake", so any "make install" will result in
an install-touch-build-install cycle, and the INSTALLED flag prevents an
infinite recursion. Of course, instead of touching, you can do whatever
is necessary to set up the project for rebuild-before-installation. This
appoach works with *nix Makefiles, but I don't know if it's suitable for
other generators, too, in particular due to "cmake --build ...".

Generally, I would recommend the same as EN and MW have before, i.e. a
search path that takes into account: Environment variables, the user's
home directory and - as a hardcoded last resort - the /etc or
${CMAKE_INSTALL_PREFIX}/etc directories.

'hope that helps.

Regards,

Michael


More information about the CMake mailing list