24

I'm trying to have CMake either run three bash commands or a bash script. However, I can't seem to get it to work.

The bash commands are:

    cd ${CMAKE_SOURCE_DIR}/dependencies/library
    make
    cd ${CMAKE_BINARY_DIR}

Essentially, I would like CMake to build the library in that directory if it does not already exist.

Here's the CMake code I tried:

if(NOT "${CMAKE_SOURCE_DIR}/dependencies/library/lib.o")
   execute_process(COMMAND cd ${CMAKE_SOURCE_DIR}/dependencies/library)
   execute_process(COMMAND make)
   execute_process(COMMAND cd ${CMAKE_BINARY_DIR})
endif(NOT "${CMAKE_SOURCE_DIR}/dependencies/library/lib.o")

However, it's not building anything. What am I doing wrong?

Also, while I'm here asking this: should the third command, to move to the binary folder, be included?

Thanks!

assignment_operator
  • 1,213
  • 4
  • 12
  • 14
  • 3
    First of all why aren't You using `WORKING_DIRECTORY` parameter instead of those `cd` commands?Something like `execute_process(COMMAND make WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/library)`. I suppose, `execute_process()` calls does not share the same environment. Also, if I were You, I'd check out the [`add_custom_target()`](http://www.cmake.org/cmake/help/v3.0/command/add_custom_target.html?highlight=add_custom_target) and [`add_custom_command()`](http://www.cmake.org/cmake/help/v3.0/command/add_custom_command.html?highlight=add_custom_command) for this kind of thing. – Kamiccolo Sep 05 '14 at 14:23
  • 1
    I can't comment on most of what @Kamiccolo said but I can say that I think the detail about `execute_process` not sharing state is almost certainly accurate. It is *incredibly* likely that the `cd` in the first command changes directory only for that process and not for any other ones. – Etan Reisner Sep 05 '14 at 14:26
  • 2
    If you intend to build a third party library, you are probably better off using the [ExternalProject](http://www.cmake.org/cmake/help/v3.0/module/ExternalProject.html) module. – sakra Sep 05 '14 at 18:47
  • Did you check: https://stackoverflow.com/questions/37553280/how-to-build-cmake-externalproject-while-configurating-main-one ? – malat Jan 10 '22 at 13:48

1 Answers1

34

execute_process() is executed during configure time. But you want this to run at build time, thus add_custom_command() and add_custom_target() is what you're looking for.

In this special case you want to generate an output file, so you should go for add_custom_command() (both are essentially the same, but command produces one or multiple output files, while target does not.

The cmake snippet for this should look something like the following:

add_custom_command(
    OUTPUT ${CMAKE_SOURCE_DIR}/dependencies/library/lib.o
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/library
    COMMAND make
)

You then have to add the output file in another target as dependency, and everything should (hopefully) work as expected.

You can also add DEPENDS statements to the add_custom_command() call to rebuild the object file in case some input sources have changed.

starball
  • 20,030
  • 7
  • 43
  • 238
Phil Be
  • 524
  • 4
  • 5