Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake and no-warn MSVC support #118

Open
wants to merge 4 commits into
base: release
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
cmake_minimum_required(VERSION 3.11)

project(greatest VERSION 1.5.0 LANGUAGES C)

#===============#
# Compiler args #
#===============#

set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
set(CMAKE_C_STANDARD 90 CACHE STRING "")

add_library("${PROJECT_NAME}_compiler_flags" INTERFACE)
if ((NOT DEFINED MSVC_VERSION
OR MSVC_VERSION STRGREATER "1900") # 2015
AND NOT (CMAKE_C_COMPILER_ID STREQUAL "OpenWatcom"))
target_compile_features("${PROJECT_NAME}_compiler_flags" INTERFACE "c_std_${CMAKE_C_STANDARD}")
else ()
message(STATUS "not adding compile features")
endif ()

if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.15")
# add compiler warning flags just when building this project via
# the BUILD_INTERFACE genex
set(gcc_like "$<COMPILE_LANG_AND_ID:C,CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc "$<COMPILE_LANG_AND_ID:C,CXX,MSVC>")
target_compile_options(
"${PROJECT_NAME}_compiler_flags"
INTERFACE
"$<${gcc_like}:$<BUILD_INTERFACE:-Wshadow;-Wformat=2;-Wall;-pedantic;-Wno-format-nonliteral;-Wno-unused-function;-Wno-long-long>>"
"$<${msvc}:$<BUILD_INTERFACE:-W3;-WX;-Zi;-permissive->>"
)
endif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.15")

# Set the build directories
if (CMAKE_SYSTEM_NAME STREQUAL "Windows"
OR CMAKE_SYSTEM_NAME STREQUAL "CYGWIN"
OR CMAKE_SYSTEM_NAME MATCHES "MINGW.*")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
else ()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
endif ()

#===========#
# Configure #
#===========#

# configure a header file to pass the version number only
configure_file(
"${CMAKE_SOURCE_DIR}/contrib/cmake/config.h.in"
"${PROJECT_NAME}Config.h"
)

#=============#
# Sub-targets #
#=============#

include(CTest)
if (BUILD_TESTING)
add_subdirectory("${CMAKE_SOURCE_DIR}/contrib/cmake/example")
add_subdirectory("${CMAKE_SOURCE_DIR}/contrib/cmake/example_cpp")
endif (BUILD_TESTING)

#=========#
# Install #
#=========#

include(GNUInstallDirs)

include(InstallRequiredSystemLibraries)
set(CPACK_BUNDLE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "SamuelMarks")
set(CPACK_PACKAGE_DESCRIPTION "A C testing library in 1 file. No dependencies, no dynamic allocation. ISC licensed.")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
if (APPLE)
set(CPACK_BUNDLE_PLIST "contrib/cmake/Info.plist")
set(CPACK_BUNDLE_ICON "contrib/cmake/Info.plist")
set(CPACK_PACKAGE_ICON "contrib/cmake/CustomVolumeIcon.icns")
endif (APPLE)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "${${PROJECT_NAME}_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${${PROJECT_NAME}_VERSION_MINOR}")
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/contrib/cmake/README.txt")
set(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/contrib/cmake/Welcome.txt")
set(CPACK_PACKAGE_CONTACT "https://github.com/silentbicycle/${PROJECT_NAME}")

include(CPack)
include(CMakePackageConfigHelpers)

# generate the config file that is includes the exports
configure_package_config_file(
"contrib/cmake/Config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)

# generate the version file for the config file
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}")
Binary file added contrib/cmake/BundleIcon.icns
Binary file not shown.
7 changes: 7 additions & 0 deletions contrib/cmake/CTestConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
set(CTEST_PROJECT_NAME "greatest")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")

set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=greatest")
set(CTEST_DROP_SITE_CDASH TRUE)
4 changes: 4 additions & 0 deletions contrib/cmake/Config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

@PACKAGE_INIT@

include ( "${CMAKE_CURRENT_LIST_DIR}/greatestTargets.cmake" )
Binary file added contrib/cmake/CustomVolumeIcon.icns
Binary file not shown.
14 changes: 14 additions & 0 deletions contrib/cmake/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>BundleGeneratorTest</string>
<key>CFBundleIconFile</key>
<string>BundleGeneratorTest.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
</dict>
</plist>
6 changes: 6 additions & 0 deletions contrib/cmake/MultiCPackConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include("release/CPackConfig.cmake")

set(CPACK_INSTALL_CMAKE_PROJECTS
"debug;greatest;ALL;/"
"release;greatest;ALL;/"
)
7 changes: 7 additions & 0 deletions contrib/cmake/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
greatest

A C testing library in 1 file. No dependencies, no dynamic allocation. ISC licensed.

------------------------------------------------------------------------

Licensed under ISC
1 change: 1 addition & 0 deletions contrib/cmake/Welcome.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This installs greatest.
9 changes: 9 additions & 0 deletions contrib/cmake/config.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef GREATEST_CONFIG_H
#define GREATEST_CONFIG_H

#define GREATEST_VERSION_MAJOR @greatest_VERSION_MAJOR@
#define GREATEST_VERSION_MINOR @greatest_VERSION_MINOR@
#define GREATEST_VERSION_PATCH @greatest_VERSION_PATCH@
#define GREATEST_VERSION "@greatest_VERSION@"

#endif /* !GREATEST_CONFIG_H */
34 changes: 34 additions & 0 deletions contrib/cmake/greatest/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
set(Header_Files "${CMAKE_SOURCE_DIR}/greatest.h")
source_group("Header Files" FILES "${Header_Files}")

add_library("${PROJECT_NAME}" INTERFACE "${Header_Files}")

target_link_libraries("${PROJECT_NAME}" INTERFACE "${PROJECT_NAME}_compiler_flags")

include(GNUInstallDirs)

#=========#
# Install #
#=========#

# setup the version numbering
set_property(TARGET "${PROJECT_NAME}" PROPERTY VERSION "${${PROJECT_NAME}_VERSION}")
set_property(TARGET "${PROJECT_NAME}" PROPERTY SOVERSION "${${PROJECT_NAME}_VERSION_MAJOR}")

install(FILES ${Header_Files}
TYPE "INCLUDE")

#====================#
# Package to install #
#====================#

set(installable_libs "${PROJECT_NAME}" "${PROJECT_NAME}_compiler_flags")
if (TARGET "${DEPENDANT_LIBRARY}")
list(APPEND installable_libs "${DEPENDANT_LIBRARY}")
endif ()
install(TARGETS ${installable_libs}
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(EXPORT "${PROJECT_NAME}Targets" DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}")
2 changes: 1 addition & 1 deletion example.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "greatest.h"

/* Define a suite, compiled seperately. */
/* Define a suite, compiled separately. */
SUITE_EXTERN(other_suite);

/* Declare a local suite. */
Expand Down
39 changes: 39 additions & 0 deletions example_shuffle.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
#include <assert.h>
#include <string.h>

#if defined(_MSC_VER) || defined(__MINGW32__)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
typedef __int64 uint64_t;
#else
#include <sys/time.h>
#include <err.h>
#endif

#include "greatest.h"

Expand Down Expand Up @@ -56,6 +63,34 @@ TEST just_fail(void) {
FAIL();
}

#if defined(_MSC_VER) || defined(__MINGW32__)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than adding a substitute implementation of gettimeofday here, it could just call GetSystemTime and SystemTimeToFileTime then use the milliseconds field. Actually replicating the overall behavior of gettimeofday isn't important -- it's just grabbing a timestamp to use as a seed for example code.

int gettimeofday(struct timeval * tp, struct timezone * tzp)
{
/* Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
* This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
* until 00:00:00 January 1, 1970 */
static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);

SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;

GetSystemTime( &system_time );
SystemTimeToFileTime( &system_time, &file_time );
time = ((uint64_t)file_time.dwLowDateTime ) ;
time += ((uint64_t)file_time.dwHighDateTime) << 32;

tp->tv_sec = (long) ((time - EPOCH) / 10000000L);
tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
return 0;
}

void err(int exit_code, const char *msg) {
fputs(msg, stderr);
exit(exit_code);
}
#endif /* defined(_MSC_VER) || defined(__MINGW32__) */

static unsigned int seed_of_time(void) {
static unsigned int counter = 1;
struct timeval tv;
Expand All @@ -72,7 +107,11 @@ static void set_suffix(unsigned int i) {
* to test conditionally including a "_" separator. */
if (i > 0) {
/* Using `sprintf` here for building with `-std=c89`. */
#if _MSC_VER
(void)sprintf_s(suffix_buf, sizeof(unsigned), "%d", i);
#else
(void)sprintf(suffix_buf, "%d", i);
#endif
greatest_set_test_suffix(suffix_buf);
}
}
Expand Down
14 changes: 12 additions & 2 deletions greatest.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ void greatest_set_test_suffix(const char *suffix);
#define GREATEST_VA_ARGS
#endif

#if defined(__STDC_LIB_EXT1__) || defined(_MSC_VER) || defined(__MINGW32__)
#define strncat_s_else_insec strncat_s
#else
#define strncat_s_else_insec(dest,_,src,count)strncat(dest, src, count)
#endif

/**********
* Macros *
Expand Down Expand Up @@ -728,10 +733,15 @@ static void greatest_buffer_test_name(const char *name) { \
struct greatest_run_info *g = &greatest_info; \
size_t len = strlen(name), size = sizeof(g->name_buf); \
memset(g->name_buf, 0x00, size); \
(void)strncat(g->name_buf, name, size - 1); \
\
(void)strncat_s_else_insec( \
g->name_buf, size, name, size - 1 \
); \
if (g->name_suffix && (len + 1 < size)) { \
g->name_buf[len] = '_'; \
strncat(&g->name_buf[len+1], g->name_suffix, size-(len+2)); \
strncat_s_else_insec( \
&g->name_buf[len+1], size, g->name_suffix, size-(len+2) \
); \
} \
} \
\
Expand Down