Skip to content

Commit

Permalink
Add FindLAPACKE.cmake and export proxTVconfig.cmake.
Browse files Browse the repository at this point in the history
FindLAPACKE.cmake is used to handle lapacke installations with no export targets.

Also complete the generation of proxTVconfig.cmake

Add a dummy project to test usage of proxTV from external project.

Add C Interface to Readme
  • Loading branch information
phcerdan committed Sep 25, 2017
1 parent 9ca0ddc commit c02cfe1
Show file tree
Hide file tree
Showing 11 changed files with 378 additions and 47 deletions.
48 changes: 48 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
cmake_minimum_required(VERSION 2.8.12)
#To avoid OpenMP warning: https://gitlab.kitware.com/cmake/cmake/issues/17292
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()

project(proxTV
DESCRIPTION "Toolbox for fast Total Variation proximity operators"
LANGUAGES C CXX
)

# Set VERSION
# Since cmake v3.0 we can just give an option to project(proxTV VERSION 3.2.1 LANGUAGES C CXX)
set(proxTV_VERSION_MAJOR 3)
set(proxTV_VERSION_MINOR 2)
set(proxTV_VERSION_PATCH 1)
# set(proxTV_VERSION_TWEAK 0)
set(proxTV_VERSION "${proxTV_VERSION_MAJOR}.${proxTV_VERSION_MINOR}.${proxTV_VERSION_PATCH}")
message(STATUS "proxTV version: ${proxTV_VERSION}")

# External Dependencies: {{{
# Use FindLAPACKE from local cmake folder
# FindLAPACK, FindOpenMP are already included in cmake installation.
# Threads is for pthreads flags.
# Append local module directory to the find_package search:
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

find_package(LAPACKE REQUIRED)
message(STATUS "Lapacke found?: ${LAPACKE_FOUND}")
message(STATUS "Lapacke libraries: ${LAPACKE_LIBRARIES}")

find_package(LAPACK REQUIRED)
message(STATUS "Lapack found?: ${LAPACKE_FOUND}")
message(STATUS "Lapack libraries: ${LAPACK_LIBRARIES}")

find_package(Threads)

find_package(OpenMP)
message(STATUS "OpenMP found?: ${OpenMP_FOUND}")

add_subdirectory(src)

# Test
option(ENABLE_TESTING "Compile tests" OFF)
if(${ENABLE_TESTING})
enable_testing()
add_subdirectory(test)
endif()
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,33 @@ More technically, the library provides efficient solvers for the following Total
| Anisotropic Total Variation on a 3-dimensional signal (video denoising) | ![alt tag](docs/img/TV3D.png) |
| Generalized N-dimensional Anisotropic Total Variation (tensor denoising) | ![alt tag](docs/img/TVND.png), with X(di) every possible 1-dimensional slice of X following dimension di.|

## C interface

You can generate a **c** static or dynamic library using **cmake**. If `libproxTV` is not provided by your package-manager, install it from source:

mkdir proxTV-dev ; cd proxTV-dev
git clone https://github.com/albarji/proxTV proxTV
mkdir build ; cd build
cmake ../proxTV
make -j4
make install

The required dependencies are `lapack` and `lapacke`, the c-interface for `lapack`, and optionally, but recommended: `OpenMP` with `pthreads` for multi-threading support.

You can provide extra options to `cmake` via the command line or a gui (i.e `ccmake`).

cmake ../proxTV -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_INSTALL_PREFIX=/opt/ -DENABLE_TESTING:BOOL=ON

To use proxTV in your `cmake` project just write in your `CMakeLists.txt`:

find_package(proxTV)
add_executable(foo main.cpp)
target_link_libraries(foo PUBLIC proxTV::proxTV)

That will propagate all the dependencies of proxTV to your target. If you haven't installed proxTV in a system folder, you have to point to the installation directory when configuring your project with `cmake`.

cmake /path/my_project_source_folder -DproxTV_DIR:PATH="/proxTV_install_folder/lib/cmake/proxTV"

## Python interface

### Quickstart
Expand Down
190 changes: 190 additions & 0 deletions cmake/FindLAPACKE.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#.rst:
# FindLAPACKE
# -------------
#
# Find the LAPACKE library
#
# Using LAPACKE:
#
# ::
#
# find_package(LAPACKE REQUIRED)
# include_directories(${LAPACKE_INCLUDE_DIRS})
# add_executable(foo foo.cc)
# target_link_libraries(foo ${LAPACKE_LIBRARIES})
#
# This module sets the following variables:
#
# ::
#
# LAPACKE_FOUND - set to true if the library is found
# LAPACKE_INCLUDE_DIRS - list of required include directories
# LAPACKE_LIBRARIES - list of libraries to be linked
# LAPACKE_VERSION_MAJOR - major version number
# LAPACKE_VERSION_MINOR - minor version number
# LAPACKE_VERSION_PATCH - patch version number
# LAPACKE_VERSION_STRING - version number as a string (ex: "0.2.18")

#=============================================================================
# Copyright 2016 Hans J. Johnson <[email protected]>
#
# Distributed under the OSI-approved BSD License (the "License")
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#=============================================================================
#
set(LAPACKE_SEARCH_PATHS
${LAPACKE_DIR}
$ENV{LAPACKE_DIR}
$ENV{CMAKE_PREFIX_PATH}
${CMAKE_PREFIX_PATH}
/usr
/usr/local
/usr/local/opt/lapack ## Mac Homebrew install path
/opt/LAPACKE
)
message(STATUS "LAPACKE_SEARCH_PATHS: ${LAPACKE_SEARCH_PATHS}")

set(CMAKE_PREFIX_PATH ${LAPACKE_SEARCH_PATHS})
list(REMOVE_DUPLICATES CMAKE_PREFIX_PATH)

## First try to find LAPACKE with NO_MODULE,
## As of 20160706 version 0.2.18 there is limited cmake support for LAPACKE
## that is not as complete as this version, if found, use it
## to identify the LAPACKE_VERSION_STRING and improve searching.
find_package(LAPACKE NO_MODULE QUIET)
if(LAPACKE_FOUND)
if(EXISTS ${LAPACKE_DIR}/lapacke-config-version.cmake)
include(${LAPACKE_DIR}/lapacke-config-version.cmake)
set(LAPACKE_VERSION_STRING ${PACKAGE_VERSION})
unset(PACKAGE_VERSION) # Use cmake conventional naming
endif()
find_package(LAPACK NO_MODULE QUIET) #Require matching versions here!
find_package(BLAS NO_MODULE QUIET) #Require matching versions here!
endif()

##################################################################################################
### First search for headers
find_path(LAPACKE_CBLAS_INCLUDE_DIR
NAMES cblas.h
PATHS ${LAPACKE_SEARCH_PATHS}
PATH_SUFFIXES include include/lapack)
find_path(LAPACKE_LAPACKE_INCLUDE_DIR
NAMES lapacke.h
PATHS ${LAPACKE_SEARCH_PATHS}
PATH_SUFFIXES include)

##################################################################################################
### Second, search for libraries
set(PATH_SUFFIXES_LIST
lib64
lib
)
find_library(LAPACKE_LIB
NAMES lapacke
PATHS ${LAPACKE_SEARCH_PATHS}
PATH_SUFFIXES ${PATH_SUFFIXES_LIST})
find_library(CBLAS_LIB
NAMES cblas
PATHS ${LAPACKE_SEARCH_PATHS}
PATH_SUFFIXES ${PATH_SUFFIXES_LIST})
find_library(LAPACK_LIB
NAMES lapack
PATHS ${LAPACKE_SEARCH_PATHS}
PATH_SUFFIXES ${PATH_SUFFIXES_LIST})
find_library(BLAS_LIB
NAMES blas
PATHS ${LAPACKE_SEARCH_PATHS}
PATH_SUFFIXES ${PATH_SUFFIXES_LIST})

## TODO: Get version components
# ------------------------------------------------------------------------
# Extract version information
# ------------------------------------------------------------------------

# WARNING: We may not be able to determine the version of some LAPACKE
set(LAPACKE_VERSION_MAJOR 0)
set(LAPACKE_VERSION_MINOR 0)
set(LAPACKE_VERSION_PATCH 0)
if(LAPACKE_VERSION_STRING)
string(REGEX REPLACE "([0-9]+).([0-9]+).([0-9]+)" "\\1" LAPACKE_VERSION_MAJOR "${LAPACKE_VERSION_STRING}")
string(REGEX REPLACE "([0-9]+).([0-9]+).([0-9]+)" "\\2" LAPACKE_VERSION_MINOR "${LAPACKE_VERSION_STRING}")
string(REGEX REPLACE "([0-9]+).([0-9]+).([0-9]+)" "\\3" LAPACKE_VERSION_PATCH "${LAPACKE_VERSION_STRING}")
endif()

#======================
# Checks 'REQUIRED', 'QUIET' and versions.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LAPACKE FOUND_VAR LAPACKE_FOUND
REQUIRED_VARS LAPACKE_CBLAS_INCLUDE_DIR
LAPACKE_LAPACKE_INCLUDE_DIR
LAPACKE_LIB
LAPACK_LIB
CBLAS_LIB
BLAS_LIB
VERSION_VAR LAPACKE_VERSION_STRING
)

if (LAPACKE_FOUND)
set(LAPACKE_INCLUDE_DIRS ${LAPACKE_CBLAS_INCLUDE_DIR} ${LAPACKE_CBLAS_INCLUDE_DIR})
list(REMOVE_DUPLICATES LAPACKE_INCLUDE_DIRS)
if("${CMAKE_C_COMPILER_ID}" MATCHES ".*Clang.*" OR
"${CMAKE_C_COMPILER_ID}" MATCHES ".*GNU.*" OR
"${CMAKE_C_COMPILER_ID}" MATCHES ".*Intel.*"
) #NOT MSVC
set(MATH_LIB m)
endif()
list(APPEND LAPACKE_LIBRARIES ${LAPACKE_LIB} ${LAPACK_LIB} ${BLAS_LIB} ${CBLAS_LIB})
# Check for a common combination, and find required gfortran support libraries

if(1)
if("${CMAKE_C_COMPILER_ID}" MATCHES ".*Clang.*" AND "${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
message(STATUS "\n\n WARNING: ${CMAKE_C_COMPILER} identified as ${CMAKE_C_COMPILER_ID}\n"
"AND: ${CMAKE_Fortran_COMPILER} identified as ${CMAKE_Fortran_COMPILER_ID}\n"
"\n"
"may be require special configurations. The most common is the need to"
"explicitly link C programs against the gfortran support library.")

endif()
else()
## This code automated code is hard to determine if it is robust in many different environments.
# Check for a common combination, and find required gfortran support libraries
if("${CMAKE_C_COMPILER_ID}" MATCHES ".*Clang.*" AND "${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
include(FortranCInterface)
FortranCInterface_VERIFY()
if(NOT FortranCInterface_VERIFIED_C)
message(FATAL_ERROR "C and fortran compilers are not compatible:\n${CMAKE_Fortran_COMPILER}:${CMAKE_C_COMPILER}")
endif()

execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -print-file-name=libgfortran.a OUTPUT_VARIABLE FORTRANSUPPORTLIB ERROR_QUIET)
string(STRIP ${FORTRANSUPPORTLIB} FORTRANSUPPORTLIB)
if(EXISTS "${FORTRANSUPPORTLIB}")
list(APPEND LAPACKE_LIBRARIES ${FORTRANSUPPORTLIB})
message(STATUS "Appending fortran support lib: ${FORTRANSUPPORTLIB}")
else()
message(FATAL_ERROR "COULD NOT FIND libgfortran.a support library:${FORTRANSUPPORTLIB}:")
endif()
endif()
endif()
list(APPEND LAPACKE_LIBRARIES ${MATH_LIB})
endif()

mark_as_advanced(
LAPACKE_FOUND
LAPACKE_INCLUDE_DIRS
LAPACKE_LIBRARIES
LAPACKE_VERSION_MAJOR
LAPACKE_VERSION_MINOR
LAPACKE_VERSION_PATCH
LAPACKE_VERSION_STRING
)

## For debugging
message(STATUS "LAPACKE_FOUND :${LAPACKE_FOUND}: - set to true if the library is found")
message(STATUS "LAPACKE_INCLUDE_DIRS :${LAPACKE_INCLUDE_DIRS}: - list of required include directories")
message(STATUS "LAPACKE_LIBRARIES :${LAPACKE_LIBRARIES}: - list of libraries to be linked")
message(STATUS "LAPACKE_VERSION_MAJOR :${LAPACKE_VERSION_MAJOR}: - major version number")
message(STATUS "LAPACKE_VERSION_MINOR :${LAPACKE_VERSION_MINOR}: - minor version number")
message(STATUS "LAPACKE_VERSION_PATCH :${LAPACKE_VERSION_PATCH}: - patch version number")
message(STATUS "LAPACKE_VERSION_STRING :${LAPACKE_VERSION_STRING}: - version number as a string")
7 changes: 7 additions & 0 deletions cmake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Modern lapacke provides a lapacke-config.cmake (minimum version unconfirmed, but 3.7.1 does)
so FindLAPACKE.cmake wouldn't be neccesary, (see #38)
however this isn't reliable for older/other lapacke versions, so we provide a FindModule from: https://github.com/mrirecon/bart/blob/master/cmake/FindLAPACKE.cmake.

Download with `curl -O https://raw.githubusercontent.com/mrirecon/bart/master/cmake/FindLAPACKE.cmake`

This FindLapacke handles properly the case a lapacke-config.cmake exists in the system.
6 changes: 6 additions & 0 deletions cmake/proxTVConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include(CMakeFindDependencyMacro)
find_dependency(LAPACKE)
find_dependency(LAPACK)
find_dependency(OpenMP)
find_dependency(Threads)
include("${CMAKE_CURRENT_LIST_DIR}/proxTVTargets.cmake")
Loading

0 comments on commit c02cfe1

Please sign in to comment.