-
Notifications
You must be signed in to change notification settings - Fork 107
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
base: release
Are you sure you want to change the base?
Changes from 2 commits
41b2f2f
28cad5e
bc3c9ed
28a3e28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
cmake_minimum_required(VERSION 3.11) | ||
|
||
project(greatest VERSION 1.5.0 LANGUAGES C CXX) | ||
|
||
#===============# | ||
# 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) | ||
target_compile_features("${PROJECT_NAME}_compiler_flags" INTERFACE "c_std_${CMAKE_C_STANDARD}") | ||
|
||
# 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->>" | ||
) | ||
|
||
# Set the build directories | ||
if (MSVC) | ||
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_CURRENT_SOURCE_DIR}/cmake/config.h.in" | ||
"${PROJECT_NAME}Config.h" | ||
) | ||
|
||
#=============# | ||
# Sub-targets # | ||
#=============# | ||
|
||
include(CTest) | ||
if (BUILD_TESTING) | ||
add_subdirectory("example") | ||
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 "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Info.plist") | ||
set(CPACK_BUNDLE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Info.plist") | ||
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/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}/cmake/README.txt") | ||
set(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/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( | ||
"${CMAKE_CURRENT_SOURCE_DIR}/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}") |
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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
@PACKAGE_INIT@ | ||
|
||
include ( "${CMAKE_CURRENT_LIST_DIR}/greatestTargets.cmake" ) |
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> |
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;/" | ||
) |
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This installs greatest. |
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 */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
foreach (example | ||
"example" | ||
"example_cpp" | ||
"example_no_runner" | ||
"example_no_suite" | ||
"example_shuffle" | ||
"example_suite" | ||
"example_trunc") | ||
set(EXEC_NAME "${PROJECT_NAME}_${example}") | ||
if (example STREQUAL "example_cpp" OR example STREQUAL "example_suite") | ||
continue() #set(Source_Files "../${example}.cpp") | ||
elseif (example STREQUAL "example") | ||
set(Source_Files "../${example}.c" "../${example}_suite.c") | ||
else () | ||
set(Source_Files "../${example}.c") | ||
endif () | ||
source_group("Source Files" FILES "${Source_Files}") | ||
|
||
add_executable("${EXEC_NAME}" "${Header_Files}" "${Source_Files}") | ||
|
||
target_link_libraries("${EXEC_NAME}" PUBLIC "${PROJECT_NAME}_compiler_flags") | ||
|
||
include(GNUInstallDirs) | ||
target_include_directories( | ||
"${EXEC_NAME}" | ||
PUBLIC | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>" | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>" | ||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" | ||
) | ||
add_test(NAME "${EXEC_NAME}" | ||
COMMAND "${CMAKE_BINARY_DIR}/${EXEC_NAME}") | ||
endforeach () |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -700,6 +700,99 @@ typedef enum greatest_test_res { | |
prng->count_run = prng->random_order = prng->initialized = 0; \ | ||
} while(0) | ||
|
||
#if defined(__STDC_LIB_EXT1__) || defined(_MSC_VER) || defined(__MINGW32__) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this really necessary? Note the bit in the README about the LOC limit -- this would exceed that, considerably. Also, it adds a substantial block of code with a different license. I'd really prefer to avoid doing that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes but Again happy to remove the code and just use a different macro-branch for MSVC, the goal is to get it to compile in MSVC without throwing any warnings related to https://learn.microsoft.com/en-us/cpp/c-runtime-library/security-features-in-the-crt |
||
#else | ||
/* Taken then modified from Apache-2.0 licensed Vector Packet Processing @ 4141ded */ | ||
#include <err.h> | ||
|
||
#define PREDICT_FALSE(x) __builtin_expect((x),0) | ||
typedef unsigned int uword __attribute__ ((mode (SI))); | ||
typedef unsigned char u8; | ||
|
||
|
||
size_t | ||
strnlen_s (const char *s, size_t maxsize) | ||
{ | ||
u8 bad; | ||
|
||
bad = (s == 0) + (maxsize == 0); | ||
if (PREDICT_FALSE (bad != 0)) | ||
{ | ||
if (s == 0) | ||
err(1, "[C11 violation] s NULL"); | ||
if (maxsize == 0) | ||
err(1, "[C11 violation] maxsize 0"); | ||
return 0; | ||
} | ||
return strnlen (s, maxsize); | ||
} | ||
|
||
errno_t | ||
strncat_s (char *__restrict__ dest, rsize_t dmax, | ||
const char *__restrict__ src, rsize_t n) | ||
{ | ||
u8 bad; | ||
uword low, hi; | ||
size_t m, dest_size, allowed_size; | ||
errno_t status = EOK; | ||
|
||
bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0); | ||
if (PREDICT_FALSE (bad != 0)) | ||
{ | ||
/* Not actually trying to concatenate anything is OK */ | ||
if (n == 0) | ||
return EOK; | ||
if (dest == 0) | ||
err(1, "[C11 violation] dest NULL"); | ||
if (src == 0) | ||
err(1, "[C11 violation] src NULL"); | ||
if (dmax == 0) | ||
err(1, "[C11 violation] dmax 0"); | ||
return EINVAL; | ||
} | ||
|
||
/* Check for src/dst overlap, which is not allowed */ | ||
low = (uword) (src < dest ? src : dest); | ||
hi = (uword) (src < dest ? dest : src); | ||
|
||
if (PREDICT_FALSE (low + (n - 1) >= hi)) | ||
{ | ||
err(1, "[C11 violation] src/dest overlap"); | ||
return EINVAL; | ||
} | ||
|
||
dest_size = clib_strnlen (dest, dmax); | ||
allowed_size = dmax - dest_size; | ||
|
||
if (PREDICT_FALSE (allowed_size == 0)) | ||
{ | ||
err(1, "[C11 violation] no space left in dest"); | ||
return (EINVAL); | ||
} | ||
|
||
if (PREDICT_FALSE (n >= allowed_size)) | ||
{ | ||
/* | ||
* unlike strcat_s, strncat_s will do the concatenation anyway when | ||
* there is not enough space in dest. But it will do the truncation and | ||
* null terminate dest | ||
*/ | ||
m = strnlen (src, allowed_size); | ||
if (m >= allowed_size) | ||
{ | ||
m = allowed_size - 1; | ||
status = EOVERFLOW; | ||
} | ||
} | ||
else | ||
m = strnlen (src, n); | ||
|
||
memcpy (dest + dest_size, src, m); | ||
dest[dest_size + m] = '\0'; | ||
return status; | ||
} | ||
#endif /* defined(__STDC_LIB_EXT1__) || defined(_MSC_VER) */ | ||
|
||
/* Include several function definitions in the main test file. */ | ||
#define GREATEST_MAIN_DEFS() \ | ||
\ | ||
|
@@ -728,10 +821,11 @@ 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(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(&g->name_buf[len+1], size, g->name_suffix, \ | ||
size-(len+2)); \ | ||
} \ | ||
} \ | ||
\ | ||
|
There was a problem hiding this comment.
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 callGetSystemTime
andSystemTimeToFileTime
then use the milliseconds field. Actually replicating the overall behavior ofgettimeofday
isn't important -- it's just grabbing a timestamp to use as a seed for example code.