-
Notifications
You must be signed in to change notification settings - Fork 165
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
Add CMake project #7
Changes from all commits
e12e3cd
43d0e4b
796a5a8
3d5300e
9436179
8a11f92
2784cac
f9dd976
8a3c23b
d205173
f1e6ba2
bfcb66e
ef719a0
1e0f1bc
3c7bd1e
5a65bb0
efd30f8
8b80a5d
368abcf
2d38081
209ec08
1d50831
7170a90
e2c75a4
a70fa51
e3ab782
1991745
1eb01ff
b3dac06
28507e6
61a8bee
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,264 @@ | ||||||
# Written in 2016-2017, 2021 by Henrik Steffen Gaßmann henrik@gassmann.onl | ||||||
# | ||||||
# To the extent possible under law, the author(s) have dedicated all | ||||||
# copyright and related and neighboring rights to this software to the | ||||||
# public domain worldwide. This software is distributed without any warranty. | ||||||
# | ||||||
# You should have received a copy of the CC0 Public Domain Dedication | ||||||
# along with this software. If not, see | ||||||
# | ||||||
# http://creativecommons.org/publicdomain/zero/1.0/ | ||||||
# | ||||||
######################################################################## | ||||||
cmake_minimum_required(VERSION 3.1) | ||||||
|
||||||
project(base64 LANGUAGES C VERSION 0.4.0) | ||||||
|
||||||
include(GNUInstallDirs) | ||||||
include(CMakeDependentOption) | ||||||
include(FeatureSummary) | ||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") | ||||||
|
||||||
####################################################################### | ||||||
# platform detection | ||||||
include(TargetArch) | ||||||
detect_target_architecture(_TARGET_ARCH) | ||||||
|
||||||
|
||||||
################################################################### | ||||||
# optional/conditional dependencies | ||||||
find_package(OpenMP) | ||||||
set_package_properties(OpenMP PROPERTIES | ||||||
TYPE OPTIONAL | ||||||
PURPOSE "Allows to utilize OpenMP" | ||||||
) | ||||||
|
||||||
|
||||||
######################################################################## | ||||||
# Compilation options | ||||||
option(BASE64_WERROR "Treat warnings as error" ON) | ||||||
option(BASE64_BUILD_TESTS "add test projects" ON) | ||||||
cmake_dependent_option(BASE64_WITH_OpenMP "use OpenMP" OFF "OpenMP_FOUND" OFF) | ||||||
add_feature_info("OpenMP codec" BASE64_WITH_OpenMP "spreads codec work accross multiple threads") | ||||||
cmake_dependent_option(BASE64_REGENERATE_TABLES "regenerate the codec tables" OFF "NOT CMAKE_CROSSCOMPILING" OFF) | ||||||
|
||||||
set(_IS_X86 "\"${_TARGET_ARCH}\" STREQUAL \"x86\" OR \"${_TARGET_ARCH}\" STREQUAL \"x64\"") | ||||||
cmake_dependent_option(BASE64_WITH_SSSE3 "add SSSE 3 codepath" ON ${_IS_X86} OFF) | ||||||
add_feature_info(SSSE3 BASE64_WITH_SSSE3 "add SSSE 3 codepath") | ||||||
cmake_dependent_option(BASE64_WITH_SSE41 "add SSE 4.1 codepath" ON ${_IS_X86} OFF) | ||||||
add_feature_info(SSE4.1 BASE64_WITH_SSE41 "add SSE 4.1 codepath") | ||||||
cmake_dependent_option(BASE64_WITH_SSE42 "add SSE 4.2 codepath" ON ${_IS_X86} OFF) | ||||||
add_feature_info(SSE4.2 BASE64_WITH_SSE42 "add SSE 4.2 codepath") | ||||||
cmake_dependent_option(BASE64_WITH_AVX "add AVX codepath" ON ${_IS_X86} OFF) | ||||||
add_feature_info(AVX BASE64_WITH_AVX "add AVX codepath") | ||||||
cmake_dependent_option(BASE64_WITH_AVX2 "add AVX 2 codepath" ON ${_IS_X86} OFF) | ||||||
add_feature_info(AVX2 BASE64_WITH_AVX2 "add AVX2 codepath") | ||||||
|
||||||
set(_IS_ARM "\"${_TARGET_ARCH}\" STREQUAL \"arm\"") | ||||||
cmake_dependent_option(BASE64_WITH_NEON32 "add NEON32 codepath" OFF ${_IS_ARM} OFF) | ||||||
add_feature_info(NEON32 BASE64_WITH_NEON32 "add NEON32 codepath") | ||||||
|
||||||
set(_IS_ARM64 "\"${_TARGET_ARCH}\" STREQUAL \"arm64\"") | ||||||
cmake_dependent_option(BASE64_WITH_NEON64 "add NEON64 codepath" ON ${_IS_ARM64} OFF) | ||||||
add_feature_info(NEON64 BASE64_WITH_NEON64 "add NEON64 codepath") | ||||||
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") | ||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") | ||||||
|
||||||
######################################################################## | ||||||
# Regenerate headers | ||||||
|
||||||
if (BASE64_REGENERATE_TABLES) | ||||||
# Generate tables in build folder and copy to source tree. | ||||||
# Don't add the tables in the source tree to the outputs, to avoid `make clean` removing them. | ||||||
add_executable(table_generator | ||||||
lib/tables/table_generator.c | ||||||
) | ||||||
|
||||||
add_custom_command(OUTPUT table_dec_32bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_dec_32bit.h" | ||||||
COMMAND table_generator > table_dec_32bit.h | ||||||
COMMAND "${CMAKE_COMMAND}" -E copy table_dec_32bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_dec_32bit.h" | ||||||
DEPENDS table_generator | ||||||
) | ||||||
set(Python_ADDITIONAL_VERSIONS 3) | ||||||
find_package(PythonInterp REQUIRED) | ||||||
add_custom_command(OUTPUT table_enc_12bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.h" | ||||||
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.py" > table_enc_12bit.h | ||||||
COMMAND "${CMAKE_COMMAND}" -E copy table_enc_12bit.h "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.h" | ||||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/lib/tables/table_enc_12bit.py" | ||||||
) | ||||||
endif() | ||||||
|
||||||
|
||||||
######################################################################## | ||||||
# library project | ||||||
add_library(base64 | ||||||
# library files | ||||||
lib/lib.c | ||||||
lib/codec_choose.c | ||||||
include/libbase64.h | ||||||
|
||||||
lib/tables/tables.c | ||||||
# Add generated headers explicitly to target, to insert them in the dependency tree | ||||||
lib/tables/table_dec_32bit.h | ||||||
lib/tables/table_enc_12bit.h | ||||||
|
||||||
# codec implementations | ||||||
lib/arch/generic/codec.c | ||||||
|
||||||
lib/arch/ssse3/codec.c | ||||||
lib/arch/sse41/codec.c | ||||||
lib/arch/sse42/codec.c | ||||||
lib/arch/avx/codec.c | ||||||
lib/arch/avx2/codec.c | ||||||
|
||||||
lib/arch/neon32/codec.c | ||||||
lib/arch/neon64/codec.c | ||||||
BurningEnlightenment marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
) | ||||||
|
||||||
target_include_directories(base64 | ||||||
PUBLIC | ||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> | ||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||||||
PRIVATE | ||||||
"${CMAKE_CURRENT_BINARY_DIR}" | ||||||
) | ||||||
|
||||||
#################################################################### | ||||||
# platform/compiler specific configuration | ||||||
set_target_properties(base64 PROPERTIES | ||||||
C_STANDARD 99 | ||||||
C_STANDARD_REQUIRED YES | ||||||
C_EXTENSIONS OFF | ||||||
DEFINE_SYMBOL BASE64_EXPORTS | ||||||
VERSION ${PROJECT_VERSION} | ||||||
SOVERSION ${PROJECT_VERSION_MAJOR} | ||||||
) | ||||||
|
||||||
#generate_export_header(base64) | ||||||
# the following definitions and those in libbase64.h have been | ||||||
# kept forward compatible in case we ever switch to generate_export_header | ||||||
if (BUILD_SHARED_LIBS) | ||||||
set_target_properties(base64 PROPERTIES | ||||||
C_VISIBILITY_PRESET hidden | ||||||
) | ||||||
else() | ||||||
target_compile_definitions(base64 | ||||||
PUBLIC | ||||||
BASE64_STATIC_DEFINE | ||||||
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. I find the |
||||||
) | ||||||
endif() | ||||||
|
||||||
target_compile_options(base64 PRIVATE | ||||||
$<$<C_COMPILER_ID:MSVC>: | ||||||
/W4 | ||||||
/we4013 # Error warning C4013: 'function' undefined; assuming extern returning int | ||||||
/we4700 # Error warning C4700: uninitialized local variable | ||||||
/we4715 # not all control paths return a value | ||||||
/we4003 # not enough actual parameters for macro | ||||||
/wd4456 # disable warning C4456: declaration of 'xxx' hides previous local declaration | ||||||
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. If all of these are legitimate issues with the code, I'd prefer to have them fixed rather than ignore the warning. 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. There is currently one violation in the windows |
||||||
> | ||||||
$<$<NOT:$<C_COMPILER_ID:MSVC>>: | ||||||
-Wall | ||||||
-Wextra | ||||||
-Wpedantic | ||||||
> | ||||||
$<$<BOOL:${BASE64_WERROR}>:$<IF:$<C_COMPILER_ID:MSVC>,/WX,-Werror>> | ||||||
) | ||||||
|
||||||
target_compile_definitions(base64 PRIVATE | ||||||
$<$<C_COMPILER_ID:MSVC>: | ||||||
# remove unnecessary warnings about unchecked iterators | ||||||
_SCL_SECURE_NO_WARNINGS | ||||||
> | ||||||
) | ||||||
|
||||||
######################################################################## | ||||||
# SIMD settings | ||||||
include(TargetSIMDInstructionSet) | ||||||
define_SIMD_compile_flags() | ||||||
|
||||||
if (_TARGET_ARCH STREQUAL "x86" OR _TARGET_ARCH STREQUAL "x64") | ||||||
macro(configure_codec _TYPE) | ||||||
if (BASE64_WITH_${_TYPE}) | ||||||
message(STATUS "Add codec: lib/arch/${_DIR}/codec.c") | ||||||
string(TOLOWER "${_TYPE}" _DIR) | ||||||
set_source_files_properties("lib/arch/${_DIR}/codec.c" PROPERTIES | ||||||
COMPILE_FLAGS "${COMPILE_FLAGS_${_TYPE}}" | ||||||
) | ||||||
|
||||||
if (${ARGC} GREATER 1 AND MSVC) | ||||||
set_source_files_properties("lib/arch/${_DIR}/codec.c" PROPERTIES | ||||||
COMPILE_DEFINITIONS ${ARGV1} | ||||||
) | ||||||
endif() | ||||||
endif() | ||||||
endmacro() | ||||||
|
||||||
configure_codec(SSSE3 __SSSE3__) | ||||||
configure_codec(SSE41 __SSSE4_1__) | ||||||
configure_codec(SSE42 __SSSE4_2__) | ||||||
configure_codec(AVX) | ||||||
configure_codec(AVX2) | ||||||
|
||||||
elseif (_TARGET_ARCH STREQUAL "arm") | ||||||
set(BASE64_NEON32_CFLAGS "${COMPILE_FLAGS_NEON32}" CACHE STRING "the NEON32 compile flags (for 'lib/arch/neon32/codec.c')") | ||||||
mark_as_advanced(BASE64_NEON32_CFLAGS) | ||||||
|
||||||
if (BASE64_WITH_NEON32) | ||||||
set_source_files_properties("lib/arch/neon32/codec.c" PROPERTIES | ||||||
COMPILE_FLAGS "${BASE64_NEON32_CFLAGS} " | ||||||
) | ||||||
endif() | ||||||
|
||||||
#elseif (_TARGET_ARCH STREQUAL "arm64" AND BASE64_WITH_NEON64) | ||||||
|
||||||
endif() | ||||||
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. Perhaps add a else()
message(WARNING "Unknown architecture: ${_TARGET_ARCH}")
endif() 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. A warning definitely makes sense. 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. Does it though? Obviously there won't be SIMD acceleration, because SIMD instruction sets are architecture specific and one chose to compile for an alien one. Or is this more about not providing official support/ not regularly testing the pure C codec on that architecture? 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. Another comment, shouldn't |
||||||
|
||||||
configure_file("${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY) | ||||||
|
||||||
######################################################################## | ||||||
# OpenMP Settings | ||||||
if (BASE64_WITH_OpenMP) | ||||||
target_compile_options(base64 | ||||||
PRIVATE | ||||||
${OpenMP_C_FLAGS} | ||||||
) | ||||||
endif() | ||||||
|
||||||
######################################################################## | ||||||
if (BASE64_BUILD_TESTS) | ||||||
enable_testing() | ||||||
add_subdirectory(test) | ||||||
endif() | ||||||
|
||||||
######################################################################## | ||||||
# cmake install | ||||||
install(DIRECTORY include/ TYPE INCLUDE) | ||||||
install(TARGETS base64 EXPORT base64-targets) | ||||||
|
||||||
include(CMakePackageConfigHelpers) | ||||||
configure_package_config_file(cmake/base64-config.cmake.in | ||||||
"${CMAKE_CURRENT_BINARY_DIR}/base64-config.cmake" | ||||||
|
||||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" | ||||||
) | ||||||
write_basic_package_version_file( | ||||||
"${CMAKE_CURRENT_BINARY_DIR}/base64-config-version.cmake" | ||||||
VERSION ${BASE64_VERSION} | ||||||
COMPATIBILITY SameMajorVersion | ||||||
) | ||||||
|
||||||
install(FILES | ||||||
"${CMAKE_CURRENT_BINARY_DIR}/base64-config.cmake" | ||||||
"${CMAKE_CURRENT_BINARY_DIR}/base64-config-version.cmake" | ||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" | ||||||
) | ||||||
|
||||||
install(EXPORT base64-targets | ||||||
NAMESPACE aklomp:: | ||||||
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. I would just use
Suggested change
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. Can you take another look at this suggestion? 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. Tough call. On one hand So then use I think 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. AFAIK there are two widely used conventions: Using a vendor/organization string or using the cmake project name (which in our case would be |
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" | ||||||
) | ||||||
|
||||||
######################################################################## | ||||||
feature_summary(WHAT PACKAGES_FOUND PACKAGES_NOT_FOUND ENABLED_FEATURES DISABLED_FEATURES) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Written in 2017 by Henrik Steffen Gaßmann henrik@gassmann.onl | ||
# | ||
# To the extent possible under law, the author(s) have dedicated all | ||
# copyright and related and neighboring rights to this software to the | ||
# public domain worldwide. This software is distributed without any warranty. | ||
# | ||
# You should have received a copy of the CC0 Public Domain Dedication | ||
# along with this software. If not, see | ||
# | ||
# http://creativecommons.org/publicdomain/zero/1.0/ | ||
# | ||
######################################################################## | ||
|
||
set(TARGET_ARCHITECTURE_TEST_FILE "${CMAKE_CURRENT_LIST_DIR}/../test-arch.c") | ||
|
||
function(detect_target_architecture OUTPUT_VARIABLE) | ||
message(STATUS "${CMAKE_CURRENT_LIST_DIR}") | ||
try_compile(_IGNORED "${CMAKE_CURRENT_BINARY_DIR}" | ||
"${TARGET_ARCHITECTURE_TEST_FILE}" | ||
OUTPUT_VARIABLE _LOG | ||
) | ||
|
||
string(REGEX MATCH "##arch=([^#]+)##" _IGNORED "${_LOG}") | ||
|
||
set(${OUTPUT_VARIABLE} "${CMAKE_MATCH_1}" PARENT_SCOPE) | ||
if (CMAKE_MATCH_1 STREQUAL "unknown") | ||
message(WARNING "could not detect the target architecture.") | ||
endif() | ||
endfunction() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Written in 2016-2017 by Henrik Steffen Gaßmann henrik@gassmann.onl | ||
# | ||
# To the extent possible under law, the author(s) have dedicated all | ||
# copyright and related and neighboring rights to this software to the | ||
# public domain worldwide. This software is distributed without any warranty. | ||
# | ||
# You should have received a copy of the CC0 Public Domain Dedication | ||
# along with this software. If not, see | ||
# | ||
# http://creativecommons.org/publicdomain/zero/1.0/ | ||
# | ||
######################################################################## | ||
|
||
######################################################################## | ||
# compiler flags definition | ||
macro(define_SIMD_compile_flags) | ||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") | ||
# x86 | ||
set(COMPILE_FLAGS_SSSE3 "-mssse3") | ||
set(COMPILE_FLAGS_SSE41 "-msse4.1") | ||
set(COMPILE_FLAGS_SSE42 "-msse4.2") | ||
set(COMPILE_FLAGS_AVX "-mavx") | ||
set(COMPILE_FLAGS_AVX2 "-mavx2") | ||
|
||
#arm | ||
set(COMPILE_FLAGS_NEON32 "-mfpu=neon") | ||
elseif(MSVC) | ||
set(COMPILE_FLAGS_SSSE3 " ") | ||
set(COMPILE_FLAGS_SSE41 " ") | ||
set(COMPILE_FLAGS_SSE42 " ") | ||
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. Support for these levels are not selectable in MSVC? Edit: to answer my own question: no, they are not. It's strange though, because what to do then? We can't really use the next best level, which is 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. To the contrary the SIMD intrinsics up to and including |
||
set(COMPILE_FLAGS_AVX "/arch:AVX") | ||
set(COMPILE_FLAGS_AVX2 "/arch:AVX2") | ||
endif() | ||
endmacro(define_SIMD_compile_flags) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
@PACKAGE_INIT@ | ||
|
||
include("${CMAKE_CURRENT_LIST_DIR}/base64-targets.cmake") | ||
|
||
check_required_components(base64) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef BASE64_CONFIG_H | ||
#define BASE64_CONFIG_H | ||
|
||
#cmakedefine01 BASE64_WITH_SSSE3 | ||
#define HAVE_SSSE3 BASE64_WITH_SSSE3 | ||
|
||
#cmakedefine01 BASE64_WITH_SSE41 | ||
#define HAVE_SSE41 BASE64_WITH_SSE41 | ||
|
||
#cmakedefine01 BASE64_WITH_SSE42 | ||
#define HAVE_SSE42 BASE64_WITH_SSE42 | ||
|
||
#cmakedefine01 BASE64_WITH_AVX | ||
#define HAVE_AVX BASE64_WITH_AVX | ||
|
||
#cmakedefine01 BASE64_WITH_AVX2 | ||
#define HAVE_AVX2 BASE64_WITH_AVX2 | ||
|
||
#cmakedefine01 BASE64_WITH_NEON32 | ||
#define HAVE_NEON32 BASE64_WITH_NEON32 | ||
|
||
#cmakedefine01 BASE64_WITH_NEON64 | ||
#define HAVE_NEON64 BASE64_WITH_NEON64 | ||
|
||
#endif // BASE64_CONFIG_H |
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.
CMake uses cmake toolchains for specifying the host architecture.
See CMAKE_SYSTEM_PROCESSOR.
Perhaps we should first try to parse
CMAKE_SYSTEM_PROCESSOR
, and then try to run the compiler?Using that approach, users can override the architecture in the case of a mis-detection.
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.
Or you could effectively transliterate the makefile into cmake (ie require users to set options). I'm all about making this as feature rich as possible, but it doesn't seem like it makes sense to wait on the perfect cmake build.