Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake build #28

Merged
merged 3 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Master CMAKE Build Script
cmake_minimum_required(VERSION 3.24)
project(
fftpack
LANGUAGES Fortran
VERSION 1.0.0
)

# Get helper macros and functions
include("${PROJECT_SOURCE_DIR}/cmake/helper.cmake")

# Confgiure everything
add_subdirectory(configure)

# Source
add_subdirectory(src)
add_fortran_library(
${PROJECT_NAME}
${PROJECT_INCLUDE_DIR}
${CMAKE_INSTALL_INCLUDEDIR}
${PROJECT_VERSION}
${PROJECT_VERSION_MAJOR}
${FFTPACK_SOURCES}
)

# Installation
add_subdirectory(install)

# Testing
option(BUILD_TESTING "Build tests")
include(CTest)
message(STATUS "Build FFTPACK tests: ${BUILD_TESTING}")
if (BUILD_TESTING)
enable_testing()
add_subdirectory(dependencies)
add_subdirectory(test)
endif()

# Examples
option(BUILD_FFTPACK_EXAMPLES "Build FFTPACK examples")
message(STATUS "Build FFTPACK examples: ${BUILD_FFTPACK_EXAMPLES}")
if (BUILD_FFTPACK_EXAMPLES)
add_subdirectory(example)
endif()
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ Alternatively, you can build using provided `Makefile`:
make
```

## Build with CMake
This library can also be built using CMake. For instructions see [Running CMake](https://cmake.org/runningcmake/). CMake version 3.24 or higher is required.

## Links
- [netlib/dfftpack1.0(fftpack4.0)](http://www.netlib.org/fftpack/)
- [Documents of fft routines in GNU/gsl based on `netlib/fftpack`](https://www.gnu.org/software/gsl/doc/html/fft.html#)
Expand Down
75 changes: 75 additions & 0 deletions cmake/helper.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# helper.cmake
#
# A collection of macros and functions making life with CMake and Fortran a
# bit simpler.

# Use to include and export headers
function(include_headers lib dir install_dir)
target_include_directories(
${lib}
INTERFACE
$<BUILD_INTERFACE:${dir}>
$<INSTALL_INTERFACE:${install_dir}>
)
endfunction()

# Use instead of add_library.
function(add_fortran_library lib_name mod_dir include_install_dir version major)
add_library(${lib_name} ${ARGN})
set_target_properties(
${lib_name}
PROPERTIES
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME ${lib_name}
VERSION ${version}
SOVERSION ${major}
Fortran_MODULE_DIRECTORY ${include_install_dir}
)
target_include_directories(
${lib_name}
PUBLIC
$<BUILD_INTERFACE:${mod_dir}>
$<INSTALL_INTERFACE:${include_install_dir}>
)
endfunction()

# Installs the library
function(install_library lib_name lib_install_dir bin_install_dir mod_dir install_dir)
install(
TARGETS ${lib_name}
EXPORT ${lib_name}Targets
RUNTIME DESTINATION ${bin_install_dir}
LIBRARY DESTINATION ${lib_install_dir}
ARCHIVE DESTINATION ${lib_install_dir}
INCLUDES DESTINATION ${install_dir}/include
)
install(
DIRECTORY ${mod_dir}
DESTINATION ${install_dir}
)
endfunction()

# Install the documentation files
function(install_documentation doc_dir install_dir)
install(
DIRECTORY ${doc_dir}
DESTINATION ${install_dir}
)
endfunction()

# Links the supplied library
function(link_library targ lib include_dir)
target_link_libraries(${targ} ${lib})
target_include_directories(${targ} PUBLIC $<BUILD_INTERFACE:${include_dir}>)
endfunction()

# ------------------------------------------------------------------------------
# Helpful Macros
macro(print_all_variables)
message(STATUS "---------- CURRENTLY DEFINED VARIABLES -----------")
get_cmake_property(varNames VARIABLES)
foreach(varName ${varNames})
message(STATUS ${varName} = ${${varName}})
endforeach()
message(STATUS "---------- END ----------")
endmacro()
23 changes: 23 additions & 0 deletions configure/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Get the macros and functions we'll need
include("${PROJECT_SOURCE_DIR}/cmake/helper.cmake")

# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
endif()

# By default, static library
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)

# Export all symbols on Windows when building libraries
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)

# Utilize the GNU installation structure
include(GNUInstallDirs)

# Locate the local include directory
set(PROJECT_INCLUDE_DIR ${PROJECT_BINARY_DIR}/include)
set(PROJECT_INCLUDE_DIR ${PROJECT_INCLUDE_DIR} PARENT_SCOPE)
3 changes: 3 additions & 0 deletions dependencies/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_subdirectory(test-drive)
set(test-drive_LIBRARY ${test-drive_LIBRARY} PARENT_SCOPE)
set(test-drive_INCLUDE_DIR ${test-drive_INCLUDE_DIR} PARENT_SCOPE)
33 changes: 33 additions & 0 deletions dependencies/test-drive/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Get the macros and functions we'll need
include("${PROJECT_SOURCE_DIR}/cmake/helper.cmake")
include(FetchContent)

# If found, use the installed version; else, import the library
if (${test-drive_FOUND})
# Inform the user of what's going on
message(STATUS "TEST-DRIVE (${test-drive_VERSION}) library found.")

# Get the mod file location
get_target_property(test-drive_INCLUDE_DIR test-drive INTERFACE_INCLUDE_DIRECTORIES)
else()
# Inform the user of what's going on
message(STATUS "TEST-DRIVE library not found. Downloading appropriate repository.")

# Fetch the proper content
FetchContent_Declare(
test-drive
GIT_TAG "origin/main"
GIT_REPOSITORY "https://github.com/fortran-lang/test-drive"
OVERRIDE_FIND_PACKAGE
)

FetchContent_MakeAvailable(test-drive)
set(test-drive_INCLUDE_DIR ${test-drive_BINARY_DIR}/include)
endif()

# Make a parent-scope variable for the library
set(test-drive_LIBRARY test-drive)
set(test-drive_LIBRARY ${test-drive_LIBRARY} PARENT_SCOPE)

# Make a parent-scope variable locating the include directory for test-drive
set(test-drive_INCLUDE_DIR ${test-drive_INCLUDE_DIR} PARENT_SCOPE)
2 changes: 2 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_executable(bench1 bench1.f90)
target_link_libraries(bench1 fftpack)
53 changes: 53 additions & 0 deletions install/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Get the macros and functions we'll need
include("${PROJECT_SOURCE_DIR}/cmake/helper.cmake")
include(CMakePackageConfigHelpers)

# Install the library and necessary include files
install_library(
${PROJECT_NAME}
${CMAKE_INSTALL_LIBDIR}
${CMAKE_INSTALL_BINDIR}
${PROJECT_INCLUDE_DIR}
${CMAKE_INSTALL_PREFIX}
)

# Define the version file
write_basic_package_version_file(
${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)

export(
EXPORT ${PROJECT_NAME}Targets
FILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}Targets.cmake
)

# Define the configuration file
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake
COPYONLY
)

install(
EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}Targets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
install(
FILES
${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/template.pc
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
@ONLY
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
3 changes: 3 additions & 0 deletions install/fftpackConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (NOT TARGET fftpack)
include("${CMAKE_CURRENT_LIST_DIR}/fftpackTargets.cmake")
endif()
9 changes: 9 additions & 0 deletions install/template.pc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
prefix = @CMAKE_INSTALL_PREFIX@
libdir = ${prefix}/@CMAKE_INSTALL_FULL_LIBDIR@
includedir = ${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: @PROJECT_NAME@
Description: FFTPACK is a package of fortran subprograms for the fast fourier transform of periodic and other symmetric sequences.
Version: @PROJECT_VERSION@
Libs: -L${libdir} -l@PROJECT_NAME@
Cflags: -I${includedir}
67 changes: 67 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Locate the source directory
set(dir ${CMAKE_CURRENT_SOURCE_DIR})

# The source files
set(FFTPACK_SOURCES
${dir}/cfftb1.f90
${dir}/cfftf1.f90
${dir}/cffti1.f90
${dir}/cosqb1.f90
${dir}/cosqf1.f90
${dir}/dcosqb.f90
${dir}/dcosqf.f90
${dir}/dcosqi.f90
${dir}/dcost.f90
${dir}/dcosti.f90
${dir}/dfftb.f90
${dir}/dfftf.f90
${dir}/dffti.f90
${dir}/dsinqb.f90
${dir}/dsinqf.f90
${dir}/dsinqi.f90
${dir}/dsint.f90
${dir}/dsinti.f90
${dir}/dzfftb.f90
${dir}/dzfftf.f90
${dir}/dzffti.f90
${dir}/ezfft1.f90
${dir}/fftpack.f90
${dir}/fftpack_dct.f90
${dir}/fftpack_fft.f90
${dir}/fftpack_fftshift.f90
${dir}/fftpack_ifft.f90
${dir}/fftpack_ifftshift.f90
${dir}/fftpack_iqct.f90
${dir}/fftpack_irfft.f90
${dir}/fftpack_qct.f90
${dir}/fftpack_rfft.f90
${dir}/passb.f90
${dir}/passb2.f90
${dir}/passb3.f90
${dir}/passb4.f90
${dir}/passb5.f90
${dir}/passf.f90
${dir}/passf2.f90
${dir}/passf3.f90
${dir}/passf4.f90
${dir}/passf5.f90
${dir}/radb2.f90
${dir}/radb3.f90
${dir}/radb4.f90
${dir}/radb5.f90
${dir}/radbg.f90
${dir}/radf2.f90
${dir}/radf3.f90
${dir}/radf4.f90
${dir}/radf5.f90
${dir}/radfg.f90
${dir}/rfftb1.f90
${dir}/rfftf1.f90
${dir}/rffti1.f90
${dir}/rk.f90
${dir}/sint1.f90
${dir}/zfftb.f90
${dir}/zfftf.f90
${dir}/zffti.f90
)
set(FFTPACK_SOURCES ${FFTPACK_SOURCES} PARENT_SCOPE)
27 changes: 27 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
include("${PROJECT_SOURCE_DIR}/cmake/helper.cmake")

macro(build_tests testname)
add_executable(${testname} ${ARGN})
link_library(${testname} fftpack ${PROJECT_INCLUDE_DIR})
link_library(${testname} test-drive ${test-drive_INCLUDE_DIR})
add_test(
NAME ${testname}
WORKING_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
COMMAND $<TARGET_FILE:${testname}>
)
endmacro()

set(FFTPACK_TEST_SOURCES
test_fftpack_dct.f90
test_fftpack_fft.f90
test_fftpack_qct.f90
test_fftpack_rfft.f90
test_fftpack_utils.f90
test_fftpack.f90
)

# Run the original FFTPACK test
build_tests(fftpack_original_tests tstfft.f)

# Run the additional FFTPACK tests
build_tests(fftpack_tests ${FFTPACK_TEST_SOURCES})