waLBerlaFunctions.cmake 15 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
#                                 This module is only built if PE_FOUND is true.
28
29
#   OPTIONAL_DEPENDS     Lists modules, that this module might depend on. For example a module could depend on mesh_common if OpenMesh is
#   [optional]           available.
30
31
32
33
34
35
#
#######################################################################################################################

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

39
    set( ALL_DEPENDENCIES ${ARG_DEPENDS} ${ARG_OPTIONAL_DEPENDS})
40
41
42
    # Module name is the directory relative to WALBERLA_MODULE_DIRS
    get_current_module_name ( moduleName )
    get_module_library_name ( moduleLibraryName ${moduleName} )
43

44
45
46
47
48
49
50
51
52
53
    # 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()

54
    # Take source files either from parameter or search all source files
55
56
57
58
59
60
61
62
63
64
    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()

65
    # Remove exclude files from the sources
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    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
82
    check_dependencies( missingDeps additionalDeps FILES ${sourceFiles} EXPECTED_DEPS ${ALL_DEPENDENCIES} ${moduleName} )
83
84
85
86
    if ( missingDeps )
        message ( WARNING "The module ${moduleName} depends on ${missingDeps} which are not listed as dependencies!" )
    endif()

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

94
    if ( hasSourceFiles )
95
       add_library( ${moduleLibraryName} STATIC ${sourceFiles} ${otherFiles} )
96
 	else( )
97
       add_custom_target( ${moduleLibraryName} SOURCES ${sourceFiles} ${otherFiles} )  # dummy IDE target
98
 	endif( )
99

100
101
    waLBerla_register_dependency ( ${moduleName} ${ARG_DEPENDS} )

102
    set_property( TARGET ${moduleName} PROPERTY CXX_STANDARD ${CMAKE_CXX_STANDARD} )
103

104
105
106
107
    # This property is needed for visual studio to group modules together
    if( WALBERLA_GROUP_PROJECTS )
       set_property( TARGET  ${moduleLibraryName}  PROPERTY  FOLDER  "SRC" )
    endif()
108

109
110
    # Install rule for library
    get_target_property( module_type ${moduleLibraryName} TYPE )
111
    if( ${module_type} MATCHES LIBRARY )
112
113
114
115
       install ( TARGETS ${moduleLibraryName}  RUNTIME DESTINATION bin
                                               LIBRARY DESTINATION lib
                                               ARCHIVE DESTINATION lib )
    endif( )
116

117
    # Install rule for header
118
119
    install ( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
              DESTINATION "walberla/${moduleName}"
120
              FILES_MATCHING PATTERN "*.h"
121
              PATTERN "*.in.h"     EXCLUDE
122
              PATTERN "CMakeFiles" EXCLUDE )
123
124
125
126
127

    # 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}"
128
                  FILES_MATCHING PATTERN "*.h"
129
                  PATTERN "*.in.h"     EXCLUDE
130
                  PATTERN "CMakeFiles" EXCLUDE )
131
132
133
    endif()


134
135
136
    # 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} )
137

138
139
140
141
142
143
144
145
146
147
148
149
150
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
#
#
151
152
153
154
155
156
#   NAME    [required]    Name of application
#   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
157
158
159
160
161
162
163
#
#  Example:
#     waLBerla_compile_app ( NAME myApp DEPENDS core field lbm/boundary )
#######################################################################################################################

function ( waLBerla_add_executable )
    set( options )
164
    set( oneValueArgs NAME GROUP)
165
    set( multiValueArgs FILES DEPENDS)
166
167
168
    cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

    if( NOT ARG_NAME )
169
      message ( FATAL_ERROR "waLBerla_add_executable called without a NAME" )
170
    endif()
171

172
173
174
175
    # 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} )
176
177
178
            if( WALBERLA_LOG_SKIPPED )
               message ( STATUS "Skipping ${ARG_NAME} since dependent module ${depMod} was not built" )
            endif()
179
180
181
            return()
        endif()
    endforeach()
182
183

    # Take source files either from parameter or search all source files
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    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()

203
    add_executable( ${ARG_NAME} ${sourceFiles} )
204

205
    target_link_modules  ( ${ARG_NAME} ${ARG_DEPENDS}  )
206
    target_link_libraries( ${ARG_NAME} ${WALBERLA_LINK_LIBRARIES_KEYWORD} ${SERVICE_LIBS} )
207
    set_property( TARGET ${ARG_NAME} PROPERTY CXX_STANDARD ${CMAKE_CXX_STANDARD} )
208
209
210
211
212
213
214

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

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
endfunction ( waLBerla_add_executable )

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

#######################################################################################################################
#
# 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} )
231

232
233
    # Module name is the directory relative to WALBERLA_MODULE_DIRS
    get_current_module_name ( moduleName )
234

235
236
237
238
239
    # 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()
240
241

    waLBerla_add_executable ( NAME ${ARG_NAME} GROUP "TESTS/${moduleName}"
242
                              DEPENDS ${ARG_DEPENDS} ${moduleName} FILES ${ARG_FILES} )
243
244


245
246
247
248
249
250
251
252
253
endfunction ( waLBerla_compile_test )
#######################################################################################################################




#######################################################################################################################
#
# Links all files in current source dir matching a globbing expression to the build directory
254
#
255
# first parameter is glob expression
256
#
257
258
259
260
261
# 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" )
#
262
# Symlinking works only under linux, on windows the files are copied. For in-source builds this does nothing.
263
264
265
266
#
#######################################################################################################################

function ( waLBerla_link_files_to_builddir globExpression )
267

268
269
270
271
    # don't need links for in-source builds
    if( CMAKE_CURRENT_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}" )
        return()
    endif()
272

273
    file( GLOB filesToLink RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${globExpression} )
274
275

    foreach( f ${filesToLink} )
276
277
278
279
280
281
282
        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()
283

284
    endforeach()
285

286
287
288
289
290
291
292
endfunction ( waLBerla_link_files_to_builddir )




#######################################################################################################################
#
293
294
# Adds an executable to CTest.
#
295
296
297
298
# 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
299
#   PROCESSES [optional] Number of MPI processes, that are used to start this test.
300
301
302
#                        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
303
#                        command line options.
304
#                        Defaults to $<TARGET_FILE:${NAME}> (for this syntax see cmake documentation of add_test )
305
#   LABELS    [optional] Additional test labels.
306
307
308
309
#
#######################################################################################################################

function ( waLBerla_execute_test )
310

311
312
   set( options NO_MODULE_LABEL )
   set( oneValueArgs NAME PROCESSES )
Christian Godenschwager's avatar
Christian Godenschwager committed
313
   set( multiValueArgs COMMAND LABELS CONFIGURATIONS DEPENDS_ON_TARGETS )
314
315
316
   cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

   if( NOT ARG_NAME )
317
      message ( FATAL_ERROR "waLBerla_execute_test called without a NAME" )
318
   endif()
319

320
   if( NOT ARG_COMMAND AND NOT TARGET ${ARG_NAME} )
321
322
323
      if( WALBERLA_LOG_SKIPPED )
         message ( STATUS "Skipping test ${ARG_NAME} since the corresponding target is not built" )
      endif()
324
      return()
325
   endif()
Christian Godenschwager's avatar
Christian Godenschwager committed
326
327
328

   foreach( dependency_target ${ARG_DEPENDS_ON_TARGETS} )
      if( NOT TARGET ${dependency_target} )
329
330
331
         if( WALBERLA_LOG_SKIPPED )
            message ( STATUS "Skipping test ${ARG_NAME} since the target ${dependency_target} is not built" )
         endif()
Christian Godenschwager's avatar
Christian Godenschwager committed
332
333
334
         return()
      endif()
   endforeach( dependency_target )
335

336
337
338
339
340
341
342
343
344
345
346
   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 )
347
348
349
350
      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} )
351
352
   elseif( numProcesses GREATER 1 )
      return()
353
354
   endif()

355
356
357
358
359
   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()
360

361
362
363
   if( ARG_NO_MODULE_LABEL )
      set_tests_properties ( ${ARG_NAME} PROPERTIES LABELS "${ARG_LABELS}" )
   else()
364
      get_current_module_name ( moduleName  )
365
366
367
368
      set_tests_properties ( ${ARG_NAME} PROPERTIES LABELS "${moduleName} ${ARG_LABELS}" )
   endif()

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

370
371
endfunction ( waLBerla_execute_test )
#######################################################################################################################