Skip to content

Commit

Permalink
Add CMake build system
Browse files Browse the repository at this point in the history
This commit adds experimental CMake build support for ISCE2.

The only changes involved should be adding CMakeLists.txt files.
All current source files, headers, and other functionality, including
the existing SCons build system, should be unaffected.

Some functionality is still a work-in-progress.
These should all be marked as TODO in the CMakeLists.txt files.
`grep TODO **.txt`

Please read CMakeLists.txt and .cmake/*.cmake for more info.
  • Loading branch information
rtburns-jpl committed Dec 22, 2019
1 parent 48fda5a commit 46fef17
Show file tree
Hide file tree
Showing 143 changed files with 2,370 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .cmake/FindCython.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Tries to run Cython using `python -m cython`
execute_process(COMMAND ${Python_EXECUTABLE} -m cython --help
RESULT_VARIABLE cython_status
ERROR_QUIET OUTPUT_QUIET)

if(NOT cython_status)
set(CYTHON_EXECUTABLE ${Python_EXECUTABLE} -m cython CACHE STRING
"Cython executable")
endif()

include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cython REQUIRED_VARS CYTHON_EXECUTABLE)

mark_as_advanced(CYTHON_EXECUTABLE)
169 changes: 169 additions & 0 deletions .cmake/FindFFTW.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#[[
Usage:
find_package(FFTW [REQUIRED] [QUIET] [COMPONENTS ...])
Be warned that this will only search for FFTW3 libraries.
It sets the following variables:
FFTW_FOUND .. true if FFTW is found on the system
FFTW_[component]_LIB_FOUND .. true if the component is found (see below)
FFTW_LIBRARIES .. full paths to all found FFTW libraries
FFTW_[component]_LIB .. full path to one component (see below)
FFTW_INCLUDE_DIRS .. FFTW include directory paths
The following variables will be checked by the function
FFTW_USE_STATIC_LIBS .. if true, only static libraries are searched
FFTW_ROOT .. if set, search under this path first
Paths will be searched in the following order:
FFTW_ROOT (if provided)
PkgConfig paths (if found)
Library/include installation directories
Default find_* paths
The following component library locations will be defined (if found):
FFTW_FLOAT_LIB
FFTW_DOUBLE_LIB
FFTW_LONGDOUBLE_LIB
FFTW_FLOAT_THREADS_LIB
FFTW_DOUBLE_THREADS_LIB
FFTW_LONGDOUBLE_THREADS_LIB
FFTW_FLOAT_OMP_LIB
FFTW_DOUBLE_OMP_LIB
FFTW_LONGDOUBLE_OMP_LIB
The following IMPORTED targets will be created (if found):
FFTW::Float
FFTW::Double
FFTW::LongDouble
FFTW::FloatThreads
FFTW::DoubleThreads
FFTW::LongDoubleThreads
FFTW::FloatOMP
FFTW::DoubleOMP
FFTW::LongDoubleOMP
]]

include(FindPackageHandleStandardArgs)

if(NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR})
set(FFTW_ROOT $ENV{FFTWDIR})
endif()

# Check if we can use PkgConfig
find_package(PkgConfig)

# Determine from PKG
if(PKG_CONFIG_FOUND)
pkg_check_modules(PKG_FFTW QUIET fftw3)
endif()

# Check whether to search static or dynamic libs
set(CMAKE_FIND_LIBRARY_SUFFIXES_SAV ${CMAKE_FIND_LIBRARY_SUFFIXES})

if(${FFTW_USE_STATIC_LIBS})
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV})
endif()

# Paths to pass to find_library for each component
set(findlib_paths
${FFTW_ROOT}
${PKG_FFTW_LIBRARY_DIRS}
${LIB_INSTALL_DIR}
)

# Find include directory
find_path(FFTW_INCLUDE_DIRS
NAMES fftw3.h
PATHS ${FFTW_ROOT}
${PKG_FFTW_INCLUDE_DIRS}
${INCLUDE_INSTALL_DIR}
PATH_SUFFIXES include
)

set(FFTW_LIBRARIES "")

foreach(dtype Float Double LongDouble)

# Single-letter suffix for the library name
string(REGEX REPLACE "(.).*" "\\1" letter ${dtype})
string(TOLOWER ${letter} letter)
# The double-precision library doesn't use a suffix
if("${letter}" STREQUAL "d")
set(letter "")
endif()

foreach(system "" Threads OMP)

# CamelCase component name used for interface libraries
# e.g. FloatThreads
set(component ${dtype}${system})

# Component library location variable used via find_library
# e.g. FFTW_DOUBLE_THREADS_LIB
if(system)
set(libvar FFTW_${dtype}_${system}_LIB)
else()
set(libvar FFTW_${dtype}_LIB)
endif()
string(TOUPPER ${libvar} libvar)

# Filename root common to all libraries
set(libname fftw3${letter})
if(system)
string(TOLOWER ${system} systemlower)
set(libname ${libname}_${systemlower})
endif()
# Actual filenames looked for by find_library
set(libnames
${libname}
lib${libname}3-3
)

find_library(
${libvar}
NAMES ${libnames}
PATHS ${findlib_paths}
PATH_SUFFIXES lib lib64
)

# Tell find_package whether this component was found
set(FFTW_${component}_FIND_QUIETLY TRUE)
find_package_handle_standard_args(FFTW_${component}
HANDLE_COMPONENTS REQUIRED_VARS ${libvar} FFTW_INCLUDE_DIRS)
# Also set the value of the legacy library-variable
# (Will be set to *-NOTFOUND if not found)
set(${libvar} ${FFTW_${component}})

# If the library was found:
if(${libvar} AND NOT TARGET FFTW::${component})
# Add it to the list of FFTW libraries
list(APPEND FFTW_LIBRARIES ${${libvar}})

# Create a corresponding interface library
add_library(FFTW::${component} IMPORTED INTERFACE)
target_include_directories(
FFTW::${component} SYSTEM INTERFACE ${FFTW_INCLUDE_DIRS})
target_link_libraries(
FFTW::${component} INTERFACE ${${libvar}})
endif()

mark_as_advanced(${libvar})

endforeach()
endforeach()

# Restore saved find_library suffixes
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV})

find_package_handle_standard_args(FFTW
REQUIRED_VARS FFTW_LIBRARIES FFTW_INCLUDE_DIRS
HANDLE_COMPONENTS
)

mark_as_advanced(
FFTW_INCLUDE_DIRS
FFTW_LIBRARIES
)
9 changes: 9 additions & 0 deletions .cmake/TargetGDAL.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
find_package(GDAL)

# Make a compatibility GDAL::GDAL interface target
# In CMake >= 3.14, this already exists for us :)
if(GDAL_FOUND AND NOT TARGET GDAL::GDAL)
add_library(GDAL::GDAL IMPORTED INTERFACE)
target_include_directories(GDAL::GDAL SYSTEM INTERFACE ${GDAL_INCLUDE_DIRS})
target_link_libraries(GDAL::GDAL INTERFACE ${GDAL_LIBRARIES})
endif()
9 changes: 9 additions & 0 deletions .cmake/TargetMotif.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
find_package(Motif)

if(MOTIF_FOUND AND NOT TARGET Motif::Motif)
add_library(Motif::Motif IMPORTED INTERFACE)
target_include_directories(Motif::Motif
SYSTEM INTERFACE ${MOTIF_INCLUDE_DIR})
target_link_libraries(Motif::Motif
INTERFACE ${MOTIF_LIBRARIES})
endif()
18 changes: 18 additions & 0 deletions .cmake/TargetX11.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
find_package(X11)

if(X11_FOUND)

foreach(component
Xmu
Xt
)

if(X11_${Xmu}_FOUND AND NOT TARGET X11::${component})
add_library(X11::${component} IMPORTED INTERFACE)
target_include_directories(X11::${component} SYSTEM
INTERFACE ${X11_${component}_INCLUDE_PATH})
target_link_libraries(X11::${component}
INTERFACE ${X11_${component}_LIB})
endif()
endforeach()
endif()
148 changes: 148 additions & 0 deletions .cmake/UseCython.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Define a function to create Cython modules.
#
# For more information on the Cython project, see http://cython.org/.
# "Cython is a language that makes writing C extensions for the Python language
# as easy as Python itself."
#
# This file defines a CMake function to build a Cython Python module.
# To use it, first include this file.
#
# include(UseCython)
#
# Then call cython_add_module to create a module.
#
# cython_add_module(<module_name> <src1> <src2> ... <srcN>)
#
# Where <module_name> is the name of the resulting Python module and
# <src1> <src2> ... are source files to be compiled into the module, e.g. *.pyx,
# *.py, *.cxx, etc. A CMake target is created with name <module_name>. This can
# be used for target_link_libraries(), etc.
#
# The sample paths set with the CMake include_directories() command will be used
# for include directories to search for *.pxd when running the Cython complire.
#
# Cache variables that effect the behavior include:
#
# CYTHON_ANNOTATE
# CYTHON_NO_DOCSTRINGS
# CYTHON_FLAGS
#
# See also FindCython.cmake

#=============================================================================
# Copyright 2011 Kitware, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#=============================================================================

# Configuration options.
set( CYTHON_ANNOTATE OFF
CACHE BOOL "Create an annotated .html file when compiling *.pyx." )
set( CYTHON_NO_DOCSTRINGS OFF
CACHE BOOL "Strip docstrings from the compiled module." )
set( CYTHON_FLAGS "" CACHE STRING
"Extra flags to the cython compiler." )
mark_as_advanced( CYTHON_ANNOTATE CYTHON_NO_DOCSTRINGS CYTHON_FLAGS )

find_package(Cython REQUIRED)
find_package(Python REQUIRED COMPONENTS Development)

# Check the version of Cython
execute_process( COMMAND ${CYTHON_EXECUTABLE} --version
OUTPUT_VARIABLE CYTHON_VERSION ERROR_VARIABLE CYTHON_VERSION )
string(REGEX MATCH "([0-9]|\\.)+" CYTHON_VERSION ${CYTHON_VERSION})
if((CYTHON_VERSION VERSION_GREATER_EQUAL 0.28.1))
message(STATUS "Found Cython: ${CYTHON_VERSION}")
else()
message(FATAL_ERROR "Could not find Cython version >= 0.28.1")
endif()

# Create a *.cxx file from a *.pyx file.
# Input the generated file basename. The generate file will put into the variable
# placed in the "generated_file" argument. Finally all the *.py and *.pyx files.
function( compile_pyx _name generated_file )

set( pyx_locations "" )

foreach( pyx_file ${ARGN} )
# Get the include directories.
get_source_file_property( pyx_location ${pyx_file} LOCATION )
get_filename_component( pyx_path ${pyx_location} PATH )
list( APPEND pyx_locations "${pyx_location}" )
endforeach() # pyx_file

# Set additional flags.
set(cython_args "")
if( CYTHON_ANNOTATE )
list(APPEND cython_args "--annotate" )
endif()

if( CYTHON_NO_DOCSTRINGS )
list(APPEND cython_args "--no-docstrings")
endif()

if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR
"${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
set(APPEND cython_args "--gdb")
endif()

list(APPEND cython_args "-${Python_VERSION_MAJOR}")

# Include directory arguments.
list(REMOVE_DUPLICATES cmake_include_directories)
foreach(_include_dir ${cmake_include_directories})
list(APPEND cython_args "-I${_include_dir}")
endforeach()

# Determining generated file name.
set(_generated_file ${CMAKE_CURRENT_BINARY_DIR}/${_name}.cxx)
set_source_files_properties( ${_generated_file} PROPERTIES GENERATED TRUE )
set( ${generated_file} ${_generated_file} PARENT_SCOPE )

# Add the command to run the compiler.
add_custom_command( OUTPUT ${_generated_file}
COMMAND ${CYTHON_EXECUTABLE}
ARGS --cplus ${cython_args} ${CYTHON_FLAGS}
--output-file ${_generated_file} ${pyx_locations}
DEPENDS ${pyx_locations}
IMPLICIT_DEPENDS CXX
COMMENT "Compiling Cython CXX source for ${_name}..."
)
endfunction()

# cython_add_module( <name> src1 src2 ... srcN )
# Build the Cython Python module.
function( cython_add_module _name )
set( pyx_module_sources "" )
set( other_module_sources "" )
foreach( _file ${ARGN} )
if( ${_file} MATCHES ".*\\.py[x]?$" )
list( APPEND pyx_module_sources ${_file} )
else()
list( APPEND other_module_sources ${_file} )
endif()
endforeach()
set( CYTHON_FLAGS ${CYTHON_FLAGS} -X embedsignature=True)
compile_pyx( ${_name} generated_file ${pyx_module_sources} )
Python_add_library( ${_name} MODULE ${generated_file} ${other_module_sources} )
if( APPLE )
set_target_properties( ${_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
endif()
# ignore overflow warnings caused by Python's implicit conversions
set_property( SOURCE ${generated_file}
PROPERTY COMPILE_OPTIONS -Wno-overflow APPEND )
# ignore Numpy deprecated API warning
# ignore warnings for using the #warning extension directive
# TODO fix -Wno-cpp for nvcc
# target_compile_options( ${_name} PRIVATE -Wno-cpp -Wno-pedantic)
endfunction()
26 changes: 26 additions & 0 deletions .cmake/isce2_buildflags.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# TODO (global build flags)
# These definitions and compile options are
# set globally for convenience.
# Perhaps we should apply them only as needed on a
# per-target basis, and propagate them via the interface?
add_definitions(-DNEEDS_F77_TRANSLATION -DF77EXTERNS_LOWERCASE_TRAILINGBAR)
add_compile_options(
$<$<COMPILE_LANGUAGE:Fortran>:-ffixed-line-length-none>
$<$<COMPILE_LANGUAGE:Fortran>:-fno-range-check>
$<$<COMPILE_LANGUAGE:Fortran>:-fno-second-underscore>)

# Set up build flags for C++ and Fortran.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED y)
set(CMAKE_CXX_EXTENSIONS n)

# TODO (fix RPATHs)
# We have to hack our RPATHs a bit for these shared libraries to be
# loaded by others on the install-side. Maybe these libraries should
# be combined and/or installed to a common ISCE2 lib directory.
# Is there a semantic way to propagate their RPATHs
# without using these global variables?
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
list(APPEND CMAKE_INSTALL_RPATH
${CMAKE_INSTALL_PREFIX}/${ISCE2_PKG}/components/isceobj/Util
)
Loading

0 comments on commit 46fef17

Please sign in to comment.