35

I'm trying to set multiple compile definitions for one of the executables I'm trying to compile in CMake (in order to activate macros used for debugging). Here's what I tried:

add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
    set_target_properties(
            trie_io_test
            PROPERTIES
            COMPILE_DEFINITIONS UNIT_TESTING=1)
    set_target_properties(
            trie_io_test
            PROPERTIES
            COMPILE_DEFINITIONS IO_TEST=1)

Unfortunately this causes only the IO_TEST to be defined.

I also tried the following:

add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
    set_target_properties(
            trie_io_test
            PROPERTIES
            COMPILE_DEFINITIONS UNIT_TESTING=1 IO_TEST=1)

But this, on the other hand, causes CMake error.

How to set both of these definitions for the executable I'm trying to build?

3 Answers 3

71

You want target_compile_definitions instead of set_target_properties:

target_compile_definitions(trie_io_test PRIVATE UNIT_TESTING=1 IO_TEST=1)
Sign up to request clarification or add additional context in comments.

7 Comments

I linked to the docs in my answer, but it's really only useful for libraries rather than exes. Libs can define their compile flags as PRIVATE, PUBLIC or INTERFACE. PRIVATE basically means the flags are only applied to this library. PUBLIC and INTERFACE flags are also applied to any target which links to it (i.e. its dependees); the difference between these two being that INTERFACE flags aren't applied to the library itself - only its dependees.
Thanks, for the reference, this is an answer to my question "What does PRIVATE mean in this case?" which I deleted, because I saw that there was a link to documentation after asking the question.
PRIVATE adds the property just to this target. INTERFACE adds the property to targets that link to this target. PUBLIC acts as both PRIVATE and INTERFACE because it adds the property to both this target and to targets that link to this target.
This appends the compile definitions, right? That is, we can use this command repeatedly with more definitions later on, right?
@einpoklum Yes, you can call it multiple times.
|
2

I find this can work for you:

add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
set_target_properties(
    trie_io_test
    PROPERTIES
    COMPILE_DEFINITIONS UNIT_TESTING=1
    COMPILE_DEFINITIONS IO_TEST=1
   )

Just by adding another COMPILE_DEFINITIONS :P

2 Comments

It didn't work for me when using with set_source_files_properties(). The second overwrites the first.
Does not work. One overwrites the other.
1

This does work:

add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
set_target_properties(
    trie_io_test
    PROPERTIES
    COMPILE_DEFINITIONS "UNIT_TESTING=1;IO_TEST=1"
   )

No clue why this makes a difference. It was my understanding that in cmake, white space separated lists are equivalent to semicolon separated strings.

3 Comments

Isn’t this effectively just validating the previous, very similar answer? If not, can you highlight the difference? I see that the code is slightly different, but it’s unclear as a reader if that difference is critical here. Can you edit your answer to provide clarification?
@JeremyCaney this is the only answer with the semicolon.
The CMake documentation states that "The COMPILE_DEFINITIONS property may be set to a semicolon-separated list of preprocessor definitions using the syntax VAR or VAR=value.". That's why it works and it can be useful if properties are set on a single source file using set_source_files_properties().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.