Skip to content

Commit

Permalink
Solve the MacOS ARM compilation problem. Changes some options and add…
Browse files Browse the repository at this point in the history
… new ones.
  • Loading branch information
aous72 committed May 1, 2024
1 parent 104c8a7 commit fbd2654
Show file tree
Hide file tree
Showing 16 changed files with 537 additions and 249 deletions.
88 changes: 77 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.11.0)

## Library name/version
include(ojph_libname.cmake)
include(ojph_version.cmake)

## project
project (openjph VERSION ${OPENJPH_VERSION} DESCRIPTION "Open source implementation of JPH" LANGUAGES CXX)
Expand All @@ -11,21 +11,63 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Building OpenJPH
################################################################################################

## Target architecture
# We use the target architecture to help with arranging files in "source_group" commands.
# The code does not use the results provided by target_arch.cmake, and relies, instead,
# on its own logic, which matches that in target_arch.cmake, to identify the architecture
include(target_arch.cmake)
target_architecture(OJPH_TARGET_ARCH)
message(STATUS "CPU Architecture is ${OJPH_TARGET_ARCH}")

## options
option(OJPH_DISABLE_INTEL_SIMD "Disables the use of SIMD instructions and associated files" OFF)
option(OJPH_ENABLE_INTEL_AVX512 "enables the use of AVX512 SIMD instructions and associated files" ON)
option(BUILD_SHARED_LIBS "Shared Libraries" ON)
option(OJPH_ENABLE_TIFF_SUPPORT "Enables input and output support for TIFF files" ON)
option(OJPH_BUILD_TESTS "Enables building test code" OFF)
option(OJPH_BUILD_EXECUTABLES "Enables building command line executables" ON)
option(OJPH_BUILD_STREAM_EXPAND "Enables building ojph_stream_expand executable" OFF)

option(OJPH_DISABLE_SIMD "Disables the use of SIMD instructions -- agnostic to architectures" OFF)
option(OJPH_DISABLE_SSE "Disables the use of SSE SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_SSE2 "Disables the use of SSE2 SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_SSSE3 "Disables the use of SSSE3 SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_SSE4 "Disables the use of SSE4 SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_AVX "Disables the use of AVX SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_AVX2 "Disables the use of AVX2 SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_AVX512 "Disables the use of AVX512 SIMD instructions and associated files" OFF)
option(OJPH_DISABLE_NEON "Disables the use of NEON SIMD instructions and associated files" OFF)

## options that are being deprecated
if (DEFINED OJPH_DISABLE_INTEL_SIMD)
message(STATUS "OJPH_DISABLE_INTEL_SIMD is being deprecated. Instead, use \"OJPH_DISABLE_SIMD\", "
"which is architecture agnostic. If you do not specify any, the default is "
"OJPH_DISABLE_SIMD=OFF.")
set(OJPH_DISABLE_SIMD ${OJPH_DISABLE_INTEL_SIMD})
message(STATUS "OJPH_DISABLE_SIMD is set to ${OJPH_DISABLE_SIMD}")
unset(OJPH_DISABLE_INTEL_SIMD)
endif()
if (DEFINED OJPH_ENABLE_INTEL_AVX512)
message(STATUS "OJPH_ENABLE_INTEL_AVX512 is being deprecated, use \"OJPH_DISABLE_AVX512\" instead."
"If you do not specify any, the default is OJPH_DISABLE_AVX512=OFF.")
if (OJPH_ENABLE_INTEL_AVX512)
set(OJPH_DISABLE_AVX512 OFF)
else()
set(OJPH_DISABLE_AVX512 ON)
endif()
message(STATUS "OJPH_DISABLE_AVX512 is set to ${OJPH_DISABLE_AVX512}")
unset(OJPH_ENABLE_INTEL_AVX512)
endif()

## Setting some of the options if EMSCRIPTEN is the compiler
# WebAssembly SIMD is treated differently. The SIMD flags above have no effect on the
# use of WASM SIMD. This is because, for WASM, both non-SIMD and SIMD are required,
# and therefore two sets of binaries are generated. For CPUs, one binary can carry both
# non-SIMD and SIMD, and the program, at run-time, can decide which path to follow,
# depending on what CPU instructions are available.
if(EMSCRIPTEN)
set(OJPH_DISABLE_INTEL_SIMD ON)
set(BUILD_SHARED_LIBS OFF)
set(OJPH_ENABLE_TIFF_SUPPORT OFF)
set(OJPH_BUILD_STREAM_EXPAND OFF)
set(OJPH_DISABLE_SIMD ON)
endif()

# This is related to how the timestamp is set for URL downloaded files.
Expand All @@ -36,15 +78,16 @@ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24.0")
endif()
endif()

## Added by Michael Smith
set(CMAKE_CXX_FLAGS_ASAN
"-fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1"
CACHE STRING "Flags used by the C++ compiler during AddressSanitizer builds."
FORCE)

## build type
## Build type
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
message( STATUS "To use AddressSanitizer, use \"cmake .. -DCMAKE_BUILD_TYPE=asan\"" )
message(STATUS "To use AddressSanitizer, use \"cmake .. -DCMAKE_BUILD_TYPE=asan\"" )
endif()
message(STATUS "Building ${CMAKE_BUILD_TYPE}")

Expand All @@ -64,11 +107,34 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
)
endif()

## The option OJPH_DISABLE_INTEL_SIMD and OJPH_ENABLE_INTEL_AVX512
if (OJPH_DISABLE_INTEL_SIMD)
add_compile_definitions(OJPH_DISABLE_INTEL_SIMD)
elseif (OJPH_ENABLE_INTEL_AVX512)
add_compile_definitions(OJPH_ENABLE_INTEL_AVX512)
## Enhanced instruction options
if (OJPH_DISABLE_SIMD)
add_compile_definitions(OJPH_DISABLE_SIMD)
else()
if(OJPH_DISABLE_SSE)
add_compile_definitions(OJPH_DISABLE_SSE)
endif()
if(OJPH_DISABLE_SSE2)
add_compile_definitions(OJPH_DISABLE_SSE2)
endif()
if(OJPH_DISABLE_SSSE3)
add_compile_definitions(OJPH_DISABLE_SSSE3)
endif()
if(OJPH_DISABLE_SSE4)
add_compile_definitions(OJPH_DISABLE_SSE4)
endif()
if(OJPH_DISABLE_AVX)
add_compile_definitions(OJPH_DISABLE_AVX)
endif()
if(OJPH_DISABLE_AVX2)
add_compile_definitions(OJPH_DISABLE_AVX2)
endif()
if(OJPH_DISABLE_AVX512)
add_compile_definitions(OJPH_DISABLE_AVX512)
endif()
if(OJPH_DISABLE_NEON)
add_compile_definitions(OJPH_DISABLE_NEON)
endif()
endif()

## Build library and applications
Expand Down
8 changes: 3 additions & 5 deletions docs/compiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,8 @@ The scripts, in the ```.devcontainer``` folder, will build a docker image that c

# Compiling for ARM and other platforms #

To compile for platforms where x86_64 SIMD instructions are not supported, such as on ARM, we need to disable SIMD instructions; this can be achieved using
Compilation should simply work now. The simple test code I have passes when run on MacOS ARM on GitHub.

cd build
cmake -DCMAKE_BUILD_TYPE=Release \ -DOJPH_DISABLE_INTEL_SIMD=ON ../
make
# Disabling SIMD instructions #

You may need to install libtiff. As I do not have an ARM board, I tested this using QEMU for aarch64 architecture, targeting a Cortex-A57 CPU. The code worked without issues, but because the ARM platform is emulated, the whole process was slow.
The code now employs the architecture-agnostic option `OJPH_DISABLE_SIMD`, which should include SIMD instructions wherever they are supported. This can be achieved with `-DOJPH_DISABLE_SIMD=ON` option during CMake configuration. Individual instruction sets can be disabled; see the options in the main CMakeLists.txt file.
2 changes: 1 addition & 1 deletion ojph_libname.cmake → ojph_version.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
################################################################################################
# Generating library name
# Generating ojph library version number
################################################################################################

############################################################
Expand Down
33 changes: 23 additions & 10 deletions src/apps/ojph_compress/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,32 @@ if(EMSCRIPTEN)
target_link_libraries(ojph_compress_simd PRIVATE openjphsimd)
install(TARGETS ojph_compress_simd DESTINATION bin)
else()
if(NOT OJPH_DISABLE_INTEL_SIMD)
add_executable(ojph_compress ${SOURCES} ${OJPH_IMG_IO_SSE4} ${OJPH_IMG_IO_AVX2})

if (MSVC)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS "/arch:AVX2")
else()
set_source_files_properties(${OJPH_IMG_IO_SSE4} PROPERTIES COMPILE_FLAGS -msse4.1)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS -mavx2)
if (NOT OJPH_DISABLE_SIMD)
if (("${OJPH_TARGET_ARCH}" MATCHES "OJPH_ARCH_X86_64") OR ("${OJPH_TARGET_ARCH}" MATCHES "OJPH_ARCH_I386"))
if (NOT OJPH_DISABLE_SSE4)
list(APPEND SOURCES ${OJPH_IMG_IO_SSE4})
source_group("others" FILES ${OJPH_IMG_IO_SSE4})
endif()
if (NOT OJPH_DISABLE_AVX2)
list(APPEND SOURCES ${OJPH_IMG_IO_AVX2})
source_group("others" FILES ${OJPH_IMG_IO_AVX2})
endif()

# Set compilation flags
if (MSVC)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS "/arch:AVX2")
else()
set_source_files_properties(${OJPH_IMG_IO_SSE4} PROPERTIES COMPILE_FLAGS -msse4.1)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS -mavx2)
endif()
elseif ("${OJPH_TARGET_ARCH}" MATCHES "OJPH_ARCH_ARM")

endif()
else()
add_executable(ojph_compress ${SOURCES})

endif()

add_executable(ojph_compress ${SOURCES})

if( USE_TIFF )
target_link_libraries(ojph_compress PUBLIC openjph ${TIFF_LIBRARIES})
else()
Expand Down
33 changes: 23 additions & 10 deletions src/apps/ojph_expand/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,32 @@ if(EMSCRIPTEN)
target_link_libraries(ojph_expand_simd PRIVATE openjphsimd)
install(TARGETS ojph_expand_simd DESTINATION bin)
else()
if(NOT OJPH_DISABLE_INTEL_SIMD)
add_executable(ojph_expand ${SOURCES} ${OJPH_IMG_IO_SSE4} ${OJPH_IMG_IO_AVX2})

if (MSVC)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS "/arch:AVX2")
else()
set_source_files_properties(${OJPH_IMG_IO_SSE4} PROPERTIES COMPILE_FLAGS -msse4.1)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS -mavx2)
if (NOT OJPH_DISABLE_SIMD)
if (("${OJPH_TARGET_ARCH}" MATCHES "OJPH_ARCH_X86_64") OR ("${OJPH_TARGET_ARCH}" MATCHES "OJPH_ARCH_I386"))
if (NOT OJPH_DISABLE_SSE4)
list(APPEND SOURCES ${OJPH_IMG_IO_SSE4})
source_group("others" FILES ${OJPH_IMG_IO_SSE4})
endif()
if (NOT OJPH_DISABLE_AVX2)
list(APPEND SOURCES ${OJPH_IMG_IO_AVX2})
source_group("others" FILES ${OJPH_IMG_IO_AVX2})
endif()

# Set compilation flags
if (MSVC)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS "/arch:AVX2")
else()
set_source_files_properties(${OJPH_IMG_IO_SSE4} PROPERTIES COMPILE_FLAGS -msse4.1)
set_source_files_properties(${OJPH_IMG_IO_AVX2} PROPERTIES COMPILE_FLAGS -mavx2)
endif()
elseif ("${OJPH_TARGET_ARCH}" MATCHES "OJPH_ARCH_ARM")

endif()
else()
add_executable(ojph_expand ${SOURCES})

endif()

add_executable(ojph_expand ${SOURCES})

if( USE_TIFF )
target_link_libraries(ojph_expand PUBLIC openjph ${TIFF_LIBRARIES})
else()
Expand Down
41 changes: 21 additions & 20 deletions src/apps/ojph_stream_expand/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@

if (OJPH_BUILD_STREAM_EXPAND)

include_directories(../common)
include_directories(../../core/common)
set(CMAKE_CXX_STANDARD 14)
file(GLOB OJPH_STREAM_EXPAND "*.cpp" "*.h")
file(GLOB OJPH_SOCKETS "../others/ojph_sockets.cpp")
file(GLOB OJPH_SOCKETS_H "../common/ojph_sockets.h")
file(GLOB OJPH_THREADS "../others/ojph_threads.cpp")
file(GLOB OJPH_THREADS_H "../common/ojph_threads.h")
include_directories(../common)
include_directories(../../core/common)
set(CMAKE_CXX_STANDARD 14)

file(GLOB OJPH_STREAM_EXPAND "*.cpp" "*.h")
file(GLOB OJPH_SOCKETS "../others/ojph_sockets.cpp")
file(GLOB OJPH_SOCKETS_H "../common/ojph_sockets.h")
file(GLOB OJPH_THREADS "../others/ojph_threads.cpp")
file(GLOB OJPH_THREADS_H "../common/ojph_threads.h")

list(APPEND SOURCES ${OJPH_STREAM_EXPAND} ${OJPH_SOCKETS} ${OJPH_SOCKETS_H} ${OJPH_THREADS} ${OJPH_THREADS_H})
list(APPEND SOURCES ${OJPH_STREAM_EXPAND} ${OJPH_SOCKETS} ${OJPH_SOCKETS_H} ${OJPH_THREADS} ${OJPH_THREADS_H})

source_group("main" FILES ${OJPH_STREAM_EXPAND})
source_group("others" FILES ${OJPH_SOCKETS} ${OJPH_THREADS})
source_group("common" FILES ${OJPH_SOCKETS_H} ${OJPH_THREADS_H})
source_group("main" FILES ${OJPH_STREAM_EXPAND})
source_group("others" FILES ${OJPH_SOCKETS} ${OJPH_THREADS})
source_group("common" FILES ${OJPH_SOCKETS_H} ${OJPH_THREADS_H})

add_executable(ojph_stream_expand ${SOURCES})
if(MSVC)
target_link_libraries(ojph_stream_expand PUBLIC openjph ws2_32)
else()
target_link_libraries(ojph_stream_expand PUBLIC openjph pthread)
endif(MSVC)
add_executable(ojph_stream_expand ${SOURCES})
if(MSVC)
target_link_libraries(ojph_stream_expand PUBLIC openjph ws2_32)
else()
target_link_libraries(ojph_stream_expand PUBLIC openjph pthread)
endif(MSVC)

install(TARGETS ojph_stream_expand DESTINATION bin)

install(TARGETS ojph_stream_expand DESTINATION bin)
endif(OJPH_BUILD_STREAM_EXPAND)
66 changes: 38 additions & 28 deletions src/apps/others/ojph_img_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,39 +471,49 @@ namespace ojph {
converter = gen_cvrt_32b3c_to_16ub3c_be;
}

#ifndef OJPH_DISABLE_INTEL_SIMD
#ifndef OJPH_DISABLE_SIMD

if (get_cpu_ext_level() >= X86_CPU_EXT_LEVEL_SSE41) {
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_8ub1c;
else
converter = sse41_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_16ub1c_be;
else
converter = sse41_cvrt_32b3c_to_16ub3c_be;
}
}
#if (defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))

if (get_cpu_ext_level() >= X86_CPU_EXT_LEVEL_AVX2) {
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = avx2_cvrt_32b1c_to_8ub1c;
else
converter = avx2_cvrt_32b3c_to_8ub3c;
#ifndef OJPH_DISABLE_SSE4
if (get_cpu_ext_level() >= X86_CPU_EXT_LEVEL_SSE41) {
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_8ub1c;
else
converter = sse41_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_16ub1c_be;
else
converter = sse41_cvrt_32b3c_to_16ub3c_be;
}
}
else {
if (num_components == 1)
converter = avx2_cvrt_32b1c_to_16ub1c_be;
else
{ } // did not find an implementation better than sse41
#endif // !OJPH_DISABLE_SSE4

#ifndef OJPH_DISABLE_AVX2
if (get_cpu_ext_level() >= X86_CPU_EXT_LEVEL_AVX2) {
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = avx2_cvrt_32b1c_to_8ub1c;
else
converter = avx2_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = avx2_cvrt_32b1c_to_16ub1c_be;
else
{ } // did not find an implementation better than sse41
}
}
}
#endif // !OJPH_DISABLE_AVX2

#elif defined(OJPH_ARCH_ARM)

#endif // !(defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))

#endif
#endif // !OJPH_DISABLE_SIMD
}

////////////////////////////////////////////////////////////////////////////
Expand Down
Loading

0 comments on commit fbd2654

Please sign in to comment.