############################################################################ # # file : robot.cmake # copyright : (C) 2008 by Mart Kelder, 2010 by J.-P. Meuret # web : www.speed-dreams.org # version : $Id$ # ############################################################################ ############################################################################ # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # ############################################################################ # @file Robots-related macros # @author Mart Kelder # @version $Id$ # Robot .def file generation for Windows builds with MSVC compilers # ROBOTNAME : Name of the robot # DEF_FILE : Target .def file path-name # Other args : Robot DLL Interface description, as a list of names of exported symbols, # but with keywords shortcuts : # - if empty, assumed keyword "LEGACY_MIN" # - if "LEGACY_MIN", means the smallest legacy scheme interface (TORCS style) # with only "${NAME}" exported # - if "LEGACY", means the complete legacy scheme interface, # with "${NAME}" and "${NAME}Shut" exported # - if "WELCOME", means the complete new scheme interface (Speed Dreams style), # with "moduleWelcome", "moduleInitialize" and "moduleTerminate" # exported # - may be a list of above keywords for multi-scheme interface # - may also be the raw list of symbols to export MACRO(GENERATE_ROBOT_DEF_FILE ROBOTNAME DEF_FILE) # Build the real list of exported symbols from the given one (that may include shortcuts) #MESSAGE(STATUS "Generating ${DEF_FILE} for ${ROBOTNAME} robot") SET(SYMBOLS) # Initialize the list FOREACH(KEYSYM ${ARGN}) IF(KEYSYM STREQUAL "LEGACY_MIN") LIST(APPEND SYMBOLS ${ROBOTNAME}) ELSEIF(KEYSYM STREQUAL "LEGACY") LIST(APPEND SYMBOLS ${ROBOTNAME}) LIST(APPEND SYMBOLS "${ROBOTNAME}Shut") ELSEIF(KEYSYM STREQUAL "WELCOME") LIST(APPEND SYMBOLS moduleWelcome moduleInitialize moduleTerminate) ELSE(KEYSYM STREQUAL "LEGACY_MIN") LIST(APPEND SYMBOLS ${KEYSYM}) ENDIF(KEYSYM STREQUAL "LEGACY_MIN") ENDFOREACH(KEYSYM ${ARGN}) # Clean duplicates LIST(REMOVE_DUPLICATES SYMBOLS) #MESSAGE(STATUS "Symbols: ${SYMBOLS}") # Build an acceptable string for the .def file from this symbol list SET(ROBOTSYMBOLS "") FOREACH(SYMBOL ${SYMBOLS}) SET(ROBOTSYMBOLS "${ROBOTSYMBOLS}\n\t${SYMBOL}") ENDFOREACH(SYMBOL ${SYMBOLS}) # Generate the .def file SET(ROBOT_NAME "${ROBOTNAME}") IF(IN_SOURCETREE) CONFIGURE_FILE(${SOURCE_DIR}/cmake/robot.def.in.cmake ${DEF_FILE}) ELSE(IN_SOURCETREE) CONFIGURE_FILE(${SD_DATADIR_ABS}/cmake/robot.def.in.cmake ${DEF_FILE}) ENDIF(IN_SOURCETREE) ENDMACRO(GENERATE_ROBOT_DEF_FILE ROBOTNAME DEF_FILE) # Robot project definition (module build and install, without associated data) # Args: # NAME : Name of the robot # INTERFACE : Robot Windows DLL Interface description (tells about exported symbols) # See GENERATE_ROBOT_DEF_FILE macro. # If not specified, defaults to "LEGACY_MIN" ; not used if MODULE used # SOURCES : List of files to use as build sources if any ; not needed if MODULE used # CLONENAMES : The names of the clones to generate # VERSION : The VERSION of the libraries to produce (robot and its clones) (def: $VERSION). # SOVERSION : The SOVERSION of the libraries to produce (in the ldconfig meaning) (def: 0.0.0). # WARNING: Not taken into account for the moment : might not work with GCC 4.5 or +. # # Example: # ROBOT_MODULE(NAME simplix VERSION 3.0.5 SOVERSION 0.0.0 # INTERFACE LEGACY WELCOME simplix_trb1 simplix_ls1 simplix_36GP # SOURCES simplix.cpp ... # CLONENAMES simplix_trb1 simplix_ls1 simplix_36GP) MACRO(ROBOT_MODULE) SET(RBM_SYNTAX "NAME,1,1,RBM_HAS_NAME,RBM_NAME") SET(RBM_SYNTAX ${RBM_SYNTAX} "VERSION,0,1,RBM_HAS_VERSION,RBM_VERSION") SET(RBM_SYNTAX ${RBM_SYNTAX} "SOVERSION,0,1,RBM_HAS_SOVERSION,RBM_SOVERSION") SET(RBM_SYNTAX ${RBM_SYNTAX} "INTERFACE,0,-1,RBM_HAS_INTERFACE,RBM_INTERFACE") SET(RBM_SYNTAX ${RBM_SYNTAX} "SOURCES,0,-1,RBM_HAS_SOURCES,RBM_SOURCES") SET(RBM_SYNTAX ${RBM_SYNTAX} "CLONENAMES,0,-1,RBM_HAS_CLONENAMES,RBM_CLONENAMES") SPLIT_ARGN(${RBM_SYNTAX} ARGUMENTS ${ARGN}) IF(NOT RBM_HAS_NAME OR NOT RBM_NAME) MESSAGE(FATAL_ERROR "Cannot build a robot module with no specified name") ENDIF() IF(NOT RBM_HAS_SOURCES OR NOT RBM_SOURCES) MESSAGE(FATAL_ERROR "Cannot build a robot module without sources / module to copy") ENDIF() IF(NOT RBM_HAS_VERSION OR NOT RBM_VERSION) SET(RBM_VERSION ${VERSION}) MESSAGE(STATUS "No version specified for robot module ${RBM_NAME} ; using ${RBM_VERSION}") ENDIF() IF(NOT RBM_HAS_SOVERSION OR NOT RBM_SOVERSION) IF(UNIX) SET(RBM_SOVERSION 0.0.0) MESSAGE(STATUS "No so-version specified for robot module ${RBM_NAME} ; using ${RBM_SOVERSION}") ENDIF() ENDIF() PROJECT("robot_${RBM_NAME}") ADD_INTERFACE_INCLUDEDIR() ADD_SDLIB_INCLUDEDIR(learning math portability robottools tgf) ADD_PLIB_INCLUDEDIR() # DLL export stuff under Windows (through a .def file or __declspec pragmas) IF(WIN32) # If an interface is specified, use the old way. IF(RBM_HAS_INTERFACE AND RBM_INTERFACE) IF(MSVC) # For MSVC compilers, generate / add a .def file for legacy / welcome interface. SET(ROBOT_DEF_FILE ${CMAKE_CURRENT_BINARY_DIR}/${RBM_NAME}_gen.def) GENERATE_ROBOT_DEF_FILE(${RBM_NAME} ${ROBOT_DEF_FILE} ${RBM_INTERFACE}) SET(RBM_SOURCES ${RBM_SOURCES} ${ROBOT_DEF_FILE}) ENDIF() # If no interface is specified, assume it's the new modern one. ELSE() # For any Windows compiler, use __declspec pragmas. ADD_DEFINITIONS(-DROBOT_DLL) ENDIF() ENDIF(WIN32) # Disable developer warning IF (COMMAND cmake_policy) CMAKE_POLICY(SET CMP0003 NEW) ENDIF(COMMAND cmake_policy) # Ignore some run-time libs to avoid MSVC link-time warnings and sometimes even crashes. IF(MSVC) SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:msvcrt.lib") ENDIF(MSVC) # The robot module is actually a module. SD_ADD_LIBRARY(${RBM_NAME} ROBOT ${RBM_SOURCES}) # Customize shared library versions. IF(UNIX) # Use ldconfig version naming scheme + no "lib" prefix under Linux # Might not work with GCC 4.5 or + (non-robot modules crash at 1st reload = after 1 dlclose) #SET_TARGET_PROPERTIES(${RBM_NAME} PROPERTIES VERSION ${RBM_VERSION}) #SET_TARGET_PROPERTIES(${RBM_NAME} PROPERTIES SOVERSION ${RBM_SOVERSION}) ELSE() SET_TARGET_PROPERTIES(${RBM_NAME} PROPERTIES VERSION ${RBM_VERSION}) ENDIF() # Link/Run-time dependencies ADD_PLIB_LIBRARY(${RBM_NAME} sg) ADD_SDLIB_LIBRARY(${RBM_NAME} portability tgf robottools) # Install target robot module shared library SD_INSTALL_FILES(LIB drivers/${RBM_NAME} TARGETS ${RBM_NAME}) # Install clone robot modules shared libraries (use ldconfig version naming scheme under Linux) IF(RBM_HAS_CLONENAMES AND RBM_CLONENAMES) GET_TARGET_PROPERTY(MODLOC ${RBM_NAME} RUNTIME_OUTPUT_DIRECTORY) IF(NOT RUNTIME_OUTPUT_DIRECTORY) GET_TARGET_PROPERTY(MODLOC ${RBM_NAME} LIBRARY_OUTPUT_DIRECTORY) ENDIF() SET(MODLOC "${MODLOC}/${RBM_NAME}${CMAKE_SHARED_MODULE_SUFFIX}") FOREACH(CLONENAME ${RBM_CLONENAMES}) SET(CLONE_MODDIR "${CMAKE_BINARY_DIR}/${SD_LIBDIR}/drivers/${CLONENAME}") SET(CLONE_MODLOC "${CLONE_MODDIR}/${CLONENAME}${CMAKE_SHARED_MODULE_SUFFIX}") SET_PROPERTY(GLOBAL APPEND PROPERTY SD_ROBOT_LIST "${CLONENAME}") IF(FALSE) #IF(UNIX) # Might not work with GCC 4.5 or + (see above) ADD_CUSTOM_COMMAND(TARGET ${RBM_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Cloning ${RBM_NAME}${CMAKE_SHARED_MODULE_SUFFIX} into ${CLONE_MODLOC}.${RBM_VERSION}" COMMAND ${CMAKE_COMMAND} -E make_directory "${CLONE_MODDIR}" COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MODLOC} ${CLONE_MODLOC}.${RBM_VERSION}) ADD_CUSTOM_COMMAND(TARGET ${RBM_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink ${CLONE_MODLOC}.${RBM_VERSION} ${CLONE_MODLOC}.${RBM_SOVERSION} COMMAND ${CMAKE_COMMAND} -E create_symlink ${CLONE_MODLOC}.${RBM_SOVERSION} ${CLONE_MODLOC}) SD_INSTALL_FILES(LIB drivers/${CLONENAME} FILES ${CLONE_MODLOC} ${CLONE_MODLOC}.${RBM_SOVERSION} ${CLONE_MODLOC}.${RBM_VERSION} ) ELSE() ADD_CUSTOM_COMMAND(TARGET ${RBM_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Creating directory ${CLONE_MODDIR}" COMMAND ${CMAKE_COMMAND} -E make_directory "${CLONE_MODDIR}" COMMAND ${CMAKE_COMMAND} -E echo "Cloning ${RBM_NAME}${CMAKE_SHARED_MODULE_SUFFIX}=${MODLOC} into ${CLONE_MODLOC}" COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MODLOC} ${CLONE_MODLOC}) SD_INSTALL_FILES(LIB drivers/${CLONENAME} FILES ${CLONE_MODLOC}) ENDIF() ENDFOREACH(CLONENAME ${RBM_CLONENAMES}) ENDIF() ENDMACRO(ROBOT_MODULE) # Robot data installation # Args: # NAME : Name of the robot (may be a clone) # PREFIX : Prefix to use to get source path for files/subdirs specified in FILES/SUBDIRS # FILES : Files to install in the robot's data dir (see PREFIX) # SUBDIRS : Sub-dirs to recusively install in the robot's data dir (see PREFIX) # PATTERNS : Files to install from SUBDIRS in the robot's data dir, # as glob patterns (defaults to *.*) # USER : If this keyword is present, also mark _any_ above specified XML file # as a user settings file (installed at run-time is the user settings folders). # MACRO(ROBOT_DATA) SET(RBD_SYNTAX "NAME,1,1,RBD_HAS_NAME,RBD_NAME") SET(RBD_SYNTAX ${RBD_SYNTAX} "PREFIX,0,1,RBD_HAS_PREFIX,RBD_PREFIX") SET(RBD_SYNTAX ${RBD_SYNTAX} "FILES,0,-1,RBD_HAS_FILES,RBD_FILES") SET(RBD_SYNTAX ${RBD_SYNTAX} "SUBDIRS,0,-1,RBD_HAS_SUBDIRS,RBD_SUBDIRS") SET(RBD_SYNTAX ${RBD_SYNTAX} "PATTERNS,0,-1,RBD_HAS_PATTERNS,RBD_PATTERNS") SET(RBD_SYNTAX ${RBD_SYNTAX} "USER,0,0,RBD_IS_USER,_") SPLIT_ARGN(${RBD_SYNTAX} ARGUMENTS ${ARGN}) #MESSAGE(STATUS "ROBOT_DATA(${RBD_NAME}): PREFIX=${RBD_PREFIX} FILES=${RBD_FILES} PATTERNS=${RBD_PATTERNS} SUBDIRS=${RBD_SUBDIRS} USER=${RBD_IS_USER}") # Check arguments syntax / values IF(NOT RBD_HAS_NAME OR NOT RBD_NAME) MESSAGE(FATAL_ERROR "Cannot install data for a robot module with no specified name") ENDIF() # Install specified files. IF(RBD_HAS_FILES AND RBD_FILES) IF(RBD_IS_USER) SD_INSTALL_FILES(DATA drivers/${RBD_NAME} USER drivers/${RBD_NAME} PREFIX ${RBD_PREFIX} FILES ${RBD_FILES}) ELSE() SD_INSTALL_FILES(DATA drivers/${RBD_NAME} PREFIX ${RBD_PREFIX} FILES ${RBD_FILES}) ENDIF() ENDIF() # Install subdirs if specified. IF(RBD_HAS_SUBDIRS AND RBD_SUBDIRS) # Install specified files. IF(RBD_IS_USER) SD_INSTALL_DIRECTORIES(DATA drivers/${RBD_NAME} USER drivers/${RBD_NAME} PREFIX ${RBD_PREFIX} DIRECTORIES ${RBD_SUBDIRS} PATTERNS ${RBD_PATTERNS}) ELSE() SD_INSTALL_DIRECTORIES(DATA drivers/${RBD_NAME} PREFIX ${RBD_PREFIX} DIRECTORIES ${RBD_SUBDIRS} PATTERNS ${RBD_PATTERNS}) ENDIF() ENDIF(RBD_HAS_SUBDIRS AND RBD_SUBDIRS) ENDMACRO(ROBOT_DATA) # Robot project definition (module build and install, with associated data) # Args: # NAME : Name of the robot # INTERFACE : Robot Windows DLL Interface description (tells about exported symbols) # See GENERATE_ROBOT_DEF_FILE macro. # If not specified, defaults to "LEGACY_MIN" ; not used if MODULE used # SOURCES : List of files to use as build sources if any ; not needed if MODULE used # PREFIX : Dir. prefix for source files/subdirs to install in the robot's data dir # FILES : Extra (non default) files to install in the robot's data dir # SUBDIRS : Data subdirectories to install in the robot's data dir MACRO(ROBOT) SET(RB_SYNTAX "NAME,1,1,RB_HAS_NAME,RB_NAME") SET(RB_SYNTAX ${RB_SYNTAX} "INTERFACE,0,-1,RB_HAS_INTERFACE,RB_INTERFACE") SET(RB_SYNTAX ${RB_SYNTAX} "SOURCES,0,-1,RB_HAS_SOURCES,RB_SOURCES") SET(RB_SYNTAX ${RB_SYNTAX} "PREFIX,0,-1,RB_HAS_PREFIX,RB_PREFIX") SET(RB_SYNTAX ${RB_SYNTAX} "FILES,0,-1,RB_HAS_FILES,RB_FILES") SET(RB_SYNTAX ${RB_SYNTAX} "SUBDIRS,0,-1,RB_HAS_SUBDIRS,RB_SUBDIRS") #SET(__DEBUG__ TRUE) SPLIT_ARGN(${RB_SYNTAX} ARGUMENTS ${ARGN}) #SET(__DEBUG__ FALSE) #MESSAGE(STATUS "ROBOT(${RB_NAME}): INTERFACE=${RB_INTERFACE} (${RB_HAS_INTERFACE}) SOURCES=${RB_SOURCES} (${RB_HAS_SOURCES}) PREFIX=${RB_PREFIX} (${RB_HAS_PREFIX}) FILES=${RB_FILES} (${RB_HAS_FILES}) SUBDIRS=${RB_SUBDIRS} (${RB_HAS_SUBDIRS})") IF(NOT RB_HAS_NAME OR NOT RB_NAME) MESSAGE(FATAL_ERROR "Cannot build a robot with no specified name") ENDIF() IF(NOT RB_HAS_SOURCES OR NOT RB_SOURCES) MESSAGE(FATAL_ERROR "Cannot build a robot without sources") ENDIF() ROBOT_MODULE(NAME ${RB_NAME} INTERFACE ${RB_INTERFACE} SOURCES ${RB_SOURCES}) ROBOT_DATA(NAME ${RB_NAME} PREFIX ${RB_PREFIX} FILES ${RB_FILES} SUBDIRS ${RB_SUBDIRS}) ENDMACRO(ROBOT)