How to Use Find -Exec in Cmake Execute_Process

CMake add_custom_target COMMAND find files and exec

Following this post
How to use find -exec in CMake execute_process?

I finally got the correct command line:

add_custom_target(${APK_BUILD_TARGET} ALL

COMMAND find ${APK_DIR} -name "*.apk" -exec jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore myKey.keystore -storepass myStorePass -keypass myKeyPass {} myName "\;"

)

So with "\;" instead of just \;

How to run execute_process in cmake with wildcard?

First you should learn that the filename expansion one of expansions done by your shell before the command is executed and it causes *.txt to expand to the list of files using special rules.

After you know that, you will naturally know that you have to run the shell to cause *.txt to expand.

COMMAND sh -c "ls *.txt"

Using file(GLOB tmp "*.txt") and passing tmp would be a more cmake-ish way.

cmake execute_process cannot find source command

Use the OUTPUT_VARIABLE option of execute_process.

Make your script look like this:

#!/bin/bash
MY_VAR=$1
echo "$MY_VAR"

And use it in your CMakeLists.txt as follows:

cmake_minimum_required(VERSION 2.6)
execute_process(COMMAND sh "var_set.sh" "VALUE" "VALUE2"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
RESULT_VARIABLE variable_RESULT
OUTPUT_VARIABLE variable_OUTPUT
)

message(STATUS ${variable_RESULT})
message(STATUS ${variable_OUTPUT})

The output of the CMake configuration step is then:

-- The C compiler identification is GNU 5.1.1
-- The CXX compiler identification is GNU 5.1.1
-- Check for working C compiler: /usr/lib64/ccache/cc
-- Check for working C compiler: /usr/lib64/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib64/ccache/c++
-- Check for working CXX compiler: /usr/lib64/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- 0
-- VALUE

-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/out

A drawback to this approach is that you will have to suppress all unwanted output in your script. Alternatively, use OUTPUT_FILE and post-process the file.

cmake execute_process COMMAND

Don't set the args as part of your command variable. You can pass them in execute_process:

set(MAKE_CMD "${CMAKE_CURRENT_SOURCE_DIR}/makeHeaders.sh")
MESSAGE("COMMAND: ${MAKE_CMD} ${CMAKE_CURRENT_SOURCE_DIR} ${INC_DIR}")
execute_process(COMMAND ${MAKE_CMD} ${CMAKE_CURRENT_SOURCE_DIR} ${INC_DIR}
RESULT_VARIABLE CMD_ERROR
OUTPUT_FILE CMD_OUTPUT)
MESSAGE( STATUS "CMD_ERROR:" ${CMD_ERROR})
MESSAGE( STATUS "CMD_OUTPUT:" ${CMD_OUTPUT})

EDIT
In adition to the above answer, if you want to add the arguments to the command variable you can do it like so:

set(MAKE_CMD "${CMAKE_CURRENT_SOURCE_DIR}/makeHeaders.sh")
list(APPEND MAKE_CMD ${CMAKE_CURRENT_SOURCE_DIR})

CMake's execute_process and arbitrary shell scripts

You can execute any shell script, using your shell's support for taking in a script within a string argument.

Example:

execute_process(
COMMAND bash "-c" "echo -n hello | sed 's/hello/world/;'"
OUTPUT_VARIABLE FOO
)

will result in FOO containing world.

Of course, you would need to escape quotes and backslashes with care. Also remember that running bash would only work on platforms which have bash - i.e. it won't work on Windows.

Create multi-COMMAND execute_process

When passing multiple commands to execute_process, these commands are separated solely by the COMMAND keyword, there is no need to "group" commands with double quotes.

Following execute_process will run 3 commands:

execute_process(COMMAND echo abc
COMMAND mkdir foo
COMMAND ssh -tt user@127.0.0.1 ls /bin)

So, when forming commands in a variable, double quotes are not needed either:

# Incorrect
list(APPEND commands "COMMAND ssh -tt user@${IP} \"${command}\"")
# Correct
list(APPEND commands COMMAND ssh -tt user@${IP} ${command})

(Quotes around the command passed to ssh for execute on the target machine are not needed either, ssh automatically treats every argument, followed the executable, as arguments to that executable.)


Note that commands in execute_process are not executed strictly in order, but piped: output of the first COMMAND is piped into the second one, output of the second one is piped into the third one, and so on.

CMake: how to make execute_process wait for subdirectory to finish?

Command execute_process executes its COMMAND immediately, at configuration stage. So it cannot be arranged after the executable is created with add_executable command: that executable will be built only at build stage.

You need to build subproject at configuration stage too. E.g. with

execute_process(COMMAND ${CMAKE_COMMAND}
-S ${CMAKE_SOURCE_DIR}/generator
-B ${CMAKE_BINARY_DIR}/generator
-G ${CMAKE_GENERATOR}
)

execute_process(COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}/generator
)

The first command invokes cmake for configure the 'generator' project, located under ${CMAKE_SOURCE_DIR}/generator directory. With -G option we use for subproject the same CMake generator, as one used for the main project.

The second command builds that project, so it produces generator executable.

After generator executable is created, you may use it for your project:

execute_process(COMMAND ${CMAKE_BINARY_DIR}/generator/<...>/generator ${CMAKE_SOURCE_DIR}/src)

Here you need to pass absolute path to the generator executable as the first parameter to COMMAND: CMake no longer have generator executable target, so it won't substitute its path automatically.

How to pass list variable in CMake's execute_process?

I think you need to escape the ; character which is the default separator for lists in CMake, but it's not clear how you do it so that it doesn't work for you.

So, try something like this

set(mylist_str "")

foreach(item ${mylist})
string(APPEND mylist_str ${item} "\;")
endforeach()

# this is for debugging
message(STATUS "List as string: ${mylist_str}")

set(cmake_args
"-DVal1=abc"
"-DVal2=${mylist_str}"
"-DVal3=\"${mylist_str}\"" # this has quotes around it
)

# this is for debugging
foreach(item ${cmake_args})
message(STATUS "A list item: ${item}")
endforeach()

multiple commands in cmake execute_process

Command execute_process has WORKING_DIRECTORY option, which intention is to set directory where COMMAND will be invoked:

execute_process(COMMAND  git describe --abbrev=0 --always 
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_VERSION
)

As for && operand, it doesn't work with execute_process, because shell isn't used for run the command. This is explicitely stated in documentation.

Normally, for achive sequential order of the commands, you need to call execute_process twice (or more). But such usage doesn't work with changing directory, that is why special option is introduced.



Related Topics



Leave a reply



Submit