Skip to content

Commit 80a8164

Browse files
authored
Modularize BLAS and LAPACK modules in CMake to make it easier to use in external projects (#1033)
2 parents fb404bb + 08b2ea9 commit 80a8164

File tree

4 files changed

+171
-145
lines changed

4 files changed

+171
-145
lines changed

cmake/stdlib.cmake

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ function(preprocess preproc preprocopts srcext trgext srcfiles trgfiles)
1212

1313
set(_trgfiles)
1414
foreach(srcfile IN LISTS srcfiles)
15-
string(REGEX REPLACE "\\.${srcext}$" ".${trgext}" trgfile ${srcfile})
15+
get_filename_component(filename ${srcfile} NAME)
16+
string(REGEX REPLACE "\\.${srcext}$" ".${trgext}" trgfile ${filename})
1617
add_custom_command(
1718
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trgfile}
1819
COMMAND ${preproc} ${preprocopts} ${CMAKE_CURRENT_SOURCE_DIR}/${srcfile} ${CMAKE_CURRENT_BINARY_DIR}/${trgfile}
@@ -47,3 +48,65 @@ function (fypp_f90pp fyppopts fyppfiles F90files)
4748
set(${F90files} ${_F90files} PARENT_SCOPE)
4849
endfunction()
4950

51+
# Helper function to configure stdlib targets
52+
#
53+
# It preprocesses the given fypp and fypp+cpp files, combines them with the
54+
# regular Fortran files, and creates a library target with the given name.
55+
# Args:
56+
# target_name [in]: Name of the library target to create
57+
# regular_sources_var [in]: Regular Fortran sources
58+
# fypp_files_var [in]: Sources to be preprocessed with fypp
59+
# cpp_files_var [in]: Sources to be preprocessed with fypp and cpp
60+
#
61+
function(configure_stdlib_target target_name regular_sources_var fypp_files_var cpp_files_var)
62+
#### Pre-process: .fpp -> .f90 via Fypp
63+
fypp_f90("${fyppFlags}" "${${fypp_files_var}}" ${target_name}_fypp_outFiles)
64+
#### Pre-process: .fypp -> .F90 via Fypp (for C preprocessor directives)
65+
fypp_f90pp("${fyppFlags}" "${${cpp_files_var}}" ${target_name}_cpp_outFiles)
66+
67+
list(APPEND all_sources ${${target_name}_fypp_outFiles})
68+
list(APPEND all_sources ${${target_name}_cpp_outFiles})
69+
list(APPEND all_sources ${${regular_sources_var}})
70+
71+
add_library(${target_name} ${all_sources})
72+
add_library(${PROJECT_NAME}::${target_name} ALIAS ${target_name})
73+
74+
set_target_properties(
75+
${target_name}
76+
PROPERTIES
77+
POSITION_INDEPENDENT_CODE ON
78+
WINDOWS_EXPORT_ALL_SYMBOLS ON
79+
)
80+
81+
if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0)
82+
target_compile_options(
83+
${target_name}
84+
PRIVATE
85+
$<$<COMPILE_LANGUAGE:Fortran>:-fno-range-check>
86+
)
87+
endif()
88+
89+
set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/mod_files/${target_name}/)
90+
set(INSTALL_MOD_DIR "${CMAKE_INSTALL_MODULEDIR}/${target_name}")
91+
# We need the module directory before we finish the configure stage since the
92+
# build interface might resolve before the module directory is generated by CMake
93+
if(NOT EXISTS "${LIB_MOD_DIR}")
94+
file(MAKE_DIRECTORY "${LIB_MOD_DIR}")
95+
endif()
96+
97+
set_target_properties(${target_name} PROPERTIES
98+
Fortran_MODULE_DIRECTORY ${LIB_MOD_DIR}
99+
)
100+
target_include_directories(${target_name} PUBLIC
101+
$<BUILD_INTERFACE:${LIB_MOD_DIR}>
102+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_MODULEDIR}>
103+
)
104+
105+
install(TARGETS ${target_name}
106+
EXPORT ${PROJECT_NAME}-targets
107+
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
108+
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
109+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
110+
)
111+
install(DIRECTORY ${LIB_MOD_DIR} DESTINATION "${INSTALL_MOD_DIR}")
112+
endfunction()

src/CMakeLists.txt

Lines changed: 10 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#### Pre-process: .fpp -> .f90 via Fypp
1+
add_subdirectory(blas)
2+
add_subdirectory(lapack)
23

3-
# Create a list of the files to be preprocessed
44
set(fppFiles
55
stdlib_ascii.fypp
66
stdlib_bitsets.fypp
@@ -36,6 +36,9 @@ set(fppFiles
3636
stdlib_linalg_determinant.fypp
3737
stdlib_linalg_qr.fypp
3838
stdlib_linalg_inverse.fypp
39+
stdlib_linalg_iterative_solvers.fypp
40+
stdlib_linalg_iterative_solvers_cg.fypp
41+
stdlib_linalg_iterative_solvers_pcg.fypp
3942
stdlib_linalg_pinv.fypp
4043
stdlib_linalg_norms.fypp
4144
stdlib_linalg_state.fypp
@@ -89,24 +92,8 @@ set(fppFiles
8992
stdlib_strings.fypp
9093
stdlib_version.fypp
9194
)
92-
93-
# Preprocessed files to contain preprocessor directives -> .F90
94-
set(cppFiles
95-
stdlib_linalg_constants.fypp
96-
stdlib_linalg_blas.fypp
97-
stdlib_linalg_lapack.fypp
98-
stdlib_linalg_iterative_solvers.fypp
99-
stdlib_linalg_iterative_solvers_cg.fypp
100-
stdlib_linalg_iterative_solvers_pcg.fypp
101-
)
102-
103-
add_subdirectory(blas)
104-
add_subdirectory(lapack)
105-
106-
fypp_f90("${fyppFlags}" "${fppFiles}" outFiles)
107-
fypp_f90pp("${fyppFlags}" "${cppFiles}" outPreprocFiles)
108-
109-
set(SRC
95+
set(cppFiles stdlib_linalg_constants.fypp)
96+
set(f90Files
11097
stdlib_ansi.f90
11198
stdlib_ansi_operator.f90
11299
stdlib_ansi_to_string.f90
@@ -127,57 +114,9 @@ set(SRC
127114
stdlib_specialfunctions_legendre.f90
128115
stdlib_quadrature_gauss.f90
129116
stdlib_stringlist_type.f90
130-
${outFiles}
131-
${outPreprocFiles}
132-
)
133-
134-
add_library(${PROJECT_NAME} ${SRC})
135-
136-
# Link to BLAS and LAPACK
137-
if(BLAS_FOUND AND LAPACK_FOUND)
138-
target_link_libraries(${PROJECT_NAME} "BLAS::BLAS")
139-
target_link_libraries(${PROJECT_NAME} "LAPACK::LAPACK")
140-
endif()
141-
142-
set_target_properties(
143-
${PROJECT_NAME}
144-
PROPERTIES
145-
POSITION_INDEPENDENT_CODE ON
146-
WINDOWS_EXPORT_ALL_SYMBOLS ON
147-
)
148-
149-
if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 10.0)
150-
target_compile_options(
151-
${PROJECT_NAME}
152-
PRIVATE
153-
$<$<COMPILE_LANGUAGE:Fortran>:-fno-range-check>
154-
)
155-
endif()
156-
157-
set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/mod_files/)
158-
# We need the module directory before we finish the configure stage since the
159-
# build interface might resolve before the module directory is generated by CMake
160-
if(NOT EXISTS "${LIB_MOD_DIR}")
161-
file(MAKE_DIRECTORY "${LIB_MOD_DIR}")
162-
endif()
163-
164-
set_target_properties(${PROJECT_NAME} PROPERTIES
165-
Fortran_MODULE_DIRECTORY ${LIB_MOD_DIR})
166-
target_include_directories(${PROJECT_NAME} PUBLIC
167-
$<BUILD_INTERFACE:${LIB_MOD_DIR}>
168-
$<INSTALL_INTERFACE:${CMAKE_INSTALL_MODULEDIR}>
117+
$<IF:$<BOOL:${f18errorstop}>,f18estop.f90,f08estop.f90>
169118
)
170119

171-
if(f18errorstop)
172-
target_sources(${PROJECT_NAME} PRIVATE f18estop.f90)
173-
else()
174-
target_sources(${PROJECT_NAME} PRIVATE f08estop.f90)
175-
endif()
120+
configure_stdlib_target(${PROJECT_NAME} f90Files fppFiles cppFiles)
176121

177-
install(TARGETS ${PROJECT_NAME}
178-
EXPORT ${PROJECT_NAME}-targets
179-
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
180-
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
181-
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
182-
)
183-
install(DIRECTORY ${LIB_MOD_DIR} DESTINATION "${CMAKE_INSTALL_MODULEDIR}")
122+
target_link_libraries(${PROJECT_NAME} PUBLIC blas lapack)

src/blas/CMakeLists.txt

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
####
2-
3-
set(dir "${CMAKE_CURRENT_SOURCE_DIR}")
4-
5-
list(APPEND fppFiles
6-
blas/stdlib_blas_constants.fypp
7-
blas/stdlib_blas.fypp
8-
blas/stdlib_blas_level1.fypp
9-
blas/stdlib_blas_level2_ban.fypp
10-
blas/stdlib_blas_level2_gen.fypp
11-
blas/stdlib_blas_level2_pac.fypp
12-
blas/stdlib_blas_level2_sym.fypp
13-
blas/stdlib_blas_level2_tri.fypp
14-
blas/stdlib_blas_level3_gen.fypp
15-
blas/stdlib_blas_level3_sym.fypp
16-
blas/stdlib_blas_level3_tri.fypp
17-
blas/stdlib_linalg_blas_aux.fypp
1+
set(blas_fppFiles
2+
../stdlib_kinds.fypp
3+
stdlib_blas_constants.fypp
4+
stdlib_blas.fypp
5+
stdlib_blas_level1.fypp
6+
stdlib_blas_level2_ban.fypp
7+
stdlib_blas_level2_gen.fypp
8+
stdlib_blas_level2_pac.fypp
9+
stdlib_blas_level2_sym.fypp
10+
stdlib_blas_level2_tri.fypp
11+
stdlib_blas_level3_gen.fypp
12+
stdlib_blas_level3_sym.fypp
13+
stdlib_blas_level3_tri.fypp
14+
stdlib_linalg_blas_aux.fypp
1815
)
16+
set(blas_cppFiles
17+
../stdlib_linalg_constants.fypp
18+
../stdlib_linalg_blas.fypp
19+
)
20+
21+
configure_stdlib_target(blas "" blas_fppFiles blas_cppFiles)
1922

20-
set(fppFiles "${fppFiles}" PARENT_SCOPE)
23+
if(BLAS_FOUND)
24+
target_link_libraries(blas PUBLIC "BLAS::BLAS")
25+
endif()

src/lapack/CMakeLists.txt

Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,77 @@
1-
list(APPEND fppFiles
2-
lapack/stdlib_lapack_base.fypp
3-
lapack/stdlib_lapack_solve.fypp
4-
lapack/stdlib_lapack_others.fypp
5-
lapack/stdlib_lapack_orthogonal_factors.fypp
6-
lapack/stdlib_lapack_eig_svd_lsq.fypp
7-
lapack/stdlib_linalg_lapack_aux.fypp
81

9-
lapack/stdlib_lapack_auxiliary.fypp
10-
lapack/stdlib_lapack_blas_like_base.fypp
11-
lapack/stdlib_lapack_blas_like_l1.fypp
12-
lapack/stdlib_lapack_blas_like_l2.fypp
13-
lapack/stdlib_lapack_blas_like_l3.fypp
14-
lapack/stdlib_lapack_blas_like_mnorm.fypp
15-
lapack/stdlib_lapack_blas_like_scalar.fypp
16-
lapack/stdlib_lapack_cosine_sine.fypp
17-
lapack/stdlib_lapack_cosine_sine2.fypp
18-
lapack/stdlib_lapack_eigv_comp.fypp
19-
lapack/stdlib_lapack_eigv_comp2.fypp
20-
lapack/stdlib_lapack_eigv_gen.fypp
21-
lapack/stdlib_lapack_eigv_gen2.fypp
22-
lapack/stdlib_lapack_eigv_gen3.fypp
23-
lapack/stdlib_lapack_eigv_std_driver.fypp
24-
lapack/stdlib_lapack_eigv_svd_bidiag_dc.fypp
25-
lapack/stdlib_lapack_eigv_svd_drivers.fypp
26-
lapack/stdlib_lapack_eigv_svd_drivers2.fypp
27-
lapack/stdlib_lapack_eigv_svd_drivers3.fypp
28-
lapack/stdlib_lapack_eigv_sym_comp.fypp
29-
lapack/stdlib_lapack_eigv_sym.fypp
30-
lapack/stdlib_lapack_eigv_tridiag.fypp
31-
lapack/stdlib_lapack_eigv_tridiag2.fypp
32-
lapack/stdlib_lapack_eigv_tridiag3.fypp
33-
lapack/stdlib_lapack_givens_jacobi_rot.fypp
34-
lapack/stdlib_lapack_householder_reflectors.fypp
35-
lapack/stdlib_lapack_lsq.fypp
36-
lapack/stdlib_lapack_lsq_aux.fypp
37-
lapack/stdlib_lapack_lsq_constrained.fypp
38-
lapack/stdlib_lapack_orthogonal_factors_ql.fypp
39-
lapack/stdlib_lapack_orthogonal_factors_qr.fypp
40-
lapack/stdlib_lapack_orthogonal_factors_rz.fypp
41-
lapack/stdlib_lapack_others_sm.fypp
42-
lapack/stdlib_lapack_solve_aux.fypp
43-
lapack/stdlib_lapack_solve_chol_comp.fypp
44-
lapack/stdlib_lapack_solve_chol.fypp
45-
lapack/stdlib_lapack_solve_ldl_comp.fypp
46-
lapack/stdlib_lapack_solve_ldl_comp2.fypp
47-
lapack/stdlib_lapack_solve_ldl_comp3.fypp
48-
lapack/stdlib_lapack_solve_ldl_comp4.fypp
49-
lapack/stdlib_lapack_solve_ldl.fypp
50-
lapack/stdlib_lapack_solve_lu_comp.fypp
51-
lapack/stdlib_lapack_solve_lu.fypp
52-
lapack/stdlib_lapack_solve_tri_comp.fypp
53-
lapack/stdlib_lapack_svd_bidiag_qr.fypp
54-
lapack/stdlib_lapack_svd_comp.fypp
55-
lapack/stdlib_lapack_svd_comp2.fypp
2+
set(lapack_fppFiles
3+
../stdlib_kinds.fypp
4+
../stdlib_linalg_state.fypp
5+
../stdlib_error.fypp
6+
../stdlib_optval.fypp
7+
../stdlib_io.fypp
8+
../stdlib_ascii.fypp
9+
../stdlib_string_type.fypp
10+
stdlib_lapack_base.fypp
11+
stdlib_lapack_solve.fypp
12+
stdlib_lapack_others.fypp
13+
stdlib_lapack_orthogonal_factors.fypp
14+
stdlib_lapack_eig_svd_lsq.fypp
15+
stdlib_linalg_lapack_aux.fypp
16+
stdlib_lapack_auxiliary.fypp
17+
stdlib_lapack_blas_like_base.fypp
18+
stdlib_lapack_blas_like_l1.fypp
19+
stdlib_lapack_blas_like_l2.fypp
20+
stdlib_lapack_blas_like_l3.fypp
21+
stdlib_lapack_blas_like_mnorm.fypp
22+
stdlib_lapack_blas_like_scalar.fypp
23+
stdlib_lapack_cosine_sine.fypp
24+
stdlib_lapack_cosine_sine2.fypp
25+
stdlib_lapack_eigv_comp.fypp
26+
stdlib_lapack_eigv_comp2.fypp
27+
stdlib_lapack_eigv_gen.fypp
28+
stdlib_lapack_eigv_gen2.fypp
29+
stdlib_lapack_eigv_gen3.fypp
30+
stdlib_lapack_eigv_std_driver.fypp
31+
stdlib_lapack_eigv_svd_bidiag_dc.fypp
32+
stdlib_lapack_eigv_svd_drivers.fypp
33+
stdlib_lapack_eigv_svd_drivers2.fypp
34+
stdlib_lapack_eigv_svd_drivers3.fypp
35+
stdlib_lapack_eigv_sym_comp.fypp
36+
stdlib_lapack_eigv_sym.fypp
37+
stdlib_lapack_eigv_tridiag.fypp
38+
stdlib_lapack_eigv_tridiag2.fypp
39+
stdlib_lapack_eigv_tridiag3.fypp
40+
stdlib_lapack_givens_jacobi_rot.fypp
41+
stdlib_lapack_householder_reflectors.fypp
42+
stdlib_lapack_lsq.fypp
43+
stdlib_lapack_lsq_aux.fypp
44+
stdlib_lapack_lsq_constrained.fypp
45+
stdlib_lapack_orthogonal_factors_ql.fypp
46+
stdlib_lapack_orthogonal_factors_qr.fypp
47+
stdlib_lapack_orthogonal_factors_rz.fypp
48+
stdlib_lapack_others_sm.fypp
49+
stdlib_lapack_solve_aux.fypp
50+
stdlib_lapack_solve_chol_comp.fypp
51+
stdlib_lapack_solve_chol.fypp
52+
stdlib_lapack_solve_ldl_comp.fypp
53+
stdlib_lapack_solve_ldl_comp2.fypp
54+
stdlib_lapack_solve_ldl_comp3.fypp
55+
stdlib_lapack_solve_ldl_comp4.fypp
56+
stdlib_lapack_solve_ldl.fypp
57+
stdlib_lapack_solve_lu_comp.fypp
58+
stdlib_lapack_solve_lu.fypp
59+
stdlib_lapack_solve_tri_comp.fypp
60+
stdlib_lapack_svd_bidiag_qr.fypp
61+
stdlib_lapack_svd_comp.fypp
62+
stdlib_lapack_svd_comp2.fypp
5663
)
64+
set(lapack_cppFiles
65+
../stdlib_linalg_constants.fypp
66+
../stdlib_linalg_lapack.fypp
67+
)
68+
set(lapack_f90Files
69+
$<IF:$<BOOL:${f18errorstop}>,../f18estop.f90,../f08estop.f90>
70+
)
71+
72+
configure_stdlib_target(lapack lapack_f90Files lapack_fppFiles lapack_cppFiles)
5773

58-
set(fppFiles "${fppFiles}" PARENT_SCOPE)
74+
if(LAPACK_FOUND)
75+
target_link_libraries(lapack PUBLIC "LAPACK::LAPACK")
76+
endif()
77+
target_link_libraries(lapack PUBLIC blas)

0 commit comments

Comments
 (0)