diff --git a/.cmake/Modules/Languages.cmake b/.cmake/Modules/Languages.cmake new file mode 100644 index 0000000..0ad61d4 --- /dev/null +++ b/.cmake/Modules/Languages.cmake @@ -0,0 +1,15 @@ + +if (NOT LANGUAGES) + set(LANGUAGES "") +endif () + +string(REPLACE "," ";" LANGUAGES "${LANGUAGES}") + +foreach (LANG ${LANGUAGES}) + enable_language(${LANG} OPTIONAL) + if (CMAKE_${LANG}_COMPILER_WORKS) + string(TOUPPER ${LANG} LANG_NAME) + set(${LANG_NAME}_BRIDGE 1) + endif () +endforeach () + diff --git a/.travis.yml b/.travis.yml index 97c285a..07926e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ script: -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} + -DLANGUAGES=CXX .. - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7024e7c..969a77c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(Criterion C CXX) +project(Criterion C) set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) @@ -29,6 +29,10 @@ if (MSVC) include_directories(dependencies/wingetopt/src/) endif () +# Language support + +include(Languages) + # Project setup & environment variables set(PROJECT_VERSION "2.1.0") @@ -40,7 +44,9 @@ add_definitions(-DCRITERION_BUILDING_DLL=1) if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") + if (CMAKE_CXX_COMPILER_WORKS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") + endif () endif () if (MSVC) @@ -85,8 +91,9 @@ find_package(PCRE) # List sources and headers set(SOURCE_FILES + src/core/wrappers/wrap.h src/core/wrappers/wrap.c - src/core/wrappers/wrap.cc + src/core/wrappers/wrappers.c src/core/abort.c src/core/abort.h src/core/report.c @@ -145,6 +152,10 @@ if (PCRE_FOUND) set(HAVE_PCRE 1) endif () +if (CMAKE_CXX_COMPILER_WORKS) + set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.cc) +endif () + set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h diff --git a/appveyor.yml b/appveyor.yml index ae99113..4b1cc8d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,6 +43,7 @@ install: -DCTESTS=ON -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" + -DLANGUAGES=CXX -G "%GENERATOR%" .. diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 549cdcd..a2f4ae2 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -33,14 +33,26 @@ # define CR_IDENTIFIER_(Category, Name, Suffix) \ Category ## _ ## Name ## _ ## Suffix +# ifdef __cplusplus +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJCXX +# else +# define CR_LANG CR_LANG_CXX +# endif +# else +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJC +# else +# define CR_LANG CR_LANG_C +# endif +# endif + # ifdef __cplusplus # define CR_TEST_PROTOTYPE_(Category, Name) \ extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) -# define CR_LANG CR_LANG_CPP # else # define CR_TEST_PROTOTYPE_(Category, Name) \ void CR_IDENTIFIER_(Category, Name, impl)(void) -# define CR_LANG CR_LANG_C # endif # define CR_SUITE_IDENTIFIER_(Name, Suffix) \ diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index cbf0aa3..2c6d96c 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -22,6 +22,7 @@ CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ .kind_ = CR_TEST_PARAMETERIZED, \ .param_ = CR_IDENTIFIER_(Category, Name, param), \ .identifier_ = #Category "/" #Name, \ diff --git a/include/criterion/types.h b/include/criterion/types.h index 27cecdd..c2c40a2 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -37,9 +37,15 @@ using std::size_t; enum criterion_language { CR_LANG_C, - CR_LANG_CPP, + CR_LANG_CXX, + CR_LANG_OBJC, + CR_LANG_OBJCXX, + + CR_LANG_SIZE_ // leave this at the end }; +extern const char *const cr_language_names[CR_LANG_SIZE_]; + enum criterion_test_kind { CR_TEST_NORMAL, CR_TEST_PARAMETERIZED, diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7bde575..136a1e0 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -19,19 +19,24 @@ set(SAMPLES redirect.c parameterized.c - signal.cc - report.cc - suites.cc - fixtures.cc - asserts.cc - more-suites.cc - description.cc - simple.cc - theories.cc - redirect.cc - parameterized.cc ) +if (CMAKE_CXX_COMPILER_WORKS) + set(SAMPLES ${SAMPLES} + signal.cc + report.cc + suites.cc + fixtures.cc + asserts.cc + more-suites.cc + description.cc + simple.cc + theories.cc + redirect.cc + parameterized.cc + ) +endif () + set(SCRIPTS tap_test early_exit diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index b2d2fca..4a38382 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -5,13 +5,18 @@ set(SAMPLES other-crashes.c theories_regression.c - failmessages.cc - exit.cc - long-messages.cc - other-crashes.cc - theories_regression.cc - - exception.cc ) +if (CMAKE_CXX_COMPILER_WORKS) + set(SAMPLES ${SAMPLES} + failmessages.cc + exit.cc + long-messages.cc + other-crashes.cc + theories_regression.cc + + exception.cc + ) +endif () + add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") diff --git a/src/config.h.in b/src/config.h.in index fef0a5c..4bc9f70 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -5,6 +5,9 @@ #cmakedefine HAVE_PCRE @HAVE_PCRE@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ +#cmakedefine CXX_BRIDGE @CXX_BRIDGE@ +#cmakedefine OBJC_BRIDGE @OBJC_BRIDGE@ + # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" # define VERSION "${PROJECT_VERSION}" diff --git a/src/core/runner.c b/src/core/runner.c index bbe870a..cd44855 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -157,11 +157,6 @@ struct criterion_test_set *criterion_init(void) { return set; } -f_wrapper *g_wrappers[] = { - [CR_LANG_C] = c_wrap, - [CR_LANG_CPP] = cpp_wrap, -}; - void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { @@ -174,7 +169,14 @@ void run_test_child(struct criterion_test *test, else if (test->data->timeout != 0) setup_timeout((uint64_t) (test->data->timeout * 1e9)); - g_wrappers[test->data->lang_](test, suite); + if (g_wrappers[test->data->lang_]) { + g_wrappers[test->data->lang_](test, suite); + } else { + criterion_test_die( + "The test is compiled in the %s programming language, but the \n" + "criterion runner have been compiled without its language support.", + cr_language_names[test->data->lang_]); + } } #define push_event(Kind, ...) \ diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index 67eeb93..b9e2d1e 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -36,7 +36,7 @@ extern "C" { static INLINE void nothing(void) {} -void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { +void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { criterion_send_event(PRE_INIT, NULL, 0); try { diff --git a/src/core/wrappers/wrap.h b/src/core/wrappers/wrap.h index b7d518f..5f20da9 100644 --- a/src/core/wrappers/wrap.h +++ b/src/core/wrappers/wrap.h @@ -25,11 +25,19 @@ # define WRAP_H_ # include "criterion/types.h" +# include "config.h" typedef void (f_wrapper)(struct criterion_test *, struct criterion_suite *); void c_wrap(struct criterion_test *test, struct criterion_suite *suite); -void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite); + +# ifdef CXX_BRIDGE +void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite); +# endif + +# ifdef OBJC_BRIDGE +void objc_wrap(struct criterion_test *test, struct criterion_suite *suite); +# endif extern f_wrapper *g_wrappers[]; diff --git a/src/core/wrappers/wrappers.c b/src/core/wrappers/wrappers.c new file mode 100644 index 0000000..a4094e1 --- /dev/null +++ b/src/core/wrappers/wrappers.c @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "wrap.h" + +f_wrapper *g_wrappers[CR_LANG_SIZE_] = { + [CR_LANG_C] = c_wrap, + +#ifdef CXX_BRIDGE + [CR_LANG_CXX] = cxx_wrap, +#endif + +#ifdef OBJC_BRIDGE + [CR_LANG_OBJC] = objc_wrap, + [CR_LANG_OBJCXX] = objc_wrap, +#endif +}; + +const char *const cr_language_names[CR_LANG_SIZE_] = { + [CR_LANG_C] = "C", + [CR_LANG_CXX] = "C++", + [CR_LANG_OBJC] = "Objective-C", + [CR_LANG_OBJCXX] = "Objective-C++", +}; + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index da63852..2899c6b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,8 @@ if (NOT MSVC) set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra") + if (CMAKE_CXX_COMPILER_WORKS) + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra") + endif () endif () include_directories(../include ../src) @@ -8,9 +10,14 @@ include_directories(../include ../src) set(TEST_SOURCES ordered-set.c asprintf.c - redirect.cc ) +if (CMAKE_CXX_COMPILER_WORKS) + set(TEST_SOURCES ${TEST_SOURCES} + redirect.cc + ) +endif () + add_executable(criterion_unit_tests EXCLUDE_FROM_ALL ${TEST_SOURCES}) target_link_libraries(criterion_unit_tests criterion)