0

I have seen How to print messages after make done with cmake? which in principle should answer my question, but it does not - so here is an example I prepared.

Say I have these two files in /tmp/cmake_test3:

main.c:

#include <stdio.h>

const char greeting[] = "hello world";

int main() {
    printf("%s!\n", greeting);
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.7)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)

project(my_project)
message("PROJECT_NAME is '${PROJECT_NAME}'")

# change the behavior by setting variable here to TRUE or FALSE
set(USE_CUSTOM_COMMAND TRUE)

add_executable(my_executable
               main.c
              )

target_compile_options(my_executable PRIVATE
                       -Wall
                       -std=c99
                      )

if(USE_CUSTOM_COMMAND)
  message("Using custom command")
  add_custom_command(TARGET my_executable POST_BUILD
                     COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan
                     "Executable: $<TARGET_FILE_DIR:my_executable>"
                     COMMENT "print out executable path"
                    )
else()
  message("Using custom target")
  add_custom_target(printout ALL
      ${CMAKE_COMMAND} -E cmake_echo_color --cyan "PC Executable: $<TARGET_FILE:my_executable>"
      COMMENT "print out executable path"
      VERBATIM
  )
  add_dependencies(printout my_executable)
endif()

So, in /tmp/cmake_test3 I do:

mkdir build && cd build
cmake ../ -DCMAKE_BUILD_TYPE=Debug

For the CMakeLists.txt posted as is, I get the following:

$ cmake ../ -DCMAKE_BUILD_TYPE=Debug
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/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/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
PROJECT_NAME is 'my_project'
Using custom command
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/cmake_test3/build

# `make` first time - outputs message printout
$ make
Scanning dependencies of target my_executable
[ 50%] Building C object CMakeFiles/my_executable.dir/main.c.o
[100%] Linking C executable my_executable
print out executable path
Executable: /tmp/cmake_test3/build
[100%] Built target my_executable

# `make` second time - no message printout
$ make
[100%] Built target my_executable

# make clean; then `make my_executable` first time - outputs message printout
$ make clean
$ make my_executable
[ 50%] Building C object CMakeFiles/my_executable.dir/main.c.o
[100%] Linking C executable my_executable
print out executable path
Executable: /tmp/cmake_test3/build
[100%] Built target my_executable

# `make my_executable` second time - no message printout
$ make my_executable
[100%] Built target my_executable

Ok, so now, change the set(USE_CUSTOM_COMMAND TRUE) to set(USE_CUSTOM_COMMAND FALSE) in the CmakeLists.txt, and let's repeat the process - still in the build/ subdirectory:

$  rm -rf *
$ cmake ../ -DCMAKE_BUILD_TYPE=Debug
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/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/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
PROJECT_NAME is 'my_project'
Using custom target
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/cmake_test3/build

# `make` first time - outputs message printout 
$ make
Scanning dependencies of target my_executable
[ 33%] Building C object CMakeFiles/my_executable.dir/main.c.o
[ 66%] Linking C executable my_executable
[ 66%] Built target my_executable
Scanning dependencies of target printout
[100%] print out executable path
PC Executable: /tmp/cmake_test3/build/my_executable
[100%] Built target printout

# `make` second time - outputs message printout
$ make
[ 66%] Built target my_executable
[100%] print out executable path
PC Executable: /tmp/cmake_test3/build/my_executable
[100%] Built target printout

# make clean; then `make my_executable` first time - no message printout
$ make clean
$ make my_executable
[ 50%] Building C object CMakeFiles/my_executable.dir/main.c.o
[100%] Linking C executable my_executable
[100%] Built target my_executable

# `make my_executable` second time - no message printout
$ make my_executable
[100%] Built target my_executable

So, how do I get a message - specified at CMake level - to print something at end of make always - that is, regardless of:

  • if a binary is built or not,
  • whether I call make or make all or make my_executable ?
sdbbs
  • 4,270
  • 5
  • 32
  • 87
  • Thanks @Tsyvarev - about forgetting `COMMAND`, that's what I thought of at first as well, but in the doc there is `... [ALL] [command1 [args1...]] [COMMAND command2 [args2...] ...] ...`, so I guess as written, my command there applies to `ALL` (actually, without `ALL`, I cannot even get the dependency to run). – sdbbs Oct 04 '22 at 10:50
  • 1
    Ok, actually CMake allows to omit `COMMAND` keyword before the first command. Also I missed the fact you want the message to be printed after `make my_executable`. I deleted my comment: it was completely wrong. – Tsyvarev Oct 04 '22 at 11:15
  • 1
    It seems that **Make** itself doesn't support changing of its "final message". The most one can is to print a message after building **specific target** (or targets). See e.g. [that question](https://stackoverflow.com/questions/2856818/how-to-print-messages-at-the-end-of-configure-make). Probably, CMake could *emulate* that printing by adding the "final message" to every target and somehow silent all printings except the last one... But I don't expect CMake developers will ever implement such things. – Tsyvarev Oct 04 '22 at 11:25
  • Thank you @Tsyvarev - your comment finalizes this question for me; feel free to post it as an answer, I'll accept it! – sdbbs Oct 05 '22 at 00:55

0 Answers0