furushchev
furushchev

Reputation: 2739

Add files in sub folders to target

I'd like to add output files in subdirectory to a build target. I wrote in CMakeLists.txt like below:

file(GLOB srcfiles "src/*.txt")
add_custom_target(subtask ALL)
set(dest_dir ${PROJECT_SOURCE_DIR}/sub/)
foreach(srcfile ${srcfiles})
  string(REGEX REPLACE "^.*/(.*).txt$" filename ${srcfile})
  add_custom_command(OUTPUT ${dest_dir}/${filename}.txt
    COMMAND ${CMAKE_COMMAND} ARGS -E make_directory ${dest_dir}
    COMMAND ${PROJECT_SOURCE_DIR}/process.sh ARGS ${srcfile}
    MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/process.sh)
    add_dependencies(subtask ${dest_dir}/${filename}.txt)
endforeach(srcfile)

And executed:

mkdir build && cmake .. && make

But sub/*.txt are not created after build.

How should I do to build all commands on build?

updated (2017/2/4)

I solved the issue: use add_custom_command for each target and then declare add_custom_target that depends on all targets of add_custom_command.

set(TARGET_FILES "")
file(GLOB SRC_FILES "src/*.txt")
foreach(SRC_FILE ${SRC_FILES})
  string(REGEX REPLACE "^.*/(.*).txt$" "\\1-foo.txt" TARGET_FILE ${SRC_FILE})
  add_custom_command(
    OUTPUT ${PROJECT_SOURCE_DIR}/sub/${TARGET_FILE}
    COMMAND ${CMAKE_COMMAND} ARGS -E make_directory ${PROJECT_SOURCE_DIR}/sub
    COMMAND ${PROJECT_SOURCE_DIR}/process.sh ARGS ${SRC_FILE}
    MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/process.sh)
  list(APPEND TARGET_FILES "${PROJECT_SOURCE_DIR}/sub/${TARGET_FILE}")
endforeach()
add_custom_target(foo_txt ALL DEPENDS ${TARGET_FILES})

Upvotes: 0

Views: 1384

Answers (1)

Florian
Florian

Reputation: 42852

It's a little unclear what you are trying to achieve, but just from looking at it I would say it should be:

set(dest_dir ${PROJECT_SOURCE_DIR}/sub)
add_custom_target(
    subtask ALL
    COMMAND ${CMAKE_COMMAND} -E make_directory ${dest_dir}
    COMMAND ${PROJECT_SOURCE_DIR}/process.sh
)

Only if the output.txt is an input for something else, you need a custom command:

set(dest_dir ${PROJECT_SOURCE_DIR}/sub)
add_custom_command(
    OUTPUT ${dest_dir}/output.txt
    COMMAND ${CMAKE_COMMAND} -E make_directory ${dest_dir}
    COMMAND ${PROJECT_SOURCE_DIR}/process.sh
    MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/process.sh
)
add_custom_target(
    subtask ALL 
    DEPENDS ${dest_dir}/output.txt 
)

Note that the default working directory for those commands is CMAKE_CURRENT_BINARY_DIR.

Edit: I think the problem in your code is the use of add_dependencies() for file level dependencies. But add_dependencies() can only be used to declare target dependencies.

Edit: With a foreach() you can either collect the dependencies or APPEND them with to a dummy output. The first looks something like this:

file(GLOB srcfiles "src/*.txt")
set(dest_dir "${PROJECT_SOURCE_DIR}/sub")
file(MAKE_DIRECTORY "${dest_dir}")
foreach(srcfile ${srcfiles})
    get_filename_component(filename "${srcfile}" NAME_WE)
    add_custom_command(
        OUTPUT "${dest_dir}/${filename}.txt"
        COMMAND ${PROJECT_SOURCE_DIR}/process.sh ${srcfile}
        MAIN_DEPENDENCY "${srcfile}"
        DEPENDS "${PROJECT_SOURCE_DIR}/process.sh"
        WORKING_DIRECTORY "${dest_dir}"
    )
    list(APPEND subtask_deps "${dest_dir}/${filename}.txt")
endforeach(srcfile)
add_custom_target(
    subtask ALL
    DEPENDS ${subtask_deps}
)

Upvotes: 1

Related Questions