diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..6acd2283 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,191 @@ +name: Build and test + +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + +jobs: + build: + strategy: + matrix: + name: [ubuntu-gcc-12, + ubuntu-gcc-13, + ubuntu-gcc-14, + ubuntu-gcc-15, + ubuntu-gcc-15-debug, + ubuntu-clang-17, + ubuntu-clang-19, + macos-xcode-15-intel, + macos-xcode-16-arm, + windows + ] + + include: + + - name: ubuntu-gcc-12 + os: ubuntu-22.04 + compiler: gcc + version: "12" + arch: "linux64" + + - name: ubuntu-gcc-13 + os: ubuntu-24.04 + compiler: gcc + version: "12" + arch: "linux64" + + - name: ubuntu-gcc-14 + os: ubuntu-24.04 + compiler: gcc + version: "12" + arch: "linux64" + + - name: ubuntu-gcc-15 + os: ubuntu-24.04 + compiler: gcc + version: "12" + buildtype: "Release" + arch: "linux64" + image: ubuntu:25.04 + + - name: ubuntu-gcc-15-debug + os: ubuntu-24.04 + compiler: gcc + version: "12" + buildtype: "Debug" + arch: "linux64" + image: ubuntu:25.04 + + - name: ubuntu-clang-17 + os: ubuntu-24.04 + compiler: clang + version: "17" + buildtype: "Release" + arch: "linux64" + + - name: ubuntu-clang-19 + os: ubuntu-24.04 + compiler: clang + version: "19" + buildtype: "Release" + arch: "linux64" + + - name: macos-xcode-15-intel + os: macos-13 + compiler: xcode + version: "15" + arch: "mac-intel64" + + - name: macos-xcode-16-arm + os: macos-14 + compiler: xcode + version: "16" + arch: "mac-arm64" + + - name: windows + os: ubuntu-24.04 + compiler: mingw + version: "N/A" + arch: "win64" + + runs-on: ${{ matrix.os }} + container: + image: ${{ matrix.image || '' }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.12 + + # Caches for different branches are isolated, so we don't need to put the branch name into the key. + # The total size for all caches in a repository is 5Gb. + + - name: Set CMake build type + run: | + CMAKE_ARGS="" + if [ -n "${{ matrix.buildtype }}" ] ; then + CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${{ matrix.buildtype }}" + fi + echo "CMAKE_ARGS=${CMAKE_ARGS}" >> $GITHUB_ENV + + - name: Install utilities (Linux) + if: runner.os == 'Linux' && matrix.name != 'windows' + run: | + # If we're running in a docker image, we are already root + if [ -n "${{ matrix.image }}" ] ; then + apt-get update && apt-get install -y sudo build-essential git cmake + fi + + sudo apt-get update + sudo apt-get install -y cmake ninja-build ccache pkg-config + sudo apt-get install -y openjdk-17-jdk libeigen3-dev + + if [ "${{ matrix.compiler }}" = "gcc" ]; then + # For newer GCCs, maybe. + # sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa + # sudo apt-get update + + sudo apt-get install -y g++-${{ matrix.version }} + echo "CC=ccache gcc-${{ matrix.version }}" >> $GITHUB_ENV + echo "CXX=ccache g++-${{ matrix.version }}" >> $GITHUB_ENV + else + sudo apt-get install -y clang-${{ matrix.version }} + echo "CC=ccache clang-${{ matrix.version }}" >> $GITHUB_ENV + echo "CXX=ccache clang++-${{ matrix.version }}" >> $GITHUB_ENV + echo "CMAKE_ARGS=${CMAKE_ARGS} -DBUILD_OPENMP=OFF" >> $GITHUB_ENV + fi + + - name: Install utilities (Linux -> Windows [cross]) + if: matrix.name == 'windows' + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build ccache pkg-config + sudo apt-get install -y dos2unix g++-mingw-w64 mingw-w64-tools wine64 zstd + + echo "CMAKE_ARGS=${CMAKE_ARGS} -DBUILD_JNI=OFF -DBUILD_OPENMP=OFF -DCMAKE_TOOLCHAIN_FILE=scripts/mingw-w64-x86_64.cmake" >> $GITHUB_ENV + + - name: Select XCode version (macOS) + if: runner.os == 'macOS' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{ matrix.version }} + + - name: Install utilities (macOS) + if: runner.os == 'macOS' + run: | + brew install cmake ninja pkg-config ccache coreutils eigen openjdk + echo "CC=ccache clang" >> $GITHUB_ENV + echo "CXX=ccache clang++" >> $GITHUB_ENV + echo "CMAKE_ARGS=${CMAKE_ARGS} -DBUILD_OPENMP=OFF" >> $GITHUB_ENV + + - name: Set up ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ matrix.name }} + restore-keys: | + ${{ matrix.name }} + + - name: Configure + run: | + mkdir build + cd build + cmake .. -G Ninja -DCMAKE_INSTALL_PREFIX=$HOME/local ${CMAKE_ARGS} + + - name: Build + run: | + ccache -p + ccache -s + ninja -C build install -j4 + ccache -s + + - name: Test + if: matrix.name != 'windows' + run: | + cd build + ./examples/synthetictest + ./examples/hmctest + diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c284465..0b311f05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,21 +62,32 @@ add_definitions( ) set(CMAKE_CXX_STANDARD 11) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -#SET(CMAKE_BUILD_TYPE Debug) -set(CMAKE_BUILD_TYPE RelWithDebInfo) +if(NOT DEFINED CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo) +endif() ## flags for standard library #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") -if(WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Ox /Ot /MT") -else(WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -pthread") - #set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -pthread") - #set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") -endif(WIN32) +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT") +else () + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +endif () + + +if (NOT "${CMAKE_BUILD_TYPE}" MATCHES Debug) + if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Ox /Ot") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + #set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") + #set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") + endif() +endif() #if(NOT WIN32) # add_definitions(-DHAVE_CONFIG_H) @@ -155,6 +166,12 @@ if(APPLE) # Seems necessary from macOS 10.15 set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +elseif(UNIX) + # This tells libhmsbeagle.so to search the same directory to find plugins. + SET(CMAKE_INSTALL_RPATH "\$ORIGIN") + # $ORIGIN/{CPU,GPU,JNI} is so that libhmsbeagle.so can find the plugins in their build location. + # $ORIGIN/../libhmsbeagle is so that examples/* can find libhmsbeagle.so + SET(CMAKE_BUILD_RPATH "\$ORIGIN:\$ORIGIN/CPU:\$ORIGIN/GPU:\$ORIGIN/JNI:\$ORIGIN/../libhmsbeagle") endif(APPLE) if (BEAGLE_OPTIMIZE_FOR_NATIVE_ARCH) @@ -170,6 +187,13 @@ if (BEAGLE_OPTIMIZE_FOR_NATIVE_ARCH) endif() endif() + +include(CheckIncludeFileCXX) +check_include_file_cxx("cpuid.h" HAVE_CPUID_H) +if (HAVE_CPUID_H) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CPUID_H") +endif() + add_subdirectory(libhmsbeagle) link_libraries(hmsbeagle) diff --git a/libhmsbeagle/CMakeLists.txt b/libhmsbeagle/CMakeLists.txt index 878ea24d..1ddeb05b 100644 --- a/libhmsbeagle/CMakeLists.txt +++ b/libhmsbeagle/CMakeLists.txt @@ -1,6 +1,5 @@ if(WIN32) add_definitions(-D_EXPORTING) - add_definitions(-DWIN32) add_definitions(-D_CONSOLE) # add_definitions(-DPACKAGE_VERSION="${BEAGLE_VERSION}") # add_definitions(-DPLUGIN_VERSION="${BEAGLE_PLUGIN_VERSION}") @@ -14,10 +13,12 @@ if(WIN32) plugin/WinSharedLibrary.h ) - set(BEAGLE_INTEGRATED_JNI_SOURCE - JNI/beagle_BeagleJNIWrapper.cpp - JNI/beagle_BeagleJNIWrapper.h - ) + if (BUILD_JNI) + set(BEAGLE_INTEGRATED_JNI_SOURCE + JNI/beagle_BeagleJNIWrapper.cpp + JNI/beagle_BeagleJNIWrapper.h + ) + endif() else(WIN32) set(BEAGLE_PLUGIN_SUFFIX ".so") set(BEAGLE_INSTALL_DIR lib) diff --git a/libhmsbeagle/CPU/BeagleCPUImpl.hpp b/libhmsbeagle/CPU/BeagleCPUImpl.hpp index 8cf0349d..d4da79d6 100644 --- a/libhmsbeagle/CPU/BeagleCPUImpl.hpp +++ b/libhmsbeagle/CPU/BeagleCPUImpl.hpp @@ -4826,7 +4826,7 @@ BEAGLE_CPU_TEMPLATE void* BeagleCPUImpl::mallocAligned(size_t size) { void *ptr = (void *) NULL; -#if defined (__APPLE__) || defined(WIN32) +#if defined (__APPLE__) || defined(_WIN32) /* presumably malloc on OS X always returns a 16-byte aligned pointer diff --git a/libhmsbeagle/CPU/BeagleCPUSSEPlugin.cpp b/libhmsbeagle/CPU/BeagleCPUSSEPlugin.cpp index c8d5aaab..6c5390d6 100644 --- a/libhmsbeagle/CPU/BeagleCPUSSEPlugin.cpp +++ b/libhmsbeagle/CPU/BeagleCPUSSEPlugin.cpp @@ -95,7 +95,7 @@ bool check_sse2(){ #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(_WIN32) #if !defined(DLS_MACOS) // For non-Mac OS X GNU C bool check_sse2() { diff --git a/libhmsbeagle/GPU/CMakeLists.txt b/libhmsbeagle/GPU/CMakeLists.txt index fca46f34..efc4764f 100644 --- a/libhmsbeagle/GPU/CMakeLists.txt +++ b/libhmsbeagle/GPU/CMakeLists.txt @@ -1,6 +1,6 @@ -find_package(OpenCL) if(BUILD_OPENCL) + find_package(OpenCL) # set(OpenCL_INCLUDE_DIRS /opt/rocm/opencl/include) # set(OpenCL_LIBRARIES /opt/rocm/opencl/lib/libOpenCL.so) if(OpenCL_FOUND OR (OpenCL_INCLUDE_DIRS AND OpenCL_LIBRARIES)) @@ -10,9 +10,11 @@ if(BUILD_OPENCL) endif(OpenCL_FOUND OR (OpenCL_INCLUDE_DIRS AND OpenCL_LIBRARIES)) endif(BUILD_OPENCL) -find_package(CUDA) -if(CUDA_FOUND AND BUILD_CUDA) - message(STATUS "CUDA Includes: ${CUDA_INCLUDE_DIRS}") - add_subdirectory("CMake_CUDA") -endif(CUDA_FOUND AND BUILD_CUDA) +if(BUILD_CUDA) + find_package(CUDA) + if(CUDA_FOUND) + message(STATUS "CUDA Includes: ${CUDA_INCLUDE_DIRS}") + add_subdirectory("CMake_CUDA") + endif(CUDA_FOUND) +endif(BUILD_CUDA) diff --git a/libhmsbeagle/plugin/Plugin.h b/libhmsbeagle/plugin/Plugin.h index 5c49cf91..3ab4183f 100644 --- a/libhmsbeagle/plugin/Plugin.h +++ b/libhmsbeagle/plugin/Plugin.h @@ -35,6 +35,9 @@ class BEAGLE_DLLEXPORT Plugin Plugin(const char* plugin_name, const char* plugin_type) : m_plugin_name(plugin_name), m_plugin_type(plugin_type) {} + // Make sure the destructor is virtual. + virtual ~Plugin() {} + virtual std::string pluginName() const{ return m_plugin_name; } virtual std::string pluginType() const{ return m_plugin_type; } diff --git a/libhmsbeagle/plugin/WinSharedLibrary.cpp b/libhmsbeagle/plugin/WinSharedLibrary.cpp index edd835ff..74c20b9f 100644 --- a/libhmsbeagle/plugin/WinSharedLibrary.cpp +++ b/libhmsbeagle/plugin/WinSharedLibrary.cpp @@ -17,7 +17,6 @@ namespace beagle { namespace plugin { SharedLibrary* SharedLibrary::openSharedLibrary(const char* name) - throw (SharedLibraryException) { return new WinSharedLibrary(name); } diff --git a/libhmsbeagle/plugin/WinSharedLibrary.h b/libhmsbeagle/plugin/WinSharedLibrary.h index 533c7f64..f4f3b65f 100644 --- a/libhmsbeagle/plugin/WinSharedLibrary.h +++ b/libhmsbeagle/plugin/WinSharedLibrary.h @@ -25,18 +25,15 @@ using namespace std; class WinSharedLibrary : public SharedLibrary { public: - WinSharedLibrary(const char* name) - throw (SharedLibraryException); + WinSharedLibrary(const char* name); ~WinSharedLibrary(); - void* findSymbol(const char* name) - throw (SharedLibraryException); + void* findSymbol(const char* name); private: HINSTANCE m_handle; }; WinSharedLibrary::WinSharedLibrary(const char* name) - throw (SharedLibraryException) : m_handle(0) { std::string libname = name; @@ -78,9 +75,8 @@ WinSharedLibrary::~WinSharedLibrary() } } void* WinSharedLibrary::findSymbol(const char* name) - throw (SharedLibraryException) { - void* sym = GetProcAddress(m_handle,name); + void* sym = (void*)GetProcAddress(m_handle,name); if (sym == 0) { char buffer[255]; diff --git a/scripts/mingw-w64-x86_64.cmake b/scripts/mingw-w64-x86_64.cmake new file mode 100644 index 00000000..e8bb7dc6 --- /dev/null +++ b/scripts/mingw-w64-x86_64.cmake @@ -0,0 +1,24 @@ +# Sample toolchain file for building for Windows from an Ubuntu Linux system. +# +# Typical usage: +# *) install cross compiler: `sudo apt-get install mingw-w64` +# *) cd build +# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake .. +# This is free and unencumbered software released into the public domain. + +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) + +# cross compilers to use for C, C++ and Fortran +set(CMAKE_C_COMPILER ccache ${TOOLCHAIN_PREFIX}-gcc-posix) +set(CMAKE_CXX_COMPILER ccache ${TOOLCHAIN_PREFIX}-g++-posix) +set(CMAKE_Fortran_COMPILER ccache ${TOOLCHAIN_PREFIX}-gfortran) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) + +# modify default behavior of FIND_XXX() commands +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)