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
How to Get Only Filenames Without Path by Using Grep
Perl: What Does Checkstack.Pl in Linux Source Do
What Happened to Socket If Network Has Broken Down
How to Install the Specific Version of Postgres
Access Bash Positional Parameter Through Variable
Storing Pid File for a Daemon Run as User
Docker Container Accessible Only via Cloudflare Cdn (Selected Ip Ranges)
Temporarily Prevent Linux from Shutting Down
Errors While Installing Opencv and Ffmpeg Through Rightscripts
Arm Assembly "Retne" Instruction
Running Multiple Compass-Sass Watch Operations Automatically
Accessing Files Outside the Document Root with Apache
Simulating a Spinner for Progress in Bash
Compare Md5 Sums in Bash Script
What's the Purpose of the Ud2 Opcode in the Linux Kernel
Bluez Blotoothctl Scan VS Hcitool Scan
Yocto Build for a Static Library Fails with Error "No Match Found"
When We Run an Executable, Do All the Sections Get Loaded into Memory at Once