waLBerlaFunctions.cmake 16.7 KB
Newer Older
1
2
3
4
5
include ( waLBerlaHelperFunctions         )
include ( waLBerlaModuleDependencySystem  )


set ( WALBERLA_GLOB_FILES *.cpp
6
7
8
                          *.c
                          *.h
                          *.cu
9
10
11
12
13
14
      CACHE INTERNAL "File endings to glob for source files" )


#######################################################################################################################
#
# Creates a walberla module library
15
#
16
17
18
19
20
21
#
# Keywords:
#   DEPENDS [required]   list of modules, that this module depends on
#   FILES   [optional]   list of all source and header files belonging to that module
#                        if this is not given, all source and header files in the directory are added.
#                        Careful: when file was added or deleted, cmake has to be run again
22
#   EXCLUDE [optional]   Files that should not be included in the module (but are located in module directory).
23
24
25
#                        This makes only sense if FILES was not specified, and all files have been added automatically.
#   BUILD_ONLY_IF_FOUND  Before building the module test if all libraries specified here are availbable.
#   [optional]           This is done using the ${arg}_FOUND variable.
26
#                        Example: waLBerla_add_module( DEPENDS someModule BUILD_ONLY_IF_FOUND pe)
27
28
29
30
31
32
33
34
35
#                                 This module is only built if PE_FOUND is true.
#
#######################################################################################################################

function ( waLBerla_add_module )
    set( options )
    set( oneValueArgs )
    set( multiValueArgs DEPENDS EXCLUDE FILES BUILD_ONLY_IF_FOUND )
    cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
36

37
38
39
    # Module name is the directory relative to WALBERLA_MODULE_DIRS
    get_current_module_name ( moduleName )
    get_module_library_name ( moduleLibraryName ${moduleName} )
40

41
42
43
44
45
46
47
48
49
50
    # Test if all required libraries are available
    # this is detected using the _FOUND variable
    foreach ( externalName ${ARG_BUILD_ONLY_IF_FOUND} )
        string( TOUPPER ${externalName} externalNameUpper )
        if ( NOT ${externalNameUpper}_FOUND )
            message ( STATUS "Module ${moduleName} is not built, because ${externalName} not available" )
            return()
        endif()
    endforeach()

51
    # Take source files either from parameter or search all source files
52
53
54
55
56
57
58
59
60
61
    file ( GLOB_RECURSE allFiles "*" )  # Find all files
    if ( ARG_FILES )
        foreach( sourceFile ${ARG_FILES} )
           get_filename_component( sourceFile ${sourceFile} ABSOLUTE )
           list( APPEND sourceFiles ${sourceFile} )
        endforeach()
    else()
        file ( GLOB_RECURSE sourceFiles ${WALBERLA_GLOB_FILES} )  # Find all source files
    endif()

62
    # Remove exclude files from the sources
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    if ( ARG_EXCLUDE )
        foreach ( fileToExclude ${ARG_EXCLUDE} )
            get_filename_component( fileToExclude ${fileToExclude} ABSOLUTE )
            list (REMOVE_ITEM sourceFiles ${fileToExclude} )
        endforeach()
    endif()

    list_minus ( otherFiles LIST1 ${allFiles} LIST2 ${sourceFiles} )
    set_source_files_properties( ${otherFiles} PROPERTIES HEADER_FILE_ONLY ON )

    if ( WALBERLA_GROUP_FILES )
       group_files( "Other Files"  FILES ${otherFiles}  )
       group_files( "Source Files" FILES ${sourceFiles} )
    endif ( )

    # Dependency Check
79
    check_dependencies( missingDeps additionalDeps FILES ${sourceFiles} EXPECTED_DEPS ${ARG_DEPENDS} ${moduleName} )
80
81
82
83
    if ( missingDeps )
        message ( WARNING "The module ${moduleName} depends on ${missingDeps} which are not listed as dependencies!" )
    endif()

84
85
    set( hasSourceFiles FALSE )
 	foreach ( sourceFile ${sourceFiles} )
Martin Bauer's avatar
Martin Bauer committed
86
 	   if ( ${sourceFile} MATCHES "\\.(c|cpp|cu)" )
87
88
89
 	      set( hasSourceFiles TRUE )
 	   endif( )
 	endforeach( )
90

91
    if ( hasSourceFiles )
92
93
94
        set( generatedSourceFiles )
        set( generatorSourceFiles )
        handle_python_codegen(sourceFiles generatedSourceFiles generatorSourceFiles codeGenRequired ${sourceFiles})
95
96
97
98
99
100
        if( NOT WALBERLA_BUILD_WITH_CODEGEN AND codeGenRequired)
            message(STATUS "Skipping ${ARG_NAME} since pystencils code generation is not enabled")
            return()
        endif()

        if ( CUDA_FOUND )
101
            cuda_add_library( ${moduleLibraryName} STATIC ${sourceFiles} ${generatedSourceFiles} ${generatorSourceFiles} ${otherFiles} )
Martin Bauer's avatar
Martin Bauer committed
102
        else()
103
            add_library( ${moduleLibraryName} STATIC ${sourceFiles} ${generatedSourceFiles} ${generatorSourceFiles} ${otherFiles} )
Martin Bauer's avatar
Martin Bauer committed
104
        endif( CUDA_FOUND )
105

106
        set_source_files_properties( ${generatedSourceFiles} PROPERTIES GENERATED TRUE )
107
108
109
 	else( )
 	   add_custom_target( ${moduleLibraryName} SOURCES ${sourceFiles} ${generatedSourceFiles} ${otherFiles} )  # dummy IDE target
 	endif( )
110

111
112
    waLBerla_register_dependency ( ${moduleName} ${ARG_DEPENDS} )

113
114
    set_property( TARGET ${moduleName} PROPERTY CXX_STANDARD 14 )

115
116
117
118
    # This property is needed for visual studio to group modules together
    if( WALBERLA_GROUP_PROJECTS )
       set_property( TARGET  ${moduleLibraryName}  PROPERTY  FOLDER  "SRC" )
    endif()
119

120
121
    # Install rule for library
    get_target_property( module_type ${moduleLibraryName} TYPE )
122
    if( ${module_type} MATCHES LIBRARY )
123
124
125
126
       install ( TARGETS ${moduleLibraryName}  RUNTIME DESTINATION bin
                                               LIBRARY DESTINATION lib
                                               ARCHIVE DESTINATION lib )
    endif( )
127

128
    # Install rule for header
129
130
    install ( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
              DESTINATION "walberla/${moduleName}"
131
              FILES_MATCHING PATTERN "*.h"
132
              PATTERN "*.in.h"     EXCLUDE
133
              PATTERN "CMakeFiles" EXCLUDE )
134
135
136
137
138

    # Install generated headers if necessary
    if ( NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR} )
        install ( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/
                  DESTINATION "walberla/${moduleName}"
139
                  FILES_MATCHING PATTERN "*.h"
140
                  PATTERN "*.in.h"     EXCLUDE
141
                  PATTERN "CMakeFiles" EXCLUDE )
142
143
144
    endif()


145
146
147
    # Report module statistics - which is later on written out to a json file
    # This file is used in the doxygen documentation to display a module graph
    #waLBerla_module_statistics ( FILES ${sourceFiles} DEPENDS ${ARG_DEPENDS} )
148

149
150
151
152
153
154
155
156
157
158
159
160
161
endfunction ( waLBerla_add_module )
#######################################################################################################################





#######################################################################################################################
#
# Compiles an application either from given source files, or otherwise globs all files in the current folder.
# The application is linked against all waLBerla modules that are listed after DEPENDS
#
#
162
#   NAME    [required]   Name of application
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#   GROUP   [optional]   IDE group name (e.g. VS)
#   DEPENDS [required]   list of modules, that this application depends on
#   FILES   [optional]   list of all source and header files belonging to that application
#                        if this is not given, all source and header files in the directory are added.
#                        Careful: when file was added or deleted, cmake has to be run again
#
#  Example:
#     waLBerla_compile_app ( NAME myApp DEPENDS core field lbm/boundary )
#######################################################################################################################

function ( waLBerla_add_executable )
    set( options )
    set( oneValueArgs NAME GROUP )
    set( multiValueArgs FILES DEPENDS )
    cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

    if( NOT ARG_NAME )
180
      message ( FATAL_ERROR "waLBerla_add_executable called without a NAME" )
181
    endif()
182

183
184
185
186
187
188
189
190
    # Skip this app, if it depends on modules that have not been built ( because they for example depend on PE)
    foreach ( depMod ${ARG_DEPENDS} )
        get_module_library_name ( depModLibraryName ${depMod} )
        if( NOT TARGET ${depModLibraryName} )
            message ( STATUS "Skipping ${ARG_NAME} since dependent module ${depMod} was not built" )
            return()
        endif()
    endforeach()
191
192

    # Take source files either from parameter or search all source files
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    set( sourceFiles )
    if ( ARG_FILES )
        foreach( sourceFile ${ARG_FILES} )
           get_filename_component( sourceFile ${sourceFile} ABSOLUTE )
           list( APPEND sourceFiles ${sourceFile} )
        endforeach()
        if ( WALBERLA_GROUP_FILES )
           group_files( "Source Files" FILES ${sourceFiles} )
        endif ( )
    else()
        file ( GLOB_RECURSE sourceFiles ${WALBERLA_GLOB_FILES} )  # Find all source files
        if ( WALBERLA_GROUP_FILES )
           file ( GLOB_RECURSE allFiles  "*" )  # Find all files
           list_minus ( otherFiles LIST1 ${allFiles} LIST2 ${sourceFiles} )
           group_files( "Source Files" FILES ${sourceFiles} )
           group_files( "Other Files" FILES ${otherFiles} )
        endif ( )
    endif()

212
213
214
    set( generatedSourceFiles )
    set( generatorSourceFiles )
    handle_python_codegen(sourceFiles generatedSourceFiles generatorSourceFiles codeGenRequired ${sourceFiles})
215

216
217
218
219
    if( NOT WALBERLA_BUILD_WITH_CODEGEN AND codeGenRequired)
        message(STATUS "Skipping ${ARG_NAME} since pystencils code generation is not enabled")
        return()
    endif()
220

221

Martin Bauer's avatar
Martin Bauer committed
222
    if ( CUDA_FOUND )
223
        cuda_add_executable( ${ARG_NAME} ${sourceFiles} ${generatedSourceFiles} ${generatorSourceFiles} )
Martin Bauer's avatar
Martin Bauer committed
224
    else()
225
        add_executable( ${ARG_NAME} ${sourceFiles} ${generatedSourceFiles} ${generatorSourceFiles} )
Martin Bauer's avatar
Martin Bauer committed
226
    endif()
227

228
    set_source_files_properties( ${generatedSourceFiles} PROPERTIES GENERATED TRUE )
Martin Bauer's avatar
Martin Bauer committed
229

230
    target_link_modules  ( ${ARG_NAME} ${ARG_DEPENDS}  )
231
    target_link_libraries( ${ARG_NAME} ${WALBERLA_LINK_LIBRARIES_KEYWORD} ${SERVICE_LIBS} )
232
    set_property( TARGET ${ARG_NAME} PROPERTY CXX_STANDARD 14 )
233
234
235
236
237
238
239

    if( WALBERLA_GROUP_PROJECTS )
        if( NOT ARG_GROUP )
            set( ARG_GROUP "APPS" )
        endif()
        set_property( TARGET  ${ARG_NAME}  PROPERTY  FOLDER  ${ARG_GROUP} )
    endif()
240

241
242
243
244
245
246
247
endfunction ( waLBerla_add_executable )

#######################################################################################################################




Martin Bauer's avatar
Martin Bauer committed
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#######################################################################################################################
#
# Function to tell CMake which C/C++/CUDA files are generated by a python file
#
# Example:
#    waLBerla_python_file_generates(MyPythonCodeGenScript.py Sweep1.cpp Sweep1.h Sweep2.h Sweep2.cu)
#
#
#######################################################################################################################
function( waLBerla_python_file_generates pythonFile )
    get_filename_component(pythonFileAbsolutePath ${pythonFile} ABSOLUTE)
    set( "WALBERLA_CODEGEN_INFO_${pythonFileAbsolutePath}" ${ARGN}
            CACHE INTERNAL "Files generated by python script ${pythonFile}" FORCE)
endfunction(waLBerla_python_file_generates)



265
266
267
268
269
270
271
272
273
274
275
#######################################################################################################################
#
# Adds a  waLBerla module test executable.
#
#######################################################################################################################

function ( waLBerla_compile_test )
    set( options )
    set( oneValueArgs NAME )
    set( multiValueArgs FILES DEPENDS )
    cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
276

277
278
    # Module name is the directory relative to WALBERLA_MODULE_DIRS
    get_current_module_name ( moduleName )
279

280
281
282
283
284
    # Filename of first source file is used as name for testcase if no name was given
    if( NOT ARG_NAME )
        list( GET ARG_FILES 0 ARG_NAME )
        get_filename_component( ARG_NAME ${ARG_NAME} NAME_WE )
    endif()
285
286

    waLBerla_add_executable ( NAME ${ARG_NAME} GROUP "TESTS/${moduleName}"
287
                              DEPENDS ${ARG_DEPENDS} ${moduleName} FILES ${ARG_FILES} )
288
289


290
291
292
293
294
295
296
297
298
endfunction ( waLBerla_compile_test )
#######################################################################################################################




#######################################################################################################################
#
# Links all files in current source dir matching a globbing expression to the build directory
299
#
300
# first parameter is glob expression
301
#
302
303
304
305
306
# Typical usage: link all parameter files in same folder as the binary was produced
#                Assuming the parameter files end with prm, write this to your CMakeLists in the
#                app or test folder:
#                waLBerla_link_files_to_builddir( "*.prm" )
#
307
# Symlinking works only under linux, on windows the files are copied. For in-source builds this does nothing.
308
309
310
311
#
#######################################################################################################################

function ( waLBerla_link_files_to_builddir globExpression )
312

313
314
315
316
    # don't need links for in-source builds
    if( CMAKE_CURRENT_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}" )
        return()
    endif()
317

318
    file( GLOB filesToLink RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${globExpression} )
319
320

    foreach( f ${filesToLink} )
321
322
323
324
325
326
327
        if( CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" )
            configure_file( ${f} ${f} COPYONLY )
        else()
            execute_process( COMMAND ${CMAKE_COMMAND} -E create_symlink
                             ${CMAKE_CURRENT_SOURCE_DIR}/${f}
                             ${CMAKE_CURRENT_BINARY_DIR}/${f} )
        endif()
328

329
    endforeach()
330

331
332
333
334
335
336
337
endfunction ( waLBerla_link_files_to_builddir )




#######################################################################################################################
#
338
339
# Adds an executable to CTest.
#
340
341
342
343
# Wrapper around add_test, that handles test labels and parallel runs
# Adds the module name as test label, plus optional user defined labels.
#
#   NAME      [required] Name of test
344
#   PROCESSES [optional] Number of MPI processes, that are used to start this test.
345
346
347
#                        If walberla is built without MPI, and PROCESSES > 1, the test is not added
#                        Defaults to 1
#   COMMAND   [optional] The command that is executed. Use this to start with parameter files or other
348
#                        command line options.
349
#                        Defaults to $<TARGET_FILE:${NAME}> (for this syntax see cmake documentation of add_test )
350
#   LABELS    [optional] Additional test labels.
351
352
353
354
#
#######################################################################################################################

function ( waLBerla_execute_test )
355

356
357
   set( options NO_MODULE_LABEL )
   set( oneValueArgs NAME PROCESSES )
Christian Godenschwager's avatar
Christian Godenschwager committed
358
   set( multiValueArgs COMMAND LABELS CONFIGURATIONS DEPENDS_ON_TARGETS )
359
360
361
   cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

   if( NOT ARG_NAME )
362
      message ( FATAL_ERROR "waLBerla_execute_test called without a NAME" )
363
   endif()
364

365
   if( NOT ARG_COMMAND AND NOT TARGET ${ARG_NAME} )
Christian Godenschwager's avatar
Christian Godenschwager committed
366
      message ( STATUS "Skipping test ${ARG_NAME} since the corresponding target is not built" )
367
      return()
368
   endif()
Christian Godenschwager's avatar
Christian Godenschwager committed
369
370
371
372
373
374
375

   foreach( dependency_target ${ARG_DEPENDS_ON_TARGETS} )
      if( NOT TARGET ${dependency_target} )
         message ( STATUS "Skipping test ${ARG_NAME} since the target ${dependency_target} is not built" )
         return()
      endif()
   endforeach( dependency_target )
376

377
378
379
380
381
382
383
384
385
386
387
   if( NOT ARG_PROCESSES )
      set ( numProcesses 1 )
   else()
      set ( numProcesses ${ARG_PROCESSES} )
   endif()

   if ( NOT ARG_COMMAND )
       set ( ARG_COMMAND $<TARGET_FILE:${ARG_NAME}> )
   endif()

   if( WALBERLA_BUILD_WITH_MPI )
388
389
390
391
      if( CMAKE_VERSION VERSION_LESS 3.10.0 )
	set ( MPIEXEC_EXECUTABLE ${MPIEXEC} )
      endif()
      list( INSERT  ARG_COMMAND  0  ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${numProcesses} ${MPIEXEC_PREFLAGS} )
392
393
   elseif( numProcesses GREATER 1 )
      return()
394
395
   endif()

396
397
398
399
400
   if( ARG_CONFIGURATIONS )
      add_test( NAME ${ARG_NAME} ${ARG_UNPARSED_ARGUMENTS} COMMAND ${ARG_COMMAND} CONFIGURATIONS ${ARG_CONFIGURATIONS} )
   else()
      add_test( NAME ${ARG_NAME} ${ARG_UNPARSED_ARGUMENTS} COMMAND ${ARG_COMMAND} )
   endif()
401

402
403
404
   if( ARG_NO_MODULE_LABEL )
      set_tests_properties ( ${ARG_NAME} PROPERTIES LABELS "${ARG_LABELS}" )
   else()
405
      get_current_module_name ( moduleName  )
406
407
408
409
      set_tests_properties ( ${ARG_NAME} PROPERTIES LABELS "${moduleName} ${ARG_LABELS}" )
   endif()

   set_tests_properties ( ${ARG_NAME} PROPERTIES PROCESSORS ${numProcesses} )
410

411
412
endfunction ( waLBerla_execute_test )
#######################################################################################################################