diff options
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/tuklib_common.cmake | 49 | ||||
-rw-r--r-- | cmake/tuklib_cpucores.cmake | 180 | ||||
-rw-r--r-- | cmake/tuklib_integer.cmake | 102 | ||||
-rw-r--r-- | cmake/tuklib_mbstr.cmake | 20 | ||||
-rw-r--r-- | cmake/tuklib_physmem.cmake | 150 | ||||
-rw-r--r-- | cmake/tuklib_progname.cmake | 18 |
6 files changed, 519 insertions, 0 deletions
diff --git a/cmake/tuklib_common.cmake b/cmake/tuklib_common.cmake new file mode 100644 index 0000000..088a3cb --- /dev/null +++ b/cmake/tuklib_common.cmake @@ -0,0 +1,49 @@ +# +# tuklib_common.cmake - common functions and macros for tuklib_*.cmake files +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +function(tuklib_add_definitions TARGET_OR_ALL DEFINITIONS) + # DEFINITIONS may be an empty string/list but it's fine here. There is + # no need to quote ${DEFINITIONS} as empty arguments are fine here. + if(TARGET_OR_ALL STREQUAL "ALL") + add_compile_definitions(${DEFINITIONS}) + else() + target_compile_definitions("${TARGET_OR_ALL}" PRIVATE ${DEFINITIONS}) + endif() +endfunction() + +function(tuklib_add_definition_if TARGET_OR_ALL VAR) + if(${VAR}) + tuklib_add_definitions("${TARGET_OR_ALL}" "${VAR}") + endif() +endfunction() + +# This is an over-simplified version of AC_USE_SYSTEM_EXTENSIONS in Autoconf +# or gl_USE_SYSTEM_EXTENSIONS in gnulib. +macro(tuklib_use_system_extensions TARGET_OR_ALL) + if(NOT WIN32) + # FIXME? The Solaris-specific __EXTENSIONS__ should be conditional + # even on Solaris. See gnulib: git log m4/extensions.m4. + # FIXME? gnulib and autoconf.git has lots of new stuff. + tuklib_add_definitions("${TARGET_OR_ALL}" + _GNU_SOURCE + __EXTENSIONS__ + _POSIX_PTHREAD_SEMANTICS + _TANDEM_SOURCE + _ALL_SOURCE + ) + + list(APPEND CMAKE_REQUIRED_DEFINITIONS + -D_GNU_SOURCE + -D__EXTENSIONS__ + -D_POSIX_PTHREAD_SEMANTICS + -D_TANDEM_SOURCE + -D_ALL_SOURCE + ) + endif() +endmacro() diff --git a/cmake/tuklib_cpucores.cmake b/cmake/tuklib_cpucores.cmake new file mode 100644 index 0000000..ea16e42 --- /dev/null +++ b/cmake/tuklib_cpucores.cmake @@ -0,0 +1,180 @@ +# +# tuklib_cpucores.cmake - see tuklib_cpucores.m4 for description and comments +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") +include(CheckCSourceCompiles) +include(CheckIncludeFile) + +function(tuklib_cpucores_internal_check) + if(WIN32 OR CYGWIN) + # Nothing to do, the tuklib_cpucores.c handles it. + set(TUKLIB_CPUCORES_DEFINITIONS "" CACHE INTERNAL "") + return() + endif() + + # glibc-based systems (GNU/Linux and GNU/kFreeBSD) have + # sched_getaffinity(). The CPU_COUNT() macro was added in glibc 2.9. + # glibc 2.9 is old enough that if someone uses the code on older glibc, + # the fallback to sysconf() should be good enough. + # + # NOTE: This required that _GNU_SOURCE is defined. We assume that whatever + # feature test macros the caller wants to use are already set in + # CMAKE_REQUIRED_DEFINES and in the target defines. + check_c_source_compiles(" + #include <sched.h> + int main(void) + { + cpu_set_t cpu_mask; + sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask); + return CPU_COUNT(&cpu_mask); + } + " + TUKLIB_CPUCORES_SCHED_GETAFFINITY) + if(TUKLIB_CPUCORES_SCHED_GETAFFINITY) + set(TUKLIB_CPUCORES_DEFINITIONS + "TUKLIB_CPUCORES_SCHED_GETAFFINITY" + CACHE INTERNAL "") + return() + endif() + + # FreeBSD has both cpuset and sysctl. Look for cpuset first because + # it's a better approach. + # + # This test would match on GNU/kFreeBSD too but it would require + # -lfreebsd-glue when linking and thus in the current form this would + # fail on GNU/kFreeBSD. The above test for sched_getaffinity() matches + # on GNU/kFreeBSD so the test below should never run on that OS. + check_c_source_compiles(" + #include <sys/param.h> + #include <sys/cpuset.h> + int main(void) + { + cpuset_t set; + cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, + sizeof(set), &set); + return 0; + } + " + TUKLIB_CPUCORES_CPUSET) + if(TUKLIB_CPUCORES_CPUSET) + set(TUKLIB_CPUCORES_DEFINITIONS "HAVE_PARAM_H;TUKLIB_CPUCORES_CPUSET" + CACHE INTERNAL "") + return() + endif() + + # On OS/2, both sysconf() and sysctl() pass the tests in this file, + # but only sysctl() works. On QNX it's the opposite: only sysconf() works + # (although it assumes that _POSIX_SOURCE, _XOPEN_SOURCE, and + # _POSIX_C_SOURCE are undefined or alternatively _QNX_SOURCE is defined). + # + # We test sysctl() first and intentionally break the sysctl() test on QNX + # so that sysctl() is never used on QNX. + check_include_file(sys/param.h HAVE_SYS_PARAM_H) + if(HAVE_SYS_PARAM_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_PARAM_H) + endif() + check_c_source_compiles(" + #ifdef __QNX__ + compile error + #endif + #ifdef HAVE_SYS_PARAM_H + # include <sys/param.h> + #endif + #include <sys/sysctl.h> + int main(void) + { + #ifdef HW_NCPUONLINE + /* This is preferred on OpenBSD, see tuklib_cpucores.c. */ + int name[2] = { CTL_HW, HW_NCPUONLINE }; + #else + int name[2] = { CTL_HW, HW_NCPU }; + #endif + int cpus; + size_t cpus_size = sizeof(cpus); + sysctl(name, 2, &cpus, &cpus_size, NULL, 0); + return 0; + } + " + TUKLIB_CPUCORES_SYSCTL) + if(TUKLIB_CPUCORES_SYSCTL) + if(HAVE_SYS_PARAM_H) + set(TUKLIB_CPUCORES_DEFINITIONS + "HAVE_PARAM_H;TUKLIB_CPUCORES_SYSCTL" + CACHE INTERNAL "") + else() + set(TUKLIB_CPUCORES_DEFINITIONS + "TUKLIB_CPUCORES_SYSCTL" + CACHE INTERNAL "") + endif() + return() + endif() + + # Many platforms support sysconf(). + check_c_source_compiles(" + #include <unistd.h> + int main(void) + { + long i; + #ifdef _SC_NPROCESSORS_ONLN + /* Many systems using sysconf() */ + i = sysconf(_SC_NPROCESSORS_ONLN); + #else + /* IRIX */ + i = sysconf(_SC_NPROC_ONLN); + #endif + return 0; + } + " + TUKLIB_CPUCORES_SYSCONF) + if(TUKLIB_CPUCORES_SYSCONF) + set(TUKLIB_CPUCORES_DEFINITIONS "TUKLIB_CPUCORES_SYSCONF" + CACHE INTERNAL "") + return() + endif() + + # HP-UX + check_c_source_compiles(" + #include <sys/param.h> + #include <sys/pstat.h> + int main(void) + { + struct pst_dynamic pst; + pstat_getdynamic(&pst, sizeof(pst), 1, 0); + (void)pst.psd_proc_cnt; + return 0; + } + " + TUKLIB_CPUCORES_PSTAT_GETDYNAMIC) + if(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC) + set(TUKLIB_CPUCORES_DEFINITIONS "TUKLIB_CPUCORES_PSTAT_GETDYNAMIC" + CACHE INTERNAL "") + return() + endif() +endfunction() + +function(tuklib_cpucores TARGET_OR_ALL) + if(NOT DEFINED TUKLIB_CPUCORES_FOUND) + message(STATUS + "Checking how to detect the number of available CPU cores") + tuklib_cpucores_internal_check() + + if(DEFINED TUKLIB_CPUCORES_DEFINITIONS) + set(TUKLIB_CPUCORES_FOUND 1 CACHE INTERNAL "") + else() + set(TUKLIB_CPUCORES_FOUND 0 CACHE INTERNAL "") + message(WARNING + "No method to detect the number of CPU cores was found") + endif() + endif() + + if(TUKLIB_CPUCORES_FOUND) + tuklib_add_definitions("${TARGET_OR_ALL}" + "${TUKLIB_CPUCORES_DEFINITIONS}") + endif() +endfunction() diff --git a/cmake/tuklib_integer.cmake b/cmake/tuklib_integer.cmake new file mode 100644 index 0000000..d7e2e28 --- /dev/null +++ b/cmake/tuklib_integer.cmake @@ -0,0 +1,102 @@ +# +# tuklib_integer.cmake - see tuklib_integer.m4 for description and comments +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") +include(TestBigEndian) +include(CheckCSourceCompiles) +include(CheckIncludeFile) +include(CheckSymbolExists) + +function(tuklib_integer TARGET_OR_ALL) + # Check for endianness. Unlike the Autoconf's AC_C_BIGENDIAN, this doesn't + # support Apple universal binaries. The CMake module will leave the + # variable unset so we can catch that situation here instead of continuing + # as if we were little endian. + test_big_endian(WORDS_BIGENDIAN) + if(NOT DEFINED WORDS_BIGENDIAN) + message(FATAL_ERROR "Cannot determine endianness") + endif() + tuklib_add_definition_if("${TARGET_OR_ALL}" WORDS_BIGENDIAN) + + # Look for a byteswapping method. + check_c_source_compiles(" + int main(void) + { + __builtin_bswap16(1); + __builtin_bswap32(1); + __builtin_bswap64(1); + return 0; + } + " + HAVE___BUILTIN_BSWAPXX) + if(HAVE___BUILTIN_BSWAPXX) + tuklib_add_definitions("${TARGET_OR_ALL}" HAVE___BUILTIN_BSWAPXX) + else() + check_include_file(byteswap.h HAVE_BYTESWAP_H) + if(HAVE_BYTESWAP_H) + tuklib_add_definitions("${TARGET_OR_ALL}" HAVE_BYTESWAP_H) + check_symbol_exists(bswap_16 byteswap.h HAVE_BSWAP_16) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_BSWAP_16) + check_symbol_exists(bswap_32 byteswap.h HAVE_BSWAP_32) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_BSWAP_32) + check_symbol_exists(bswap_64 byteswap.h HAVE_BSWAP_64) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_BSWAP_64) + else() + check_include_file(sys/endian.h HAVE_SYS_ENDIAN_H) + if(HAVE_SYS_ENDIAN_H) + tuklib_add_definitions("${TARGET_OR_ALL}" HAVE_SYS_ENDIAN_H) + else() + check_include_file(sys/byteorder.h HAVE_SYS_BYTEORDER_H) + tuklib_add_definition_if("${TARGET_OR_ALL}" + HAVE_SYS_BYTEORDER_H) + endif() + endif() + endif() + + # 16-bit and 32-bit unaligned access is fast on x86(-64), + # big endian PowerPC, and usually on 32/64-bit ARM too. + # There are others too and ARM could be a false match. + # + # Guess the default value for the option. + # CMake's ability to give info about the target arch seems bad. + # The the same arch can have different name depending on the OS. + # + # FIXME: The regex is based on guessing, not on factual information! + # + # NOTE: Compared to the Autoconf test, this lacks the GCC/Clang test + # on ARM and always assumes that unaligned is fast on ARM. + set(FAST_UNALIGNED_GUESS OFF) + if(CMAKE_SYSTEM_PROCESSOR MATCHES + "[Xx3456]86|^[Xx]64|^[Aa][Mm][Dd]64|^[Aa][Rr][Mm]|^aarch|^powerpc|^ppc") + if(NOT WORDS_BIGENDIAN OR + NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc|^ppc") + set(FAST_UNALIGNED_GUESS ON) + endif() + endif() + option(TUKLIB_FAST_UNALIGNED_ACCESS + "Enable if the system supports *fast* unaligned memory access \ +with 16-bit and 32-bit integers." + "${FAST_UNALIGNED_GUESS}") + tuklib_add_definition_if("${TARGET_OR_ALL}" TUKLIB_FAST_UNALIGNED_ACCESS) + + # Unsafe type punning: + option(TUKLIB_USE_UNSAFE_TYPE_PUNNING + "This introduces strict aliasing violations and \ +may result in broken code. However, this might improve performance \ +in some cases, especially with old compilers \ +(e.g. GCC 3 and early 4.x on x86, GCC < 6 on ARMv6 and ARMv7)." + OFF) + tuklib_add_definition_if("${TARGET_OR_ALL}" TUKLIB_USE_UNSAFE_TYPE_PUNNING) + + # Check for GCC/Clang __builtin_assume_aligned(). + check_c_source_compiles( + "int main(void) { __builtin_assume_aligned(\"\", 1); return 0; }" + HAVE___BUILTIN_ASSUME_ALIGNED) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE___BUILTIN_ASSUME_ALIGNED) +endfunction() diff --git a/cmake/tuklib_mbstr.cmake b/cmake/tuklib_mbstr.cmake new file mode 100644 index 0000000..e073be6 --- /dev/null +++ b/cmake/tuklib_mbstr.cmake @@ -0,0 +1,20 @@ +# +# tuklib_mbstr.cmake - see tuklib_mbstr.m4 for description and comments +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") +include(CheckSymbolExists) + +function(tuklib_mbstr TARGET_OR_ALL) + check_symbol_exists(mbrtowc wchar.h HAVE_MBRTOWC) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_MBRTOWC) + + # NOTE: wcwidth() requires _GNU_SOURCE or _XOPEN_SOURCE on GNU/Linux. + check_symbol_exists(wcwidth wchar.h HAVE_WCWIDTH) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_WCWIDTH) +endfunction() diff --git a/cmake/tuklib_physmem.cmake b/cmake/tuklib_physmem.cmake new file mode 100644 index 0000000..f5ed888 --- /dev/null +++ b/cmake/tuklib_physmem.cmake @@ -0,0 +1,150 @@ +# +# tuklib_physmem.cmake - see tuklib_physmem.m4 for description and comments +# +# NOTE: Compared tuklib_physmem.m4, this lacks support for Tru64, IRIX, and +# Linux sysinfo() (usually sysconf() is used on GNU/Linux). +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") +include(CheckCSourceCompiles) +include(CheckIncludeFile) + +function(tuklib_physmem_internal_check) + # Shortcut on Windows: + if(WIN32 OR CYGWIN) + # Nothing to do, the tuklib_physmem.c handles it. + set(TUKLIB_PHYSMEM_DEFINITIONS "" CACHE INTERNAL "") + return() + endif() + + # Full check for special cases: + check_c_source_compiles(" + #if defined(_WIN32) || defined(__CYGWIN__) || defined(__OS2__) \ + || defined(__DJGPP__) || defined(__VMS) \ + || defined(AMIGA) || defined(__AROS__) || defined(__QNX__) + int main(void) { return 0; } + #else + compile error + #endif + " + TUKLIB_PHYSMEM_SPECIAL) + if(TUKLIB_PHYSMEM_SPECIAL) + # Nothing to do, the tuklib_physmem.c handles it. + set(TUKLIB_PHYSMEM_DEFINITIONS "" CACHE INTERNAL "") + return() + endif() + + # Look for AIX-specific solution before sysconf(), because the test + # for sysconf() will pass on AIX but won't actually work + # (sysconf(_SC_PHYS_PAGES) compiles but always returns -1 on AIX). + check_c_source_compiles(" + #include <sys/systemcfg.h> + int main(void) + { + (void)_system_configuration.physmem; + return 0; + } + " + TUKLIB_PHYSMEM_AIX) + if(TUKLIB_PHYSMEM_AIX) + set(TUKLIB_PHYSMEM_DEFINITIONS "TUKLIB_PHYSMEM_AIX" CACHE INTERNAL "") + return() + endif() + + # sysconf() + check_c_source_compiles(" + #include <unistd.h> + int main(void) + { + long i; + i = sysconf(_SC_PAGESIZE); + i = sysconf(_SC_PHYS_PAGES); + return 0; + } + " + TUKLIB_PHYSMEM_SYSCONF) + if(TUKLIB_PHYSMEM_SYSCONF) + set(TUKLIB_PHYSMEM_DEFINITIONS "TUKLIB_PHYSMEM_SYSCONF" + CACHE INTERNAL "") + return() + endif() + + # sysctl() + check_include_file(sys/param.h HAVE_SYS_PARAM_H) + if(HAVE_SYS_PARAM_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_PARAM_H) + endif() + + check_c_source_compiles(" + #ifdef HAVE_SYS_PARAM_H + # include <sys/param.h> + #endif + #include <sys/sysctl.h> + int main(void) + { + int name[2] = { CTL_HW, HW_PHYSMEM }; + unsigned long mem; + size_t mem_ptr_size = sizeof(mem); + sysctl(name, 2, &mem, &mem_ptr_size, NULL, 0); + return 0; + } + " + TUKLIB_PHYSMEM_SYSCTL) + if(TUKLIB_PHYSMEM_SYSCTL) + if(HAVE_SYS_PARAM_H) + set(TUKLIB_PHYSMEM_DEFINITIONS + "HAVE_PARAM_H;TUKLIB_PHYSMEM_SYSCTL" + CACHE INTERNAL "") + else() + set(TUKLIB_PHYSMEM_DEFINITIONS + "TUKLIB_PHYSMEM_SYSCTL" + CACHE INTERNAL "") + endif() + return() + endif() + + # HP-UX + check_c_source_compiles(" + #include <sys/param.h> + #include <sys/pstat.h> + int main(void) + { + struct pst_static pst; + pstat_getstatic(&pst, sizeof(pst), 1, 0); + (void)pst.physical_memory; + (void)pst.page_size; + return 0; + } + " + TUKLIB_PHYSMEM_PSTAT_GETSTATIC) + if(TUKLIB_PHYSMEM_PSTAT_GETSTATIC) + set(TUKLIB_PHYSMEM_DEFINITIONS "TUKLIB_PHYSMEM_PSTAT_GETSTATIC" + CACHE INTERNAL "") + return() + endif() +endfunction() + +function(tuklib_physmem TARGET_OR_ALL) + if(NOT DEFINED TUKLIB_PHYSMEM_FOUND) + message(STATUS "Checking how to detect the amount of physical memory") + tuklib_physmem_internal_check() + + if(DEFINED TUKLIB_PHYSMEM_DEFINITIONS) + set(TUKLIB_PHYSMEM_FOUND 1 CACHE INTERNAL "") + else() + set(TUKLIB_PHYSMEM_FOUND 0 CACHE INTERNAL "") + message(WARNING + "No method to detect the amount of physical memory was found") + endif() + endif() + + if(TUKLIB_PHYSMEM_FOUND) + tuklib_add_definitions("${TARGET_OR_ALL}" + "${TUKLIB_PHYSMEM_DEFINITIONS}") + endif() +endfunction() diff --git a/cmake/tuklib_progname.cmake b/cmake/tuklib_progname.cmake new file mode 100644 index 0000000..d4ab006 --- /dev/null +++ b/cmake/tuklib_progname.cmake @@ -0,0 +1,18 @@ +# +# tuklib_progname.cmake - see tuklib_progname.m4 for description and comments +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") +include(CheckSymbolExists) + +function(tuklib_progname TARGET_OR_ALL) + # NOTE: This glibc extension requires _GNU_SOURCE. + check_symbol_exists(program_invocation_name errno.h + HAVE_PROGRAM_INVOCATION_NAME) + tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_PROGRAM_INVOCATION_NAME) +endfunction() |