aboutsummaryrefslogtreecommitdiff
path: root/cmake
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2020-02-24 23:38:16 +0200
committerLasse Collin <lasse.collin@tukaani.org>2020-02-25 00:00:32 +0200
commit7e3493d40eac0c3fa3d5124097745a70e15c41f6 (patch)
tree8fe76b6569d9193749064ff5271c70ebff9355e0 /cmake
parentUpdate m4/.gitignore. (diff)
downloadxz-7e3493d40eac0c3fa3d5124097745a70e15c41f6.tar.xz
Build: Add very limited experimental CMake support.
This does *NOT* replace the Autotools-based build system in the foreseeable future. See the comment in the beginning of CMakeLists.txt. So far this has been tested only on GNU/Linux but I commit it anyway to make it easier for others to test. Since I haven't played much with CMake before, it's likely that there are things that have been done in a silly or wrong way and need to be fixed.
Diffstat (limited to 'cmake')
-rw-r--r--cmake/tuklib_common.cmake47
-rw-r--r--cmake/tuklib_cpucores.cmake173
-rw-r--r--cmake/tuklib_integer.cmake100
-rw-r--r--cmake/tuklib_mbstr.cmake20
-rw-r--r--cmake/tuklib_physmem.cmake149
-rw-r--r--cmake/tuklib_progname.cmake19
6 files changed, 508 insertions, 0 deletions
diff --git a/cmake/tuklib_common.cmake b/cmake/tuklib_common.cmake
new file mode 100644
index 00000000..c3d2c536
--- /dev/null
+++ b/cmake/tuklib_common.cmake
@@ -0,0 +1,47 @@
+#
+# 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)
+ 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 00000000..34546b0d
--- /dev/null
+++ b/cmake/tuklib_cpucores.cmake
@@ -0,0 +1,173 @@
+#
+# 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(CACHE{TUKLIB_CPUCORES_DEFINITIONS})
+ return()
+ endif()
+
+ 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)
+ {
+ int name[2] = { CTL_HW, HW_NCPU };
+ 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)
+ message(STATUS "Checking how to detect the number of available CPU cores")
+
+ tuklib_cpucores_internal_check()
+
+ if(NOT DEFINED CACHE{TUKLIB_CPUCORES_DEFINITIONS})
+ set(TUKLIB_CPUCORES_FOUND 0 PARENT_SCOPE)
+ message(WARNING
+ "No method to detect the number of CPU cores was found")
+ else()
+ set(TUKLIB_CPUCORES_FOUND 1 PARENT_SCOPE)
+ 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 00000000..aeb7ff6f
--- /dev/null
+++ b/cmake/tuklib_integer.cmake
@@ -0,0 +1,100 @@
+#
+# 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 00000000..a39a96b4
--- /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 00000000..dc895a15
--- /dev/null
+++ b/cmake/tuklib_physmem.cmake
@@ -0,0 +1,149 @@
+#
+# 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)
+ if(CACHE{TUKLIB_PHYSMEM_DEFINITIONS})
+ return()
+ endif()
+
+ # 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)
+ message(STATUS "Checking how to detect the amount of physical memory")
+
+ tuklib_physmem_internal_check()
+
+ if(NOT DEFINED CACHE{TUKLIB_PHYSMEM_DEFINITIONS})
+ set(TUKLIB_PHYSMEM_FOUND 0 PARENT_SCOPE)
+ message(WARNING
+ "No method to detect the amount of physical memory was found")
+ else()
+ set(TUKLIB_PHYSMEM_FOUND 1 PARENT_SCOPE)
+ 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 00000000..417495e6
--- /dev/null
+++ b/cmake/tuklib_progname.cmake
@@ -0,0 +1,19 @@
+#
+# 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_DECL_PROGRAM_INVOCATION_NAME)
+ tuklib_add_definition_if(${TARGET_OR_ALL}
+ HAVE_DECL_PROGRAM_INVOCATION_NAME)
+endfunction()