diff --git a/cmake/stdlib.cmake b/cmake/stdlib.cmake index bdaf87d1f..0ec86e299 100644 --- a/cmake/stdlib.cmake +++ b/cmake/stdlib.cmake @@ -12,7 +12,8 @@ function(preprocess preproc preprocopts srcext trgext srcfiles trgfiles) set(_trgfiles) foreach(srcfile IN LISTS srcfiles) - string(REGEX REPLACE "\\.${srcext}$" ".${trgext}" trgfile ${srcfile}) + get_filename_component(filename ${srcfile} NAME) + string(REGEX REPLACE "\\.${srcext}$" ".${trgext}" trgfile ${filename}) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trgfile} COMMAND ${preproc} ${preprocopts} ${CMAKE_CURRENT_SOURCE_DIR}/${srcfile} ${CMAKE_CURRENT_BINARY_DIR}/${trgfile} @@ -47,3 +48,65 @@ function (fypp_f90pp fyppopts fyppfiles F90files) set(${F90files} ${_F90files} PARENT_SCOPE) endfunction() +# Helper function to configure stdlib targets +# +# It preprocesses the given fypp and fypp+cpp files, combines them with the +# regular Fortran files, and creates a library target with the given name. +# Args: +# target_name [in]: Name of the library target to create +# regular_sources_var [in]: Regular Fortran sources +# fypp_files_var [in]: Sources to be preprocessed with fypp +# cpp_files_var [in]: Sources to be preprocessed with fypp and cpp +# +function(configure_stdlib_target target_name regular_sources_var fypp_files_var cpp_files_var) + #### Pre-process: .fpp -> .f90 via Fypp + fypp_f90("${fyppFlags}" "${${fypp_files_var}}" ${target_name}_fypp_outFiles) + #### Pre-process: .fypp -> .F90 via Fypp (for C preprocessor directives) + fypp_f90pp("${fyppFlags}" "${${cpp_files_var}}" ${target_name}_cpp_outFiles) + + list(APPEND all_sources ${${target_name}_fypp_outFiles}) + list(APPEND all_sources ${${target_name}_cpp_outFiles}) + list(APPEND all_sources ${${regular_sources_var}}) + + add_library(${target_name} ${all_sources}) + add_library(${PROJECT_NAME}::${target_name} ALIAS ${target_name}) + + set_target_properties( + ${target_name} + PROPERTIES + POSITION_INDEPENDENT_CODE ON + WINDOWS_EXPORT_ALL_SYMBOLS ON + ) + + if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0) + target_compile_options( + ${target_name} + PRIVATE + $<$:-fno-range-check> + ) + endif() + + set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/mod_files/${target_name}/) + set(INSTALL_MOD_DIR "${CMAKE_INSTALL_MODULEDIR}/${target_name}") + # We need the module directory before we finish the configure stage since the + # build interface might resolve before the module directory is generated by CMake + if(NOT EXISTS "${LIB_MOD_DIR}") + file(MAKE_DIRECTORY "${LIB_MOD_DIR}") + endif() + + set_target_properties(${target_name} PROPERTIES + Fortran_MODULE_DIRECTORY ${LIB_MOD_DIR} + ) + target_include_directories(${target_name} PUBLIC + $ + $ + ) + + install(TARGETS ${target_name} + EXPORT ${PROJECT_NAME}-targets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ) + install(DIRECTORY ${LIB_MOD_DIR} DESTINATION "${INSTALL_MOD_DIR}") +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ff2342fc..9280d3397 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ -#### Pre-process: .fpp -> .f90 via Fypp +add_subdirectory(blas) +add_subdirectory(lapack) -# Create a list of the files to be preprocessed set(fppFiles stdlib_ascii.fypp stdlib_bitsets.fypp @@ -36,6 +36,9 @@ set(fppFiles stdlib_linalg_determinant.fypp stdlib_linalg_qr.fypp stdlib_linalg_inverse.fypp + stdlib_linalg_iterative_solvers.fypp + stdlib_linalg_iterative_solvers_cg.fypp + stdlib_linalg_iterative_solvers_pcg.fypp stdlib_linalg_pinv.fypp stdlib_linalg_norms.fypp stdlib_linalg_state.fypp @@ -89,24 +92,8 @@ set(fppFiles stdlib_strings.fypp stdlib_version.fypp ) - -# Preprocessed files to contain preprocessor directives -> .F90 -set(cppFiles - stdlib_linalg_constants.fypp - stdlib_linalg_blas.fypp - stdlib_linalg_lapack.fypp - stdlib_linalg_iterative_solvers.fypp - stdlib_linalg_iterative_solvers_cg.fypp - stdlib_linalg_iterative_solvers_pcg.fypp -) - -add_subdirectory(blas) -add_subdirectory(lapack) - -fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) -fypp_f90pp("${fyppFlags}" "${cppFiles}" outPreprocFiles) - -set(SRC +set(cppFiles stdlib_linalg_constants.fypp) +set(f90Files stdlib_ansi.f90 stdlib_ansi_operator.f90 stdlib_ansi_to_string.f90 @@ -127,57 +114,9 @@ set(SRC stdlib_specialfunctions_legendre.f90 stdlib_quadrature_gauss.f90 stdlib_stringlist_type.f90 - ${outFiles} - ${outPreprocFiles} -) - -add_library(${PROJECT_NAME} ${SRC}) - -# Link to BLAS and LAPACK -if(BLAS_FOUND AND LAPACK_FOUND) - target_link_libraries(${PROJECT_NAME} "BLAS::BLAS") - target_link_libraries(${PROJECT_NAME} "LAPACK::LAPACK") -endif() - -set_target_properties( - ${PROJECT_NAME} - PROPERTIES - POSITION_INDEPENDENT_CODE ON - WINDOWS_EXPORT_ALL_SYMBOLS ON -) - -if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0) - target_compile_options( - ${PROJECT_NAME} - PRIVATE - $<$:-fno-range-check> - ) -endif() - -set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/mod_files/) -# We need the module directory before we finish the configure stage since the -# build interface might resolve before the module directory is generated by CMake -if(NOT EXISTS "${LIB_MOD_DIR}") - file(MAKE_DIRECTORY "${LIB_MOD_DIR}") -endif() - -set_target_properties(${PROJECT_NAME} PROPERTIES - Fortran_MODULE_DIRECTORY ${LIB_MOD_DIR}) -target_include_directories(${PROJECT_NAME} PUBLIC - $ - $ + $,f18estop.f90,f08estop.f90> ) -if(f18errorstop) - target_sources(${PROJECT_NAME} PRIVATE f18estop.f90) -else() - target_sources(${PROJECT_NAME} PRIVATE f08estop.f90) -endif() +configure_stdlib_target(${PROJECT_NAME} f90Files fppFiles cppFiles) -install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}-targets - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" -) -install(DIRECTORY ${LIB_MOD_DIR} DESTINATION "${CMAKE_INSTALL_MODULEDIR}") +target_link_libraries(${PROJECT_NAME} PUBLIC blas lapack) diff --git a/src/blas/CMakeLists.txt b/src/blas/CMakeLists.txt index 5099b909e..6b4f4b048 100644 --- a/src/blas/CMakeLists.txt +++ b/src/blas/CMakeLists.txt @@ -1,20 +1,25 @@ -#### - -set(dir "${CMAKE_CURRENT_SOURCE_DIR}") - -list(APPEND fppFiles - blas/stdlib_blas_constants.fypp - blas/stdlib_blas.fypp - blas/stdlib_blas_level1.fypp - blas/stdlib_blas_level2_ban.fypp - blas/stdlib_blas_level2_gen.fypp - blas/stdlib_blas_level2_pac.fypp - blas/stdlib_blas_level2_sym.fypp - blas/stdlib_blas_level2_tri.fypp - blas/stdlib_blas_level3_gen.fypp - blas/stdlib_blas_level3_sym.fypp - blas/stdlib_blas_level3_tri.fypp - blas/stdlib_linalg_blas_aux.fypp +set(blas_fppFiles + ../stdlib_kinds.fypp + stdlib_blas_constants.fypp + stdlib_blas.fypp + stdlib_blas_level1.fypp + stdlib_blas_level2_ban.fypp + stdlib_blas_level2_gen.fypp + stdlib_blas_level2_pac.fypp + stdlib_blas_level2_sym.fypp + stdlib_blas_level2_tri.fypp + stdlib_blas_level3_gen.fypp + stdlib_blas_level3_sym.fypp + stdlib_blas_level3_tri.fypp + stdlib_linalg_blas_aux.fypp ) +set(blas_cppFiles + ../stdlib_linalg_constants.fypp + ../stdlib_linalg_blas.fypp +) + +configure_stdlib_target(blas "" blas_fppFiles blas_cppFiles) -set(fppFiles "${fppFiles}" PARENT_SCOPE) +if(BLAS_FOUND) + target_link_libraries(blas PUBLIC "BLAS::BLAS") +endif() diff --git a/src/lapack/CMakeLists.txt b/src/lapack/CMakeLists.txt index a8f3445ce..c988164c0 100644 --- a/src/lapack/CMakeLists.txt +++ b/src/lapack/CMakeLists.txt @@ -1,58 +1,77 @@ -list(APPEND fppFiles - lapack/stdlib_lapack_base.fypp - lapack/stdlib_lapack_solve.fypp - lapack/stdlib_lapack_others.fypp - lapack/stdlib_lapack_orthogonal_factors.fypp - lapack/stdlib_lapack_eig_svd_lsq.fypp - lapack/stdlib_linalg_lapack_aux.fypp - lapack/stdlib_lapack_auxiliary.fypp - lapack/stdlib_lapack_blas_like_base.fypp - lapack/stdlib_lapack_blas_like_l1.fypp - lapack/stdlib_lapack_blas_like_l2.fypp - lapack/stdlib_lapack_blas_like_l3.fypp - lapack/stdlib_lapack_blas_like_mnorm.fypp - lapack/stdlib_lapack_blas_like_scalar.fypp - lapack/stdlib_lapack_cosine_sine.fypp - lapack/stdlib_lapack_cosine_sine2.fypp - lapack/stdlib_lapack_eigv_comp.fypp - lapack/stdlib_lapack_eigv_comp2.fypp - lapack/stdlib_lapack_eigv_gen.fypp - lapack/stdlib_lapack_eigv_gen2.fypp - lapack/stdlib_lapack_eigv_gen3.fypp - lapack/stdlib_lapack_eigv_std_driver.fypp - lapack/stdlib_lapack_eigv_svd_bidiag_dc.fypp - lapack/stdlib_lapack_eigv_svd_drivers.fypp - lapack/stdlib_lapack_eigv_svd_drivers2.fypp - lapack/stdlib_lapack_eigv_svd_drivers3.fypp - lapack/stdlib_lapack_eigv_sym_comp.fypp - lapack/stdlib_lapack_eigv_sym.fypp - lapack/stdlib_lapack_eigv_tridiag.fypp - lapack/stdlib_lapack_eigv_tridiag2.fypp - lapack/stdlib_lapack_eigv_tridiag3.fypp - lapack/stdlib_lapack_givens_jacobi_rot.fypp - lapack/stdlib_lapack_householder_reflectors.fypp - lapack/stdlib_lapack_lsq.fypp - lapack/stdlib_lapack_lsq_aux.fypp - lapack/stdlib_lapack_lsq_constrained.fypp - lapack/stdlib_lapack_orthogonal_factors_ql.fypp - lapack/stdlib_lapack_orthogonal_factors_qr.fypp - lapack/stdlib_lapack_orthogonal_factors_rz.fypp - lapack/stdlib_lapack_others_sm.fypp - lapack/stdlib_lapack_solve_aux.fypp - lapack/stdlib_lapack_solve_chol_comp.fypp - lapack/stdlib_lapack_solve_chol.fypp - lapack/stdlib_lapack_solve_ldl_comp.fypp - lapack/stdlib_lapack_solve_ldl_comp2.fypp - lapack/stdlib_lapack_solve_ldl_comp3.fypp - lapack/stdlib_lapack_solve_ldl_comp4.fypp - lapack/stdlib_lapack_solve_ldl.fypp - lapack/stdlib_lapack_solve_lu_comp.fypp - lapack/stdlib_lapack_solve_lu.fypp - lapack/stdlib_lapack_solve_tri_comp.fypp - lapack/stdlib_lapack_svd_bidiag_qr.fypp - lapack/stdlib_lapack_svd_comp.fypp - lapack/stdlib_lapack_svd_comp2.fypp +set(lapack_fppFiles + ../stdlib_kinds.fypp + ../stdlib_linalg_state.fypp + ../stdlib_error.fypp + ../stdlib_optval.fypp + ../stdlib_io.fypp + ../stdlib_ascii.fypp + ../stdlib_string_type.fypp + stdlib_lapack_base.fypp + stdlib_lapack_solve.fypp + stdlib_lapack_others.fypp + stdlib_lapack_orthogonal_factors.fypp + stdlib_lapack_eig_svd_lsq.fypp + stdlib_linalg_lapack_aux.fypp + stdlib_lapack_auxiliary.fypp + stdlib_lapack_blas_like_base.fypp + stdlib_lapack_blas_like_l1.fypp + stdlib_lapack_blas_like_l2.fypp + stdlib_lapack_blas_like_l3.fypp + stdlib_lapack_blas_like_mnorm.fypp + stdlib_lapack_blas_like_scalar.fypp + stdlib_lapack_cosine_sine.fypp + stdlib_lapack_cosine_sine2.fypp + stdlib_lapack_eigv_comp.fypp + stdlib_lapack_eigv_comp2.fypp + stdlib_lapack_eigv_gen.fypp + stdlib_lapack_eigv_gen2.fypp + stdlib_lapack_eigv_gen3.fypp + stdlib_lapack_eigv_std_driver.fypp + stdlib_lapack_eigv_svd_bidiag_dc.fypp + stdlib_lapack_eigv_svd_drivers.fypp + stdlib_lapack_eigv_svd_drivers2.fypp + stdlib_lapack_eigv_svd_drivers3.fypp + stdlib_lapack_eigv_sym_comp.fypp + stdlib_lapack_eigv_sym.fypp + stdlib_lapack_eigv_tridiag.fypp + stdlib_lapack_eigv_tridiag2.fypp + stdlib_lapack_eigv_tridiag3.fypp + stdlib_lapack_givens_jacobi_rot.fypp + stdlib_lapack_householder_reflectors.fypp + stdlib_lapack_lsq.fypp + stdlib_lapack_lsq_aux.fypp + stdlib_lapack_lsq_constrained.fypp + stdlib_lapack_orthogonal_factors_ql.fypp + stdlib_lapack_orthogonal_factors_qr.fypp + stdlib_lapack_orthogonal_factors_rz.fypp + stdlib_lapack_others_sm.fypp + stdlib_lapack_solve_aux.fypp + stdlib_lapack_solve_chol_comp.fypp + stdlib_lapack_solve_chol.fypp + stdlib_lapack_solve_ldl_comp.fypp + stdlib_lapack_solve_ldl_comp2.fypp + stdlib_lapack_solve_ldl_comp3.fypp + stdlib_lapack_solve_ldl_comp4.fypp + stdlib_lapack_solve_ldl.fypp + stdlib_lapack_solve_lu_comp.fypp + stdlib_lapack_solve_lu.fypp + stdlib_lapack_solve_tri_comp.fypp + stdlib_lapack_svd_bidiag_qr.fypp + stdlib_lapack_svd_comp.fypp + stdlib_lapack_svd_comp2.fypp ) +set(lapack_cppFiles + ../stdlib_linalg_constants.fypp + ../stdlib_linalg_lapack.fypp +) +set(lapack_f90Files + $,../f18estop.f90,../f08estop.f90> +) + +configure_stdlib_target(lapack lapack_f90Files lapack_fppFiles lapack_cppFiles) -set(fppFiles "${fppFiles}" PARENT_SCOPE) +if(LAPACK_FOUND) + target_link_libraries(lapack PUBLIC "LAPACK::LAPACK") +endif() +target_link_libraries(lapack PUBLIC blas)