Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/kicklib2/cmake/tools/TargetUtilities.cmake @ 8703

Last change on this file since 8703 was 8341, checked in by rgrieder, 14 years ago

Added new library linking keywords for the Add Target Command.
That makes OS specific library linking less tedious to read.

  • Property svn:eol-style set to native
File size: 14.7 KB
Line 
1 #
2 #             ORXONOX - the hottest 3D action shooter ever to exist
3 #                             > www.orxonox.net <
4 #
5 #        This program is free software; you can redistribute it and/or
6 #         modify it under the terms of the GNU General Public License
7 #        as published by the Free Software Foundation; either version 2
8 #            of the License, or (at your option) any later version.
9 #
10 #       This program is distributed in the hope that it will be useful,
11 #        but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #                 GNU General Public License for more details.
14 #
15 #   You should have received a copy of the GNU General Public License along
16 #      with this program; if not, write to the Free Software Foundation,
17 #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 #
19 #
20 #  Author:
21 #    Reto Grieder
22 #  Description:
23 #    Adds a library or an executable like ADD_LIBRARY/ADD_EXECUTABLE, but
24 #    accepts a lot more input information. Simply supply the keywords
25 #    described below in any order you wish.
26 #    The output is then stored in "_arg_ARGNAME" where ARGNAME is the the
27 #    name of the switch or list.
28 #
29 #    Switches: (when given --> TRUE, FALSE otherwise)
30 #      FIND_HEADER_FILES: Searches the current directory for all header files
31 #                         and adds them to the target.
32 #      EXCLUDE_FROM_ALL:  Inherited from ADD_LIBRARY/ADD_EXECUTABLE
33 #      ORXONOX_EXTERNAL:  Specify this for third party libraries
34 #      NO_DLL_INTERFACE:  Link statically with MSVC
35 #      NO_SOURCE_GROUPS:  Don't create msvc source groups
36 #      MODULE:            For dynamic module libraries (libraries only)
37 #      WIN32:             Inherited from ADD_EXECUTABLE (executables only)
38 #      PCH_NO_DEFAULT:    Do not make precompiled header files default if
39 #                         specified with PCH_FILE
40 #      NO_INSTALL:        Do not install the target at all
41 #      NO_VERSION:        Prevents adding any version to a target
42 #
43 #    Lists:
44 #      LINK_LIBRARIES:    Redirects to TARGET_LINK_LIBRARIES
45 #      LINK_LIBS_LINUX:   Redirects to TARGET_LINK_LIBRARIES only on Linux
46 #      LINK_LIBS_WIN32:   Redirects to TARGET_LINK_LIBRARIES only on Windows
47 #      LINK_LIBS_APPLE:   Redirects to TARGET_LINK_LIBRARIES only on Apple
48 #      LINK_LIBS_UNIX:    Redirects to TARGET_LINK_LIBRARIES only on UNIX
49 #      VERSION:           Set version to the binary
50 #      SOURCE_FILES:      Source files for the target
51 #      DEFINE_SYMBOL:     Sets the DEFINE_SYMBOL target property
52 #      TOLUA_FILES:       Files with tolua interface
53 #      PCH_FILE:          Precompiled header file
54 #      PCH_EXCLUDE:       Source files to be excluded from PCH support
55 #      OUTPUT_NAME:       If you want a different name than the target name
56 #  Note:
57 #    This function also installs the target!
58 #  Prerequisistes:
59 #    ORXONOX_DEFAULT_LINK
60 #  Parameters:
61 #    _target_name, ARGN for the macro arguments
62 #
63
64INCLUDE(CMakeDependentOption)
65INCLUDE(CapitaliseName)
66INCLUDE(GenerateToluaBindings)
67INCLUDE(ParseMacroArguments)
68INCLUDE(SourceFileUtilities)
69IF(PCH_COMPILER_SUPPORT)
70  INCLUDE(PrecompiledHeaderFiles)
71ENDIF()
72
73MACRO(ORXONOX_ADD_LIBRARY _target_name)
74  TU_ADD_TARGET(${_target_name} LIBRARY "MODULE" ${ARGN})
75ENDMACRO(ORXONOX_ADD_LIBRARY)
76
77MACRO(ORXONOX_ADD_EXECUTABLE _target_name)
78  TU_ADD_TARGET(${_target_name} EXECUTABLE "WIN32" ${ARGN})
79ENDMACRO(ORXONOX_ADD_EXECUTABLE)
80
81
82MACRO(TU_ADD_TARGET _target_name _target_type _additional_switches)
83  CAPITALISE_NAME(${_target_name} _target_name_capitalised)
84  STRING(TOUPPER "${_target_name}" _target_name_upper)
85
86  # Specify all possible options (either switch or with add. arguments)
87  SET(_switches   FIND_HEADER_FILES  EXCLUDE_FROM_ALL  ORXONOX_EXTERNAL
88                  NO_DLL_INTERFACE   NO_SOURCE_GROUPS  PCH_NO_DEFAULT 
89                  NO_INSTALL         NO_VERSION        ${_additional_switches})
90  SET(_list_names LINK_LIBRARIES     VERSION           SOURCE_FILES
91                  DEFINE_SYMBOL      TOLUA_FILES       PCH_FILE
92                  PCH_EXCLUDE        OUTPUT_NAME       LINK_LIBS_LINUX
93                  LINK_LIBS_WIN32    LINK_LIBS_APPLE   LINK_LIBS_UNIX)
94
95  PARSE_MACRO_ARGUMENTS("${_switches}" "${_list_names}" ${ARGN})
96
97  # Process source files with support for compilations
98  # Note: All file paths are relative to the root source directory, even the
99  #       name of the compilation file.
100  SET(_${_target_name}_source_files)
101  SET(_get_compilation_file FALSE)
102  SET(_add_to_compilation FALSE)
103  FOREACH(_file ${_arg_SOURCE_FILES})
104    IF(_file STREQUAL "COMPILATION_BEGIN")
105      # Next file is the name of the compilation
106      SET(_get_compilation_file TRUE)
107    ELSEIF(_file STREQUAL "COMPILATION_END")
108      IF(NOT _compilation_file)
109        MESSAGE(FATAL_ERROR "No name provided for source file compilation")
110      ENDIF()
111      IF(NOT DISABLE_COMPILATIONS)
112        IF(NOT _compilation_include_string)
113          MESSAGE(STATUS "Warning: Empty source file compilation!")
114        ENDIF()
115        IF(EXISTS ${_compilation_file})
116          FILE(READ ${_compilation_file} _include_string_file)
117        ENDIF()
118        IF(NOT _compilation_include_string STREQUAL "${_include_string_file}")
119          FILE(WRITE ${_compilation_file} "${_compilation_include_string}")
120        ENDIF()
121        LIST(APPEND _${_target_name}_source_files ${_compilation_file})
122      ENDIF()
123      SET(_add_to_compilation FALSE)
124    ELSEIF(_get_compilation_file)
125      SET(_compilation_file ${CMAKE_BINARY_DIR}/${_file})
126      SET(_get_compilation_file FALSE)
127      SET(_add_to_compilation TRUE)
128      SET(_compilation_include_string)
129    ELSE()
130      # Default, add source file
131
132      # Prepare relative paths
133      IF(NOT _file MATCHES "^(.\\:|\\/)")
134        # Path can be relative to the current source directory if the file was
135        # not added with the source file macros. Otherwise there is a "./" at
136        # the beginning of each file and the filename is relative
137        # to the CMAKE_SOURCE_DIR
138        STRING(REGEX REPLACE "^\\.\\/(.+)$" "\\1" _temp ${_file})
139        IF(NOT ${_temp} STREQUAL ${_file})
140          SET(_file ${CMAKE_SOURCE_DIR}/${_temp})
141        ELSE()
142          SET(_file ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
143        ENDIF()
144      ENDIF()
145
146      LIST(APPEND _${_target_name}_source_files ${_file})
147
148      # Handle compilations
149      IF(_add_to_compilation AND NOT DISABLE_COMPILATIONS)
150        IF(_file MATCHES "\\.(c|cc|cpp|cxx)$")
151          SET(_compilation_include_string "${_compilation_include_string}#include \"${_file}\"\n")
152        ENDIF()
153        # Don't compile these files, even if they are source files
154        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
155      ENDIF()
156    ENDIF()
157  ENDFOREACH(_file)
158
159  # Assemble all header files of the library
160  IF(_arg_FIND_HEADER_FILES)
161    GET_ALL_HEADER_FILES(_${_target_name}_header_files)
162  ENDIF()
163
164  # Combine source and header files
165  SET(_${_target_name}_files
166    ${_${_target_name}_header_files}
167    ${_${_target_name}_source_files}
168  )
169  # Remove potential duplicates
170  LIST(REMOVE_DUPLICATES _${_target_name}_files)
171
172  # TOLUA_FILES
173  IF(_arg_TOLUA_FILES)
174    GENERATE_TOLUA_BINDINGS(${_target_name_capitalised} _${_target_name}_files
175                            INPUTFILES ${_arg_TOLUA_FILES})
176    # Workaround for XCode: The folder where the bind files are written to has
177    # to be present beforehand.
178    IF(CMAKE_CONFIGURATION_TYPES)
179      FOREACH(_dir ${CMAKE_CONFIGURATION_TYPES})
180        FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_dir})
181      ENDFOREACH(_dir)
182    ENDIF()
183  ENDIF()
184
185  # First part (pre target) of precompiled header files
186  IF(PCH_COMPILER_SUPPORT AND _arg_PCH_FILE)
187    # Provide convenient option to control PCH
188    IF(_arg_PCH_NO_DEFAULT)
189      SET(PCH_DEFAULT FALSE)
190    ELSE()
191      SET(PCH_DEFAULT TRUE)
192    ENDIF()
193    CMAKE_DEPENDENT_OPTION(PCH_ENABLE_${_target_name_upper}
194      "Enable using precompiled header files for library ${_target_name}." ${PCH_DEFAULT} PCH_ENABLE OFF)
195
196    IF(PCH_ENABLE_${_target_name_upper})
197      PRECOMPILED_HEADER_FILES_PRE_TARGET(${_target_name} ${_arg_PCH_FILE} _${_target_name}_files EXCLUDE ${_arg_PCH_EXCLUDE})
198    ENDIF()
199  ENDIF()
200
201  # Generate the source groups
202  IF(MSVC AND NOT _arg_NO_SOURCE_GROUPS)
203    GENERATE_SOURCE_GROUPS(${_${_target_name}_files})
204
205    IF(NOT _arg_ORXONOX_EXTERNAL)
206      # Move the ...Prereqs.h and the PCH files to the 'Config' section
207      IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_target_name_capitalised}Prereqs.h)
208        SOURCE_GROUP("Config" FILES ${_target_name_capitalised}Prereqs.h)
209      ENDIF()
210      IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_arg_PCH_FILE})
211        SOURCE_GROUP("Config" FILES ${CMAKE_CURRENT_SOURCE_DIR}/${_arg_PCH_FILE})
212      ENDIF()
213    ENDIF()
214  ENDIF()
215
216  # Set link mode (SHARED/STATIC)
217  IF(MSVC AND _arg_NO_DLL_INTERFACE)
218    # Certain libraries don't have dllexport/dllimport and can't be linked shared with MSVC
219    SET(_link_mode STATIC)
220  ELSEIF(_arg_ORXONOX_EXTERNAL)
221    # Externals can be linked shared or statically
222    SET(_link_mode ${ORXONOX_EXTERNAL_LINK_MODE})
223  ELSE()
224    # All our own libraries are linked dynamically because of static symbols
225    SET(_link_mode SHARED)
226  ENDIF()
227
228  # No warnings needed from third party libraries
229  IF(_arg_ORXONOX_EXTERNAL)
230    REMOVE_COMPILER_FLAGS("-W3 -W4" MSVC)
231    ADD_COMPILER_FLAGS("-w" NOT MSVC)
232    ADD_COMPILER_FLAGS("-W0" MSVC)
233  ENDIF()
234
235  # Don't compile header files
236  FOREACH(_file ${_${_target_name}_files})
237    IF(NOT _file MATCHES "\\.(c|cc|cpp|cxx|mm)$")
238      SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
239    ENDIF()
240  ENDFOREACH(_file)
241
242
243
244  # Add the library/executable
245  IF("${_target_type}" STREQUAL "LIBRARY")
246    ADD_LIBRARY(${_target_name} ${_link_mode}
247                ${_arg_EXCLUDE_FROM_ALL} ${_${_target_name}_files})
248  ELSE()
249    ADD_EXECUTABLE(${_target_name} ${_arg_WIN32} ${_arg_EXCLUDE_FROM_ALL}
250                   ${_${_target_name}_files})
251  ENDIF()
252
253
254
255  # Change library prefix to "lib"
256  IF(MSVC AND ${_target_type} STREQUAL "LIBRARY")
257    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES
258      PREFIX "lib"
259    )
260  ENDIF()
261
262  # MSVC hack to exclude external library sources from the intellisense database
263  # (IntelliSense stops working when adding "-Zm1000" as compile flag. "/Zm1000"
264  # would not work because of the slash)
265  IF(_arg_ORXONOX_EXTERNAL AND MSVC)
266    GET_TARGET_PROPERTY(_compile_flags ${_target_name} COMPILE_FLAGS)
267    IF(NOT _compile_flags)
268      SET(_compile_flags)
269    ENDIF()
270    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES COMPILE_FLAGS "${_compile_flags} -Zm1000")
271  ENDIF()
272
273  # Configure modules
274  IF (_arg_MODULE)
275    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES
276      RUNTIME_OUTPUT_DIRECTORY ${CMAKE_MODULE_OUTPUT_DIRECTORY} # Windows
277      LIBRARY_OUTPUT_DIRECTORY ${CMAKE_MODULE_OUTPUT_DIRECTORY} # Unix
278    )
279    ADD_MODULE(${_target_name})
280    # Ensure that the main program depends on the module
281    SET(ORXONOX_MODULES ${ORXONOX_MODULES} ${_target_name} CACHE INTERNAL "")
282  ENDIF()
283
284  # Static library flags are not globally available
285  IF(ORXONOX_STATIC_LINKER_FLAGS)
286    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES STATIC_LIBRARY_FLAGS ${ORXONOX_STATIC_LINKER_FLAGS})
287  ENDIF()
288
289  # LINK_LIBRARIES
290  IF(_arg_LINK_LIBRARIES)
291    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBRARIES})
292  ENDIF()
293  IF(_arg_LINK_LIBS_LINUX AND LINUX)
294    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_LINUX})
295  ENDIF()
296  IF(_arg_LINK_LIBS_WIN32 AND WIN32)
297    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_WIN32})
298  ENDIF()
299  IF(_arg_LINK_LIBS_APPLE AND APPLE)
300    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_APPLE})
301  ENDIF()
302  IF(_arg_LINK_LIBS_UNIX AND UNIX)
303    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_UNIX})
304  ENDIF()
305
306  # RPATH settings for the installation
307  IF("${_target_type}" STREQUAL "LIBRARY")
308    IF(_arg_MODULE)
309      SET(_rpath "${MODULE_RPATH}")
310    ELSE()
311      SET(_rpath "${LIBRARY_RPATH}")
312    ENDIF()
313  ELSE()
314    SET(_rpath "${RUNTIME_RPATH}")
315  ENDIF()
316  SET_TARGET_PROPERTIES(${_target_name} PROPERTIES INSTALL_RPATH "${_rpath}")
317
318  # DEFINE_SYMBOL
319  IF(_arg_DEFINE_SYMBOL)
320    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES DEFINE_SYMBOL ${_arg_DEFINE_SYMBOL})
321  ELSEIF(NOT _arg_ORXONOX_EXTERNAL)
322    # Automatically add the macro definitions for our own libraries
323    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES DEFINE_SYMBOL "${_target_name_upper}_SHARED_BUILD")
324  ENDIF()
325
326  # VERSION
327  IF(_arg_VERSION)
328    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES VERSION ${_arg_VERSION})
329  ELSEIF(NOT _arg_ORXONOX_EXTERNAL AND NOT _arg_NO_VERSION AND NOT ${_target_type} STREQUAL "EXECUTABLE")
330    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES VERSION ${ORXONOX_VERSION})
331  ENDIF()
332
333  # OUTPUT_NAME
334  IF(_arg_OUTPUT_NAME)
335    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES OUTPUT_NAME  ${_arg_OUTPUT_NAME})
336  ENDIF()
337
338  # Second part of precompiled header files
339  IF(PCH_COMPILER_SUPPORT AND PCH_ENABLE_${_target_name_upper} AND _arg_PCH_FILE)
340    PRECOMPILED_HEADER_FILES_POST_TARGET(${_target_name} ${_arg_PCH_FILE})
341  ENDIF()
342
343  # Install all targets except for static ones (executables also have SHARED in _link_mode)
344  IF(${_link_mode} STREQUAL "SHARED" AND NOT _arg_NO_INSTALL)
345    IF(_arg_MODULE)
346      INSTALL(TARGETS ${_target_name}
347        RUNTIME DESTINATION ${MODULE_INSTALL_DIRECTORY}
348        LIBRARY DESTINATION ${MODULE_INSTALL_DIRECTORY}
349      )
350    ELSE()
351      INSTALL(TARGETS ${_target_name}
352        RUNTIME DESTINATION ${RUNTIME_INSTALL_DIRECTORY}
353        LIBRARY DESTINATION ${LIBRARY_INSTALL_DIRECTORY}
354      )
355    ENDIF()
356  ENDIF()
357
358ENDMACRO(TU_ADD_TARGET)
359
360
361# Creates a helper file with name <name_of_the_library>${ORXONOX_MODULE_EXTENSION}
362# This helps finding dynamically loadable modules at runtime
363
364FUNCTION(ADD_MODULE _target)
365  # We use the properties to get the name because the librarys name may differ from
366  # the target name (for example orxonox <-> liborxonox)
367
368  GET_TARGET_PROPERTY(_target_loc ${_target} LOCATION)
369  GET_FILENAME_COMPONENT(_target_name ${_target_loc} NAME_WE)
370
371  IF(CMAKE_CONFIGURATION_TYPES)
372    FOREACH(_config ${CMAKE_CONFIGURATION_TYPES})
373      SET(_module_filename ${CMAKE_MODULE_OUTPUT_DIRECTORY}/${_config}/${_target_name}${ORXONOX_MODULE_EXTENSION})
374
375      FILE(WRITE ${_module_filename})
376
377      INSTALL(
378        FILES ${_module_filename}
379        DESTINATION ${MODULE_INSTALL_DIRECTORY}
380        CONFIGURATIONS ${_config}
381      )
382    ENDFOREACH()
383  ELSE()
384    SET(_module_filename ${CMAKE_MODULE_OUTPUT_DIRECTORY}/${_target_name}${ORXONOX_MODULE_EXTENSION})
385
386    FILE(WRITE ${_module_filename})
387
388    INSTALL(
389      FILES ${_module_filename}
390      DESTINATION ${MODULE_INSTALL_DIRECTORY}
391    )
392  ENDIF()
393ENDFUNCTION(ADD_MODULE)
Note: See TracBrowser for help on using the repository browser.