Johannes
Johannes

Reputation: 3099

Can not generate a CMake command

My CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)
project(main)

SET(MAIN main)
SET(MAIN_OUT "${CMAKE_CURRENT_BINARY_DIR}/out.txt")
add_executable(${MAIN} main.cpp)

# command is unknown
add_custom_command(OUTPUT ${MAIN_OUT}
    POST_BUILD
    COMMAND ./${MAIN} > ${MAIN_OUT}
    DEPENDS ${MAIN}
)

After compiling, I just want to be able to type

make out.txt

However, cmake seems to be unaware of this target ("no rule"). In the build directory, a call of

grep out.txt -r *

finds no files containing out.txt. How can I make my target callable? I know this has probably asked before, but I have not found it.

Upvotes: 1

Views: 406

Answers (1)

Fraser
Fraser

Reputation: 78280

If you want to be able to type "make out.txt", you probably want add_custom_target instead of add_custom_command. This creates a target which can be built, and in building executes the specified commands.

Rather than call this target "out.txt" which would misleadingly make it look like a text file instead of a target, I'd recommend something more like "RunMain" or "GetOutputOfMain".

If you can specify a recent version of CMake as the minimum, you can use "generator expressions" within the command part of your add_custom_target call. This isn't documented for add_custom_target, but you can read about generator expressions in the docs for add_custom_command. I'm not sure what the minimum required version of CMake should be set to in order to have generator expressions available.

So, your CMakeLists.txt could be changed to something like:

cmake_minimum_required(VERSION 2.8.10)
project(Test)

add_executable(MyExe main.cpp)

set(MainOut "${CMAKE_CURRENT_BINARY_DIR}/out.txt")
add_custom_target(RunMain $<TARGET_FILE:MyExe> > ${MainOut}
                  COMMENT "Running MyExe with output redirected to ${MainOut}")

# Ensure MyExe is built before trying to build the custom target
add_dependencies(RunMain MyExe)

Then just do make RunMain to generate out.txt.

If you don't want to specify such a high minimum version, you can use the obsolete LOCATION target property instead:

get_target_property(MyExeLocation MyExe LOCATION)
add_custom_target(
    RunMain ${MyExeLocation} > ${MainOut}
    COMMENT "Running ${MyExeLocation} with output redirected to ${MainOut}")

Upvotes: 2

Related Questions