Skip to content

Commit

Permalink
Changes to enable building the library for WIN32
Browse files Browse the repository at this point in the history
  • Loading branch information
thoni56 committed Jun 11, 2019
1 parent a96be46 commit 81d5d72
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 30 deletions.
95 changes: 95 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
= Building Cgreen =

Here's some quick notes on what we know about various problems
building Cgreen on multiple platforms.

Cgreen is CMake-based but we have tried to make building as convenient
as possible.

== General instructions ==

On platforms where Cgreen can be built in full here are the simple instructions:

- In the root directory just do

make

or

make unit

This will configure an out-of-source CMake build directory in 'build',
compile everything and run some unit tests. If you want the CTest
tests, try

make test

To install, do

sudo make install

== Linux/Posix/Darwin/Cygwin/Msys2 ==

Everything just works as expected ;-) except that for Cygwin where you
don't need 'sudo' to install.

For all these platforms you get a complete native/Posix Cgreen
installation.

NOTE that for Cygwin and Msys2 the build cannot be used for Windows
applications. Both platforms are Posix-layers incompatible with
Windows. However, for Msys2, read on.

== Windows ==

As Cgreen uses Posix fork() and dynamic library loading, creating a
fully working Windows build is not straight forward. However, some
progress is being made. Here's the closest we have come so far:

- Use Msys2/Mingw32 (this is the Mingw32 cross-compilation variant of
Msys2, NOT the Posix-compliant variant...)

- Ensure that you have the Mingw32 toolchain installed, including
mingw32-cmake

- Create a 'build' directory and 'cd' into it

- Do

cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE:string=Debug ..
make

This will partially succeed. It will currently break when trying to
build the `cgreen-runner`. (`cgreen-runner` dynamically loads
libraries and discover tests in them and runs those.)

The current status is that this creates `libcgreen.dll` and
`libcgreen.dll.a` which allows you to use the "main program runner"
strategy for creating Cgreen tests.

Unfortunately, at this point tests will crash when forking so you need
to prevent this and have all tests run in the same process:

CGREEN_NO_FORK=1 all_tests.exe

It is also unknown at this time if mocks works at all.

But this is a work in progress, and we are happy to get this far.

=== cgreen-runner ===

==== dlfcn =====

The reflective runner `cgreen-runner` relies on Posix functionality to
dynamically load and inspect dynamically loadable libraries (DDLs,
.so's, .dylib's, ...)

Fortunately there is an adapter available for the Windows API,
dlfcn-win32. It is even available for Msys2/Mingw32. Install it with

pacman -Syu mingw32/mingw-w64-i686-dlfcn


==== fnmatch ====

Current stumbling stone is fnmatch.h...
2 changes: 1 addition & 1 deletion cmake/Modules/MacroAddTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
macro (macro_add_test)
add_test(${ARGN})
if (CYGWIN OR WIN32)
set_tests_properties(${ARGV1} PROPERTIES ENVIRONMENT PATH=${PROJECT_BINARY_DIR}/src:$ENV{PATH})
set_tests_properties(${ARGV1} PROPERTIES ENVIRONMENT PATH=${PROJECT_BINARY_DIR}/src)
endif ()
endmacro(macro_add_test)
2 changes: 1 addition & 1 deletion include/cgreen/cgreen_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <stdint.h>

typedef enum {INTEGER, STRING, DOUBLE, POINTER} CgreenValueType;
typedef enum {INTEGER, STRING, DOUBLE_TYPE, POINTER} CgreenValueType;

typedef struct {
CgreenValueType type;
Expand Down
11 changes: 9 additions & 2 deletions include/cgreen/internal/windows_headers/wincompat.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#ifndef __WINCOMPAT_H__
#define __WINCOMPAT_H__
#ifdef _MSC_VER
#if defined(_MSC_VER) || defined(__MINGW32__)
#include "stdarg.h"
#include "windows.h"
#include "direct.h"
#include <shlwapi.h>

#define gmtime_r(x,y) gmtime_s(y,x)

Expand All @@ -25,6 +26,12 @@ typedef int pid_t;
#define PRIdPTR "Id"
#endif

/* Simple replacement for isatty() */
#define isatty(x) 1

/* Simple replacement for setenv() */
#define setenv(variable, value, overwrite) SetEnvironmentVariable(variable, value)


#endif //_MSC_VER
#endif //__WINCOMPAT_H__

30 changes: 17 additions & 13 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,29 +76,33 @@ set(cgreen_SRCS
xml_reporter.c
)

if (MSYS)
if(WIN32)
# Msys2 is difficult since it really is three different "OS":es, Msys native, W32 and W64
# To get somewhere, let's use the native Msys2, which actually is Cygwin/UNIX.
LIST(APPEND cgreen_SRCS
posix_cgreen_pipe.c
posix_cgreen_time.c
posix_runner_platform.c
)
# If "cross-compiling" using MinGW32...
if(MINGW)
LIST(APPEND cgreen_SRCS
win32_cgreen_pipe.c
win32_cgreen_time.c
win32_runner_platform.c
)
else()
# ... we assume native MSYS2...
LIST(APPEND cgreen_SRCS
posix_cgreen_pipe.c
posix_cgreen_time.c
posix_runner_platform.c
)
endif()
elseif (UNIX OR CYGWIN)
LIST(APPEND cgreen_SRCS
posix_cgreen_pipe.c
posix_cgreen_time.c
posix_runner_platform.c
)
elseif(WIN32)
LIST(APPEND cgreen_SRCS
win32_cgreen_pipe.c
win32_cgreen_time.c
win32_runner_platform.c
)
else()
message(FATAL_ERROR "Cgreen can currently only be compiled for Msys2, Cygwin, MacOSX and Windows.")
endif()

SET_SOURCE_FILES_PROPERTIES(${cgreen_SRCS} PROPERTIES LANGUAGE C)

set(cgreen_SRCS ${cgreen_SRCS}
Expand Down
5 changes: 4 additions & 1 deletion src/cdash_reporter.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#ifdef _MSC_VER
#include <wincompat.h>
#endif
#ifdef __MINGW32__
#include "cgreen/internal/windows_headers/wincompat.h"
#endif

#include <cgreen/cdash_reporter.h>
#include "cdash_reporter_internal.h"
Expand Down Expand Up @@ -85,7 +88,7 @@ TestReporter *create_cdash_reporter(CDashInfo *info) {
memo->info = info;
memo->begin = cdash_build_stamp(sbuildstamp, 15);
reporter->memo = memo;

set_cdash_reporter_printer(reporter, fprintf);
set_cdash_reporter_vprinter(reporter, vfprintf);

Expand Down
2 changes: 1 addition & 1 deletion src/cgreen_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ CgreenValue make_cgreen_pointer_value(void *pointer) {
}

CgreenValue make_cgreen_double_value(double d) {
CgreenValue value = {DOUBLE, {0}};
CgreenValue value = {DOUBLE_TYPE, {0}};
value.value.double_value = d;
return value;
}
Expand Down
8 changes: 4 additions & 4 deletions src/mocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ static void handle_missing_expectation_for(const char *function, const char *moc


static CgreenValue convert_boxed_double_to_cgreen_value(CgreenValue actual) {
actual.type = DOUBLE;
actual.type = DOUBLE_TYPE;
actual.value.double_value = unbox_double(actual.value.integer_value);
return actual;
}
Expand Down Expand Up @@ -278,7 +278,7 @@ intptr_t mock_(TestReporter* test_reporter, const char *function, const char *mo
expectation->times_triggered++;
destroy_expectation_if_time_to_die(expectation);

if (stored_result.type == DOUBLE) {
if (stored_result.type == DOUBLE_TYPE) {
#ifdef V2
/* TODO: for v2 we should ensure that the user is not trying to return a double
through 'mock()' when there is a 'mock_double()' available, which there isn't yet.
Expand Down Expand Up @@ -343,7 +343,7 @@ static CgreenVector *create_vector_of_actuals(va_list actuals, int count) {
static Constraint *create_appropriate_equal_constraint_for(const char *parameter_name,
CgreenValue actual) {
Constraint *constraint;
if (actual.type == DOUBLE)
if (actual.type == DOUBLE_TYPE)
constraint = create_equal_to_double_constraint(actual.value.double_value,
parameter_name);
else
Expand Down Expand Up @@ -654,7 +654,7 @@ void print_learned_mocks(void) {
fprintf(stderr, "\texpect(%s", function_name);
for (c = 0; c < cgreen_vector_size(expectation->constraints); c++) {
Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, c);
if (constraint->expected_value.type == DOUBLE)
if (constraint->expected_value.type == DOUBLE_TYPE)
fprintf(stderr, ", when(%s, is_equal_to_double(%f))", constraint->expected_value_name,
constraint->expected_value.value.double_value);
else
Expand Down
10 changes: 5 additions & 5 deletions src/win32_runner_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "runner.h"
#include "cgreen/internal/runner_platform.h"
#include "cgreen/messaging.h"
#include "wincompat.h"
#include "cgreen/internal/windows_headers/wincompat.h"
#include "cgreen/internal/cgreen_time.h"

#include "win32_cgreen.h"
Expand Down Expand Up @@ -64,7 +64,7 @@ static void run_named_test_child(TestSuite *suite, const char *name, TestReporte
reporter->duration = cgreen_time_duration_in_milliseconds(test_starting_milliseconds,
cgreen_time_get_current_milliseconds());

(*reporter->finish_suite)(reporter, newSuite->filename, newSuite->line, test_duration);
(*reporter->finish_suite)(reporter, newSuite->filename, newSuite->line);
(*suite->teardown)();
}
}
Expand All @@ -91,7 +91,7 @@ void run_specified_test_if_child(TestSuite *suite, TestReporter *reporter){
reporter->duration = cgreen_time_duration_in_milliseconds(test_starting_milliseconds,
cgreen_time_get_current_milliseconds());

reporter_finish_test(reporter, suite->filename, suite->line, NULL, test_duration);
reporter_finish_test(reporter, suite->filename, suite->line, NULL);

return; //never happens because we call stop inside run_named_test_child
}
Expand Down Expand Up @@ -120,7 +120,7 @@ static void AddEnvironmentVariable(struct environment* env,const char* varName,
StringCbCatA(env->p_head, envSize, "=");
StringCbCatA(env->p_head, envSize, valueString);
StringCbCatA(env->p_head, envSize, "\0");
len = strnlen_s(env->p_head, envSize);
len = strnlen(env->p_head, envSize);
env->p_head += (len + 1);
}

Expand Down Expand Up @@ -174,7 +174,7 @@ void run_test_in_its_own_process(TestSuite *suite, CgreenTest *test, TestReporte
reporter->duration = cgreen_time_duration_in_milliseconds(test_starting_milliseconds,
cgreen_time_get_current_milliseconds());

(*reporter->finish_test)(reporter, test->filename, test->line, NULL, test_duration);
(*reporter->finish_test)(reporter, test->filename, test->line, NULL);

return;
}
Expand Down
6 changes: 5 additions & 1 deletion tests/all_c_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ TestSuite *xml_reporter_tests(void);

int main(int argc, char **argv) {
int suite_result;
#ifdef __cplusplus
TestSuite *suite = create_named_test_suite("all_cpp_tests");
#else
TestSuite *suite = create_named_test_suite("all_c_tests");
TestReporter *reporter = create_text_reporter();
#endif
TestReporter *reporter = create_text_reporter();

add_suite(suite, assertion_tests());
add_suite(suite, breadcrumb_tests());
Expand Down
2 changes: 1 addition & 1 deletion tests/cgreen_value_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Ensure(CgreenValue, makes_pointer_value) {

Ensure(CgreenValue, makes_double_value) {
CgreenValue value = make_cgreen_double_value(3.1415926);
assert_that(value.type, is_equal_to(DOUBLE));
assert_that(value.type, is_equal_to(DOUBLE_TYPE));
assert_that_double(value.value.double_value, is_equal_to_double(3.1415926));
destroy_cgreen_value(value);
}
2 changes: 2 additions & 0 deletions tests/constraint_messages_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ Ensure(ConstraintMessage, for_no_mock_parameters_with_parameter_constraint) {
forgot_to_pass_parameters_mock(0);
}

#ifndef __WIN32__
Ensure(ConstraintMessage, increments_exception_count_when_terminating_via_SIGQUIT) {
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit core_limit;
Expand All @@ -226,6 +227,7 @@ Ensure(ConstraintMessage, increments_exception_count_when_terminating_via_SIGQUI
#endif
raise(SIGQUIT);
}
#endif

Ensure(ConstraintMessage, increments_exception_count_when_terminating_via_SIGTERM) {
raise(SIGTERM);
Expand Down
3 changes: 3 additions & 0 deletions tests/environment_variables_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include <unistd.h>
#include <stdlib.h>

#ifdef WIN32
#include "../include/cgreen/internal/windows_headers/wincompat.h"
#endif

#ifdef __cplusplus
using namespace cgreen;
Expand Down
2 changes: 2 additions & 0 deletions tests/messaging_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Ensure(can_send_message) {
assert_that(receive_cgreen_message(messaging), is_equal_to(99));
}

#ifndef WIN32
static int signal_received = 0;
static void catch_signal(int s) {
(void)s;
Expand Down Expand Up @@ -61,6 +62,7 @@ Ensure(failure_reported_and_exception_thrown_when_messaging_would_block) {
assert_that(loop, is_less_than(LOOPS));
assert_that(panic_message, contains_string("Too many assertions"));
}
#endif

TestSuite *messaging_tests(void) {
TestSuite *suite = create_test_suite();
Expand Down
5 changes: 5 additions & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ if(CYGWIN)
add_definitions(-std=gnu99)
endif()

#if (WIN32)
# find_package(dlfcn-win32 REQUIRED)
# set(CMAKE_DL_LIBS dlfcn-win32::dl)
#endif()

add_executable(cgreen-runner ${RUNNER_SRCS})
target_link_libraries(cgreen-runner ${CGREEN_SHARED_LIBRARY} ${CMAKE_DL_LIBS})

Expand Down
7 changes: 7 additions & 0 deletions tools/cgreen-runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@
#include "runner.h"
#include "discoverer.h"

#ifdef __MINGW32__
#include "../include/cgreen/internal/windows_headers/wincompat.h"
#endif

/*----------------------------------------------------------------------*/
static int file_exists(const char *filename)
{
if (! filename) return 0;
#ifdef __MINGW32__
return PathFileExistsA(filename);
#else
return (access(filename, F_OK) == 0);
#endif
}


Expand Down

0 comments on commit 81d5d72

Please sign in to comment.