aboutsummaryrefslogtreecommitdiffstats
path: root/cmake/env.cmake
blob: 677c94c4f94895f9e3e71caf7ceb40efc05c6216 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#
# Set environment variables and execute a program.
# Attempts to emulate "cmake -E env" which is only available since CMake 3.1.
#
# Copyright 2018 Peter Wu <peter@lekensteyn.nl>
# SPDX-License-Identifier: MIT
#
# Usage:
#
#   cmake -P env.cmake [NAME=VALUE]... [COMMAND [ARG]...]
#
# Limitations due to CMake:
#
# - The command and arguments cannot be keywords for the "execute_process"
#   command ("COMMAND", "ENCODING", "TIMEOUT", "WORKING_DIRECTORY", etc.).
# - Empty arguments are ignored, arguments with a trailing backslash ("\") will
#   have the slash replaced by a forward slash ("/").
# - If a program fails, a message will be printed and exit code 1 is returned.

# Choose between two evils for the command line limitations:
# (1) Hard-coded number of maximum arguments and repetitive lines.
# (2) Limitations on the arguments (due to use of lists).
# (3) A combination of both.
# For simplicity, (2) is chosen here.
set(command)

math(EXPR argsCount "${CMAKE_ARGC} - 1")
set(skip_args ${argsCount})
set(maybe_env TRUE)

foreach(argNumber RANGE ${argsCount})
  set(arg "${CMAKE_ARGV${argNumber}}")

  if(skip_args EQUAL 0)
    # Escape ";" (list separator) to avoid splitting arguments.
    string(REPLACE ";" "\\;" argForList "${arg}")

    # Prevent a trailing backslash from escaping the next list separator.
    # Hopefully it is just a path separator, otherwise there will be problems.
    if(argForList MATCHES "(.*)\\\\$")
      message(WARNING "Trailing backslash is converted to forward slash in: ${arg}")
      set(argForList "${CMAKE_MATCH_1}/")
    endif()

    if(argForList STREQUAL "")
      message(WARNING "Empty arguments are currently not supported and ignored")
    endif()

    if(maybe_env)
      # Try to parse NAME=VALUE
      if(arg MATCHES "^([^=]+)=(.*)$")
        set("ENV{${CMAKE_MATCH_1}}" "${CMAKE_MATCH_2}")
      else()
        set(maybe_env FALSE)
        list(APPEND command "${argForList}")
      endif()
    else()
      # Definitely no more env vars.
      list(APPEND command "${argForList}")
    endif()
  else()
    # Skip arguments until "-P env.cmake" is found.
    if(arg STREQUAL "-P")
      # just skip "env.cmake" from now on
      set(skip_args 1)
    else()
      math(EXPR skip_args "${skip_args} - 1")
    endif()
  endif()
endforeach()

execute_process(COMMAND ${command} RESULT_VARIABLE exitCode)

if(NOT exitCode EQUAL 0)
  message(FATAL_ERROR "Process exited with ${exitCode}")
endif()