开发者

How to make temp directory in CMake?

I need the CMake analog of mktemp command in linux. Wha开发者_如何学JAVAt macro provides this?


Was looking for this too to evaluate expressions as suggested in the CMake Wiki. Wrote some macros and an example for generating temp file names and executing them:

#!/usr/bin/cmake -P

macro(temp_name fname)
  if(${ARGC} GREATER 1) # Have to escape ARGC to correctly compare
    set(_base ${ARGV1})
  else(${ARGC} GREATER 1)
    set(_base ".cmake-tmp")
  endif(${ARGC} GREATER 1)
  set(_counter 0)
  while(EXISTS "${_base}${_counter}")
    math(EXPR _counter "${_counter} + 1")
  endwhile(EXISTS "${_base}${_counter}")
  set(${fname} "${_base}${_counter}")
endmacro(temp_name)

# Evaluate expression
# Suggestion from the Wiki: http://cmake.org/Wiki/CMake/Language_Syntax
# Unfortunately, no built-in stuff for this: http://public.kitware.com/Bug/view.php?id=4034
macro(eval expr)
  temp_name(_fname)
  file(WRITE ${_fname} "${expr}")
  include(${_fname})
  file(REMOVE ${_fname})
endmacro(eval)


# Examples

eval("message(\"Hai\")")

set(funcs a;b)
macro(test_a arg)
  message("A: ${arg}")
endmacro(test_a)
macro(test_b arg)
  message("B: ${arg}")
endmacro(test_b)

foreach(func ${funcs})
  set(func_name test_${func})
  eval("${func_name}(\"Test\")")
endforeach(func)

Output:

Hai
A: Test
B: Test

Note that in Linux you can set this script to executable and run it using cmake -P. Useful for testing stuff out.


There is no direct CMake analog of "mktemp".

From inside a CMake script or CMakeLists.txt file, your best bet is to use the

file(MAKE_DIRECTORY "/path/to/dir/name")

command, and give it a name of a directory that you know you have write access to. Help for the file command is found here: https://cmake.org/cmake/help/latest/command/file.html

You could also possibly simply use

$ENV{TMP}

if there is an environment variable that points you to a system-provided temp directory.

If you are invoking CMake directly, you could also use

cmake -E make_directory /path/to/dir/name

Finally, see also the execute_process command, which allows you to call arbitrary command line tools from within a cmake script or CMakeLists file and capture the output. That may prove useful if you have another tool that you can call that gives you mktemp functionality. https://cmake.org/cmake/help/latest/command/execute_process.html


I implemented the following macro:

#!/usr/bin/cmake -P
include(CMakeParseArguments)

function(MKTEMP)
  set(options CREATE_FOLDER CREATE_FILE)
  set(oneValueArgs PREFIX PARENT OUTPUT_VARIABLE)
  cmake_parse_arguments(MKTEMP "${options}" "${oneValueArgs}" "" ${ARGN})

  if(NOT DEFINED MKTEMP_CREATE_FOLDER)
    set(MKTEMP_CREATE_FOLDER FALSE)
  endif()

  if(NOT DEFINED MKTEMP_CREATE_FILE)
    set(MKTEMP_CREATE_FILE FALSE)
  endif()

  if(MKTEMP_CREATE_FOLDER AND MKTEMP_CREATE_FILE)
    # Can not create folder and file with the same name
    message(FATAL_ERROR "Both flags CREATE_FOLDER and CREATE_FILE are set")
  endif()

  if(NOT DEFINED MKTEMP_PREFIX)
    set(MKTEMP_PREFIX "tmp")
  endif()

  if(NOT DEFINED MKTEMP_PARENT)
    set(MKTEMP_PARENT "$ENV{TMP}")
  endif()

  set(_COUNTER 0)
  while(EXISTS "${MKTEMP_PARENT}/${MKTEMP_PREFIX}${_COUNTER}")
    math(EXPR _COUNTER "${_COUNTER} + 1")
  endwhile()
  set(_NAME "${MKTEMP_PARENT}/${MKTEMP_PREFIX}${_COUNTER}")
  set(${MKTEMP_OUTPUT_VARIABLE} "${_NAME}" PARENT_SCOPE)

  if(MKTEMP_CREATE_FOLDER)
    file(MAKE_DIRECTORY "${_NAME}")
  elseif(MKTEMP_CREATE_FILE)
    file(WRITE "${_NAME}" "")
  endif()
endfunction()    

Usage:

# only generate name - with default prefix ("tmp")
MKTEMP(OUTPUT_VARIABLE TMPONLYNAME)
message("TMPONLYNAME is ${TMPONLYNAME}")

# only generate name - with custom prefix ("myapp")
MKTEMP(PREFIX "myapp" OUTPUT_VARIABLE TMPONLYNAME)
message("TMPONLYNAME is ${TMPONLYNAME}")

# only generate name - use current folder as temp
MKTEMP(PARENT "." OUTPUT_VARIABLE TMPONLYNAME)
message("TMPONLYNAME is ${TMPONLYNAME}")

# create file
MKTEMP(PREFIX "myapp" OUTPUT_VARIABLE TMPFILE CREATE_FILE)
message("TMPFILE is ${TMPFILE}")
# ... work with file ...
file(REMOVE "${TMPFILE}")

# create folder
MKTEMP(PREFIX "myapp" OUTPUT_VARIABLE TMPFOLDER CREATE_FOLDER)
message("TMPFOLDER is ${TMPFOLDER}")
# ... work with folder ...
file(REMOVE_RECURSE "${TMPFOLDER}")

Example of output on my Windows environment ("myapp7" the same because of deletion):

TMPONLYNAME is C:\Users\msuslov\AppData\Local\Temp\tmp1
TMPONLYNAME is C:\Users\msuslov\AppData\Local\Temp\myapp7
TMPONLYNAME is .\tmp0
TMPFILE is C:\Users\msuslov\AppData\Local\Temp\myapp7
TMPFOLDER is C:\Users\msuslov\AppData\Local\Temp\myapp7
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜