diff options
author | Adam <Adam@anope.org> | 2010-07-15 22:55:02 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2010-07-15 22:55:02 -0400 |
commit | a22f8d3b2de88b9bb6f80f0c2780846ae23ab389 (patch) | |
tree | a2fdf570868896a787df8a1169951b0028e68d6b /cmake | |
parent | 43b1e43afb85639485e36d24da351dc0f121be6e (diff) |
Moved some files and diretories around, made cmake skip files it knows it can't compile because of missing dependices.
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/Anope.cmake | 540 | ||||
-rw-r--r-- | cmake/NSIS.template.in | 825 | ||||
-rw-r--r-- | cmake/ReadFile.cmake | 5 |
3 files changed, 1370 insertions, 0 deletions
diff --git a/cmake/Anope.cmake b/cmake/Anope.cmake new file mode 100644 index 000000000..97734199f --- /dev/null +++ b/cmake/Anope.cmake @@ -0,0 +1,540 @@ +############################################################################### +# strip_string(<input string> <output string>) +# +# A macro to handle stripping the leading and trailing spaces from a string, +# uses string(STRIP) if using CMake 2.6.x or better, otherwise uses +# string(REGEX REPLACE). +############################################################################### +macro(strip_string INPUT_STRING OUTPUT_STRING) + if(CMAKE26_OR_BETTER) + # For CMake 2.6.x or better, we can just use the STRIP sub-command of string() + string(STRIP ${INPUT_STRING} ${OUTPUT_STRING}) + else(CMAKE26_OR_BETTER) + # For CMake 2.4.x, we will have to use the REGEX REPLACE sub-command of string() instead + # First check if the input string is empty or not + if (${INPUT_STRING} STREQUAL "") + set(${OUTPUT_STRING} "") + else(${INPUT_STRING} STREQUAL "") + # Determine if the string is entirely empty or not + string(REGEX MATCH "^[ \t]*$" EMPTY_STRING "${INPUT_STRING}") + if(EMPTY_STRING) + set(${OUTPUT_STRING} "") + else(EMPTY_STRING) + # We detect if there is any leading whitespace and remove any if there is + string(SUBSTRING "${INPUT_STRING}" 0 1 FIRST_CHAR) + if(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t") + string(REGEX REPLACE "^[ \t]+" "" TEMP_STRING "${INPUT_STRING}") + else(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t") + set(TEMP_STRING "${INPUT_STRING}") + endif(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t") + # Next we detect if there is any trailing whitespace and remove any if there is + string(LENGTH "${TEMP_STRING}" STRING_LEN) + math(EXPR STRING_LEN "${STRING_LEN} - 1") + string(SUBSTRING "${TEMP_STRING}" ${STRING_LEN} 1 LAST_CHAR) + if(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t") + string(REGEX REPLACE "[ \t]+$" "" ${OUTPUT_STRING} "${TEMP_STRING}") + else(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t") + set(${OUTPUT_STRING} "${TEMP_STRING}") + endif(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t") + endif(EMPTY_STRING) + endif(${INPUT_STRING} STREQUAL "") + endif(CMAKE26_OR_BETTER) +endmacro(strip_string) + +############################################################################### +# append_to_list(<list> <args>...) +# +# A macro to handle appending to lists, uses list(APPEND) if using CMake 2.4.2 +# or better, otherwise uses set() instead. +############################################################################### +macro(append_to_list LIST) + if(CMAKE242_OR_BETTER) + # For CMake 2.4.2 or better, we can just use the APPEND sub-command of list() + list(APPEND ${LIST} ${ARGN}) + else(CMAKE242_OR_BETTER) + # For CMake 2.4.x before 2.4.2, we have to do this manually use set() instead + set(${LIST} ${${LIST}} ${ARGN}) + endif(CMAKE242_OR_BETTER) +endmacro(append_to_list) + +############################################################################### +# find_in_list(<list> <value> <output variable>) +# +# A macro to handle searching within a list, will store the result in the +# given <output variable>, uses list(FIND) if using CMake 2.6.x or better +# (or CMake 2.4.8 or better), otherwise it iterates through the list to find +# the item. +############################################################################### +macro(find_in_list LIST ITEM_TO_FIND FOUND) + if(CMAKE248_OR_BETTER) + # For CMake 2.4.8 or better, we can use the FIND sub-command of list() + list(FIND ${LIST} ${ITEM_TO_FIND} ITEM_FOUND) + else(CMAKE248_OR_BETTER) + # For CMake 2.4.x before 2.4.8, we have to do this ourselves (NOTE: This is very slow due to a lack of break() as well) + # Firstly we set the position to -1 indicating nothing found, we also use a temporary position + set(ITEM_FOUND -1) + set(POS 0) + # Iterate through the list + foreach(ITEM ${${LIST}}) + # If the item we are looking at is the item we are trying to find, set that we've found the item + if(${ITEM} STREQUAL ${ITEM_TO_FIND}) + set(ITEM_FOUND ${POS}) + endif(${ITEM} STREQUAL ${ITEM_TO_FIND}) + # Increase the position value by 1 + math(EXPR POS "${POS} + 1") + endforeach(ITEM) + endif(CMAKE248_OR_BETTER) + # Set the given FOUND variable to the result + set(${FOUND} ${ITEM_FOUND}) +endmacro(find_in_list) + +############################################################################### +# remove_list_duplicates(<list>) +# +# A macro to handle removing duplicates from a list, uses +# list(REMOVE_DUPLICATES) if using CMake 2.6.x or better, otherwise it uses +# a slower method of creating a temporary list and only adding to it when +# a duplicate item hasn't been found. +############################################################################### +macro(remove_list_duplicates LIST) + if(CMAKE26_OR_BETTER) + # For CMake 2.6.x or better, this can be done automatically + list(REMOVE_DUPLICATES ${LIST}) + else(CMAKE26_OR_BETTER) + # For CMake 2.4.x, we have to do this ourselves, firstly we'll clear a temporary list + set(NEW_LIST) + # Iterate through the old list + foreach(ITEM ${${LIST}}) + # Check if the item is in the new list + find_in_list(NEW_LIST ${ITEM} FOUND_ITEM) + if(FOUND_ITEM EQUAL -1) + # If the item was not found, append it to the list + append_to_list(NEW_LIST ${ITEM}) + endif(FOUND_ITEM EQUAL -1) + endforeach(ITEM) + # Replace the old list with the new list + set(${LIST} ${NEW_LIST}) + endif(CMAKE26_OR_BETTER) +endmacro(remove_list_duplicates) + +############################################################################### +# remove_item_from_list(<list> <value>) +# +# A macro to handle removing a value from a list, uses list(REMOVE_ITEM) in +# both cases, but can remove the value itself using CMake 2.4.2 or better, +# while older versions use a slower method of iterating the list to find the +# index of the value to remove. +############################################################################### +macro(remove_item_from_list LIST VALUE) + if(CMAKE242_OR_BETTER) + # For CMake 2.4.2 or better, this can be done automatically + list(REMOVE_ITEM ${LIST} ${VALUE}) + else(CMAKE242_OR_BETTER) + # For CMake 2.4.x before 2.4.2, we have to do this ourselves, firstly we set the index and a variable to indicate if the item was found + set(INDEX 0) + set(FOUND FALSE) + # Iterate through the old list + foreach(ITEM ${${LIST}}) + # If the item hasn't been found yet, but the current item is the same, remove it + if(NOT FOUND) + if(ITEM STREQUAL ${VALUE}) + set(FOUND TRUE) + list(REMOVE_ITEM ${LIST} ${INDEX}) + endif(ITEM STREQUAL ${VALUE}) + endif(NOT FOUND) + # Increase the index value by 1 + math(EXPR INDEX "${INDEX} + 1") + endforeach(ITEM) + endif(CMAKE242_OR_BETTER) +endmacro(remove_item_from_list) + +############################################################################### +# sort_list(<list>) +# +# A macro to handle sorting a list, uses list(SORT) if using CMake 2.4.4 or +# better, otherwise it uses a slower method of creating a temporary list and +# adding elements in alphabetical order. +############################################################################### +macro(sort_list LIST) + if(CMAKE244_OR_BETTER) + # For CMake 2.4.4 or better, this can be done automatically + list(SORT ${LIST}) + else(CMAKE244_OR_BETTER) + # For CMake 2.4.x before 2.4.4, we have to do this ourselves, firstly we'll create a teporary list + set(NEW_LIST) + # Iterate through the old list + foreach(ITEM ${${LIST}}) + # Temporary index position for the new list, as well as temporary value to store if the item was ever found + set(INDEX 0) + set(FOUND FALSE) + # Iterate through the new list + foreach(NEW_ITEM ${NEW_LIST}) + # Compare the items, only if nothing was found before + if(NOT FOUND) + if(NEW_ITEM STRGREATER "${ITEM}") + set(FOUND TRUE) + list(INSERT NEW_LIST ${INDEX} ${ITEM}) + endif(NEW_ITEM STRGREATER "${ITEM}") + endif(NOT FOUND) + # Increase the index value by 1 + math(EXPR INDEX "${INDEX} + 1") + endforeach(NEW_ITEM) + # If the item was never found, just append it to the end + if(NOT FOUND) + append_to_list(NEW_LIST ${ITEM}) + endif(NOT FOUND) + endforeach(ITEM) + # Replace the old list with the new list + set(${LIST} ${NEW_LIST}) + endif(CMAKE244_OR_BETTER) +endmacro(sort_list) + +############################################################################### +# read_from_file(<filename> <regex> <output variable>) +# +# A macro to handle reading specific lines from a file, uses file(STRINGS) if +# using CMake 2.6.x or better, otherwise we read in the entire file and +# perform a string(REGEX MATCH) on each line of the file instead. This +# macro can also be used to read in all the lines of a file if REGEX is set +# to "". +############################################################################### +macro(read_from_file FILE REGEX STRINGS) + if(CMAKE26_OR_BETTER) + # For CMake 2.6.x or better, we can just use the STRINGS sub-command to get the lines that match the given regular expression (if one is given, otherwise get all lines) + if(REGEX STREQUAL "") + file(STRINGS ${FILE} RESULT) + else(REGEX STREQUAL "") + file(STRINGS ${FILE} RESULT REGEX ${REGEX}) + endif(REGEX STREQUAL "") + else(CMAKE26_OR_BETTER) + # For CMake 2.4.x, we need to do this manually, firstly we read the file in + execute_process(COMMAND ${CMAKE_COMMAND} -DFILE:STRING=${FILE} -P ${Anope_SOURCE_DIR}/ReadFile.cmake ERROR_VARIABLE ALL_STRINGS) + # Next we replace all newlines with semicolons + string(REGEX REPLACE "\n" ";" ALL_STRINGS ${ALL_STRINGS}) + if(REGEX STREQUAL "") + # For no regular expression, just set the result to all the lines + set(RESULT ${ALL_STRINGS}) + else(REGEX STREQUAL "") + # Clear the result list + set(RESULT) + # Iterate through all the lines of the file + foreach(STRING ${ALL_STRINGS}) + # Check for a match against the given regular expression + string(REGEX MATCH ${REGEX} STRING_MATCH ${STRING}) + # If we had a match, append the match to the list + if(STRING_MATCH) + append_to_list(RESULT ${STRING}) + endif(STRING_MATCH) + endforeach(STRING) + endif(REGEX STREQUAL "") + endif(CMAKE26_OR_BETTER) + # Set the given STRINGS variable to the result + set(${STRINGS} ${RESULT}) +endmacro(read_from_file) + +############################################################################### +# extract_include_filename(<line> <output variable> [<optional output variable of quote type>]) +# +# This macro will take a #include line and extract the filename. +############################################################################### +macro(extract_include_filename INCLUDE FILENAME) + # Strip the leading and trailing spaces from the include line + strip_string(${INCLUDE} INCLUDE_STRIPPED) + # Make sure to only do the following if there is a string + if(INCLUDE_STRIPPED STREQUAL "") + set(FILE "") + else(INCLUDE_STRIPPED STREQUAL "") + # Extract the filename including the quotes or angle brackets + string(REGEX REPLACE "^.*([\"<].*[\">]).*$" "\\1" FILE "${INCLUDE_STRIPPED}") + # If an optional 3rd argument is given, we'll store if the quote style was quoted or angle bracketed + if(${ARGC} GREATER 2) + string(SUBSTRING ${FILE} 0 1 QUOTE) + if(QUOTE STREQUAL "<") + set(${ARGV2} "angle brackets") + else(QUOTE STREQUAL "<") + set(${ARGV2} "quotes") + endif(QUOTE STREQUAL "<") + endif(${ARGC} GREATER 2) + # Now remove the quotes or angle brackets + string(REGEX REPLACE "^[\"<](.*)[\">]$" "\\1" FILE "${FILE}") + endif(INCLUDE_STRIPPED STREQUAL "") + # Set the filename to the the given variable + set(${FILENAME} "${FILE}") +endmacro(extract_include_filename) + +############################################################################### +# find_includes(<source filename> <output variable>) +# +# This macro will search through a file for #include lines, regardless of +# whitespace, but only returns the lines that are valid for the current +# platform CMake is running on. +############################################################################### +macro(find_includes SRC INCLUDES) + # Read all lines from the file that start with #, regardless of whitespace before the # + read_from_file(${SRC} "^[ \t]*#.*$" LINES) + # Set that any #include lines found are valid, and create temporary variables for the last found #ifdef/#ifndef + set(VALID_LINE TRUE) + set(LAST_DEF) + set(LAST_CHECK) + # Create an empty include list + set(INCLUDES_LIST) + # Iterate through all the # lines + foreach(LINE ${LINES}) + # Search for #ifdef, #ifndef, #else, #endif, and #include + string(REGEX MATCH "^[ \t]*#[ \t]*ifdef[ \t]*.*$" FOUND_IFDEF ${LINE}) + string(REGEX MATCH "^[ \t]*#[ \t]*ifndef[ \t]*.*$" FOUND_IFNDEF ${LINE}) + string(REGEX MATCH "^[ \t]*#[ \t]*else.*$" FOUND_ELSE ${LINE}) + string(REGEX MATCH "^[ \t]*#[ \t]*endif.*$" FOUND_ENDIF ${LINE}) + string(REGEX MATCH "^[ \t]*#[ \t]*include[ \t]*[\"<].*[\">][\ t]*.*$" FOUND_INCLUDE ${LINE}) + # If we found a #ifdef on the line, extract the data after the #ifdef and set if the lines after it are valid based on the variables in CMake + if(FOUND_IFDEF) + # Extract the define + string(REGEX REPLACE "^[ \t]*#[ \t]*ifdef[ \t]*(.*)$" "\\1" DEFINE ${LINE}) + # Replace _WIN32 with WIN32, so we can check if the WIN32 variable of CMake is set instead of _WIN32 + if(DEFINE STREQUAL "_WIN32") + set(DEFINE WIN32) + endif(DEFINE STREQUAL "_WIN32") + # Set the last define to this one, and set the last check to true, so when #else is encountered, we can do an opposing check + set(LAST_DEF ${DEFINE}) + set(LAST_CHECK TRUE) + # If the define is true (it either exists or is a non-false result), the lines following will be checked, otherwise they will be skipped + if(${DEFINE}) + set(VALID_LINE TRUE) + else(${DEFINE}) + set(VALID_LINE FALSE) + endif(${DEFINE}) + else(FOUND_IFDEF) + # If we found a #ifndef on the line, the same thing as #ifdef is done, except with the checks in the opposite direction + if(FOUND_IFNDEF) + # Extract the define + string(REGEX REPLACE "^[ \t]*#[ \t]*ifndef[ \t]*(.*)$" "\\1" DEFINE ${LINE}) + # Replace _WIN32 with WIN32, so we can check if the WIN32 variable of CMake is set instead of _WIN32 + if(DEFINE STREQUAL "_WIN32") + set(DEFINE WIN32) + endif(DEFINE STREQUAL "_WIN32") + # Set the last define to this one, and set the last check to false, so when #else is encountered, we can do an opposing check + set(LAST_DEF ${DEFINE}) + set(LAST_CHECK FALSE) + # If the define is not true (it either doesn't exists or is a false result), the lines following will be checked, otherwise they will be skipped + if(${DEFINE}) + set(VALID_LINE FALSE) + else(${DEFINE}) + set(VALUE_LINE TRUE) + endif(${DEFINE}) + else(FOUND_IFNDEF) + # If we found a #else on the line, we check the last define in the opposite direction + if(FOUND_ELSE) + # When LAST_CHECK is true, we were inside a #ifdef, now act as if we are entering a #ifndef section by doing an opposing check + if(LAST_CHECK) + if(${LAST_DEF}) + set(VALID_LINE FALSE) + else(${LAST_DEF}) + set(VALID_LINE TRUE) + endif(${LAST_DEF}) + # When LAST_CHECK is false, we were inside a #ifndef, now act as if we are entering a #ifdef section by doing an opposing check + else(LAST_CHECK) + if(${LAST_DEF}) + set(VALID_LINE TRUE) + else(${LAST_DEF}) + set(VALID_LINE FALSE) + endif(${LAST_DEF}) + endif(LAST_CHECK) + else(FOUND_ELSE) + # If we found a #endif on the line, we'll assume everything following the line is valid until we meet another one of the above lines + if(FOUND_ENDIF) + set(VALID_LINE TRUE) + else(FOUND_ENDIF) + # If we found a #include on the line, add the entire line to the list of includes unless the line isn't valid + if(FOUND_INCLUDE) + if(VALID_LINE) + append_to_list(INCLUDES_LIST "${LINE}") + endif(VALID_LINE) + endif(FOUND_INCLUDE) + endif(FOUND_ENDIF) + endif(FOUND_ELSE) + endif(FOUND_IFNDEF) + endif(FOUND_IFDEF) + endforeach(LINE) + set(${INCLUDES} ${INCLUDES_LIST}) +endmacro(find_includes) + +############################################################################### +# calculate_depends(<source filename> <output variable set to TRUE on fail> [<optional output variable for includes>]) +# +# This macro is used in most of the src (sub)directories to calculate the +# header file dependencies for the given source file. +############################################################################### +macro(calculate_depends SRC SKIP) + # Temporarily set that we didn't get a 2nd argument before we actually check if we did get one or not + set(CHECK_ANGLE_INCLUDES FALSE) + # Check for a second argument + if(${ARGC} GREATER 1) + set(CHECK_ANGLE_INCLUDES TRUE) + endif(${ARGC} GREATER 1) + # Find all the lines in the given source file that have any form of #include on them, regardless of whitespace, but only if they are valid for the platform we are on + find_includes(${SRC} INCLUDES) + # Reset the list of headers to empty + set(HEADERS) + # Reset skip + set(${SKIP} FALSE) + # Iterate through the strings containing #include (if any) + foreach(INCLUDE ${INCLUDES}) + # Extract the filename from the #include line + extract_include_filename(${INCLUDE} FILENAME QUOTE_TYPE) + if(QUOTE_TYPE STREQUAL "angle brackets") + # The following checks will only be done if there was a request for angle includes to be checked + if(CHECK_ANGLE_INCLUDES) + # Find the path of the include file + if(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR}) + find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include) + else(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR}) + find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME}) + endif(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR}) + # If the include file was found, add it's path to the list of include paths, but only if it doesn't already exist and isn't in the defaults for the compiler + if(FOUND_${FILENAME}_INCLUDE) + find_in_list(DEFAULT_INCLUDE_DIRS "${FOUND_${FILENAME}_INCLUDE}" FOUND_IN_DEFAULTS) + if(FOUND_IN_DEFAULTS EQUAL -1) + find_in_list(${ARGV1} "${FOUND_${FILENAME}_INCLUDE}" FOUND_IN_INCLUDES) + if(FOUND_IN_INCLUDES EQUAL -1) + append_to_list(${ARGV1} "${FOUND_${FILENAME}_INCLUDE}") + endif(FOUND_IN_INCLUDES EQUAL -1) + endif(FOUND_IN_DEFAULTS EQUAL -1) + else(FOUND_${FILENAME}_INCLUDE) + set(${SKIP} TRUE) + message("${SRC} needs header file ${FILENAME} but we were unable to locate that header file! Check that the header file is within the search path of your OS.") + endif(FOUND_${FILENAME}_INCLUDE) + endif(CHECK_ANGLE_INCLUDES) + endif(QUOTE_TYPE STREQUAL "angle brackets") + endforeach(INCLUDE) +endmacro(calculate_depends) + +############################################################################### +# calculate_libraries(<source filename> <output variable set to TRUE on fail> <output variable for linker flags> <output variable for extra depends>) +# +# This macro is used in most of the module (sub)directories to calculate the +# library dependencies for the given source file. +############################################################################### +macro(calculate_libraries SRC SKIP SRC_LDFLAGS EXTRA_DEPENDS) + # Set up a temporary LDFLAGS for this file + set(THIS_LDFLAGS "${LDFLAGS}") + # Reset extra dependencies + set(EXTRA_DEPENDENCIES) + # Reset library paths + set(LIBRARY_PATHS) + # Reset libraries + set(LIBRARIES) + # Default to not skipping this file + set(${SKIP} FALSE) + # Check to see if there are any lines matching: /* RequiredLibraries: [something] */ + read_from_file(${SRC} "/\\\\*[ \t]*RequiredLibraries:[ \t]*.*[ \t]*\\\\*/" REQUIRED_LIBRARIES) + # Iterate through those lines + foreach(REQUIRED_LIBRARY ${REQUIRED_LIBRARIES}) + # Strip off the /* RequiredLibraries: and */ from the line + string(REGEX REPLACE "/\\*[ \t]*RequiredLibraries:[ \t]*([^ \t]*)[ \t]*\\*/" "\\1" REQUIRED_LIBRARY ${REQUIRED_LIBRARY}) + # Replace all commas with semicolons + string(REGEX REPLACE "," ";" REQUIRED_LIBRARY ${REQUIRED_LIBRARY}) + # Iterate through the libraries given + foreach(LIBRARY ${REQUIRED_LIBRARY}) + # Locate the library to see if it exists + if(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR}) + find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib) + else(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR}) + find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY}) + endif(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR}) + # If the library was found, we will add it to the linker flags + if(FOUND_${LIBRARY}_LIBRARY) + # Get the path only of the library, to add it to linker flags + get_filename_component(LIBRARY_PATH ${FOUND_${LIBRARY}_LIBRARY} PATH) + if(MSVC) + # For Visual Studio, instead of editing the linker flags, we'll add the library to a separate list of extra dependencies + append_to_list(EXTRA_DEPENDENCIES "${FOUND_${LIBRARY}_LIBRARY}") + else(MSVC) + # For all others, add the library paths and libraries + append_to_list(LIBRARY_PATHS "${LIBRARY_PATH}") + append_to_list(LIBRARIES "${LIBRARY}") + endif(MSVC) + else(FOUND_${LIBRARY}_LIBRARY) + # Skip this file + set(${SKIP} TRUE) + # In the case of the library not being found, we fatally error so CMake stops trying to generate + message("${SRC} needs library ${LIBRARY} but we were unable to locate that library! Check that the library is within the search path of your OS.") + endif(FOUND_${LIBRARY}_LIBRARY) + endforeach(LIBRARY) + endforeach(REQUIRED_LIBRARY) + if(NOT ${SKIP}) + # Remove duplicates from the library paths + if(LIBRARY_PATHS) + remove_list_duplicates(LIBRARY_PATHS) + endif(LIBRARY_PATHS) + # Remove diplicates from the libraries + if(LIBRARIES) + remove_list_duplicates(LIBRARIES) + endif(LIBRARIES) + # Iterate through library paths and add them to the linker flags + foreach(LIBRARY_PATH ${LIBRARY_PATHS}) + find_in_list(DEFAULT_LIBRARY_DIRS "${LIBRARY_PATH}" FOUND_IN_DEFAULTS) + if(FOUND_IN_DEFAULTS EQUAL -1) + set(THIS_LDFLAGS "${THIS_LDFLAGS} -L${LIBRARY_PATH}") + endif(FOUND_IN_DEFAULTS EQUAL -1) + endforeach(LIBRARY_PATH) + # Iterate through libraries and add them to the linker flags + foreach(LIBRARY ${LIBRARIES}) + set(THIS_LDFLAGS "${THIS_LDFLAGS} -l${LIBRARY}") + endforeach(LIBRARY) + set(${SRC_LDFLAGS} "${THIS_LDFLAGS}") + set(${EXTRA_DEPENDS} "${EXTRA_DEPENDENCIES}") + endif(NOT ${SKIP}) +endmacro(calculate_libraries) + +############################################################################### +# check_functions(<source filename> <output variable set to TRUE on success>) +# +# This macro is used in most of the module (sub)directories to calculate the +# fcuntion dependencies for the given source file. +############################################################################### +macro(check_functions SRC SUCCESS) + # Default to true + set(${SUCCESS} TRUE) + # Check to see if there are any lines matching: /* RequiredFunctions: [something] */ + read_from_file(${SRC} "/\\\\*[ \t]*RequiredFunctions:[ \t]*.*[ \t]*\\\\*/" REQUIRED_FUNCTIONS) + # Iterate through those lines + foreach(REQUIRED_FUNCTION ${REQUIRED_FUNCTIONS}) + # Strip off the /* RequiredFunctions: and */ from the line + string(REGEX REPLACE "/\\*[ \t]*RequiredFunctions:[ \t]*([^ \t]*)[ \t]*\\*/" "\\1" REQUIRED_FUNCTION ${REQUIRED_FUNCTION}) + # Replace all commas with semicolons + string(REGEX REPLACE "," ";" REQUIRED_FUNCTION ${REQUIRED_FUNCTION}) + # Iterate through the functions given + foreach(FUNCTION ${REQUIRED_FUNCTION}) + # Check if the function exists + check_function_exists(${REQUIRED_FUNCTION} HAVE_${REQUIRED_FUNCTION}) + # If we don't have the function warn the user and set SUCCESS to FALSE + if(NOT HAVE_${REQUIRED_FUNCTION}) + message("${SRC} needs function ${REQUIRED_FUNCTION} but we were unable to locate that function!") + set(${SUCCESS} FALSE) + endif(NOT HAVE_${REQUIRED_FUNCTION}) + endforeach(FUNCTION) + endforeach(REQUIRED_FUNCTION) +endmacro(check_functions) + +############################################################################### +# add_to_cpack_ignored_files(<item> [TRUE]) +# +# A macro to update the environment variable CPACK_IGNORED_FILES which +# contains a list of files for CPack to ignore. If the optional 2nd argument +# of TRUE is given, periods will be converted to \\. for CPack. +############################################################################### +macro(add_to_cpack_ignored_files ITEM) + # Temporary copy of the orignal item + set(REAL_ITEM "${ITEM}") + # If we have 2+ arguments, assume that the second one was something like TRUE (doesn't matter really) and convert periods so they will be \\. for CPack + if(${ARGC} GREATER 1) + string(REPLACE "." "\\\\." REAL_ITEM ${REAL_ITEM}) + endif(${ARGC} GREATER 1) + # If the environment variable is already defined, just tack the item to the end + if(DEFINED ENV{CPACK_IGNORED_FILES}) + set(ENV{CPACK_IGNORED_FILES} "$ENV{CPACK_IGNORED_FILES};${REAL_ITEM}") + # Otherwise set the environment variable to the item + else(DEFINED ENV{CPACK_IGNORED_FILES}) + set(ENV{CPACK_IGNORED_FILES} "${REAL_ITEM}") + endif(DEFINED ENV{CPACK_IGNORED_FILES}) +endmacro(add_to_cpack_ignored_files) diff --git a/cmake/NSIS.template.in b/cmake/NSIS.template.in new file mode 100644 index 000000000..a9c91a2b7 --- /dev/null +++ b/cmake/NSIS.template.in @@ -0,0 +1,825 @@ +; CPack install script designed for a nmake build + +;-------------------------------- +; You must define these values + + !define VERSION "@CPACK_PACKAGE_VERSION@" + !define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@" + +;-------------------------------- +;Variables + + Var MUI_TEMP + Var STARTMENU_FOLDER + Var SV_ALLUSERS + Var START_MENU + Var DO_NOT_ADD_TO_PATH + Var ADD_TO_PATH_ALL_USERS + Var ADD_TO_PATH_CURRENT_USER + Var INSTALL_DESKTOP + +;-------------------------------- +;Include Modern UI + + !include "MUI2.nsh" + + ;Default installation folder + InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + +;-------------------------------- +;General + + ;Name and file + Name "@CPACK_PACKAGE_NAME@ @CPACK_PACKAGE_VERSION@" + OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@" + + ;Set compression + SetCompressor @CPACK_NSIS_COMPRESSOR@ + +@CPACK_NSIS_DEFINES@ + + !include Sections.nsh + +;--- Component support macros: --- +; The code for the add/remove functionality is from: +; http://nsis.sourceforge.net/Add/Remove_Functionality +; It has been modified slightly and extended to provide +; inter-component dependencies. +Var AR_SecFlags +Var AR_RegFlags +@CPACK_NSIS_SECTION_SELECTED_VARS@ + +; Loads the "selected" flag for the section named SecName into the +; variable VarName. +!macro LoadSectionSelectedIntoVar SecName VarName + SectionGetFlags ${${SecName}} $${VarName} + IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits +!macroend + +; Loads the value of a variable... can we get around this? +!macro LoadVar VarName + IntOp $R0 0 + $${VarName} +!macroend + +; Sets the value of a variable +!macro StoreVar VarName IntValue + IntOp $${VarName} 0 + ${IntValue} +!macroend + +!macro InitSection SecName + ; This macro reads component installed flag from the registry and + ;changes checked state of the section on the components page. + ;Input: section index constant name specified in Section command. + + ClearErrors + ;Reading component status from registry + ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" "Installed" + IfErrors "default_${SecName}" + ;Status will stay default if registry value not found + ;(component was never installed) + IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags + IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off + IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit + + ; Note whether this component was installed before + !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags + IntOp $R0 $AR_RegFlags & $AR_RegFlags + + ;Writing modified flags + SectionSetFlags ${${SecName}} $AR_SecFlags + + "default_${SecName}:" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected +!macroend + +!macro FinishSection SecName + ; This macro reads section flag set by user and removes the section + ;if it is not selected. + ;Then it writes component installed flag to registry + ;Input: section index constant name specified in Section command. + + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags + ;Checking lowest bit: + IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED} + IntCmp $AR_SecFlags 1 "leave_${SecName}" + ;Section is not selected: + ;Calling Section uninstall macro and writing zero installed flag + !insertmacro "Remove_${${SecName}}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \ + "Installed" 0 + Goto "exit_${SecName}" + + "leave_${SecName}:" + ;Section is selected: + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \ + "Installed" 1 + + "exit_${SecName}:" +!macroend + +!macro RemoveSection SecName + ; This macro is used to call section's Remove_... macro + ;from the uninstaller. + ;Input: section index constant name specified in Section command. + + !insertmacro "Remove_${${SecName}}" +!macroend + +; Determine whether the selection of SecName changed +!macro MaybeSelectionChanged SecName + !insertmacro LoadVar ${SecName}_selected + SectionGetFlags ${${SecName}} $R1 + IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits + + ; See if the status has changed: + IntCmp $R0 $R1 "${SecName}_unchanged" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected + + IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected" + !insertmacro "Deselect_required_by_${SecName}" + goto "${SecName}_unchanged" + + "${SecName}_was_selected:" + !insertmacro "Select_${SecName}_depends" + + "${SecName}_unchanged:" +!macroend +;--- End of Add/Remove macros --- + +;-------------------------------- +;Interface Settings + + !define MUI_ABORTWARNING + +;---------------------------------------- +; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02" +;---------------------------------------- +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 + +;==================================================== +; get_NT_environment +; Returns: the selected environment +; Output : head of the stack +;==================================================== +!macro select_NT_profile UN +Function ${UN}select_NT_profile + StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single + DetailPrint "Selected environment for all users" + Push "all" + Return + environment_single: + DetailPrint "Selected environment for current user only." + Push "current" + Return +FunctionEnd +!macroend +!insertmacro select_NT_profile "" +!insertmacro select_NT_profile "un." +;---------------------------------------------------- +!define NT_current_env 'HKCU "Environment"' +!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + +!ifndef WriteEnvStr_RegKey + !ifdef ALL_USERS + !define WriteEnvStr_RegKey \ + 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + !else + !define WriteEnvStr_RegKey 'HKCU "Environment"' + !endif +!endif + +; AddToPath - Adds the given dir to the search path. +; Input - head of the stack +; Note - Win9x systems requires reboot + +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + + # don't add if the path doesn't exist + IfFileExists "$0\*.*" "" AddToPath_done + + ReadEnvStr $1 PATH + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + GetFullPathName /SHORT $3 $0 + Push "$1;" + Push "$3;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$3\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + + Call IsNT + Pop $1 + StrCmp $1 1 AddToPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 -1 END + FileReadByte $1 $2 + IntCmp $2 26 0 +2 +2 # DOS EOF + FileSeek $1 -1 END # write over EOF + FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" + FileClose $1 + SetRebootFlag true + Goto AddToPath_done + + AddToPath_NT: + ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" + StrCmp $1 "" AddToPath_NTdoIt + Push $1 + Call Trim + Pop $1 + StrCpy $0 "$1;$0" + AddToPath_NTdoIt: + WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $0 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + AddToPath_done: + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + +; RemoveFromPath - Remove a given dir from the path +; Input: head of the stack + +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + IntFmt $6 "%c" 26 # DOS EOF + + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCpy $5 $3 1 -1 # read last char + StrCmp $5 $6 0 +2 # if DOS EOF + StrCpy $3 $3 -1 # remove DOS EOF so we can compare + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + unRemoveFromPath_dosLoopRemoveLine: + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 ";" +2 # if last char != ; + StrCpy $1 "$1;" # append ; + Push $1 + Push "$0;" + Call un.StrStr ; Find `$0;` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 ";" 0 +2 # if last char == ; + StrCpy $3 $3 -1 # remove last char + + WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $3 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Uninstall sutff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +########################################### +# Utility Functions # +########################################### + +;==================================================== +; IsNT - Returns 1 if the current system is NT, 0 +; otherwise. +; Output: head of the stack +;==================================================== +; IsNT +; no input +; output, top of the stack = 1 if NT or 0 if not +; +; Usage: +; Call IsNT +; Pop $R0 +; ($R0 at this point is 1 or 0) + +!macro IsNT un +Function ${un}IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd +!macroend +!insertmacro IsNT "" +!insertmacro IsNT "un." + +; StrStr +; input, top of stack = string to search for +; top of stack-1 = string to search in +; output, top of stack (replaces with the portion of the string remaining) +; modifies no other variables. +; +; Usage: +; Push "this is a long ass string" +; Push "ass" +; Call StrStr +; Pop $R0 +; ($R0 at this point is "ass string") + +!macro StrStr un +Function ${un}StrStr +Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop +done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd +!macroend +!insertmacro StrStr "" +!insertmacro StrStr "un." + +Function Trim ; Added by Pelaca + Exch $R1 + Push $R2 +Loop: + StrCpy $R2 "$R1" 1 -1 + StrCmp "$R2" " " RTrim + StrCmp "$R2" "$\n" RTrim + StrCmp "$R2" "$\r" RTrim + StrCmp "$R2" ";" RTrim + GoTo Done +RTrim: + StrCpy $R1 "$R1" -1 + Goto Loop +Done: + Pop $R2 + Exch $R1 +FunctionEnd + +Function ConditionalAddToRegisty + Pop $0 + Pop $1 + StrCmp "$0" "" ConditionalAddToRegisty_EmptyString + WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" \ + "$1" "$0" + ;MessageBox MB_OK "Set Registry: '$1' to '$0'" + DetailPrint "Set install registry entry: '$1' to '$0'" + ConditionalAddToRegisty_EmptyString: +FunctionEnd + +;-------------------------------- + +!ifdef CPACK_USES_DOWNLOAD +Function DownloadFile + IfFileExists $INSTDIR\* +2 + CreateDirectory $INSTDIR + Pop $0 + + ; Skip if already downloaded + IfFileExists $INSTDIR\$0 0 +2 + Return + + StrCpy $1 "@CPACK_DOWNLOAD_SITE@" + + try_again: + NSISdl::download "$1/$0" "$INSTDIR\$0" + + Pop $1 + StrCmp $1 "success" success + StrCmp $1 "Cancelled" cancel + MessageBox MB_OK "Download failed: $1" + cancel: + Return + success: +FunctionEnd +!endif + +;-------------------------------- +; Installation types +@CPACK_NSIS_INSTALLATION_TYPES@ + +;-------------------------------- +; Component sections +@CPACK_NSIS_COMPONENT_SECTIONS@ + +;-------------------------------- +; Define some macro setting for the gui +@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ +@CPACK_NSIS_INSTALLER_ICON_CODE@ +@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ + +;-------------------------------- +;Pages + !define MUI_LANGDLL_REGISTRY_ROOT "SHCTX" + !define MUI_LANGDLL_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" + !define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language" + + !insertmacro MUI_PAGE_WELCOME + + !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page Configuration + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + + @CPACK_NSIS_PAGE_COMPONENTS@ + + !insertmacro MUI_PAGE_INSTFILES + + !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\docs\README.txt" + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "English" + !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "German" + !insertmacro MUI_LANGUAGE "Italian" + !insertmacro MUI_LANGUAGE "Portuguese" + !insertmacro MUI_LANGUAGE "Spanish" + +;-------------------------------- +;Installer Sections + +Section "-Core installation" + ;Use the entire tree produced by the INSTALL target. Keep the + ;list of directories here in sync with the RMDir commands below. + SetOutPath "$INSTDIR" + @CPACK_NSIS_FULL_INSTALL@ + + ;Store installation folder + WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + + ;Create uninstaller + WriteUninstaller "$INSTDIR\Uninstall.exe" + Push "DisplayName" + Push "@CPACK_NSIS_DISPLAY_NAME@" + Call ConditionalAddToRegisty + Push "DisplayVersion" + Push "@CPACK_PACKAGE_VERSION@" + Call ConditionalAddToRegisty + Push "Publisher" + Push "@CPACK_PACKAGE_VENDOR@" + Call ConditionalAddToRegisty + Push "UninstallString" + Push "$INSTDIR\Uninstall.exe" + Call ConditionalAddToRegisty + Push "NoRepair" + Push "1" + Call ConditionalAddToRegisty + + !ifdef CPACK_NSIS_ADD_REMOVE + ;Create add/remove functionality + Push "ModifyPath" + Push "$INSTDIR\AddRemove.exe" + Call ConditionalAddToRegisty + !else + Push "NoModify" + Push "1" + Call ConditionalAddToRegisty + !endif + + ; Optional registration + Push "DisplayIcon" + Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@" + Call ConditionalAddToRegisty + Push "HelpLink" + Push "@CPACK_NSIS_HELP_LINK@" + Call ConditionalAddToRegisty + Push "URLInfoAbout" + Push "@CPACK_NSIS_URL_INFO_ABOUT@" + Call ConditionalAddToRegisty + Push "Contact" + Push "@CPACK_NSIS_CONTACT@" + Call ConditionalAddToRegisty + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + + ;Create shortcuts + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" +@CPACK_NSIS_CREATE_ICONS@ +@CPACK_NSIS_CREATE_ICONS_EXTRA@ + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" + + ; Write special uninstall registry entries + Push "StartMenu" + Push "$STARTMENU_FOLDER" + Call ConditionalAddToRegisty + Push "DoNotAddToPath" + Push "$DO_NOT_ADD_TO_PATH" + Call ConditionalAddToRegisty + Push "AddToPathAllUsers" + Push "$ADD_TO_PATH_ALL_USERS" + Call ConditionalAddToRegisty + Push "AddToPathCurrentUser" + Push "$ADD_TO_PATH_CURRENT_USER" + Call ConditionalAddToRegisty + Push "InstallToDesktop" + Push "$INSTALL_DESKTOP" + Call ConditionalAddToRegisty + +@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@ + + !insertmacro MUI_STARTMENU_WRITE_END + +SectionEnd + +;-------------------------------- +; determine admin versus local install +Function un.onInit + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + Goto done + StrCmp $1 "Power" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + Goto done + + noLM: + ;Get installation folder from registry if available + + done: + + !insertmacro MUI_UNGETLANGUAGE +FunctionEnd + +;--- Add/Remove callback functions: --- +!macro SectionList MacroName + ;This macro used to perform operation on multiple sections. + ;List all of your components in following manner here. +@CPACK_NSIS_COMPONENT_SECTION_LIST@ +!macroend + +Section -FinishComponents + ;Removes unselected components and writes component status to registry + !insertmacro SectionList "FinishSection" + +!ifdef CPACK_NSIS_ADD_REMOVE + ; Get the name of the installer executable + System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1' + StrCpy $R3 $R0 + + ; Strip off the last 13 characters, to see if we have AddRemove.exe + StrLen $R1 $R0 + IntOp $R1 $R0 - 13 + StrCpy $R2 $R0 13 $R1 + StrCmp $R2 "AddRemove.exe" addremove_installed + + ; We're not running AddRemove.exe, so install it + CopyFiles $R3 $INSTDIR\AddRemove.exe + + addremove_installed: +!endif +SectionEnd +;--- End of Add/Remove callback functions --- + +;-------------------------------- +; Component dependencies +Function .onSelChange + !insertmacro SectionList MaybeSelectionChanged +FunctionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + ReadRegStr $START_MENU SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "StartMenu" + ;MessageBox MB_OK "Start menu is in: $START_MENU" + ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "DoNotAddToPath" + ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathAllUsers" + ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathCurrentUser" + ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS" + ReadRegStr $INSTALL_DESKTOP SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "InstallToDesktop" + ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " + +@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + + ;Remove files we installed. + ;Keep the list of directories here in sync with the File commands above. +@CPACK_NSIS_DELETE_FILES@ +@CPACK_NSIS_DELETE_DIRECTORIES@ + +!ifdef CPACK_NSIS_ADD_REMOVE + ;Remove the add/remove program + Delete "$INSTDIR\AddRemove.exe" +!endif + + ;Remove the uninstaller itself. + Delete "$INSTDIR\Uninstall.exe" + DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" + + ;Remove the installation directory if it is empty. + RMDir "$INSTDIR" + + ; Remove the registry entries. + DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ; Removes all optional components + !insertmacro SectionList "RemoveSection" + + !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + startMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors startMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + ; If the user changed the shortcut, then untinstall may not work. This should + ; try to fix it. + StrCpy $MUI_TEMP "$START_MENU" + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + secondStartMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors secondStartMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop + secondStartMenuDeleteLoopDone: + + DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + Push $INSTDIR\bin + StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 + Call un.RemoveFromPath + doNotRemoveFromPath: +SectionEnd + +;-------------------------------- +; determine admin versus local install +; Is install for "AllUsers" or "JustMe"? +; Default to "JustMe" - set to "AllUsers" if admin or on Win9x +; This function is used for the very first "custom page" of the installer. +; This custom page does not show up visibly, but it executes prior to the +; first visible page and sets up $INSTDIR properly... +; Choose different default installation folder based on SV_ALLUSERS... +; "Program Files" for AllUsers, "My Documents" for JustMe... + +Function .onInit + !insertmacro MUI_LANGDLL_DISPLAY + ; Reads components status for registry + !insertmacro SectionList "InitSection" + + StrCpy $SV_ALLUSERS "JustMe" + StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + StrCmp $1 "Power" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + + noLM: + StrCpy $SV_ALLUSERS "AllUsers" + ;Get installation folder from registry if available + + done: + StrCmp $SV_ALLUSERS "AllUsers" 0 +2 + StrCpy $INSTDIR "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + +FunctionEnd diff --git a/cmake/ReadFile.cmake b/cmake/ReadFile.cmake new file mode 100644 index 000000000..be60f1fa7 --- /dev/null +++ b/cmake/ReadFile.cmake @@ -0,0 +1,5 @@ +# This file is external to the read_from_file macro in Anope.cmake in order to +# get around a possible memory leak in older versions of CMake. + +file(READ "${FILE}" RESULT) +message("${RESULT}") |