diff --git a/.gitignore b/.gitignore index 7422cead3..bae3d057f 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,4 @@ test/sblat3 test/zblat1 test/zblat2 test/zblat3 +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..2dbb6f059 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +## +## Author: Hank Anderson +## Copyright: (c) Stat-Ease, Inc. +## Created: 12/23/14 +## Last Modified: 12/23/14 +## + +cmake_minimum_required(VERSION 2.8.4) +project(OpenBLAS) + +# is this necessary? lapack-netlib has its own fortran checks in its CMakeLists.txt +#enable_language(Fortran) + +message(WARNING "CMake support is experimental. This will not produce the same Makefiles that OpenBLAS ships with.") + +include("${CMAKE_SOURCE_DIR}/cmake/system.cmake") + + diff --git a/cmake/c_check.cmake b/cmake/c_check.cmake new file mode 100644 index 000000000..20c0aa72f --- /dev/null +++ b/cmake/c_check.cmake @@ -0,0 +1,29 @@ +## +## Author: Hank Anderson +## Copyright: (c) Stat-Ease, Inc. +## Created: 12/29/14 +## Last Modified: 12/29/14 +## Description: Ported from the OpenBLAS/c_check perl script. +## This is triggered by prebuild.cmake and runs before any of the code is built. +## Creates config.h and Makefile.conf. + +# N.B. c_check is not cross-platform, so instead try to use CMake variables. Alternatively, could use try_compile to get some of this info the same way c_check does. + +# run c_check (creates the TARGET files) +# message(STATUS "Running c_check...") +# execute_process(COMMAND perl c_check ${TARGET_MAKE} ${TARGET_CONF} ${CMAKE_CXX_COMPILER} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + +# TODO: is ${BINARY} sufficient for the __32BIT__ define? +# TODO: CMAKE_SYSTEM_PROCESSOR is not set by CMake, need to set it manually when doing a cross-compile +# TODO: CMAKE_CXX_COMPILER_ID and CMAKE_SYSTEM_NAME are probably not the same strings as OpenBLAS is expecting +# TODO: detect this +set(NEED_FU 1) + +file(WRITE ${TARGET_CONF} + "#define OS_${CMAKE_SYSTEM_NAME}\t1\n" + "#define ARCH_${CMAKE_SYSTEM_PROCESSOR}\t1\n" + "#define C_${CMAKE_CXX_COMPILER_ID}\t1\n" + "#define __${BINARY}BIT__\t1\n" + "#define FUNDERSCORE\t${NEED_FU}\n") + diff --git a/cmake/f_check.cmake b/cmake/f_check.cmake new file mode 100644 index 000000000..a291430aa --- /dev/null +++ b/cmake/f_check.cmake @@ -0,0 +1,37 @@ +## +## Author: Hank Anderson +## Copyright: (c) Stat-Ease, Inc. +## Created: 12/29/14 +## Last Modified: 12/29/14 +## Description: Ported from the OpenBLAS/f_check perl script. +## This is triggered by prebuild.cmake and runs before any of the code is built. +## Appends Fortran information to config.h and Makefile.conf. + + +if (NOT ${ONLY_CBLAS}) + # N.B. f_check is not cross-platform, so instead try to use CMake variables + # run f_check (appends to TARGET files) +# message(STATUS "Running f_check...") +# execute_process(COMMAND perl f_check ${TARGET_MAKE} ${TARGET_CONF} ${CMAKE_Fortran_COMPILER} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + + # TODO: is BU makefile macro needed? + # TODO: detect whether underscore needed, set #defines appropriately - use try_compile + # TODO: set FEXTRALIB flags a la f_check? + + set(BU "_") + file(APPEND ${TARGET_CONF} + "#define BUNDERSCORE _\n" + "#define NEEDBUNDERSCORE 1\n" + "#define NEED2UNDERSCORES 0\n") + +else () + + #When we only build CBLAS, we set NOFORTRAN=2 + set(NOFORTRAN 2) + set(NO_FBLAS 1) + set(BU "_") + file(APPEND ${TARGET_CONF} + "#define BUNDERSCORE _\n" + "#define NEEDBUNDERSCORE 1\n") +endif() diff --git a/cmake/prebuild.cmake b/cmake/prebuild.cmake new file mode 100644 index 000000000..34a683a4f --- /dev/null +++ b/cmake/prebuild.cmake @@ -0,0 +1,55 @@ +## +## Author: Hank Anderson +## Copyright: (c) Stat-Ease, Inc. +## Created: 12/29/14 +## Last Modified: 12/29/14 +## Description: Ported from OpenBLAS/Makefile.prebuild +## This is triggered by system.cmake and runs before any of the code is built. +## Creates config.h and Makefile.conf by first running the c_check perl script (which creates those files). +## Next it runs f_check and appends some fortran information to the files. +## Finally it runs getarch and getarch_2nd for even more environment information. + +# CPUIDEMU = ../../cpuid/table.o + +if (DEFINED CPUIDEMU) + set(EXFLAGS "-DCPUIDEMU -DVENDOR=99") +endif () + +if (DEFINED TARGET_CORE) + # set the C flags for just this file + set_source_files_properties(getarch_2nd.c PROPERTIES COMPILE_FLAGS "-DBUILD_KERNEL") + set(TARGET_MAKE "Makefile_kernel.conf") + set(TARGET_CONF "config_kernel.h") +else() + set(TARGET_MAKE "Makefile.conf") + set(TARGET_CONF "config.h") +endif () + +include("${CMAKE_SOURCE_DIR}/cmake/c_check.cmake") +include("${CMAKE_SOURCE_DIR}/cmake/f_check.cmake") + +# compile getarch +# TODO: need to use execute_process here, or compilation won't happen until later - maybe make temporary CMakeLists.txt file using file() ? +#add_executable(getarch getarch.c cpuid.S ${CPUIDEMU} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +# +## run getarch, which appends even more to the TARGET files +#message(STATUS "Running getarch") +#execute_process(COMMAND getarch 0 >> ${TARGET_MAKE} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +#execute_process(COMMAND getarch 1 >> ${TARGET_CONF} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +# +## config.h is ready for getarch_2nd now, so compile that +#set(GETARCH2_SOURCES getarch_2nd.c config.h) +#add_executable(getarch_2nd getarch_2nd.c config.h) +# +## finally run getarch_2nd, appending yet more to the TARGET files +#message(STATUS "Running getarch_2nd") +#execute_process(COMMAND getarch_2nd 0 >> ${TARGET_MAKE} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +#execute_process(COMMAND getarch_2nd 1 >> ${TARGET_CONF} +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + +# TODO: need to read in the vars from Makefile.conf/Makefile_kernel.conf + diff --git a/cmake/system.cmake b/cmake/system.cmake new file mode 100644 index 000000000..e5c66f3ed --- /dev/null +++ b/cmake/system.cmake @@ -0,0 +1,130 @@ +## +## Author: Hank Anderson +## Copyright: (c) Stat-Ease, Inc. +## Created: 12/29/14 +## Last Modified: 12/29/14 +## Description: Ported from OpenBLAS/Makefile.system +## + +set(NETLIB_LAPACK_DIR "${CMAKE_SOURCE_DIR}/lapack-netlib") + +# TODO: Makefile.system detects Darwin (mac) and switches to clang here -hpa +# http://stackoverflow.com/questions/714100/os-detecting-makefile + +# TODO: Makefile.system sets HOSTCC = $(CC) here if not already set -hpa + +# TARGET_CORE will override TARGET which is used in DYNAMIC_ARCH=1. +if (DEFINED TARGET_CORE) + set(TARGET ${TARGET_CORE}) +endif () + +# Force fallbacks for 32bit +if (DEFINED BINARY AND DEFINED TARGET AND BINARY EQUAL 32) + message(STATUS "Compiling a ${BINARY}-bit binary.") + set(NO_AVX 1) + if (${TARGET} STREQUAL "HASWELL" OR ${TARGET} STREQUAL "SANDYBRIDGE") + set(TARGET "NEHALEM") + endif () + if (${TARGET} STREQUAL "BULLDOZER" OR ${TARGET} STREQUAL "PILEDRIVER") + set(TARGET "BARCELONA") + endif () +endif () + +if (DEFINED TARGET) + message(STATUS "Targetting the ${TARGET} architecture.") + set(GETARCH_FLAGS "-DFORCE_${TARGET}") +endif () + +if (${INTERFACE64}) + message(STATUS "Using 64-bit integers.") + set(GETARCH_FLAGS "${GETARCH_FLAGS} -DUSE64BITINT") +endif () + +if (NOT DEFINED GEMM_MULTITHREAD_THRESHOLD) + set(GEMM_MULTITHREAD_THRESHOLD 4) +endif () +message(STATUS "GEMM multithread threshold set to ${GEMM_MULTITHREAD_THRESHOLD}.") +set(GETARCH_FLAGS "${GETARCH_FLAGS} -DGEMM_MULTITHREAD_THRESHOLD=${GEMM_MULTITHREAD_THRESHOLD}") + +if (${NO_AVX}) + message(STATUS "Disabling Advanced Vector Extensions (AVX).") + set(GETARCH_FLAGS "${GETARCH_FLAGS} -DNO_AVX") +endif () + +if (${NO_AVX2}) + message(STATUS "Disabling Advanced Vector Extensions 2 (AVX2).") + set(GETARCH_FLAGS "${GETARCH_FLAGS} -DNO_AVX2") +endif () + +if (CMAKE_BUILD_TYPE STREQUAL Debug) + set(GETARCH_FLAGS "${GETARCH_FLAGS} -g") +endif () + +# TODO: let CMake handle this? -hpa +#if (${QUIET_MAKE}) +# set(MAKE "${MAKE} -s") +#endif() + +if (NOT DEFINED NO_PARALLEL_MAKE) + set(NO_PARALLEL_MAKE 0) +endif () +set(GETARCH_FLAGS "${GETARCH_FLAGS} -DNO_PARALLEL_MAKE=${NO_PARALLEL_MAKE}") + +if (CMAKE_CXX_COMPILER STREQUAL loongcc) + set(GETARCH_FLAGS "${GETARCH_FLAGS} -static") +endif () + +#if don't use Fortran, it will only compile CBLAS. +if (${ONLY_CBLAS}) + set(NO_LAPACK 1) +else () + set(ONLY_CBLAS 0) +endif () + +include("${CMAKE_SOURCE_DIR}/cmake/prebuild.cmake") + +if (NOT DEFINED NUM_THREADS) + # TODO: NUM_CORES comes from `getarch.c` or `cpuid_x86.c`. This is built and executed above in `Makefile.prebuild`, and the results are in `Makefile.conf` and `Makefile_kernel.conf`. -hpa + set(NUM_THREADS ${NUM_CORES}) +endif () + +if (NUM_THREADS EQUALS 1) + # TODO: was "override USE_THREAD = 0", do we need override here? -hpa + set(USE_THREAD 0) +endif () + +if (DEFINED USE_THREAD) + if (NOT ${USE_THREAD}) + unset(SMP) + else () + set(SMP 1) + endif () +else () + # N.B. this is NUM_THREAD in Makefile.system which is probably a bug -hpa + if (${NUM_THREADS} EQUALS 1) + unset(SMP) + else () + set(SMP 1) + endif () +endif () + +if (${SMP}) + message("SMP enabled.") +endif () + +if (NOT DEFINED NEED_PIC) + set(NEED_PIC 1) +endif () + +# TODO: I think CMake should be handling all this stuff -hpa +unset(ARFLAGS) +set(CPP "${COMPILER} -E") +set(AR "${CROSS_SUFFIX}ar") +set(AS "$(CROSS_SUFFIX)as") +set(LD "$(CROSS_SUFFIX)ld") +set(RANLIB "$(CROSS_SUFFIX)ranlib") +set(NM "$(CROSS_SUFFIX)nm") +set(DLLWRAP "$(CROSS_SUFFIX)dllwrap") +set(OBJCOPY "$(CROSS_SUFFIX)objcopy") +set(OBJCONV "$(CROSS_SUFFIX)objconv") +