[CMake] set_target_properties not setting COMPILE_DEFINITIONS?

Michael Hertling mhertling at online.de
Tue Mar 29 01:47:27 EDT 2011


On 03/28/2011 08:23 PM, David Doria wrote:
> I have setup a list of definitions:
> 
> SET(MAIN_BUILD_DEFINITIONS "${MAIN_BUILD_DEFINITIONS} UNIX;")
> SET(MAIN_BUILD_DEFINITIONS "${MAIN_BUILD_DEFINITIONS} PIXEL_DIMENSION=3;")
> 
> I display them and apply them to my executable as follows:
> 
> add_executable(ImageCompleter ${MainSources})
> message("Main build definitions: " ${MAIN_BUILD_DEFINITIONS})
> set_target_properties(ImageCompleter PROPERTIES COMPILE_DEFINITIONS
> "${MAIN_BUILD_DEFINITIONS}")
> 
> The output is:
> Main build definitions:  UNIX PIXEL_DIMENSION=3
> 
> which looks correct (i.e. UNIX was defined)
> 
> However, in my code there is:
> 
> #if defined(UNIX)
> 	... some code...
> #else
> #error "Not implemented for this platform!"
> #endif
> 
> When I build, the error is produced, indicating that UNIX was not defined.
> 
> I created a small standalone example and it worked as expected... any
> suggestions of what else to check?
> 
> Thanks,
> 
> David

AFAICS, you mess up the value of the MAIN_BUILD_DEFINITIONS
list variable. Look at the following CMakeLists.txt file:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(COMPDEFS C)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c)
SET(MAIN_BUILD_DEFINITIONS
    "${MAIN_BUILD_DEFINITIONS} UNIX;")
LIST(LENGTH MAIN_BUILD_DEFINITIONS n)
MESSAGE("MAIN_BUILD_DEFINITIONS: ${MAIN_BUILD_DEFINITIONS} -- n=${n}")
SET(MAIN_BUILD_DEFINITIONS
    "${MAIN_BUILD_DEFINITIONS} PIXEL_DIMENSION=3;")
LIST(LENGTH MAIN_BUILD_DEFINITIONS n)
MESSAGE("MAIN_BUILD_DEFINITIONS: ${MAIN_BUILD_DEFINITIONS} -- n=${n}")
SET_TARGET_PROPERTIES(main PROPERTIES
    COMPILE_DEFINITIONS "${MAIN_BUILD_DEFINITIONS}")

CMake's output contains:

MAIN_BUILD_DEFINITIONS:  UNIX; -- n=2
MAIN_BUILD_DEFINITIONS:  UNIX; PIXEL_DIMENSION=3; -- n=3

Provided that MAIN_BUILD_DEFINITIONS is initially empty, the command
SET(MAIN_BUILD_DEFINITIONS "${MAIN_BUILD_DEFINITIONS} UNIX;") makes
MAIN_BUILD_DEFINITIONS a list of *two* elements: " UNIX" - note the
leading blank - and the empty string "", and the second SET() adds
"PIXEL_DIMENSION=3". Probably, this is not what you intended. ;)

Instead, try

LIST(APPEND MAIN_BUILD_DEFINITIONS "UNIX")
LIST(APPEND MAIN_BUILD_DEFINITIONS "PIXEL_DIMENSION=3")

and CMake's output changes to

MAIN_BUILD_DEFINITIONS: UNIX -- n=1
MAIN_BUILD_DEFINITIONS: UNIX;PIXEL_DIMENSION=3 -- n=2

which should work when used as COMPILE_DEFINITIONS property.

IMO, the rule of thumb is: Don't use semicolons explicitly in SET()
commands to assign list variables, but let CMake do this by itself.
Moreover, be particularly careful when SETting list values, e.g.

SET(A1 "a")
SET(AB1 "${A1} b")
LIST(LENGTH AB1 n)
MESSAGE("AB1: ${AB1} -- n=${n}")
SET(A2 "a" "a")
SET(AB2 "${A2} b")
LIST(LENGTH AB2 n)
MESSAGE("AB2: ${AB2} -- n=${n}")

results in

AB1: a b -- n=1
AB2: a;a b -- n=2

i.e. AB1 is a non-list value which might by unexpected, and AB2 remains
a list with just two elements which might be unexpected, too. Here, the
correct coding is SET(AB1 "${A1}" "b") and SET(AB2 "${A2}" "b") which
could nevertheless lead to AB{1,2} being lists of length two with an
empty first element if AB{1,2} have been empty before. When adding
elements to lists it's best to use the LIST(APPEND ...) command.

BTW, I can see the abovementioned CMakeLists.txt work correctly with
CMake 2.8.4, so what version of CMake do you use for your project?

Regards,

Michael


More information about the CMake mailing list