# - This is a support module for easy Mono/C# handling with CMake # It defines the following macros: # # ADD_CS_LIBRARY ( ) # ADD_CS_EXECUTABLE ( ) # INSTALL_GAC () # # Note that the order of the arguments is important. # # You can optionally set the variable CS_FLAGS to tell the macros whether # to pass additional flags to the compiler. This is particularly useful to # set assembly references, unsafe code, etc... These flags are always reset # after the target was added so you don't have to care about that. # # copyright (c) 2007 Arno Rehn arno@arnorehn.de # # Redistribution and use is allowed according to the terms of the GPL license. # ----- support macros ----- MACRO(GET_CS_LIBRARY_TARGET_DIR) IF (NOT LIBRARY_OUTPUT_PATH) SET(CS_LIBRARY_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) ELSE (NOT LIBRARY_OUTPUT_PATH) SET(CS_LIBRARY_TARGET_DIR ${LIBRARY_OUTPUT_PATH}) ENDIF (NOT LIBRARY_OUTPUT_PATH) ENDMACRO(GET_CS_LIBRARY_TARGET_DIR) MACRO(GET_CS_EXECUTABLE_TARGET_DIR) IF (NOT EXECUTABLE_OUTPUT_PATH) SET(CS_EXECUTABLE_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) ELSE (NOT EXECUTABLE_OUTPUT_PATH) SET(CS_EXECUTABLE_TARGET_DIR ${EXECUTABLE_OUTPUT_PATH}) ENDIF (NOT EXECUTABLE_OUTPUT_PATH) ENDMACRO(GET_CS_EXECUTABLE_TARGET_DIR) MACRO(MAKE_PROPER_FILE_LIST) FOREACH(file ${ARGN}) # first assume it's a relative path FILE(GLOB globbed ${CMAKE_CURRENT_SOURCE_DIR}/${file}) IF(globbed) FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file} native) ELSE(globbed) FILE(TO_NATIVE_PATH ${file} native) ENDIF(globbed) SET(proper_file_list ${proper_file_list} ${native}) SET(native "") ENDFOREACH(file) ENDMACRO(MAKE_PROPER_FILE_LIST) # ----- end support macros ----- MACRO(ADD_CS_LIBRARY target) GET_CS_LIBRARY_TARGET_DIR() SET(target_DLL "${CS_LIBRARY_TARGET_DIR}/${target}.dll") MAKE_PROPER_FILE_LIST(${ARGN}) FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_DLL}) SET(target_KEY "${CMAKE_CURRENT_SOURCE_DIR}/${target}.key") SET(target_CS_FLAGS "${CS_FLAGS}") IF(${target}_CS_FLAGS) LIST(APPEND target_CS_FLAGS ${${target}_CS_FLAGS}) ENDIF(${target}_CS_FLAGS) IF(EXISTS ${target_KEY}) LIST(APPEND target_CS_FLAGS -keyfile:${target_KEY}) ENDIF(EXISTS ${target_KEY}) FOREACH(ref ${${target}_REFS}) SET(ref_DLL ${CMAKE_CURRENT_BINARY_DIR}/${ref}.dll) IF(EXISTS ${ref_DLL}) LIST(APPEND target_CS_FLAGS -r:${ref_DLL}) ELSE(EXISTS ${ref_DLL}) LIST(APPEND target_CS_FLAGS -r:${ref}) ENDIF(EXISTS ${ref_DLL}) ENDFOREACH(ref ${${target}_REFS}) ADD_CUSTOM_COMMAND (OUTPUT ${target_DLL} COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_DLL} -target:library ${proper_file_list} MAIN_DEPENDENCY ${proper_file_list} DEPENDS ${ARGN} COMMENT "Building ${relative_path}") ADD_CUSTOM_TARGET (${target} ALL DEPENDS ${target_DLL}) FOREACH(ref ${${target}_REFS}) GET_TARGET_PROPERTY(is_target ${ref} TYPE) IF(is_target) ADD_DEPENDENCIES(${target} ${ref}) ENDIF(is_target) ENDFOREACH(ref ${${target}_REFS}) SET(relative_path "") SET(proper_file_list "") ENDMACRO(ADD_CS_LIBRARY) MACRO(ADD_CS_EXECUTABLE target) GET_CS_EXECUTABLE_TARGET_DIR() # Seems like cmake doesn't like the ".exe" ending for custom commands. # If we call it ${target}.exe, 'make' will later complain about a missing rule. # Create a fake target instead. SET(target_EXE "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe") SET(target_TOUCH "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe-built") GET_DIRECTORY_PROPERTY(clean ADDITIONAL_MAKE_CLEAN_FILES) LIST(APPEND clean ${target}.exe) SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean}") MAKE_PROPER_FILE_LIST(${ARGN}) FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_EXE}) SET(target_CS_FLAGS "${CS_FLAGS}") FOREACH(ref ${${target}_REFS}) SET(ref_DLL ${CMAKE_CURRENT_SOURCE_DIR}/${ref}.dll) IF(EXISTS ${ref_DLL}) LIST(APPEND target_CS_FLAGS -r:${ref_DLL}) ELSE(EXISTS ${ref_DLL}) LIST(APPEND target_CS_FLAGS -r:${ref}) ENDIF(EXISTS ${ref_DLL}) ENDFOREACH(ref ${${target}_REFS}) ADD_CUSTOM_COMMAND (OUTPUT "${target_TOUCH}" COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_EXE} ${proper_file_list} COMMAND ${CMAKE_COMMAND} -E touch ${target_TOUCH} MAIN_DEPENDENCY ${ARGN} DEPENDS ${ARGN} COMMENT "Building ${relative_path}") ADD_CUSTOM_TARGET ("${target}" ALL DEPENDS "${target_TOUCH}") FOREACH(ref ${${target}_REFS}) GET_TARGET_PROPERTY(is_target ${ref} TYPE) IF(is_target) ADD_DEPENDENCIES(${target} ${ref}) ENDIF(is_target) ENDFOREACH(ref ${${target}_REFS}) SET(relative_path "") SET(proper_file_list "") ENDMACRO(ADD_CS_EXECUTABLE) MACRO(INSTALL_GAC target) GET_CS_LIBRARY_TARGET_DIR() INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${GACUTIL_EXECUTABLE} -i ${CS_LIBRARY_TARGET_DIR}/${target}.dll -package 2.0)") ENDMACRO(INSTALL_GAC target)