diff options
author | Brad King <brad.king@kitware.com> | 2008-01-14 14:20:58 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2008-01-14 14:20:58 (GMT) |
commit | 8262ccfd4efddd4928070c637ef7c414633b4b1e (patch) | |
tree | c276e3f4ec61422534586a008739bd668e1b9ce3 /Tests/Preprocess | |
parent | 2c42f755225c0cb30f04f07c9f5bd23f65ad0bd2 (diff) | |
download | CMake-8262ccfd4efddd4928070c637ef7c414633b4b1e.zip CMake-8262ccfd4efddd4928070c637ef7c414633b4b1e.tar.gz CMake-8262ccfd4efddd4928070c637ef7c414633b4b1e.tar.bz2 |
ENH: Create COMPILE_DEFINITIONS property for targets and source files. Create <config>_COMPILE_DEFINITIONS property as per-configuration version. Add Preprocess test to test the feature. Document limitations on Xcode and VS6 generators.
Diffstat (limited to 'Tests/Preprocess')
-rw-r--r-- | Tests/Preprocess/CMakeLists.txt | 181 | ||||
-rw-r--r-- | Tests/Preprocess/file_def.h | 1 | ||||
-rw-r--r-- | Tests/Preprocess/preprocess.c | 170 | ||||
-rw-r--r-- | Tests/Preprocess/preprocess.cxx | 197 | ||||
-rw-r--r-- | Tests/Preprocess/preprocess.h.in | 16 | ||||
-rw-r--r-- | Tests/Preprocess/preprocess_vs6.cxx | 3 | ||||
-rw-r--r-- | Tests/Preprocess/target_def.h | 1 |
7 files changed, 569 insertions, 0 deletions
diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt new file mode 100644 index 0000000..3631072 --- /dev/null +++ b/Tests/Preprocess/CMakeLists.txt @@ -0,0 +1,181 @@ +project(Preprocess) + +# This test is meant both as a test and as a reference for supported +# syntax on native tool command lines. + +#----------------------------------------------------------------------------- +# Construct a C-string literal to test passing through a definition on +# the command line. We configure the value into a header so it can be +# checked in the executable at runtime. The semicolon is handled +# specially because it needs to be escaped in the COMPILE_DEFINITIONS +# property value to avoid separating definitions but the string value +# must not have it escaped inside the configured header. +set(STRING_EXTRA "") + +if("${CMAKE_GENERATOR}" MATCHES "Make" AND MSVC) + set(NMAKE 1) +endif("${CMAKE_GENERATOR}" MATCHES "Make" AND MSVC) + +if(NOT BORLAND) + # Borland: ; + # The Borland compiler will simply not accept a non-escaped semicolon + # on the command line. If it is escaped \; then the escape character + # shows up in the preprocessing output too. + set(SEMICOLON "\;") +endif(NOT BORLAND) + +if(NOT BORLAND AND NOT WATCOM) + # Borland, WMake: multiple spaces + # The make tool seems to remove extra whitespace from inside + # quoted strings when passing to the compiler. It does not have + # trouble passing to other tools, and the compiler may be directly + # invoked from the command line. + set(STRING_EXTRA "${STRING_EXTRA} ") +endif(NOT BORLAND AND NOT WATCOM) + +if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio") + # VS: , + # Visual Studio will not accept a comma in the value of a definition. + # The comma-separated list of PreprocessorDefinitions in the project + # file seems to be parsed before the content of entries is examined. + set(STRING_EXTRA "${STRING_EXTRA},") +endif(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio") + +if(NOT MINGW) + # MinGW: & + # When inside -D"FOO=\"a & b\"" MinGW make wants -D"FOO=\"a "&" b\"" + # but it does not like quoted ampersand elsewhere. + set(STRING_EXTRA "${STRING_EXTRA}&") +endif(NOT MINGW) + +if(NOT MINGW) + # MinGW: | + # When inside -D"FOO=\"a | b\"" MinGW make wants -D"FOO=\"a "|" b\"" + # but it does not like quoted pipe elsewhere. + set(STRING_EXTRA "${STRING_EXTRA}|") +endif(NOT MINGW) + +if(NOT BORLAND AND NOT MINGW AND NOT NMAKE) + # Borland, NMake, MinGW: ^ + # When inside -D"FOO=\"a ^ b\"" they make wants -D"FOO=\"a "^" b\"" + # but do not like quoted carrot elsewhere. In NMake the non-quoted + # syntax works when the flags are not in a make variable. + set(STRING_EXTRA "${STRING_EXTRA}^") +endif(NOT BORLAND AND NOT MINGW AND NOT NMAKE) + +if(NOT BORLAND AND NOT MINGW AND NOT NMAKE) + # Borland, MinGW: < > + # Angle-brackets have funny behavior that is hard to escape. + set(STRING_EXTRA "${STRING_EXTRA}<>") +endif(NOT BORLAND AND NOT MINGW AND NOT NMAKE) + +# General: \" +# Make tools do not reliably accept \\\" syntax: +# - MinGW and MSYS make tools crash with \\\" +# - Borland make actually wants a mis-matched quote \\" +# or $(BACKSLASH)\" where BACKSLASH is a variable set to \\ +# - VS IDE gets confused about the bounds of the definition value \\\" +# - NMake is okay with just \\\" +if(NMAKE OR "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") + set(STRING_EXTRA "${STRING_EXTRA}\\\"") +endif(NMAKE OR "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") + +# General: # +# MSVC will not accept a # in the value of a string definition on the +# command line. The character seems to be simply replaced by an +# equals =. According to "cl -help" definitions may be specified by +# -DMACRO#VALUE as well as -DMACRO=VALUE. It must be implemented by a +# simple search-and-replace. +# +# The Borland compiler will parse both # and \# as just # but the make +# tool seems to want \# sometimes and not others. +# +# Unix make does not like # in variable settings without extra +# escaping. This could probably be fixed but since MSVC does not +# support it and it is not an operator it is not worthwhile. + +# Compose the final test string. +set(STRING_VALUE "hello `~!@$%*)(_+-=}{][:'.?/ ${STRING_EXTRA}world") + +#----------------------------------------------------------------------------- +# Function-style macro command-line support: +# - Borland does not support +# - MSVC does not support +# - Watcom does not support +# - GCC supports + +# Too few platforms support this to bother implementing. +# People can just configure headers with the macros. + +#----------------------------------------------------------------------------- +# Construct a sample expression to pass as a macro definition. + +set(EXPR "x*y+!(x==(y+1*2))*f(x%2)") + +if(NOT WATCOM) + # Watcom does not support - or / because it parses them as options. + set(EXPR "${EXPR}+y/x-x") +endif(NOT WATCOM) + +#----------------------------------------------------------------------------- + +# Inform the test if the debug configuration is getting built. +# The NDEBUG definition takes care of this for release. +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DPREPROCESS_DEBUG") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DPREPROCESS_DEBUG") + +# Inform the test if it built from Xcode or VS6 IDE. +if(XCODE) + set(PREPROCESS_XCODE 1) +endif(XCODE) +if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6") + set(PREPROCESS_VS6 1) + set(VS6 _vs6) +endif("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6") + +# Test old-style definitions. +add_definitions(-DOLD_DEF -DOLD_EXPR=2) + +set(FILE_PATH "${Preprocess_SOURCE_DIR}/file_def.h") +set(TARGET_PATH "${Preprocess_SOURCE_DIR}/target_def.h") + +# Create a list of definition property strings. +set(TARGET_DEFS "TARGET_DEF") +set(FILE_DEFS "FILE_DEF") + +# Add definitions with values. VS6 does not support this. +if(NOT PREPROCESS_VS6) + list(APPEND TARGET_DEFS + "TARGET_STRING=\"${STRING_VALUE}${SEMICOLON}\"" + "TARGET_EXPR=${EXPR}" + "TARGET_PATH=\"${TARGET_PATH}\"" + ) + list(APPEND FILE_DEFS + "FILE_STRING=\"${STRING_VALUE}${SEMICOLON}\"" + "FILE_EXPR=${EXPR}" + "FILE_PATH=\"${FILE_PATH}\"" + ) +endif(NOT PREPROCESS_VS6) + +add_executable(Preprocess preprocess.c preprocess${VS6}.cxx) +set_target_properties(Preprocess PROPERTIES + COMPILE_DEFINITIONS "${TARGET_DEFS}" + DEBUG_COMPILE_DEFINITIONS "TARGET_DEF_DEBUG" + RELEASE_COMPILE_DEFINITIONS "TARGET_DEF_RELEASE" + ) +set_source_files_properties(preprocess.c preprocess${VS6}.cxx PROPERTIES + COMPILE_DEFINITIONS "${FILE_DEFS}" + DEBUG_COMPILE_DEFINITIONS "FILE_DEF_DEBUG" + RELEASE_COMPILE_DEFINITIONS "FILE_DEF_RELEASE" + ) + +# Helper target for running test manually in build tree. +add_custom_target(drive COMMAND Preprocess) + +# Configure the header file with the desired string value. +if(SEMICOLON) + set(STRING_VALUE "${STRING_VALUE};") +endif(SEMICOLON) +configure_file(${Preprocess_SOURCE_DIR}/preprocess.h.in + ${Preprocess_BINARY_DIR}/preprocess.h) +include_directories(${Preprocess_BINARY_DIR}) diff --git a/Tests/Preprocess/file_def.h b/Tests/Preprocess/file_def.h new file mode 100644 index 0000000..fbf8986 --- /dev/null +++ b/Tests/Preprocess/file_def.h @@ -0,0 +1 @@ +#define FILE_PATH_DEF diff --git a/Tests/Preprocess/preprocess.c b/Tests/Preprocess/preprocess.c new file mode 100644 index 0000000..baa18df --- /dev/null +++ b/Tests/Preprocess/preprocess.c @@ -0,0 +1,170 @@ +#include <preprocess.h> + +#include FILE_PATH +#include TARGET_PATH + +#include <string.h> +#include <stdio.h> + +int check_defines_C(void) +{ + int result = 1; +#ifndef PREPROCESS_VS6 + if(strcmp(FILE_STRING, STRING_VALUE) != 0) + { + fprintf(stderr, + "FILE_STRING has wrong value in C [%s]\n", FILE_STRING); + result = 0; + } + if(strcmp(TARGET_STRING, STRING_VALUE) != 0) + { + fprintf(stderr, + "TARGET_STRING has wrong value in C [%s]\n", TARGET_STRING); + result = 0; + } + { + int x = 2; + int y = 3; + if((FILE_EXPR) != (EXPR)) + { + fprintf(stderr, "FILE_EXPR did not work in C [%s]\n", + TO_STRING(FILE_EXPR)); + result = 0; + } + if((TARGET_EXPR) != (EXPR)) + { + fprintf(stderr, "TARGET_EXPR did not work in C [%s]\n", + TO_STRING(FILE_EXPR)); + result = 0; + } + } +#endif +#ifdef NDEBUG +# ifdef FILE_DEF_DEBUG + { + fprintf(stderr, "FILE_DEF_DEBUG should not be defined in C\n"); + result = 0; + } +# endif +# ifdef TARGET_DEF_DEBUG + { + fprintf(stderr, "TARGET_DEF_DEBUG should not be defined in C\n"); + result = 0; + } +# endif +# ifndef FILE_DEF_RELEASE +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, "FILE_DEF_RELEASE should be defined in C\n"); + result = 0; + } +# endif +# endif +# ifndef TARGET_DEF_RELEASE + { + fprintf(stderr, "TARGET_DEF_RELEASE should be defined in C\n"); + result = 0; + } +# endif +#endif +#ifdef PREPROCESS_DEBUG +# ifndef FILE_DEF_DEBUG +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, "FILE_DEF_DEBUG should be defined in C\n"); + result = 0; + } +# endif +# endif +# ifndef TARGET_DEF_DEBUG + { + fprintf(stderr, "TARGET_DEF_DEBUG should be defined in C\n"); + result = 0; + } +# endif +# ifdef FILE_DEF_RELEASE + { + fprintf(stderr, "FILE_DEF_RELEASE should not be defined in C\n"); + result = 0; + } +# endif +# ifdef TARGET_DEF_RELEASE + { + fprintf(stderr, "TARGET_DEF_RELEASE should not be defined in C\n"); + result = 0; + } +# endif +#endif +#if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG) +# if !defined(FILE_DEF_DEBUG) || !defined(TARGET_DEF_DEBUG) +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, + "FILE_DEF_DEBUG and TARGET_DEF_DEBUG inconsistent in C\n"); + result = 0; + } +# endif +# endif +# if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE) + { + fprintf(stderr, "DEBUG and RELEASE definitions inconsistent in C\n"); + result = 0; + } +# endif +#endif +#if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE) +# if !defined(FILE_DEF_RELEASE) || !defined(TARGET_DEF_RELEASE) +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, + "FILE_DEF_RELEASE and TARGET_DEF_RELEASE inconsistent in C\n"); + result = 0; + } +# endif +# endif +# if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG) + { + fprintf(stderr, "RELEASE and DEBUG definitions inconsistent in C\n"); + result = 0; + } +# endif +#endif +#ifndef FILE_PATH_DEF + { + fprintf(stderr, "FILE_PATH_DEF not defined in C\n"); + result = 0; + } +#endif +#ifndef TARGET_PATH_DEF + { + fprintf(stderr, "TARGET_PATH_DEF not defined in C\n"); + result = 0; + } +#endif +#ifndef FILE_DEF + { + fprintf(stderr, "FILE_DEF not defined in C\n"); + result = 0; + } +#endif +#ifndef TARGET_DEF + { + fprintf(stderr, "TARGET_DEF not defined in C\n"); + result = 0; + } +#endif +#ifndef OLD_DEF + { + fprintf(stderr, "OLD_DEF not defined in C\n"); + result = 0; + } +#endif +#if !defined(OLD_EXPR) || OLD_EXPR != 2 + { + fprintf(stderr, "OLD_EXPR id not work in C [%s]\n", + TO_STRING(OLD_EXPR)); + result = 0; + } +#endif + return result; +} diff --git a/Tests/Preprocess/preprocess.cxx b/Tests/Preprocess/preprocess.cxx new file mode 100644 index 0000000..07b7183 --- /dev/null +++ b/Tests/Preprocess/preprocess.cxx @@ -0,0 +1,197 @@ +#include <preprocess.h> + +#include FILE_PATH +#include TARGET_PATH + +#include <string.h> +#include <stdio.h> + +extern "C" int check_defines_C(void); + +int check_defines_CXX() +{ + int result = 1; +#ifndef PREPROCESS_VS6 + if(strcmp(FILE_STRING, STRING_VALUE) != 0) + { + fprintf(stderr, + "FILE_STRING has wrong value in CXX [%s]\n", FILE_STRING); + result = 0; + } + if(strcmp(TARGET_STRING, STRING_VALUE) != 0) + { + fprintf(stderr, + "TARGET_STRING has wrong value in CXX [%s]\n", TARGET_STRING); + result = 0; + } + { + int x = 2; + int y = 3; + if((FILE_EXPR) != (EXPR)) + { + fprintf(stderr, "FILE_EXPR did not work in CXX [%s]\n", + TO_STRING(FILE_EXPR)); + result = 0; + } + if((TARGET_EXPR) != (EXPR)) + { + fprintf(stderr, "TARGET_EXPR did not work in CXX [%s]\n", + TO_STRING(FILE_EXPR)); + result = 0; + } + } +#endif +#ifdef NDEBUG +# ifdef FILE_DEF_DEBUG + { + fprintf(stderr, "FILE_DEF_DEBUG should not be defined in CXX\n"); + result = 0; + } +# endif +# ifdef TARGET_DEF_DEBUG + { + fprintf(stderr, "TARGET_DEF_DEBUG should not be defined in CXX\n"); + result = 0; + } +# endif +# ifndef FILE_DEF_RELEASE +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, "FILE_DEF_RELEASE should be defined in CXX\n"); + result = 0; + } +# endif +# endif +# ifndef TARGET_DEF_RELEASE + { + fprintf(stderr, "TARGET_DEF_RELEASE should be defined in CXX\n"); + result = 0; + } +# endif +#endif +#ifdef PREPROCESS_DEBUG +# ifndef FILE_DEF_DEBUG +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, "FILE_DEF_DEBUG should be defined in CXX\n"); + result = 0; + } +# endif +# endif +# ifndef TARGET_DEF_DEBUG + { + fprintf(stderr, "TARGET_DEF_DEBUG should be defined in CXX\n"); + result = 0; + } +# endif +# ifdef FILE_DEF_RELEASE + { + fprintf(stderr, "FILE_DEF_RELEASE should not be defined in CXX\n"); + result = 0; + } +# endif +# ifdef TARGET_DEF_RELEASE + { + fprintf(stderr, "TARGET_DEF_RELEASE should not be defined in CXX\n"); + result = 0; + } +# endif +#endif +#if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG) +# if !defined(FILE_DEF_DEBUG) || !defined(TARGET_DEF_DEBUG) +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, + "FILE_DEF_DEBUG and TARGET_DEF_DEBUG inconsistent in CXX\n"); + result = 0; + } +# endif +# endif +# if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE) + { + fprintf(stderr, "DEBUG and RELEASE definitions inconsistent in CXX\n"); + result = 0; + } +# endif +#endif +#if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE) +# if !defined(FILE_DEF_RELEASE) || !defined(TARGET_DEF_RELEASE) +# ifndef PREPROCESS_XCODE + { + fprintf(stderr, + "FILE_DEF_RELEASE and TARGET_DEF_RELEASE inconsistent in CXX\n"); + result = 0; + } +# endif +# endif +# if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG) + { + fprintf(stderr, "RELEASE and DEBUG definitions inconsistent in CXX\n"); + result = 0; + } +# endif +#endif +#ifndef FILE_PATH_DEF + { + fprintf(stderr, "FILE_PATH_DEF not defined in CXX\n"); + result = 0; + } +#endif +#ifndef TARGET_PATH_DEF + { + fprintf(stderr, "TARGET_PATH_DEF not defined in CXX\n"); + result = 0; + } +#endif +#ifndef FILE_DEF + { + fprintf(stderr, "FILE_DEF not defined in CXX\n"); + result = 0; + } +#endif +#ifndef TARGET_DEF + { + fprintf(stderr, "TARGET_DEF not defined in CXX\n"); + result = 0; + } +#endif +#ifndef OLD_DEF + { + fprintf(stderr, "OLD_DEF not defined in CXX\n"); + result = 0; + } +#endif +#if !defined(OLD_EXPR) || OLD_EXPR != 2 + { + fprintf(stderr, "OLD_EXPR id not work in C [%s]\n", + TO_STRING(OLD_EXPR)); + result = 0; + } +#endif + return result; +} + +int main() +{ + int result = 1; + + if(!check_defines_C()) + { + result = 0; + } + + if(!check_defines_CXX()) + { + result = 0; + } + + if(result) + { + printf("All preprocessor definitions are correct.\n"); + return 0; + } + else + { + return 1; + } +} diff --git a/Tests/Preprocess/preprocess.h.in b/Tests/Preprocess/preprocess.h.in new file mode 100644 index 0000000..3e1c7a0 --- /dev/null +++ b/Tests/Preprocess/preprocess.h.in @@ -0,0 +1,16 @@ +/* Define configured macros. */ +#define STRING_VALUE "@STRING_VALUE@" +#define EXPR @EXPR@ +#cmakedefine PREPROCESS_XCODE +#cmakedefine PREPROCESS_VS6 + +#ifdef PREPROCESS_VS6 +# define FILE_PATH "@FILE_PATH@" +# define TARGET_PATH "@TARGET_PATH@" +#endif + +/* Declarations and macros shared by all sources. */ +#define TO_STRING(x) TO_STRING0(x) +#define TO_STRING0(x) #x + +static int f(int i) { return i*3; } diff --git a/Tests/Preprocess/preprocess_vs6.cxx b/Tests/Preprocess/preprocess_vs6.cxx new file mode 100644 index 0000000..9df89f6 --- /dev/null +++ b/Tests/Preprocess/preprocess_vs6.cxx @@ -0,0 +1,3 @@ +// The VS6 IDE does not support object name configuration so we need a +// source file with a different name. Include the real source file. +#include "preprocess.cxx" diff --git a/Tests/Preprocess/target_def.h b/Tests/Preprocess/target_def.h new file mode 100644 index 0000000..f016d5c --- /dev/null +++ b/Tests/Preprocess/target_def.h @@ -0,0 +1 @@ +#define TARGET_PATH_DEF |