From 7abd574798f9900abfe502f3941cffaa774062b1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 23 Jun 2014 16:33:33 -0400 Subject: [PATCH] cmake: Add '-E env' command-line tool Extend the cmake command-line interface to support cmake -E env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]... This will be useful to run processes with modified environments without using a shell or a full "cmake -P" script to wrap it. Extend the RunCMake.CommandLine test to cover success and failure cases. Inspired-by: Jonathan Bohren --- Help/manual/cmake.1.rst | 2 +- Help/release/dev/cmake-E-env.rst | 4 ++ Source/cmcmd.cxx | 51 +++++++++++++++++++ .../CommandLine/E_env-bad-arg1-result.txt | 1 + .../CommandLine/E_env-bad-arg1-stderr.txt | 1 + .../CommandLine/E_env-no-command0-result.txt | 1 + .../CommandLine/E_env-no-command0-stderr.txt | 1 + .../CommandLine/E_env-no-command1-result.txt | 1 + .../CommandLine/E_env-no-command1-stderr.txt | 1 + .../RunCMake/CommandLine/E_env-set-stdout.txt | 1 + Tests/RunCMake/CommandLine/E_env-set.cmake | 5 ++ .../CommandLine/E_env-unset-stdout.txt | 1 + Tests/RunCMake/CommandLine/E_env-unset.cmake | 5 ++ Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 6 +++ 14 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/cmake-E-env.rst create mode 100644 Tests/RunCMake/CommandLine/E_env-bad-arg1-result.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-bad-arg1-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-no-command0-result.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-no-command0-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-no-command1-result.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-no-command1-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-set-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-set.cmake create mode 100644 Tests/RunCMake/CommandLine/E_env-unset-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/E_env-unset.cmake diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 5743ab7982..8dfc16ac6c 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -38,7 +38,7 @@ Options For true platform independence, CMake provides a list of commands that can be used on all systems. Run with -E help for the usage information. Commands available are: chdir, compare_files, copy, - copy_directory, copy_if_different, echo, echo_append, environment, + copy_directory, copy_if_different, echo, echo_append, env, environment, make_directory, md5sum, remove, remove_directory, rename, sleep, tar, time, touch, touch_nocreate. In addition, some platform specific commands are available. On Windows: delete_regv, write_regv. On diff --git a/Help/release/dev/cmake-E-env.rst b/Help/release/dev/cmake-E-env.rst new file mode 100644 index 0000000000..4bdcd0c296 --- /dev/null +++ b/Help/release/dev/cmake-E-env.rst @@ -0,0 +1,4 @@ +cmake-E-env +----------- + +* The :manual:`cmake(1)` ``-E`` option learned a new ``env`` command. diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 9aee975cce..a0c67e00ae 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -61,6 +61,8 @@ void CMakeCommandUsage(const char* program) << " echo [string]... - displays arguments as text\n" << " echo_append [string]... - displays arguments as text but no new " "line\n" + << " env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...\n" + << " - run command in a modified environment\n" << " environment - display the current environment\n" << " make_directory dir - create a directory\n" << " md5sum file1 [...] - compute md5sum of files\n" @@ -190,6 +192,55 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) return 0; } + else if (args[1] == "env" ) + { + std::vector::const_iterator ai = args.begin() + 2; + std::vector::const_iterator ae = args.end(); + for(; ai != ae; ++ai) + { + std::string const& a = *ai; + if(cmHasLiteralPrefix(a, "--unset=")) + { + // Unset environment variable. + cmSystemTools::UnPutEnv(a.c_str() + 8); + } + else if(!a.empty() && a[0] == '-') + { + // Environment variable and command names cannot start in '-', + // so this must be an unknown option. + std::cerr << "cmake -E env: unknown option '" << a << "'" + << std::endl; + return 1; + } + else if(a.find("=") != a.npos) + { + // Set environment variable. + cmSystemTools::PutEnv(a.c_str()); + } + else + { + // This is the beginning of the command. + break; + } + } + + if(ai == ae) + { + std::cerr << "cmake -E env: no command given" << std::endl; + return 1; + } + + // Execute command from remaining arguments. + std::vector cmd(ai, ae); + int retval; + if(cmSystemTools::RunSingleCommand( + cmd, 0, &retval, NULL, cmSystemTools::OUTPUT_PASSTHROUGH)) + { + return retval; + } + return 1; + } + #if defined(CMAKE_BUILD_WITH_CMAKE) // Command to create a symbolic link. Fails on platforms not // supporting them. diff --git a/Tests/RunCMake/CommandLine/E_env-bad-arg1-result.txt b/Tests/RunCMake/CommandLine/E_env-bad-arg1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-bad-arg1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_env-bad-arg1-stderr.txt b/Tests/RunCMake/CommandLine/E_env-bad-arg1-stderr.txt new file mode 100644 index 0000000000..2143ba417b --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-bad-arg1-stderr.txt @@ -0,0 +1 @@ +^cmake -E env: unknown option '-bad-arg1'$ diff --git a/Tests/RunCMake/CommandLine/E_env-no-command0-result.txt b/Tests/RunCMake/CommandLine/E_env-no-command0-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-no-command0-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_env-no-command0-stderr.txt b/Tests/RunCMake/CommandLine/E_env-no-command0-stderr.txt new file mode 100644 index 0000000000..d2efa53673 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-no-command0-stderr.txt @@ -0,0 +1 @@ +^cmake -E env: no command given$ diff --git a/Tests/RunCMake/CommandLine/E_env-no-command1-result.txt b/Tests/RunCMake/CommandLine/E_env-no-command1-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-no-command1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_env-no-command1-stderr.txt b/Tests/RunCMake/CommandLine/E_env-no-command1-stderr.txt new file mode 100644 index 0000000000..d2efa53673 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-no-command1-stderr.txt @@ -0,0 +1 @@ +^cmake -E env: no command given$ diff --git a/Tests/RunCMake/CommandLine/E_env-set-stdout.txt b/Tests/RunCMake/CommandLine/E_env-set-stdout.txt new file mode 100644 index 0000000000..feff1176ea --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-set-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly set in environment: 1$ diff --git a/Tests/RunCMake/CommandLine/E_env-set.cmake b/Tests/RunCMake/CommandLine/E_env-set.cmake new file mode 100644 index 0000000000..c2639b6634 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-set.cmake @@ -0,0 +1,5 @@ +if(DEFINED ENV{TEST_ENV}) + message(STATUS "TEST_ENV is correctly set in environment: $ENV{TEST_ENV}") +else() + message(FATAL_ERROR "TEST_ENV is incorrectly not set in environment") +endif() diff --git a/Tests/RunCMake/CommandLine/E_env-unset-stdout.txt b/Tests/RunCMake/CommandLine/E_env-unset-stdout.txt new file mode 100644 index 0000000000..a1d5c01083 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-unset-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly not set in environment$ diff --git a/Tests/RunCMake/CommandLine/E_env-unset.cmake b/Tests/RunCMake/CommandLine/E_env-unset.cmake new file mode 100644 index 0000000000..04976fb40a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-unset.cmake @@ -0,0 +1,5 @@ +if(DEFINED ENV{TEST_ENV}) + message(FATAL_ERROR "TEST_ENV is incorrectly set in environment") +else() + message(STATUS "TEST_ENV is correctly not set in environment") +endif() diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index f3d9637690..5622a5ba8c 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -31,6 +31,12 @@ if(UNIX) ) endif() +run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env) +run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1) +run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1) +run_cmake_command(E_env-set ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake) +run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake) + run_cmake_command(E_sleep-no-args ${CMAKE_COMMAND} -E sleep) run_cmake_command(E_sleep-bad-arg1 ${CMAKE_COMMAND} -E sleep x) run_cmake_command(E_sleep-bad-arg2 ${CMAKE_COMMAND} -E sleep 1 -1)