1# @HEADER
2# ************************************************************************
3#
4#            TriBITS: Tribal Build, Integrate, and Test System
5#                    Copyright 2013 Sandia Corporation
6#
7# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8# the U.S. Government retains certain rights in this software.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions are
12# met:
13#
14# 1. Redistributions of source code must retain the above copyright
15# notice, this list of conditions and the following disclaimer.
16#
17# 2. Redistributions in binary form must reproduce the above copyright
18# notice, this list of conditions and the following disclaimer in the
19# documentation and/or other materials provided with the distribution.
20#
21# 3. Neither the name of the Corporation nor the names of the
22# contributors may be used to endorse or promote products derived from
23# this software without specific prior written permission.
24#
25# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36#
37# ************************************************************************
38# @HEADER
39
40
41INCLUDE(TribitsAddExecutableTestHelpers)
42INCLUDE(TribitsCommonArgsHelpers)
43INCLUDE(TribitsAddTestHelpers)
44INCLUDE(TribitsGeneralMacros)
45INCLUDE(TribitsReportInvalidTribitsUsage)
46
47INCLUDE(PrintVar)
48INCLUDE(AppendSet)
49INCLUDE(CMakeParseArguments)
50
51###
52### WARNING: See "NOTES TO DEVELOPERS" at the bottom of the file
53### TribitsPackageMacros.cmake before trying to change anything in this file!
54###
55
56
57#
58# @FUNCTION: TRIBITS_ADD_EXECUTABLE()
59#
60# Function used to create an executable (typically for a test or example),
61# using the built-in CMake command ``ADD_EXECUTABLE()``.
62#
63# Usage::
64#
65#   TRIBITS_ADD_EXECUTABLE(
66#     <exeRootName>  [NOEXEPREFIX]  [NOEXESUFFIX]  [ADD_DIR_TO_NAME]
67#     SOURCES <src0> <src1> ...
68#     [CATEGORIES <category0>  <category1> ...]
69#     [HOST <host0> <host1> ...]
70#     [XHOST <host0> <host1> ...]
71#     [HOSTTYPE <hosttype0> <hosttype1> ...]
72#     [XHOSTTYPE <hosttype0> <hosttype1> ...]
73#     [EXCLUDE_IF_NOT_TRUE <varname0> <varname1> ...]
74#     [DIRECTORY <dir>]
75#     [TESTONLYLIBS <lib0> <lib1> ...]
76#     [IMPORTEDLIBS <lib0> <lib1> ...]
77#     [COMM [serial] [mpi]]
78#     [LINKER_LANGUAGE (C|CXX|Fortran)]
79#     [TARGET_DEFINES -D<define0> -D<define1> ...]
80#     [INSTALLABLE]
81#     [ADDED_EXE_TARGET_NAME_OUT <exeTargetName>]
82#     )
83#
84# *Sections:*
85#
86# * `Formal Arguments (TRIBITS_ADD_EXECUTABLE())`_
87# * `Executable and Target Name (TRIBITS_ADD_EXECUTABLE())`_
88# * `Additional Executable and Source File Properties (TRIBITS_ADD_EXECUTABLE())`_
89# * `Install Target (TRIBITS_ADD_EXECUTABLE())`_
90#
91# .. _Formal Arguments (TRIBITS_ADD_EXECUTABLE()):
92#
93# **Formal Arguments (TRIBITS_ADD_EXECUTABLE())**
94#
95#   ``<exeRootName>``
96#
97#     The root name of the executable (and CMake target) (see `Executable and
98#     Target Name (TRIBITS_ADD_EXECUTABLE())`_).  This must be the first
99#     argument.
100#
101#   ``NOEXEPREFIX``
102#
103#     If passed in, then ``${PACKAGE_NAME}_`` is not added the beginning of
104#     the executable name (see `Executable and Target Name
105#     (TRIBITS_ADD_EXECUTABLE())`_).
106#
107#   ``NOEXESUFFIX``
108#
109#     If passed in, then ``${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX}`` and
110#     not added to the end of the executable name (except for native Windows
111#     builds, see `Executable and Target Name (TRIBITS_ADD_EXECUTABLE())`_).
112#
113#   ``ADD_DIR_TO_NAME``
114#
115#     If passed in, the directory path relative to the package's base
116#     directory (with "/" replaced by "_") is added to the executable name
117#     (see `Executable and Target Name (TRIBITS_ADD_EXECUTABLE())`_).  This
118#     provides a simple way to create unique test executable names inside of a
119#     given TriBITS package.  Only test executables in the same directory
120#     would need to have unique ``<execRootName>`` passed in.
121#
122#   ``SOURCES <src0> <src1> ...``
123#
124#     Gives the source files that will be compiled into the built executable.
125#     By default, these sources are assumed to be in the current working
126#     directory (or can contain the relative path or absolute path).  If
127#     ``<srci>`` is an absolute path, then that full file path is used.  This
128#     list of sources (with adjusted directory path) are passed into
129#     ``ADD_EXECUTABLE(<exeTargetName> ... )``.  After calling this function,
130#     the properties of the source files can be altered using the built-in
131#     CMake command ``SET_SOURCE_FILE_PROPERTIES()``.
132#
133#   ``DIRECTORY <dir>``
134#
135#     If specified, then the generated executable ``<exeTargetName>`` is
136#     placed in the relative or absolute directory ``<dir>``.  If ``<dir>`` is
137#     not an absolute path, then the generated executable is placed in the
138#     directory ``${CMAKE_CURRENT_BINARY_DIR}/<dir>/``.  Also, the sources for
139#     the executable listed in ``SOURCES <src0> <src1> ...`` are assumed to be
140#     in the relative or absolute directory ``<dir>`` instead of the current
141#     source directory.  This directory path is prepended to each source file
142#     name ``<srci>`` unless ``<srci>`` is an absolute path.  If ``<dir>`` is
143#     not an absolute path, then source files listed in ``SOURCES`` are
144#     assumed to be in the directory ``${CMAKE_CURRENT_SOURCE_DIR}/<dir>/``.
145#
146#   ``CATEGORIES <category0> <category1> ...``
147#
148#     Gives the `Test Test Categories`_ for which this test will be added.
149#     See `TRIBITS_ADD_TEST()`_ for more details.
150#
151#   ``HOST <host0> <host1> ...``
152#
153#     The list of hosts for which to enable the test (see `TRIBITS_ADD_TEST()`_).
154#
155#   ``XHOST <host0> <host1> ...``
156#
157#     The list of hosts for which **not** to enable the test (see
158#     `TRIBITS_ADD_TEST()`_).
159#
160#   ``HOSTTYPE <hosttype0> <hosttype1> ...``
161#
162#     The list of host types for which to enable the test (see
163#     `TRIBITS_ADD_TEST()`_).
164#
165#   ``XHOSTTYPE <hosttype0> <hosttype1> ...``
166#
167#     The list of host types for which **not** to enable the test (see
168#     `TRIBITS_ADD_TEST()`_).
169#
170#   ``EXCLUDE_IF_NOT_TRUE <varname0> <varname1> ...``
171#
172#     If specified, gives the names of CMake variables that must evaluate to
173#     true, or the test will not be added (see `TRIBITS_ADD_TEST()`_).
174#
175#   ``TESTONLYLIBS <lib0> <lib1> ...``
176#
177#     Specifies extra test-only libraries defined in this CMake project that
178#     will be linked to the executable using ``TARGET_LINK_LIBRARY()``.  Note
179#     that regular libraries (i.e. not ``TESTONLY``) defined in the current SE
180#     package or any upstream SE packages can *NOT* be listed!  TriBITS
181#     automatically links non ``TESTONLY`` libraries in this package and
182#     upstream packages to the executable.  The only libraries that should be
183#     listed in this argument are either ``TESTONLY`` libraries.  The include
184#     directories for each test-only library will automatically be added
185#     using::
186#
187#       INCLUDE_DIRECTORIES(${<libi>_INCLUDE_DIRS})
188#
189#     where ``<libi>_INCLUDE_DIRS`` was set by::
190#
191#       TRIBITS_ADD_LIBRARY(<libi> ... TESTONLY ...)
192#
193#     Therefore, to link to a defined ``TESTONLY`` library in any upstream
194#     enabled package, one just needs to pass in the library name through
195#     ``TESTONLYLIBS ... <libi> ...`` and that is it!
196#
197#   ``IMPORTEDLIBS <lib0> <lib1> ...``
198#
199#     Specifies extra external libraries that will be linked to the executable
200#     using ``TARGET_LINK_LIBRARY()``.  This can only be used for libraries
201#     that are built external from this CMake project and are not provided
202#     through a proper `TriBITS TPL`_.  The latter usage of passing in
203#     external libraries is not recommended.  External libraries should be
204#     handled as declared `TriBITS TPLs`_.  So far, the only case where
205#     ``IMPORTEDLIBS`` has been shown to be necessary is to pass in the
206#     standard C math library ``m``.  In every other case, a TriBITS TPL
207#     should be used instead.
208#
209#   ``COMM [serial] [mpi]``
210#
211#     If specified, selects if the test will be added in serial and/or MPI
212#     mode.  See the ``COMM`` argument in the script
213#     `TRIBITS_ADD_TEST()`_ for more details.
214#
215#   ``LINKER_LANGUAGE (C|CXX|Fortran)``
216#
217#     If specified, overrides the linker language used by setting the built-in
218#     CMake target property ``LINKER_LANGUAGE``.  TriBITS sets the default
219#     linker language as follows::
220#
221#       IF (${PROJECT_NAME}_ENABLE_CXX)
222#         SET(LINKER_LANGUAGE CXX)
223#       ELSEIF (${PROJECT_NAME}_ENABLE_C)
224#         SET(LINKER_LANGUAGE C)
225#       ELSE()
226#         # Let CMake set the default linker language it wants based
227#         # on source file extensions passed into ``ADD_EXECUTABLE()``.
228#       ENDIF()
229#
230#     The reason for this logic is that on some platform if you have a Fortran
231#     or C main that links to C++ libraries, then you need the C++ compiler to
232#     do the final linking.  CMake does not seem to automatically know that it
233#     is pulling in C++ libraries and therefore needs to be told use C++ for
234#     linking.  This is the correct default behavior for mixed-language
235#     projects. However, this argument allows the developer to override this
236#     logic and use any linker language desired based on other considerations.
237#
238#   ``TARGET_DEFINES -D<define0> -D<define1> ...``
239#
240#     Add the listed defines using
241#     ``TARGET_COMPILE_DEFINITIONS(<exeTargetName> ...)``.  These should only
242#     affect the listed sources for the built executable and not other
243#     targets.
244#
245#   ``INSTALLABLE``
246#
247#     If passed in, then an install target will be added to install the built
248#     executable into the ``${CMAKE_INSTALL_PREFIX}/bin/`` directory (see
249#     `Install Target (TRIBITS_ADD_EXECUTABLE())`_).
250#
251#   ``ADDED_EXE_TARGET_NAME_OUT <exeTargetName>``
252#
253#     If specified, then on output the variable ``<exeTargetName>`` will be
254#     set with the name of the executable target passed to
255#     ``ADD_EXECUTABLE(<exeTargetName> ... )``.  Having this name allows the
256#     calling ``CMakeLists.txt`` file access and set additional target
257#     properties (see `Additional Executable and Source File Properties
258#     (TRIBITS_ADD_EXECUTABLE())`_).
259#
260# .. _Executable and Target Name (TRIBITS_ADD_EXECUTABLE()):
261#
262# **Executable and Target Name (TRIBITS_ADD_EXECUTABLE())**
263#
264# By default, the full name of the executable and target name
265# is::
266#
267#   <exeTargetName> = ${PACKAGE_NAME}_<exeRootName>
268#
269# If ``ADD_DIR_TO_NAME`` is set, then the directory path relative to the
270# package base directory (with "/" replaced with "_"), or ``<relDirName>``, is
271# added to the executable name to form::
272#
273#   <exeTargetName> = ${PACKAGE_NAME}_<relDirName>_<exeRootName>
274#
275# If the option ``NOEXEPREFIX`` is passed in, then the prefix
276# ``${PACKAGE_NAME}_`` is removed.
277#
278# The executable suffix ``${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX}`` will be
279# added to the actual executable file name if the option ``NOEXESUFFIX`` is
280# *not* passed in but this suffix is never added to the target name.
281# (However, note that on Windows platforms, the default ``*.exe`` extension is
282# always added because windows will not run an executable in many contexts
283# unless it has the ``*.exe`` extension.)
284#
285# The reason that a default prefix is prepended to the executable and target
286# name is because the primary reason to create an executable is typically to
287# create a test or an example that is private to the package.  This prefix
288# helps to namespace the executable and its target so as to avoid name clashes
289# with targets in other packages.  It also helps to avoid clashes if the
290# executable gets installed into the install directory (if ``INSTALLABLE`` is
291# specified).  For general utility executables on Linux/Unix systems,
292# ``NOEXEPREFIX`` and ``NOEXESUFFIX`` should be passed in.  In this case, one
293# must be careful to pick ``<exeRootName>`` that will be sufficiently globally
294# unique.  Please use common sense when picking non-namespaced names.
295#
296# .. _Additional Executable and Source File Properties (TRIBITS_ADD_EXECUTABLE()):
297#
298# **Additional Executable and Source File Properties (TRIBITS_ADD_EXECUTABLE())**
299#
300# Once ``ADD_EXECUTABLE(<exeTargetName> ... )`` is called and this function
301# exists, one can set and change properties on the ``<exeTargetName>``
302# executable target using the built-in ``SET_TARGET_PROPERTIES()`` command as
303# well as properties on any of the source files listed in ``SOURCES`` using
304# the built-in ``SET_SOURCE_FILE_PROPERTIES()`` command just like in any CMake
305# project.  IF the executable is added, its name will be returned by the
306# argument ``ADDED_EXE_TARGET_NAME_OUT <exeTargetName>``.  For example::
307#
308#   TRIBITS_ADD_EXECUTABLE( someExe ...
309#     ADDED_EXE_TARGET_NAME_OUT  someExe_TARGET_NAME )
310#
311#   IF (someExe_TARGET_NAME)
312#     SET_TARGET_PROPERTIES( ${someExe_TARGET_NAME}
313#       PROPERTIES  LINKER_LANGUAGE  CXX )
314#   ENDIF()
315#
316# The ``IF(someExe_TARGET_NAME)`` is needed in case the executable does not
317# get added for some reason (see `Formal Arguments
318# (TRIBITS_ADD_EXECUTABLE())`_ for logic that can result in the executable
319# target not getting added).
320#
321# .. _Install Target (TRIBITS_ADD_EXECUTABLE()):
322#
323# **Install Target (TRIBITS_ADD_EXECUTABLE())**
324#
325# If ``INSTALLABLE`` is passed in, then an install target using the built-in
326# CMake command ``INSTALL(TARGETS <exeTargetName> ...)`` is added to install
327# the built executable into the ``${CMAKE_INSTALL_PREFIX}/bin/`` directory
328# (actual install directory path is determined by
329# ``${PROJECT_NAME}_INSTALL_RUNTIME_DIR``, see `Setting the install prefix`_).
330#
331FUNCTION(TRIBITS_ADD_EXECUTABLE EXE_NAME)
332
333  IF(${PROJECT_NAME}_VERBOSE_CONFIGURE)
334    MESSAGE("")
335    MESSAGE("TRIBITS_ADD_EXECUTABLE: ${EXE_NAME} ${ARGN}")
336  ENDIF()
337
338  #
339  # Confirm that package and subpackage macros/functions have been called inteh correct order
340  #
341
342  IF (CURRENTLY_PROCESSING_SUBPACKAGE)
343
344    # This is a subpackage being processed
345
346    IF(NOT ${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_CALLED)
347      TRIBITS_REPORT_INVALID_TRIBITS_USAGE(
348        "Must call TRIBITS_SUBPACKAGE() before TRIBITS_ADD_EXECUTABLE()"
349        " in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}")
350    ENDIF()
351
352    IF(${SUBPACKAGE_FULLNAME}_TRIBITS_SUBPACKAGE_POSTPROCESS_CALLED)
353      TRIBITS_REPORT_INVALID_TRIBITS_USAGE(
354        "Must call TRIBITS_ADD_EXECUTABLE() before "
355        " TRIBITS_SUBPACKAGE_POSTPROCESS() in ${CURRENT_SUBPACKAGE_CMAKELIST_FILE}")
356    ENDIF()
357
358  ELSE()
359
360    # This is a package being processed
361
362    IF(NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_DECL_CALLED)
363      TRIBITS_REPORT_INVALID_TRIBITS_USAGE(
364        "Must call TRIBITS_PACKAGE() or TRIBITS_PACKAGE_DECL() before"
365        " TRIBITS_ADD_EXECUTABLE() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}")
366    ENDIF()
367
368    IF(${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS_CALLED)
369      TRIBITS_REPORT_INVALID_TRIBITS_USAGE(
370        "Must call TRIBITS_ADD_EXECUTABLE() before "
371        " TRIBITS_PACKAGE_POSTPROCESS() in ${TRIBITS_PACKAGE_CMAKELIST_FILE}")
372    ENDIF()
373
374  ENDIF()
375
376
377  #
378  # A) Parse the input arguments
379  #
380
381  CMAKE_PARSE_ARGUMENTS(
382    #prefix
383    PARSE
384    #options
385    "NOEXEPREFIX;NOEXESUFFIX;ADD_DIR_TO_NAME;INSTALLABLE"
386    #one_value_keywords
387    ""
388    #multi_value_keywords
389    "SOURCES;CATEGORIES;HOST;XHOST;HOSTTYPE;XHOSTTYPE;EXCLUDE_IF_NOT_TRUE;DIRECTORY;TESTONLYLIBS;IMPORTEDLIBS;DEPLIBS;COMM;LINKER_LANGUAGE;TARGET_DEFINES;DEFINES;ADDED_EXE_TARGET_NAME_OUT"
390    ${ARGN}
391    )
392
393  TRIBITS_CHECK_FOR_UNPARSED_ARGUMENTS()
394
395  IF(PARSE_ADDED_EXE_TARGET_NAME_OUT)
396    SET(${PARSE_ADDED_EXE_TARGET_NAME_OUT} PARENT_SCOPE)
397  ENDIF()
398
399  #
400  # B) Exclude building the test executable based on some criteria
401  #
402
403  SET(ADD_THE_TEST FALSE)
404  SET(TEST_NAME ${EXE_NAME})  # For error message
405  TRIBITS_ADD_TEST_PROCESS_CATEGORIES(ADD_THE_TEST)
406  IF (NOT ADD_THE_TEST)
407    RETURN()
408  ENDIF()
409  SET(TEST_NAME)
410
411  SET(ADD_THE_TEST FALSE)
412  TRIBITS_ADD_TEST_PROCESS_HOST_HOSTTYPE(ADD_THE_TEST)
413  IF (NOT ADD_THE_TEST)
414    RETURN()
415  ENDIF()
416
417  TRIBITS_PROCESS_COMM_ARGS(ADD_SERIAL_EXE  ADD_MPI_EXE  ${PARSE_COMM})
418  IF (NOT ADD_SERIAL_EXE AND NOT ADD_MPI_EXE)
419    RETURN()
420  ENDIF()
421
422  #
423  # C) Add the executable
424  #
425
426  SET(LIBRARY_NAME_PREFIX "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}")
427
428  IF (NOT TRIBITS_ADD_EXECUTABLE_UNIT_TESTING)
429    TRIBITS_INCLUDE_DIRECTORIES(REQUIRED_DURING_INSTALLATION_TESTING
430      ${${PACKAGE_NAME}_INCLUDE_DIRS})
431#    SET_PROPERTY(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS
432#      ${${PACKAGE_NAME}_LIBRARY_DIRS})
433  ENDIF()
434
435  SET (EXE_SOURCES)
436  SET(EXE_BINARY_NAME ${EXE_NAME})
437
438  # If requested create a modifier for the name that will be inserted between
439  # the package name and the given name or exe_name for the test
440  IF(PARSE_ADD_DIR_TO_NAME)
441    SET(DIRECTORY_NAME "")
442    TRIBITS_CREATE_NAME_FROM_CURRENT_SOURCE_DIRECTORY(DIRECTORY_NAME)
443    SET(EXE_BINARY_NAME ${DIRECTORY_NAME}_${EXE_BINARY_NAME})
444  ENDIF()
445
446  IF(DEFINED PACKAGE_NAME AND NOT PARSE_NOEXEPREFIX)
447    SET(EXE_BINARY_NAME ${PACKAGE_NAME}_${EXE_BINARY_NAME})
448  ENDIF()
449
450  # Exclude the build if requested
451  IF (${EXE_BINARY_NAME}_EXE_DISABLE)
452    MESSAGE("-- "
453      "${EXE_BINARY_NAME} EXE NOT being built due to ${EXE_BINARY_NAME}_EXE_DISABLE="
454      "'${${EXE_BINARY_NAME}_EXE_DISABLE}'")
455    RETURN()
456  ENDIF()
457
458  # If exe is in subdirectory prepend that dir name to the source files
459  IF(PARSE_DIRECTORY )
460    FOREACH( SOURCE_FILE ${PARSE_SOURCES} )
461      IF(IS_ABSOLUTE ${SOURCE_FILE})
462        SET (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE})
463      ELSE()
464        SET (EXE_SOURCES ${EXE_SOURCES} ${PARSE_DIRECTORY}/${SOURCE_FILE})
465      ENDIF()
466    ENDFOREACH( )
467  ELSE()
468    FOREACH( SOURCE_FILE ${PARSE_SOURCES} )
469      SET (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE})
470    ENDFOREACH( )
471  ENDIF()
472
473  # Assert that TESTONLYLIBS only contains TESTONLY libs!
474  FOREACH(TESTONLYLIB ${PARSE_TESTONLYLIBS})
475    SET(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${TESTONLYLIB}")
476    IF (NOT ${PREFIXED_LIB}_INCLUDE_DIRS)
477      MESSAGE(FATAL_ERROR "ERROR: '${TESTONLYLIB}' in TESTONLYLIBS not a TESTONLY lib!"
478        "  If this a regular library in this SE package or in an dependent upstream SE"
479        " package then TriBITS will link automatically to it.  If you remove this and it"
480        " does not link, then you need to add a new SE package dependency to"
481        " this SE package's dependencies file"
482        " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake")
483    ELSEIF(PARSE_INSTALLABLE)
484      MESSAGE(FATAL_ERROR "ERROR: TESTONLY lib '${TESTONLYLIB}' not allowed with"
485        " INSTALLABLE executable!  An INSTALLABLE executable can only depend on"
486        " non-TESTONLY libraries!  Otherwise, when shared libs are used, and"
487        " TESTONLY library would not be installed and the installed executable"
488        " would be unusable!" )
489    ENDIF()
490  ENDFOREACH()
491
492  # Assert that IMPORTEDLIBS are not TESTONLY libs are not regular package
493  # libs!
494  FOREACH(IMPORTEDLIB ${PARSE_IMPORTEDLIBS})
495    SET(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${IMPORTEDLIB}")
496    IF (${PREFIXED_LIB}_INCLUDE_DIRS)
497      MESSAGE(FATAL_ERROR
498        "ERROR: Lib '${IMPORTEDLIB}' being passed through"
499        " IMPORTEDLIBS is not allowed to be a TESTONLY lib!"
500        "  Use TESTONLYLIBS instead!" )
501    ENDIF()
502    LIST(FIND ${PACKAGE_NAME}_LIBRARIES ${PREFIXED_LIB} FOUND_IDX)
503    IF (NOT FOUND_IDX EQUAL -1)
504      MESSAGE(FATAL_ERROR
505        "ERROR: Lib '${IMPORTEDLIB}' in IMPORTEDLIBS is in"
506        " this SE package and is *not* an external lib!"
507        "  TriBITS takes care of linking against libs the current"
508        " SE package automatically.  Please remove '${IMPORTEDLIB}' from IMPORTEDLIBS!")
509    ELSEIF (TARGET ${PREFIXED_LIB})
510      MESSAGE(FATAL_ERROR
511        "ERROR: Lib '${IMPORTEDLIB}' being passed through"
512        " IMPORTEDLIBS is *not* an external library but instead is a library"
513        " defined in this CMake project!"
514        "  TriBITS takes care of linking against libraries in dependent upstream"
515        " SE packages.  If you want to link to a library in an upstream SE"
516        " package then add the SE package name for that library to the appropriate"
517        " list in this SE package's dependencies file"
518        " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake")
519    ENDIF()
520  ENDFOREACH()
521
522  # Convert from old DEPLIBS to TESTONLYLIBS and IMPORTEDLIBS
523  FOREACH(DEPLIB ${PARSE_DEPLIBS})
524    SET(PREFIXED_LIB "${${PROJECT_NAME}_LIBRARY_NAME_PREFIX}${DEPLIB}")
525    IF (${PREFIXED_LIB}_INCLUDE_DIRS)
526      MESSAGE(WARNING "WARNING: Passing TESTONLY lib '${DEPLIB}' through DEPLIBS"
527        " is deprecated!  Instead, please pass through TESTONLYLIBS instead!"
528        "  DEPLIBS is deprecated!")
529      LIST(APPEND PARSE_TESTONLYLIBS ${DEPLIB})
530    ELSEIF (TARGET ${PREFIXED_LIB})
531      MESSAGE(WARNING "WARNING: Passing non-TESTONLY lib '${DEPLIB}' through DEPLIBS"
532      " is deprecated!  The library '${DEPLIB}' appears to be a"
533      " library defined in this CMake project."
534      "  TriBITS takes care of linking against libraries in dependent upstream"
535      " SE packages.  Therefore, please remove '${DEPLIB}' from this list."
536      "   If you want to link to a library from an upstream SE"
537      " package, then add the SE package name to the appropriate category"
538      " in this SE package's dependencies file: "
539      " ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/Dependencies.cmake")
540    ELSE()
541      MESSAGE(WARNING "WARNING: Passing external lib '${DEPLIB}' through"
542        " DEPLIBS is deprecated!  Instead, pass through IMPORTEDLIBS!"
543        "  DEPLIBS is deprecated!"
544        "  Please note that only external libs are allowed to be passed through"
545        " IMPORTEDLIBS.")
546      LIST(APPEND PARSE_IMPORTEDLIBS ${DEPLIB})
547    ENDIF()
548  ENDFOREACH()
549
550  FOREACH(TESTONLYLIB_IN ${PARSE_TESTONLYLIBS})
551    SET(TESTONLYLIB "${LIBRARY_NAME_PREFIX}${TESTONLYLIB_IN}")
552    IF (${TESTONLYLIB}_INCLUDE_DIRS)
553      IF (${PROJECT_NAME}_VERBOSE_CONFIGURE)
554        MESSAGE(STATUS "Adding include directories ${TESTONLYLIB}_INCLUDE_DIRS ...")
555      ENDIF()
556      INCLUDE_DIRECTORIES(${${TESTONLYLIB}_INCLUDE_DIRS})
557    ENDIF()
558  ENDFOREACH()
559
560  IF (PARSE_DEFINES)
561    MESSAGE(WARNING "WARNING: Passing extra defines through 'DEFINES' ${PARSE_DEFINES}"
562      " is deprecated.  Instead, pass them through 'TARGET_DEFINES'.  The 'DEFINES'"
563      " argument was incorrectly implemented by calling ADD_DEFINITIONS() which has"
564      " directory scope and not function scope as was documented.  This resulted in"
565      " confusing behavior.  If one wishes to set defines at the directly level,"
566      " just call ADD_DEFINITIONS() directly.")
567    ADD_DEFINITIONS(${PARSE_DEFINES})
568  ENDIF()
569
570  IF(${PROJECT_NAME}_VERBOSE_CONFIGURE)
571    MESSAGE("TRIBITS_ADD_EXECUTABLE: ADD_EXECUTABLE(${EXE_BINARY_NAME} ${EXE_SOURCES})")
572  ENDIF()
573  ADD_EXECUTABLE(${EXE_BINARY_NAME} ${EXE_SOURCES})
574  APPEND_GLOBAL_SET(${PARENT_PACKAGE_NAME}_ALL_TARGETS ${EXE_BINARY_NAME})
575
576  IF(PARSE_ADDED_EXE_TARGET_NAME_OUT)
577    SET(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${EXE_BINARY_NAME} PARENT_SCOPE)
578  ENDIF()
579
580  IF (PARSE_TARGET_DEFINES)
581    TARGET_COMPILE_DEFINITIONS(${EXE_BINARY_NAME} PUBLIC ${PARSE_TARGET_DEFINES})
582  ENDIF()
583
584  IF(PARSE_NOEXESUFFIX AND NOT WIN32)
585    SET_TARGET_PROPERTIES(${EXE_BINARY_NAME} PROPERTIES SUFFIX "")
586  ELSE()
587    SET_TARGET_PROPERTIES(${EXE_BINARY_NAME} PROPERTIES SUFFIX
588      ${${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX})
589  ENDIF()
590
591  TRIBITS_SET_LINKER_LANGUAGE_FROM_ARG( ${EXE_BINARY_NAME}
592    "${PARSE_LINKER_LANGUAGE}" )
593
594  SET(LINK_LIBS)
595
596  # First, add in the passed in TESTONLY dependent libraries
597  IF (PARSE_TESTONLYLIBS)
598    FOREACH(LIB ${PARSE_TESTONLYLIBS})
599      LIST(APPEND LINK_LIBS "${LIBRARY_NAME_PREFIX}${LIB}")
600    ENDFOREACH()
601  ENDIF()
602
603  # Second, add the package's own regular libraries
604  IF(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING)
605    LIST(APPEND LINK_LIBS ${${PACKAGE_NAME}_LIBRARIES})
606  ELSE()
607    LIST(APPEND LINK_LIBS ${${PACKAGE_NAME}_INSTALLATION_LIBRARIES})
608  ENDIF()
609
610  # Third, add the IMPORTEDLIBS
611  IF (PARSE_IMPORTEDLIBS)
612    LIST(APPEND LINK_LIBS ${PARSE_IMPORTEDLIBS})
613  ENDIF()
614
615  # Call INCLUDE_DIRECTORIES() and LINK_DIRECTORIES(...) for upstream
616  # dependent Packages and TPLs and accumulate the list of libraries that will
617  # need to be linked to.
618
619  IF(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING
620    AND NOT ${PACKAGE_NAME}_INCLUDE_DIRS
621    )
622    # No libraries have been added for this package so
623    # add the upstream package and TPL includes and libraries
624    TRIBITS_SORT_AND_APPEND_PACKAGE_INCLUDE_AND_LINK_DIRS_AND_LIBS(
625      ${PACKAGE_NAME}  LIB  LINK_LIBS)
626    TRIBITS_SORT_AND_APPEND_TPL_INCLUDE_AND_LINK_DIRS_AND_LIBS(
627      ${PACKAGE_NAME}  LIB  LINK_LIBS)
628  ENDIF()
629
630  TRIBITS_SORT_AND_APPEND_PACKAGE_INCLUDE_AND_LINK_DIRS_AND_LIBS(
631    ${PACKAGE_NAME}  TEST  LINK_LIBS)
632
633  IF(NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING)
634    TRIBITS_SORT_AND_APPEND_TPL_INCLUDE_AND_LINK_DIRS_AND_LIBS(
635      ${PACKAGE_NAME}  TEST  LINK_LIBS)
636  ELSE()
637    LIST(APPEND LINK_LIBS ${${PACKAGE_NAME}_INSTALLATION_TPL_LIBRARIES})
638  ENDIF()
639
640  # Last, add last_lib to get extra link options on the link line
641  IF (${PROJECT_NAME}_EXTRA_LINK_FLAGS)
642    LIST(APPEND LINK_LIBS last_lib)
643  ENDIF()
644
645  IF (${PROJECT_NAME}_DUMP_LINK_LIBS)
646      MESSAGE("-- ${EXE_NAME}:LINK_LIBS='${LINK_LIBS}'")
647  ENDIF()
648
649  TARGET_LINK_LIBRARIES(${EXE_BINARY_NAME} ${LINK_LIBS})
650
651  ASSERT_DEFINED(${PROJECT_NAME}_LINK_SEARCH_START_STATIC)
652  IF (${PROJECT_NAME}_LINK_SEARCH_START_STATIC)
653    #MESSAGE("${EXE_BINARY_NAME}: Adding property LINK_SEARCH_START_STATIC")
654    SET_PROPERTY(TARGET ${EXE_BINARY_NAME} PROPERTY LINK_SEARCH_START_STATIC 1)
655  ENDIF()
656
657  IF(PARSE_DIRECTORY)
658    SET_TARGET_PROPERTIES( ${EXE_BINARY_NAME} PROPERTIES
659      RUNTIME_OUTPUT_DIRECTORY ${PARSE_DIRECTORY} )
660  ENDIF()
661
662  SET_PROPERTY(TARGET ${EXE_BINARY_NAME} APPEND PROPERTY
663    LABELS ${PACKAGE_NAME}Exes ${PARENT_PACKAGE_NAME}Exes)
664
665  IF(${PROJECT_NAME}_INSTALL_EXECUTABLES AND PARSE_INSTALLABLE)
666    INSTALL(
667      TARGETS ${EXE_BINARY_NAME}
668      EXPORT ${PROJECT_NAME}
669        DESTINATION ${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}
670      COMPONENT ${PACKAGE_NAME}
671    )
672  ENDIF()
673ENDFUNCTION()
674
675
676#
677# Setup include directories and library dependencies
678#
679
680#IF (${PROJECT_NAME}_VERBOSE_CONFIGURE)
681#  MESSAGE("TribitsAddExecutable.cmake")
682#  PRINT_VAR(${PACKAGE_NAME}_INCLUDE_DIRS)
683#  PRINT_VAR(${PACKAGE_NAME}_LIBRARY_DIRS)
684#ENDIF()
685#
686#IF (NOT TRIBITS_ADD_EXECUTABLE_UNIT_TESTING)
687#  INCLUDE_DIRECTORIES(REQUIRED_DURING_INSTALLATION_TESTING
688#    ${${PACKAGE_NAME}_INCLUDE_DIRS})
689#  SET_PROPERTY(DIRECTORY APPEND PROPERTY PACKAGE_LIBRARY_DIRS
690#    ${${PACKAGE_NAME}_LIBRARY_DIRS})
691#ENDIF()
692