0

I have a CMake Project with a macro inside my CPP file to enable some debugging code, as shown below:

main.cpp

#ifdef MY_FLAG_DEBUG
  // added for debugging only
  cv::imwrite("segmentation.png", img);
#endif

I defined MY_FLAG_DEBUG inside CMakeLists.txt. Please see below:

CMakeLists.txt

option(MY_FLAG "Use MY_FLAG" OFF) # OFF by default
if(MY_FLAG)
  add_definitions(-DMY_FLAG_DEBUG)
endif()

# if(MY_FLAG)
#   target_compile_definitions(${PROJECT_NAME}
#     PRIVATE "${PROJECT_NAME}_BUILDING_DLL"
#     PRIVATE MY_FLAG_DEBUG
#   )
# else()
#   target_compile_definitions(${PROJECT_NAME}
#     PRIVATE "${PROJECT_NAME}_BUILDING_DLL"
#   )
# endif(MY_FLAG)

target_compile_definitions(${PROJECT_NAME}
  PRIVATE "${PROJECT_NAME}_BUILDING_DLL"
)

It works BUT shows the following error when no command-line argument is given (MY_FLAG is unset):

CMake Warning:
  Manually-specified variables were not used by the project:

    MY_FLAG

The above approach declares two variables inside CMakeLists.txt to enable a macro. Moreover, it turned out that the above is an old practice, and target_compile_definitions should be preferred. I tried, but it could not work. Please see the commented lines in the CMakeLists.txt file. In addition, I found the following posts 1 and 2. Unfortunately, they did not discuss unused variables.

My goal is to enable the macro only when specified as a command-line argument.

Questions

  1. How to use a newer command, i.e., target_compile_definitions in this case?
  2. How to modify the existing approach so that CMake does not display a warning?
ravi
  • 6,140
  • 18
  • 77
  • 154
  • "It works BUT shows the following error when no command-line argument is given" - Strange: the warning you got is solely about variables specified in the command line. "The above approach declares two variables inside CMakeLists.txt to enable a macro." - What two variables you are talking about? I see definition of `MY_FLAG` variable only. – Tsyvarev Jun 22 '22 at 10:55
  • @Tsyvarev: Sorry for the confusion. _What two variables you are talking about?_ The another, I meant the `-DMY_FLAG_DEBUG`. It makes the CPP code a bit harder to read. I would love to use ONLY `MY_FLAG` such as `#ifdef MY_FLAG // some CPP here #endif` – ravi Jun 22 '22 at 11:02
  • But what is exactly "not work"? Is macro definition `MY_FLAG_DEBUG` added when you pass `-DMY_FLAG=ON` in the command line? – Tsyvarev Jun 22 '22 at 11:37
  • @Tsyvarev: I added questions in my post. May I request you to have a look once again? – ravi Jun 22 '22 at 12:43
  • 1
    On Stack Overflow we tend to have a **single question** in a question post, but you ask 2 questions which has a little common. 1. Your usage of `target_compile_definitions` *seems* to be correct. If you have any problem with it, then ask specifically about that problems. 2. CMake shouldn't emit a warning about not used variable if that variable is not passed via command line. Probably, you run not the project you show us, or there are other inconsistencies. – Tsyvarev Jun 22 '22 at 13:22
  • @Tsyvarev: Thanks! I am using `target_compile_definitions`, the only problem is that cmake is caching `MY_FLAG`. Basically, when I am not providing any command-line arguments, I suppose cmake to build using default option, but it is not doing so. I tried `unset(MY_FLAG CACHE)` after `endif(MY_FLAG)` but no help. Any comments? – ravi Jun 23 '22 at 03:03
  • "Basically, when I am not providing any command-line arguments, I suppose cmake to build using default option, but it is not doing so." - Finally, the **actual** problem... No, CMake doesn't behave as you expected. CMake treats command line options as **modification** of options passed previously. That is, if option is specified in the command line, then it overwrites the previous value. Otherwise the previous value is used. For unset option (that is, it will be initialized with default value) use `-U` parameter to `cmake`: `-UMY_FLAG`. – Tsyvarev Jun 23 '22 at 07:34
  • @Tsyvarev: Sorry for extending this discussion. I found -U flag previously. I wish to mention it inside `CMakeLists.txt`, so I added `unset(MY_FLAG CACHE)` after `endif(MY_FLAG)` but no success. – ravi Jun 23 '22 at 09:25

2 Answers2

0

Probably the issue is the wrong target name in the target_compile_definitions command; you are using ${PROJECT_NAME} instead of the named target.
The quote from cmake manual:
"The named target must have been created by a command such as add_executable() or add_library()"

CMakeList.txt

cmake_minimum_required(VERSION 3.22)
project(my_flag_proj)
option(MY_FLAG "Use MY_FLAG" OFF) # OFF by default

add_executable(my_flag_test)
target_sources(my_flag_test PRIVATE main.cpp)
if(MY_FLAG)
   target_compile_definitions(my_flag_test
     PRIVATE "${PROJECT_NAME}_BUILDING_DLL"
     PRIVATE MY_FLAG_DEBUG
   )
 else()
   target_compile_definitions(my_flag_test
     PRIVATE "${PROJECT_NAME}_BUILDING_DLL"
   )
endif(MY_FLAG)

main.cpp

#include <iostream>

int main() {
#ifdef MY_FLAG_DEBUG
    std::cout << "MY_FLAG_DEBUG is defined" << std::endl;
#else
    std::cout << "MY_FLAG_DEBUG is undefined" << std::endl;
#endif
    return 0;
}

Output

$cmake -S . -B flagOn -DMY_FLAG=ON 
$cmake -S . -B flagOff
$cmake --build flagOn
$cmake --build flagOff
$./flagOn/my_flag_test && ./flagOff/my_flag_test 
MY_FLAG_DEBUG is defined
MY_FLAG_DEBUG is undefined

TonnyRed
  • 36
  • 3
-1

If you want to use custom CMake flags, call cmake as such:

~/proj/build $ cmake .. -DMY_TARGET_THING=1

Make sure you prefix it with -D and give it a value, otherwise CMake won't parse the option

SimonC
  • 1,547
  • 1
  • 19
  • 43