summaryrefslogtreecommitdiffstats
path: root/project/cmake/scripts/common
diff options
context:
space:
mode:
Diffstat (limited to 'project/cmake/scripts/common')
-rw-r--r--project/cmake/scripts/common/addon-helpers.cmake80
-rw-r--r--project/cmake/scripts/common/archsetup.cmake99
-rw-r--r--project/cmake/scripts/common/checkcommits.cmake75
-rw-r--r--project/cmake/scripts/common/generateversionedfiles.cmake13
-rw-r--r--project/cmake/scripts/common/generatorsetup.cmake24
-rw-r--r--project/cmake/scripts/common/macros.cmake373
-rw-r--r--project/cmake/scripts/common/managestring.cmake235
-rw-r--r--project/cmake/scripts/common/pathsetup.cmake3
-rw-r--r--project/cmake/scripts/common/prepare-env.cmake33
-rw-r--r--project/cmake/scripts/common/projectmacros.cmake84
10 files changed, 995 insertions, 24 deletions
diff --git a/project/cmake/scripts/common/addon-helpers.cmake b/project/cmake/scripts/common/addon-helpers.cmake
index b94df2a..9541df4 100644
--- a/project/cmake/scripts/common/addon-helpers.cmake
+++ b/project/cmake/scripts/common/addon-helpers.cmake
@@ -10,13 +10,23 @@ add_custom_target(addon-package
10 COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target package) 10 COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target package)
11 11
12macro(add_cpack_workaround target version ext) 12macro(add_cpack_workaround target version ext)
13 if(NOT PACKAGE_DIR)
14 set(PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}/zips")
15 endif()
16
13 add_custom_command(TARGET addon-package PRE_BUILD 17 add_custom_command(TARGET addon-package PRE_BUILD
14 COMMAND ${CMAKE_COMMAND} -E rename addon-${target}-${version}.${ext} ${target}-${version}.${ext}) 18 COMMAND ${CMAKE_COMMAND} -E make_directory ${PACKAGE_DIR}
19 COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_PACKAGE_DIRECTORY}/addon-${target}-${version}.${ext} ${PACKAGE_DIR}/${target}-${version}.${ext})
15endmacro() 20endmacro()
16 21
17# Grab the version from a given add-on's addon.xml 22# Grab the version from a given add-on's addon.xml
18macro (addon_version dir prefix) 23macro (addon_version dir prefix)
19 FILE(READ ${dir}/addon.xml ADDONXML) 24 IF(EXISTS ${PROJECT_SOURCE_DIR}/${dir}/addon.xml.in)
25 FILE(READ ${PROJECT_SOURCE_DIR}/${dir}/addon.xml.in ADDONXML)
26 ELSE()
27 FILE(READ ${dir}/addon.xml ADDONXML)
28 ENDIF()
29
20 STRING(REGEX MATCH "<addon[^>]*version.?=.?.[0-9\\.]+" VERSION_STRING ${ADDONXML}) 30 STRING(REGEX MATCH "<addon[^>]*version.?=.?.[0-9\\.]+" VERSION_STRING ${ADDONXML})
21 STRING(REGEX REPLACE ".*version=.([0-9\\.]+).*" "\\1" ${prefix}_VERSION ${VERSION_STRING}) 31 STRING(REGEX REPLACE ".*version=.([0-9\\.]+).*" "\\1" ${prefix}_VERSION ${VERSION_STRING})
22 message(STATUS ${prefix}_VERSION=${${prefix}_VERSION}) 32 message(STATUS ${prefix}_VERSION=${${prefix}_VERSION})
@@ -34,6 +44,25 @@ macro (build_addon target prefix libs)
34 SET_TARGET_PROPERTIES(${target} PROPERTIES PREFIX "lib") 44 SET_TARGET_PROPERTIES(${target} PROPERTIES PREFIX "lib")
35 ENDIF(OS STREQUAL "android") 45 ENDIF(OS STREQUAL "android")
36 46
47 # get the library's location
48 SET(LIBRARY_LOCATION $<TARGET_FILE:${target}>)
49 # get the library's filename
50 if("${CORE_SYSTEM_NAME}" STREQUAL "android")
51 # for android we need the filename without any version numbers
52 set(LIBRARY_FILENAME $<TARGET_LINKER_FILE_NAME:${target}>)
53 else()
54 SET(LIBRARY_FILENAME $<TARGET_FILE_NAME:${target}>)
55 endif()
56
57 # if there's an addon.xml.in we need to generate the addon.xml
58 IF(EXISTS ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in)
59 SET(PLATFORM ${CORE_SYSTEM_NAME})
60
61 FILE(READ ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in addon_file)
62 STRING(CONFIGURE "${addon_file}" addon_file_conf @ONLY)
63 FILE(GENERATE OUTPUT ${PROJECT_SOURCE_DIR}/${target}/addon.xml CONTENT "${addon_file_conf}")
64 ENDIF()
65
37 # set zip as default if addon-package is called without PACKAGE_XXX 66 # set zip as default if addon-package is called without PACKAGE_XXX
38 SET(CPACK_GENERATOR "ZIP") 67 SET(CPACK_GENERATOR "ZIP")
39 SET(ext "zip") 68 SET(ext "zip")
@@ -51,33 +80,62 @@ macro (build_addon target prefix libs)
51 set(CPACK_COMPONENTS_IGNORE_GROUPS 1) 80 set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
52 list(APPEND CPACK_COMPONENTS_ALL ${target}-${${prefix}_VERSION}) 81 list(APPEND CPACK_COMPONENTS_ALL ${target}-${${prefix}_VERSION})
53 # Pack files together to create an archive 82 # Pack files together to create an archive
54 INSTALL(DIRECTORY ${target} DESTINATION ./ COMPONENT ${target}-${${prefix}_VERSION}) 83 INSTALL(DIRECTORY ${target} DESTINATION ./ COMPONENT ${target}-${${prefix}_VERSION} PATTERN "addon.xml.in" EXCLUDE)
55 IF(WIN32) 84 IF(WIN32)
56 # get the installation location for the addon's target 85 if(NOT CPACK_PACKAGE_DIRECTORY)
57 get_property(dll_location TARGET ${target} PROPERTY LOCATION) 86 # determine the temporary path
87 file(TO_CMAKE_PATH "$ENV{TEMP}" WIN32_TEMP_PATH)
88 string(LENGTH "${WIN32_TEMP_PATH}" WIN32_TEMP_PATH_LENGTH)
89 string(LENGTH "${PROJECT_BINARY_DIR}" PROJECT_BINARY_DIR_LENGTH)
90
91 # check if the temporary path is shorter than the default packaging directory path
92 if(WIN32_TEMP_PATH_LENGTH GREATER 0 AND WIN32_TEMP_PATH_LENGTH LESS PROJECT_BINARY_DIR_LENGTH)
93 # set the directory used by CPack for packaging to the temp directory
94 set(CPACK_PACKAGE_DIRECTORY ${WIN32_TEMP_PATH})
95 endif()
96 endif()
97
58 # in case of a VC++ project the installation location contains a $(Configuration) VS variable 98 # in case of a VC++ project the installation location contains a $(Configuration) VS variable
59 # we replace it with ${CMAKE_BUILD_TYPE} (which doesn't cover the case when the build configuration 99 # we replace it with ${CMAKE_BUILD_TYPE} (which doesn't cover the case when the build configuration
60 # is changed within Visual Studio) 100 # is changed within Visual Studio)
61 string(REPLACE "$(Configuration)" "${CMAKE_BUILD_TYPE}" dll_location "${dll_location}") 101 string(REPLACE "$(Configuration)" "${CMAKE_BUILD_TYPE}" LIBRARY_LOCATION "${LIBRARY_LOCATION}")
62 102
63 # install the generated DLL file 103 # install the generated DLL file
64 INSTALL(PROGRAMS ${dll_location} DESTINATION ${target} 104 INSTALL(PROGRAMS ${LIBRARY_LOCATION} DESTINATION ${target}
65 COMPONENT ${target}-${${prefix}_VERSION}) 105 COMPONENT ${target}-${${prefix}_VERSION})
66 106
67 IF(CMAKE_BUILD_TYPE MATCHES Debug) 107 IF(CMAKE_BUILD_TYPE MATCHES Debug)
68 # for debug builds also install the PDB file 108 # for debug builds also install the PDB file
69 get_filename_component(dll_directory ${dll_location} DIRECTORY) 109 get_filename_component(LIBRARY_DIR ${LIBRARY_LOCATION} DIRECTORY)
70 INSTALL(FILES ${dll_directory}/${target}.pdb DESTINATION ${target} 110 INSTALL(FILES ${LIBRARY_DIR}/${target}.pdb DESTINATION ${target}
71 COMPONENT ${target}-${${prefix}_VERSION}) 111 COMPONENT ${target}-${${prefix}_VERSION})
72 ENDIF() 112 ENDIF()
73 ELSE(WIN32) 113 ELSE(WIN32)
114 if(NOT CPACK_PACKAGE_DIRECTORY)
115 set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR})
116 endif()
74 INSTALL(TARGETS ${target} DESTINATION ${target} 117 INSTALL(TARGETS ${target} DESTINATION ${target}
75 COMPONENT ${target}-${${prefix}_VERSION}) 118 COMPONENT ${target}-${${prefix}_VERSION})
76 ENDIF(WIN32) 119 ENDIF(WIN32)
77 add_cpack_workaround(${target} ${${prefix}_VERSION} ${ext}) 120 add_cpack_workaround(${target} ${${prefix}_VERSION} ${ext})
78 ELSE(PACKAGE_ZIP OR PACKAGE_TGZ) 121 ELSE(PACKAGE_ZIP OR PACKAGE_TGZ)
79 INSTALL(TARGETS ${target} DESTINATION lib/kodi/addons/${target}) 122 if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
80 INSTALL(DIRECTORY ${target} DESTINATION share/kodi/addons) 123 if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR NOT CMAKE_INSTALL_PREFIX)
124 message(STATUS "setting install paths to match ${APP_NAME}: CMAKE_INSTALL_PREFIX: ${${APP_NAME_UC}_PREFIX}")
125 set(CMAKE_INSTALL_PREFIX "${${APP_NAME_UC}_PREFIX}" CACHE PATH "${APP_NAME} install prefix" FORCE)
126 set(CMAKE_INSTALL_LIBDIR "${${APP_NAME_UC}_LIB_DIR}" CACHE PATH "${APP_NAME} install libdir" FORCE)
127 elseif(NOT CMAKE_INSTALL_PREFIX STREQUAL "${${APP_NAME_UC}_PREFIX}" AND NOT OVERRIDE_PATHS)
128 message(FATAL_ERROR "CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} differs from ${APP_NAME} prefix ${${APP_NAME_UC}_PREFIX}. Please pass -DOVERRIDE_PATHS=1 to skip this check")
129 else()
130 if(NOT CMAKE_INSTALL_LIBDIR)
131 set(CMAKE_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib/${APP_NAME_LC}")
132 endif()
133 endif()
134 else()
135 set(CMAKE_INSTALL_LIBDIR "lib/${APP_NAME_LC}")
136 endif()
137 INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}/addons/${target})
138 INSTALL(DIRECTORY ${target} DESTINATION share/${APP_NAME_LC}/addons PATTERN "addon.xml.in" EXCLUDE)
81 ENDIF(PACKAGE_ZIP OR PACKAGE_TGZ) 139 ENDIF(PACKAGE_ZIP OR PACKAGE_TGZ)
82endmacro() 140endmacro()
83 141
diff --git a/project/cmake/scripts/common/archsetup.cmake b/project/cmake/scripts/common/archsetup.cmake
new file mode 100644
index 0000000..dff5558
--- /dev/null
+++ b/project/cmake/scripts/common/archsetup.cmake
@@ -0,0 +1,99 @@
1# This script configures the build for a given architecture.
2# Flags and stringified arch is set up.
3# General compiler tests belongs here.
4#
5# On return, the following variables are set:
6# CMAKE_SYSTEM_NAME - a lowercased system name
7# CPU - the CPU on the target
8# ARCH - the system architecture
9# ARCH_DEFINES - list of compiler definitions for this architecture
10# SYSTEM_DEFINES - list of compiler definitions for this system
11# DEP_DEFINES - compiler definitions for system dependencies (e.g. LIRC)
12# + the results of compiler tests etc.
13
14include(CheckCXXSourceCompiles)
15include(CheckSymbolExists)
16include(CheckFunctionExists)
17
18# Macro to check if a given type exists in a given header
19# Arguments:
20# header the header to check
21# type the type to check for existence
22# var the compiler definition to set if type exists
23# On return:
24# If type was found, the definition is added to SYSTEM_DEFINES
25macro(check_type header type var)
26 check_cxx_source_compiles("#include <${header}>
27 int main()
28 {
29 ${type} s;
30 }" ${var})
31 if(${var})
32 list(APPEND SYSTEM_DEFINES -D${var}=1)
33 endif()
34endmacro()
35
36# Macro to check if a given builtin function exists
37# Arguments:
38# func the function to check
39# var the compiler definition to set if type exists
40# On return:
41# If type was found, the definition is added to SYSTEM_DEFINES
42macro(check_builtin func var)
43 check_cxx_source_compiles("
44 int main()
45 {
46 ${func};
47 }" ${var})
48 if(${var})
49 list(APPEND SYSTEM_DEFINES -D${var}=1)
50 endif()
51endmacro()
52
53
54# -------- Main script ---------
55message(STATUS "System type: ${CMAKE_SYSTEM_NAME}")
56if(NOT CORE_SYSTEM_NAME)
57 string(TOLOWER ${CMAKE_SYSTEM_NAME} CORE_SYSTEM_NAME)
58endif()
59
60if(WITH_CPU)
61 set(CPU ${WITH_CPU})
62elseif(NOT CMAKE_TOOLCHAIN_FILE)
63 set(CPU ${CMAKE_SYSTEM_PROCESSOR})
64endif()
65
66if(CMAKE_TOOLCHAIN_FILE)
67 if(NOT EXISTS "${CMAKE_TOOLCHAIN_FILE}")
68 message(FATAL_ERROR "Toolchain file ${CMAKE_TOOLCHAIN_FILE} does not exist.")
69 elseif(NOT DEPENDS_PATH OR NOT NATIVEPREFIX)
70 message(FATAL_ERROR "Toolchain did not define DEPENDS_PATH or NATIVEPREFIX. Possibly outdated depends.")
71 endif()
72endif()
73
74# Main cpp
75set(CORE_MAIN_SOURCE ${CORE_SOURCE_DIR}/xbmc/platform/posix/main.cpp)
76
77# system specific arch setup
78include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/archsetup.cmake)
79
80message(STATUS "Core system type: ${CORE_SYSTEM_NAME}")
81message(STATUS "Platform: ${PLATFORM}")
82message(STATUS "CPU: ${CPU}, ARCH: ${ARCH}")
83
84check_type(string std::u16string HAVE_STD__U16_STRING)
85check_type(string std::u32string HAVE_STD__U32_STRING)
86check_type(string char16_t HAVE_CHAR16_T)
87check_type(string char32_t HAVE_CHAR32_T)
88check_type(stdint.h uint_least16_t HAVE_STDINT_H)
89check_symbol_exists(posix_fadvise fcntl.h HAVE_POSIX_FADVISE)
90check_builtin("long* temp=0; long ret=__sync_add_and_fetch(temp, 1)" HAS_BUILTIN_SYNC_ADD_AND_FETCH)
91check_builtin("long* temp=0; long ret=__sync_sub_and_fetch(temp, 1)" HAS_BUILTIN_SYNC_SUB_AND_FETCH)
92check_builtin("long* temp=0; long ret=__sync_val_compare_and_swap(temp, 1, 1)" HAS_BUILTIN_SYNC_VAL_COMPARE_AND_SWAP)
93if(HAVE_POSIX_FADVISE)
94 list(APPEND SYSTEM_DEFINES -DHAVE_POSIX_FADVISE=1)
95endif()
96check_function_exists(localtime_r HAVE_LOCALTIME_R)
97if(HAVE_LOCALTIME_R)
98 list(APPEND SYSTEM_DEFINES -DHAVE_LOCALTIME_R=1)
99endif()
diff --git a/project/cmake/scripts/common/checkcommits.cmake b/project/cmake/scripts/common/checkcommits.cmake
new file mode 100644
index 0000000..304e623
--- /dev/null
+++ b/project/cmake/scripts/common/checkcommits.cmake
@@ -0,0 +1,75 @@
1find_package(Git REQUIRED)
2
3macro(sanity_check message)
4 if(status_code)
5 message(FATAL_ERROR "${message}")
6 endif()
7endmacro()
8
9# Check that there are no changes in working-tree
10execute_process(COMMAND ${GIT_EXECUTABLE} diff --quiet
11 RESULT_VARIABLE status_code)
12sanity_check("Cannot run with working tree changes. Commit, stash or drop them.")
13
14# Setup base of tests
15set(check_base $ENV{CHECK_BASE})
16if(NOT check_base)
17 set(check_base origin/master)
18endif()
19
20# Setup end of tests
21set(check_head $ENV{CHECK_HEAD})
22if(NOT check_head)
23 set(check_head HEAD)
24endif()
25
26# Setup target to build
27set(check_target $ENV{CHECK_TARGET})
28if(NOT check_target)
29 set(check_target check)
30endif()
31
32# Build threads
33set(build_threads $ENV{CHECK_THREADS})
34if(NOT build_threads)
35 if(UNIX)
36 execute_process(COMMAND nproc
37 OUTPUT_VARIABLE build_threads)
38 string(REGEX REPLACE "(\r?\n)+$" "" build_threads "${build_threads}")
39 endif()
40endif()
41
42# Record current HEAD
43execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
44 OUTPUT_VARIABLE current_branch)
45
46string(REGEX REPLACE "(\r?\n)+$" "" current_branch "${current_branch}")
47
48# Grab revision list
49execute_process(COMMAND ${GIT_EXECUTABLE} rev-list ${check_base}..${check_head} --reverse
50 OUTPUT_VARIABLE rev_list)
51
52string(REPLACE "\n" ";" rev_list ${rev_list})
53foreach(rev ${rev_list})
54 # Checkout
55 message("Testing revision ${rev}")
56 execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${rev}
57 RESULT_VARIABLE status_code)
58 sanity_check("Failed to checkout ${rev}")
59
60 # Build
61 if(build_threads GREATER 2)
62 execute_process(COMMAND ${CMAKE_COMMAND} "--build" "${CMAKE_BINARY_DIR}" "--target" "${check_target}" "--use-stderr" "--" "-j${build_threads}"
63 RESULT_VARIABLE status_code)
64 else()
65 execute_process(COMMAND ${CMAKE_COMMAND} "--build" "${CMAKE_BINARY_DIR}" "--target" "${check_target}" "--use-stderr"
66 RESULT_VARIABLE status_code)
67 endif()
68 if(status_code)
69 execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${current_branch})
70 endif()
71 sanity_check("Failed to build target for revision ${rev}")
72endforeach()
73
74message("Everything checks out fine")
75execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${current_branch})
diff --git a/project/cmake/scripts/common/generateversionedfiles.cmake b/project/cmake/scripts/common/generateversionedfiles.cmake
new file mode 100644
index 0000000..9a4080a
--- /dev/null
+++ b/project/cmake/scripts/common/generateversionedfiles.cmake
@@ -0,0 +1,13 @@
1include(${CORE_SOURCE_DIR}/project/cmake/scripts/common/macros.cmake)
2
3core_find_versions()
4file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/addons/xbmc.addon)
5file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/addons/kodi.guilib)
6configure_file(${CORE_SOURCE_DIR}/addons/xbmc.addon/addon.xml.in
7 ${CMAKE_BINARY_DIR}/addons/xbmc.addon/addon.xml @ONLY)
8configure_file(${CORE_SOURCE_DIR}/addons/kodi.guilib/addon.xml.in
9 ${CMAKE_BINARY_DIR}/addons/kodi.guilib/addon.xml @ONLY)
10configure_file(${CORE_SOURCE_DIR}/xbmc/CompileInfo.cpp.in
11 ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/xbmc/CompileInfo.cpp @ONLY)
12set(prefix ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR})
13set(APP_LIBDIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/kodi)
diff --git a/project/cmake/scripts/common/generatorsetup.cmake b/project/cmake/scripts/common/generatorsetup.cmake
new file mode 100644
index 0000000..75083ca
--- /dev/null
+++ b/project/cmake/scripts/common/generatorsetup.cmake
@@ -0,0 +1,24 @@
1# Configure single-/multiconfiguration generators and variables
2#
3# CORE_BUILD_CONFIG that is set to
4# - CMAKE_BUILD_TYPE for single configuration generators such as make, nmake
5# - a variable that expands on build time to the current configuration for
6# multi configuration generators such as VS or Xcode
7if(CMAKE_CONFIGURATION_TYPES)
8 if(CMAKE_BUILD_TYPE)
9 message(FATAL_ERROR "CMAKE_BUILD_TYPE must not be defined for multi-configuration generators")
10 endif()
11 set(CORE_BUILD_CONFIG ${CMAKE_CFG_INTDIR})
12 message(STATUS "Generator: Multi-configuration (${CMAKE_GENERATOR})")
13else()
14 if(CMAKE_BUILD_TYPE)
15 set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
16 CACHE STRING "Choose build type (${CMAKE_BUILD_TYPES})" FORCE)
17 else()
18 # Set default
19 set(CMAKE_BUILD_TYPE Release
20 CACHE STRING "Choose build type (${CMAKE_BUILD_TYPES})" FORCE)
21 endif()
22 set(CORE_BUILD_CONFIG ${CMAKE_BUILD_TYPE})
23 message(STATUS "Generator: Single-configuration: ${CMAKE_BUILD_TYPE} (${CMAKE_GENERATOR})")
24endif()
diff --git a/project/cmake/scripts/common/macros.cmake b/project/cmake/scripts/common/macros.cmake
new file mode 100644
index 0000000..dd2233b
--- /dev/null
+++ b/project/cmake/scripts/common/macros.cmake
@@ -0,0 +1,373 @@
1# This script holds the main functions used to construct the build system
2
3# include system specific macros
4include(${CORE_SOURCE_DIR}/project/cmake/scripts/${CORE_SYSTEM_NAME}/macros.cmake)
5
6# Add a library, optionally as a dependency of the main application
7# Arguments:
8# name name of the library to add
9# Optional Arguments:
10# NO_MAIN_DEPENDS if specified, the library is not added to main depends
11# Implicit arguments:
12# SOURCES the sources of the library
13# HEADERS the headers of the library (only for IDE support)
14# OTHERS other library related files (only for IDE support)
15# On return:
16# Library will be built, optionally added to ${core_DEPENDS}
17function(core_add_library name)
18 cmake_parse_arguments(arg "NO_MAIN_DEPENDS" "" "" ${ARGN})
19 add_library(${name} STATIC ${SOURCES} ${HEADERS} ${OTHERS})
20 set_target_properties(${name} PROPERTIES PREFIX "")
21 if(NOT arg_NO_MAIN_DEPENDS)
22 set(core_DEPENDS ${name} ${core_DEPENDS} CACHE STRING "" FORCE)
23 endif()
24
25 # Add precompiled headers to Kodi main libraries
26 if(WIN32 AND "${CMAKE_CURRENT_LIST_DIR}" MATCHES "^${CORE_SOURCE_DIR}/xbmc")
27 add_precompiled_header(${name} pch.h ${CORE_SOURCE_DIR}/xbmc/win32/pch.cpp
28 PCH_TARGET kodi)
29 endif()
30
31 # IDE support
32 if(CMAKE_GENERATOR MATCHES "Xcode")
33 file(RELATIVE_PATH parentfolder ${CORE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..)
34 set_target_properties(${name} PROPERTIES FOLDER "${parentfolder}")
35 elseif(CMAKE_GENERATOR MATCHES "Visual Studio")
36 file(RELATIVE_PATH foldername ${CORE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
37 set_target_properties(${name} PROPERTIES FOLDER "${foldername}")
38 source_group(" " REGULAR_EXPRESSION ".*")
39 endif()
40endfunction()
41
42# Add a test library, and add sources to list for gtest integration macros
43function(core_add_test_library name)
44 core_add_library(${name} NO_MAIN_DEPENDS)
45 set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL 1)
46 foreach(src ${SOURCES})
47 set(test_sources ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${test_sources} CACHE STRING "" FORCE)
48 endforeach()
49 set(test_archives ${test_archives} ${name} CACHE STRING "" FORCE)
50endfunction()
51
52# Add a data file to installation list with a mirror in build tree
53# Arguments:
54# file full path to file to mirror
55# relative the relative base of file path in the build/install tree
56# give another parameter to exclude from install target
57# Implicit arguments:
58# CORE_SOURCE_DIR - root of source tree
59# On return:
60# file is added to ${install_data} and mirrored in build tree
61function(copy_file_to_buildtree file relative)
62 if(NOT WIN32)
63 string(REPLACE "\(" "\\(" file ${file})
64 string(REPLACE "\)" "\\)" file ${file})
65 endif()
66 string(REPLACE "${relative}/" "" outfile ${file})
67
68 if(NOT TARGET export-files)
69 add_custom_target(export-files ALL COMMENT "Copying files into build tree")
70 endif()
71 if(NOT ${CORE_SOURCE_DIR} MATCHES ${CMAKE_BINARY_DIR})
72 if(VERBOSE)
73 message(STATUS "copy_file_to_buildtree - copying file: ${file} -> ${CMAKE_CURRENT_BINARY_DIR}/${outfile}")
74 endif()
75 add_custom_command(TARGET export-files COMMAND ${CMAKE_COMMAND} -E copy_if_different "${file}" "${CMAKE_CURRENT_BINARY_DIR}/${outfile}")
76 endif()
77 if(NOT ARGN)
78 list(APPEND install_data ${outfile})
79 set(install_data ${install_data} PARENT_SCOPE)
80 endif()
81endfunction()
82
83# add data files to installation list with a mirror in build tree.
84# reads list of files to install from a given list of text files.
85# Arguments:
86# pattern globbing pattern for text files to read
87# give another parameter to exclude from installation target
88# Implicit arguments:
89# CORE_SOURCE_DIR - root of source tree
90# On return:
91# files are added to ${install_data} and mirrored in build tree
92function(copy_files_from_filelist_to_buildtree pattern)
93 foreach(arg ${ARGN})
94 list(APPEND pattern ${arg})
95 endforeach()
96 # copies files listed in text files to the buildtree
97 # Input: [glob pattern: filepattern]
98 list(SORT pattern)
99 if(VERBOSE)
100 message(STATUS "copy_files_from_filelist_to_buildtree - got pattern: ${pattern}")
101 endif()
102 foreach(pat ${pattern})
103 file(GLOB filenames ${pat})
104 foreach(filename ${filenames})
105 string(STRIP ${filename} filename)
106 core_file_read_filtered(fstrings ${filename})
107 foreach(dir ${fstrings})
108 file(GLOB_RECURSE files RELATIVE ${CORE_SOURCE_DIR} ${CORE_SOURCE_DIR}/${dir})
109 foreach(file ${files})
110 if(ARGN)
111 copy_file_to_buildtree(${CORE_SOURCE_DIR}/${file} ${CORE_SOURCE_DIR} 1)
112 else()
113 copy_file_to_buildtree(${CORE_SOURCE_DIR}/${file} ${CORE_SOURCE_DIR})
114 endif()
115 endforeach()
116 endforeach()
117 endforeach()
118 endforeach()
119 set(install_data ${install_data} PARENT_SCOPE)
120endfunction()
121
122# helper macro to set modified variables in parent scope
123macro(export_dep)
124 set(SYSTEM_INCLUDES ${SYSTEM_INCLUDES} PARENT_SCOPE)
125 set(DEPLIBS ${DEPLIBS} PARENT_SCOPE)
126 set(DEP_DEFINES ${DEP_DEFINES} PARENT_SCOPE)
127 set(${depup}_FOUND ${${depup}_FOUND} PARENT_SCOPE)
128 mark_as_advanced(${depup}_LIBRARIES)
129endmacro()
130
131# add a required dependency of main application
132# Arguments:
133# dep name of find rule for dependency, used uppercased for variable prefix
134# On return:
135# dependency added to ${SYSTEM_INCLUDES}, ${DEPLIBS} and ${DEP_DEFINES}
136function(core_require_dep dep)
137 find_package(${dep} REQUIRED)
138 string(TOUPPER ${dep} depup)
139 list(APPEND SYSTEM_INCLUDES ${${depup}_INCLUDE_DIRS})
140 list(APPEND DEPLIBS ${${depup}_LIBRARIES})
141 list(APPEND DEP_DEFINES ${${depup}_DEFINITIONS})
142 export_dep()
143endfunction()
144
145# add a required dyloaded dependency of main application
146# Arguments:
147# dep name of find rule for dependency, used uppercased for variable prefix
148# On return:
149# dependency added to ${SYSTEM_INCLUDES}, ${dep}_SONAME is set up
150function(core_require_dyload_dep dep)
151 find_package(${dep} REQUIRED)
152 string(TOUPPER ${dep} depup)
153 list(APPEND SYSTEM_INCLUDES ${${depup}_INCLUDE_DIRS})
154 list(APPEND DEP_DEFINES ${${depup}_DEFINITIONS})
155 find_soname(${depup} REQUIRED)
156 export_dep()
157 set(${depup}_SONAME ${${depup}_SONAME} PARENT_SCOPE)
158endfunction()
159
160# helper macro for optional deps
161macro(setup_enable_switch)
162 string(TOUPPER ${dep} depup)
163 if (ARGV1)
164 set(enable_switch ${ARGV1})
165 else()
166 set(enable_switch ENABLE_${depup})
167 endif()
168endmacro()
169
170# add an optional dependency of main application
171# Arguments:
172# dep name of find rule for dependency, used uppercased for variable prefix
173# On return:
174# dependency optionally added to ${SYSTEM_INCLUDES}, ${DEPLIBS} and ${DEP_DEFINES}
175function(core_optional_dep dep)
176 setup_enable_switch()
177 if(${enable_switch})
178 find_package(${dep})
179 if(${depup}_FOUND)
180 list(APPEND SYSTEM_INCLUDES ${${depup}_INCLUDE_DIRS})
181 list(APPEND DEPLIBS ${${depup}_LIBRARIES})
182 list(APPEND DEP_DEFINES ${${depup}_DEFINITIONS})
183 set(final_message ${final_message} "${depup} enabled: Yes" PARENT_SCOPE)
184 export_dep()
185 else()
186 set(final_message ${final_message} "${depup} enabled: No" PARENT_SCOPE)
187 endif()
188 endif()
189endfunction()
190
191# add an optional dyloaded dependency of main application
192# Arguments:
193# dep name of find rule for dependency, used uppercased for variable prefix
194# On return:
195# dependency optionally added to ${SYSTEM_INCLUDES}, ${DEP_DEFINES}, ${dep}_SONAME is set up
196function(core_optional_dyload_dep dep)
197 setup_enable_switch()
198 if(${enable_switch})
199 find_package(${dep})
200 if(${depup}_FOUND)
201 list(APPEND SYSTEM_INCLUDES ${${depup}_INCLUDE_DIRS})
202 find_soname(${depup} REQUIRED)
203 list(APPEND DEP_DEFINES ${${depup}_DEFINITIONS})
204 set(final_message ${final_message} "${depup} enabled: Yes" PARENT_SCOPE)
205 export_dep()
206 set(${depup}_SONAME ${${depup}_SONAME} PARENT_SCOPE)
207 endif()
208 endif()
209endfunction()
210
211function(core_file_read_filtered result filepattern)
212 # Reads STRINGS from text files
213 # with comments filtered out
214 # Result: [list: result]
215 # Input: [glob pattern: filepattern]
216 file(GLOB filenames ${filepattern})
217 list(SORT filenames)
218 foreach(filename ${filenames})
219 if(VERBOSE)
220 message(STATUS "core_file_read_filtered - filename: ${filename}")
221 endif()
222 file(STRINGS ${filename} fstrings REGEX "^[^#//]")
223 foreach(fstring ${fstrings})
224 string(REGEX REPLACE "^(.*)#(.*)" "\\1" fstring ${fstring})
225 string(REGEX REPLACE "//.*" "" fstring ${fstring})
226 string(STRIP ${fstring} fstring)
227 list(APPEND filename_strings ${fstring})
228 endforeach()
229 endforeach()
230 set(${result} ${filename_strings} PARENT_SCOPE)
231endfunction()
232
233function(core_add_subdirs_from_filelist files)
234 # Adds subdirectories from a sorted list of files
235 # Input: [list: filenames] [bool: sort]
236 foreach(arg ${ARGN})
237 list(APPEND files ${arg})
238 endforeach()
239 list(SORT files)
240 if(VERBOSE)
241 message(STATUS "core_add_subdirs_from_filelist - got pattern: ${files}")
242 endif()
243 foreach(filename ${files})
244 string(STRIP ${filename} filename)
245 core_file_read_filtered(fstrings ${filename})
246 foreach(subdir ${fstrings})
247 STRING_SPLIT(subdir " " ${subdir})
248 list(GET subdir 0 subdir_src)
249 list(GET subdir -1 subdir_dest)
250 if(VERBOSE)
251 message(STATUS " core_add_subdirs_from_filelist - adding subdir: ${CORE_SOURCE_DIR}${subdir_src} -> ${CORE_BUILD_DIR}/${subdir_dest}")
252 endif()
253 add_subdirectory(${CORE_SOURCE_DIR}/${subdir_src} ${CORE_BUILD_DIR}/${subdir_dest})
254 endforeach()
255 endforeach()
256endfunction()
257
258macro(core_add_optional_subdirs_from_filelist pattern)
259 # Adds subdirectories from text files
260 # if the option(s) in the 3rd field are enabled
261 # Input: [glob pattern: filepattern]
262 foreach(arg ${ARGN})
263 list(APPEND pattern ${arg})
264 endforeach()
265 foreach(elem ${pattern})
266 string(STRIP ${elem} elem)
267 list(APPEND filepattern ${elem})
268 endforeach()
269
270 file(GLOB filenames ${filepattern})
271 list(SORT filenames)
272 if(VERBOSE)
273 message(STATUS "core_add_optional_subdirs_from_filelist - got pattern: ${filenames}")
274 endif()
275
276 foreach(filename ${filenames})
277 if(VERBOSE)
278 message(STATUS "core_add_optional_subdirs_from_filelist - reading file: ${filename}")
279 endif()
280 file(STRINGS ${filename} fstrings REGEX "^[^#//]")
281 foreach(line ${fstrings})
282 string(REPLACE " " ";" line "${line}")
283 list(GET line 0 subdir_src)
284 list(GET line 1 subdir_dest)
285 list(GET line 3 opts)
286 foreach(opt ${opts})
287 if(ENABLE_${opt})
288 if(VERBOSE)
289 message(STATUS " core_add_optional_subdirs_from_filelist - adding subdir: ${CORE_SOURCE_DIR}${subdir_src} -> ${CORE_BUILD_DIR}/${subdir_dest}")
290 endif()
291 add_subdirectory(${CORE_SOURCE_DIR}/${subdir_src} ${CORE_BUILD_DIR}/${subdir_dest})
292 else()
293 if(VERBOSE)
294 message(STATUS " core_add_optional_subdirs_from_filelist: OPTION ${opt} not enabled for ${subdir_src}, skipping subdir")
295 endif()
296 endif()
297 endforeach()
298 endforeach()
299 endforeach()
300endmacro()
301
302macro(today RESULT)
303 if (WIN32)
304 execute_process(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT})
305 string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}})
306 elseif(UNIX)
307 execute_process(COMMAND date -u +%F
308 OUTPUT_VARIABLE ${RESULT})
309 string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}})
310 else()
311 message(SEND_ERROR "date not implemented")
312 set(${RESULT} 000000)
313 endif()
314 string(REGEX REPLACE "(\r?\n)+$" "" ${RESULT} "${${RESULT}}")
315endmacro()
316
317function(core_find_git_rev)
318 if(EXISTS ${CORE_SOURCE_DIR}/VERSION)
319 file(STRINGS ${CORE_SOURCE_DIR}/VERSION VERSION_FILE)
320 string(SUBSTRING "${VERSION_FILE}" 1 16 GIT_REV)
321 else()
322 find_package(Git)
323 if(GIT_FOUND AND EXISTS ${CORE_SOURCE_DIR}/.git)
324 execute_process(COMMAND ${GIT_EXECUTABLE} diff-files --ignore-submodules --quiet --
325 RESULT_VARIABLE status_code
326 WORKING_DIRECTORY ${CORE_SOURCE_DIR})
327 if (NOT status_code)
328 execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --cached --ignore-submodules --quiet HEAD --
329 RESULT_VARIABLE status_code
330 WORKING_DIRECTORY ${CORE_SOURCE_DIR})
331 endif()
332 today(DATE)
333 execute_process(COMMAND ${GIT_EXECUTABLE} --no-pager log --abbrev=7 -n 1
334 --pretty=format:"%h-dirty" HEAD
335 OUTPUT_VARIABLE LOG_UNFORMATTED
336 WORKING_DIRECTORY ${CORE_SOURCE_DIR})
337 string(SUBSTRING ${LOG_UNFORMATTED} 1 7 HASH)
338 else()
339 execute_process(COMMAND ${GIT_EXECUTABLE} --no-pager log --abbrev=7 -n 1
340 --pretty=format:"%h %cd" HEAD
341 OUTPUT_VARIABLE LOG_UNFORMATTED
342 WORKING_DIRECTORY ${CORE_SOURCE_DIR})
343 string(SUBSTRING ${LOG_UNFORMATTED} 1 7 HASH)
344 string(SUBSTRING ${LOG_UNFORMATTED} 9 10 DATE)
345 string(REPLACE "-" "" DATE ${DATE})
346 endif()
347 set(GIT_REV "${DATE}-${HASH}")
348 endif()
349 if(GIT_REV)
350 set(APP_SCMID ${GIT_REV} PARENT_SCOPE)
351 endif()
352endfunction()
353
354macro(core_find_versions)
355 include(CMakeParseArguments)
356 core_file_read_filtered(version_list ${CORE_SOURCE_DIR}/version.txt)
357 string(REPLACE " " ";" version_list "${version_list}")
358 cmake_parse_arguments(APP "" "VERSION_MAJOR;VERSION_MINOR;VERSION_TAG;VERSION_CODE;ADDON_API;APP_NAME;COMPANY_NAME" "" ${version_list})
359
360 set(APP_NAME ${APP_APP_NAME}) # inconsistency in upstream
361 string(TOLOWER ${APP_APP_NAME} APP_NAME_LC)
362 set(COMPANY_NAME ${APP_COMPANY_NAME})
363 set(APP_VERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR})
364 if(APP_VERSION_TAG)
365 set(APP_VERSION ${APP_VERSION}-${APP_VERSION_TAG})
366 endif()
367 string(REPLACE "." "," FILE_VERSION ${APP_ADDON_API}.0)
368 string(TOLOWER ${APP_VERSION_TAG} APP_VERSION_TAG_LC)
369 file(STRINGS ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h guilib_version REGEX "^.*GUILIB_API_VERSION (.*)$")
370 string(REGEX REPLACE ".*\"(.*)\"" "\\1" guilib_version ${guilib_version})
371 file(STRINGS ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h guilib_version_min REGEX "^.*GUILIB_MIN_API_VERSION (.*)$")
372 string(REGEX REPLACE ".*\"(.*)\"" "\\1" guilib_version_min ${guilib_version_min})
373endmacro()
diff --git a/project/cmake/scripts/common/managestring.cmake b/project/cmake/scripts/common/managestring.cmake
new file mode 100644
index 0000000..7321f4c
--- /dev/null
+++ b/project/cmake/scripts/common/managestring.cmake
@@ -0,0 +1,235 @@
1# - Collection of String utility macros.
2# Defines the following macros:
3# STRING_TRIM(var str [NOUNQUOTE])
4# - Trim a string by removing the leading and trailing spaces,
5# just like STRING(STRIP ...) in CMake 2.6 and later.
6# This macro is needed as CMake 2.4 does not support STRING(STRIP ..)
7# This macro also remove quote and double quote marks around the string,
8# unless NOUNQUOTE is defined.
9# * Parameters:
10# + var: A variable that stores the result.
11# + str: A string.
12# + NOUNQUOTE: (Optional) do not remove the double quote mark around the string.
13#
14# STRING_UNQUOTE(var str)
15# - Remove double quote marks and quote marks around a string.
16# If the string is not quoted, then it returns an empty string.
17# * Parameters:
18# + var: A variable that stores the result.
19# + str: A string.
20#
21# STRING_JOIN(var delimiter str_list [str...])
22# - Concatenate strings, with delimiter inserted between strings.
23# * Parameters:
24# + var: A variable that stores the result.
25# + str_list: A list of string.
26# + str: (Optional) more string to be join.
27#
28# STRING_SPLIT(var delimiter str [NOESCAPE_SEMICOLON])
29# - Split a string into a list using a delimiter, which can be in 1 or more
30# characters long.
31# * Parameters:
32# + var: A variable that stores the result.
33# + delimiter: To separate a string.
34# + str: A string.
35# + NOESCAPE_SEMICOLON: (Optional) Do not escape semicolons.
36#
37
38IF(NOT DEFINED _MANAGE_STRING_CMAKE_)
39 SET(_MANAGE_STRING_CMAKE_ "DEFINED")
40
41 MACRO(STRING_TRIM var str)
42 SET(${var} "")
43 IF (NOT "${ARGN}" STREQUAL "NOUNQUOTE")
44 # Need not trim a quoted string.
45 STRING_UNQUOTE(_var "${str}")
46 IF(NOT _var STREQUAL "")
47 # String is quoted
48 SET(${var} "${_var}")
49 ENDIF(NOT _var STREQUAL "")
50 ENDIF(NOT "${ARGN}" STREQUAL "NOUNQUOTE")
51
52 IF(${var} STREQUAL "")
53 SET(_var_1 "${str}")
54 STRING(REGEX REPLACE "^[ \t\r\n]+" "" _var_2 "${str}" )
55 STRING(REGEX REPLACE "[ \t\r\n]+$" "" _var_3 "${_var_2}" )
56 SET(${var} "${_var_3}")
57 ENDIF(${var} STREQUAL "")
58 ENDMACRO(STRING_TRIM var str)
59
60 # Internal macro
61 # Variable cannot be escaped here, as variable is already substituted
62 # at the time it passes to this macro.
63 MACRO(STRING_ESCAPE var str)
64 # ';' and '\' are tricky, need to be encoded.
65 # '#' => '#H'
66 # '\' => '#B'
67 # ';' => '#S'
68 SET(_NOESCAPE_SEMICOLON "")
69 SET(_NOESCAPE_HASH "")
70
71 FOREACH(_arg ${ARGN})
72 IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
73 SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON")
74 ELSEIF(${_arg} STREQUAL "NOESCAPE_HASH")
75 SET(_NOESCAPE_HASH "NOESCAPE_HASH")
76 ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
77 ENDFOREACH(_arg)
78
79 IF(_NOESCAPE_HASH STREQUAL "")
80 STRING(REGEX REPLACE "#" "#H" _ret "${str}")
81 ELSE(_NOESCAPE_HASH STREQUAL "")
82 SET(_ret "${str}")
83 ENDIF(_NOESCAPE_HASH STREQUAL "")
84
85 STRING(REGEX REPLACE "\\\\" "#B" _ret "${_ret}")
86 IF(_NOESCAPE_SEMICOLON STREQUAL "")
87 STRING(REGEX REPLACE ";" "#S" _ret "${_ret}")
88 ENDIF(_NOESCAPE_SEMICOLON STREQUAL "")
89 SET(${var} "${_ret}")
90 ENDMACRO(STRING_ESCAPE var str)
91
92 MACRO(STRING_UNESCAPE var str)
93 # '#B' => '\'
94 # '#H' => '#'
95 # '#D' => '$'
96 # '#S' => ';'
97 SET(_ESCAPE_VARIABLE "")
98 SET(_NOESCAPE_SEMICOLON "")
99 SET(_ret "${str}")
100 FOREACH(_arg ${ARGN})
101 IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
102 SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON")
103 ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE")
104 SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE")
105 STRING(REGEX REPLACE "#D" "$" _ret "${_ret}")
106 ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
107 ENDFOREACH(_arg)
108
109 STRING(REGEX REPLACE "#B" "\\\\" _ret "${_ret}")
110 IF(_NOESCAPE_SEMICOLON STREQUAL "")
111 # ';' => '#S'
112 STRING(REGEX REPLACE "#S" "\\\\;" _ret "${_ret}")
113 ELSE(_NOESCAPE_SEMICOLON STREQUAL "")
114 STRING(REGEX REPLACE "#S" ";" _ret "${_ret}")
115 ENDIF(_NOESCAPE_SEMICOLON STREQUAL "")
116
117 IF(NOT _ESCAPE_VARIABLE STREQUAL "")
118 # '#D' => '$'
119 STRING(REGEX REPLACE "#D" "$" _ret "${_ret}")
120 ENDIF(NOT _ESCAPE_VARIABLE STREQUAL "")
121 STRING(REGEX REPLACE "#H" "#" _ret "${_ret}")
122 SET(${var} "${_ret}")
123 ENDMACRO(STRING_UNESCAPE var str)
124
125
126 MACRO(STRING_UNQUOTE var str)
127 STRING_ESCAPE(_ret "${str}" ${ARGN})
128 IF(_ret MATCHES "^[ \t\r\n]+")
129 STRING(REGEX REPLACE "^[ \t\r\n]+" "" _ret "${_ret}")
130 ENDIF(_ret MATCHES "^[ \t\r\n]+")
131 IF(_ret MATCHES "^\"")
132 # Double quote
133 STRING(REGEX REPLACE "\"\(.*\)\"[ \t\r\n]*$" "\\1" _ret "${_ret}")
134 ELSEIF(_ret MATCHES "^'")
135 # Single quote
136 STRING(REGEX REPLACE "'\(.*\)'[ \t\r\n]*$" "\\1" _ret "${_ret}")
137 ELSE(_ret MATCHES "^\"")
138 SET(_ret "")
139 ENDIF(_ret MATCHES "^\"")
140
141 # Unencoding
142 STRING_UNESCAPE(${var} "${_ret}" ${ARGN})
143 ENDMACRO(STRING_UNQUOTE var str)
144
145 MACRO(STRING_JOIN var delimiter str_list)
146 SET(_ret "")
147 FOREACH(_str ${str_list})
148 IF(_ret STREQUAL "")
149 SET(_ret "${_str}")
150 ELSE(_ret STREQUAL "")
151 SET(_ret "${_ret}${delimiter}${_str}")
152 ENDIF(_ret STREQUAL "")
153 ENDFOREACH(_str ${str_list})
154
155 FOREACH(_str ${ARGN})
156 IF(_ret STREQUAL "")
157 SET(_ret "${_str}")
158 ELSE(_ret STREQUAL "")
159 SET(_ret "${_ret}${delimiter}${_str}")
160 ENDIF(_ret STREQUAL "")
161 ENDFOREACH(_str ${str_list})
162 SET(${var} "${_ret}")
163 ENDMACRO(STRING_JOIN var delimiter str_list)
164
165 MACRO(STRING_SPLIT var delimiter str)
166 SET(_max_tokens "")
167 SET(_NOESCAPE_SEMICOLON "")
168 SET(_ESCAPE_VARIABLE "")
169 FOREACH(_arg ${ARGN})
170 IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
171 SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON")
172 ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE")
173 SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE")
174 ELSE(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
175 SET(_max_tokens ${_arg})
176 ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON")
177 ENDFOREACH(_arg)
178
179 IF(NOT _max_tokens)
180 SET(_max_tokens -1)
181 ENDIF(NOT _max_tokens)
182
183 STRING_ESCAPE(_str "${str}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE})
184 STRING_ESCAPE(_delimiter "${delimiter}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE})
185
186 SET(_str_list "")
187 SET(_token_count 0)
188 STRING(LENGTH "${_delimiter}" _de_len)
189
190 WHILE(NOT _token_count EQUAL _max_tokens)
191 MATH(EXPR _token_count ${_token_count}+1)
192 IF(_token_count EQUAL _max_tokens)
193 # Last token, no need splitting
194 SET(_str_list ${_str_list} "${_str}")
195 ELSE(_token_count EQUAL _max_tokens)
196 # in case encoded characters are delimiters
197 STRING(LENGTH "${_str}" _str_len)
198 SET(_index 0)
199 SET(_token "")
200 SET(_str_remain "")
201 MATH(EXPR _str_end ${_str_len}-${_de_len}+1)
202 SET(_bound "k")
203 WHILE(_index LESS _str_end)
204 STRING(SUBSTRING "${_str}" ${_index} ${_de_len} _str_cursor)
205 IF(_str_cursor STREQUAL _delimiter)
206 # Get the token
207 STRING(SUBSTRING "${_str}" 0 ${_index} _token)
208 # Get the rest
209 MATH(EXPR _rest_index ${_index}+${_de_len})
210 MATH(EXPR _rest_len ${_str_len}-${_index}-${_de_len})
211 STRING(SUBSTRING "${_str}" ${_rest_index} ${_rest_len} _str_remain)
212 SET(_index ${_str_end})
213 ELSE(_str_cursor STREQUAL _delimiter)
214 MATH(EXPR _index ${_index}+1)
215 ENDIF(_str_cursor STREQUAL _delimiter)
216 ENDWHILE(_index LESS _str_end)
217
218 IF(_str_remain STREQUAL "")
219 # Meaning: end of string
220 LIST(APPEND _str_list "${_str}")
221 SET(_max_tokens ${_token_count})
222 ELSE(_str_remain STREQUAL "")
223 LIST(APPEND _str_list "${_token}")
224 SET(_str "${_str_remain}")
225 ENDIF(_str_remain STREQUAL "")
226 ENDIF(_token_count EQUAL _max_tokens)
227 ENDWHILE(NOT _token_count EQUAL _max_tokens)
228
229
230 # Unencoding
231 STRING_UNESCAPE(${var} "${_str_list}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE})
232 ENDMACRO(STRING_SPLIT var delimiter str)
233
234ENDIF(NOT DEFINED _MANAGE_STRING_CMAKE_)
235
diff --git a/project/cmake/scripts/common/pathsetup.cmake b/project/cmake/scripts/common/pathsetup.cmake
new file mode 100644
index 0000000..54b352d
--- /dev/null
+++ b/project/cmake/scripts/common/pathsetup.cmake
@@ -0,0 +1,3 @@
1# This script configures installation paths
2
3include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/pathsetup.cmake)
diff --git a/project/cmake/scripts/common/prepare-env.cmake b/project/cmake/scripts/common/prepare-env.cmake
index 3413c45..b9a39e7 100644
--- a/project/cmake/scripts/common/prepare-env.cmake
+++ b/project/cmake/scripts/common/prepare-env.cmake
@@ -12,6 +12,8 @@ if(EXISTS "${APP_ROOT}/version.txt")
12 set(${name} "${value}") 12 set(${name} "${value}")
13 endif() 13 endif()
14 endforeach() 14 endforeach()
15 string(TOLOWER ${APP_NAME} APP_NAME_LC)
16 string(TOUPPER ${APP_NAME} APP_NAME_UC)
15endif() 17endif()
16 18
17# bail if we can't parse versions 19# bail if we can't parse versions
@@ -19,16 +21,21 @@ if(NOT DEFINED APP_VERSION_MAJOR OR NOT DEFINED APP_VERSION_MINOR)
19 message(FATAL_ERROR "Could not determine app version! make sure that ${APP_ROOT}/version.txt exists") 21 message(FATAL_ERROR "Could not determine app version! make sure that ${APP_ROOT}/version.txt exists")
20endif() 22endif()
21 23
24# in case we need to download something, set KODI_MIRROR to the default if not alread set
25if(NOT DEFINED KODI_MIRROR)
26 set(KODI_MIRROR "http://mirrors.kodi.tv")
27endif()
28
22### copy all the addon binding header files to include/kodi 29### copy all the addon binding header files to include/kodi
23# make sure include/kodi exists and is empty 30# make sure include/kodi exists and is empty
24set(KODI_LIB_DIR ${DEPENDS_PATH}/lib/kodi) 31set(APP_LIB_DIR ${DEPENDS_PATH}/lib/${APP_NAME_LC})
25if(NOT EXISTS "${KODI_LIB_DIR}/") 32if(NOT EXISTS "${APP_LIB_DIR}/")
26 file(MAKE_DIRECTORY ${KODI_LIB_DIR}) 33 file(MAKE_DIRECTORY ${APP_LIB_DIR})
27endif() 34endif()
28 35
29set(KODI_INCLUDE_DIR ${DEPENDS_PATH}/include/kodi) 36set(APP_INCLUDE_DIR ${DEPENDS_PATH}/include/${APP_NAME_LC})
30if(NOT EXISTS "${KODI_INCLUDE_DIR}/") 37if(NOT EXISTS "${APP_INCLUDE_DIR}/")
31 file(MAKE_DIRECTORY ${KODI_INCLUDE_DIR}) 38 file(MAKE_DIRECTORY ${APP_INCLUDE_DIR})
32endif() 39endif()
33 40
34# we still need XBMC_INCLUDE_DIR and XBMC_LIB_DIR for backwards compatibility to xbmc 41# we still need XBMC_INCLUDE_DIR and XBMC_LIB_DIR for backwards compatibility to xbmc
@@ -49,13 +56,13 @@ if(NOT WIN32)
49 endif() 56 endif()
50endif() 57endif()
51 58
52# kodi-config.cmake.in (further down) expects a "prefix" variable
53get_filename_component(prefix "${DEPENDS_PATH}" ABSOLUTE)
54
55# generate the proper kodi-config.cmake file 59# generate the proper kodi-config.cmake file
56configure_file(${APP_ROOT}/project/cmake/kodi-config.cmake.in ${KODI_LIB_DIR}/kodi-config.cmake @ONLY) 60configure_file(${APP_ROOT}/project/cmake/kodi-config.cmake.in ${APP_LIB_DIR}/kodi-config.cmake @ONLY)
61
57# copy cmake helpers to lib/kodi 62# copy cmake helpers to lib/kodi
58file(COPY ${APP_ROOT}/project/cmake/scripts/common/addon-helpers.cmake ${APP_ROOT}/project/cmake/scripts/common/addoptions.cmake DESTINATION ${KODI_LIB_DIR}) 63file(COPY ${APP_ROOT}/project/cmake/scripts/common/addon-helpers.cmake
64 ${APP_ROOT}/project/cmake/scripts/common/addoptions.cmake
65 DESTINATION ${APP_LIB_DIR})
59 66
60# generate xbmc-config.cmake for backwards compatibility to xbmc 67# generate xbmc-config.cmake for backwards compatibility to xbmc
61configure_file(${APP_ROOT}/project/cmake/xbmc-config.cmake.in ${XBMC_LIB_DIR}/xbmc-config.cmake @ONLY) 68configure_file(${APP_ROOT}/project/cmake/xbmc-config.cmake.in ${XBMC_LIB_DIR}/xbmc-config.cmake @ONLY)
@@ -69,7 +76,7 @@ foreach(binding ${bindings})
69 string(REPLACE "+=" ";" binding "${binding}") 76 string(REPLACE "+=" ";" binding "${binding}")
70 list(GET binding 1 header) 77 list(GET binding 1 header)
71 # copy the header file to include/kodi 78 # copy the header file to include/kodi
72 file(COPY ${APP_ROOT}/${header} DESTINATION ${KODI_INCLUDE_DIR}) 79 file(COPY ${APP_ROOT}/${header} DESTINATION ${APP_INCLUDE_DIR})
73 80
74 # auto-generate header files for backwards compatibility to xbmc with deprecation warning 81 # auto-generate header files for backwards compatibility to xbmc with deprecation warning
75 # but only do it if the file doesn't already exist 82 # but only do it if the file doesn't already exist
@@ -95,7 +102,7 @@ if(WIN32)
95 else() 102 else()
96 set(PATCH_ARCHIVE_NAME "patch-2.5.9-7-bin-1") 103 set(PATCH_ARCHIVE_NAME "patch-2.5.9-7-bin-1")
97 set(PATCH_ARCHIVE "${PATCH_ARCHIVE_NAME}.zip") 104 set(PATCH_ARCHIVE "${PATCH_ARCHIVE_NAME}.zip")
98 set(PATCH_URL "http://mirrors.xbmc.org/build-deps/win32/${PATCH_ARCHIVE}") 105 set(PATCH_URL "${KODI_MIRROR}/build-deps/win32/${PATCH_ARCHIVE}")
99 set(PATCH_DOWNLOAD ${BUILD_DIR}/download/${PATCH_ARCHIVE}) 106 set(PATCH_DOWNLOAD ${BUILD_DIR}/download/${PATCH_ARCHIVE})
100 107
101 # download the archive containing patch.exe 108 # download the archive containing patch.exe
diff --git a/project/cmake/scripts/common/projectmacros.cmake b/project/cmake/scripts/common/projectmacros.cmake
new file mode 100644
index 0000000..d0739c4
--- /dev/null
+++ b/project/cmake/scripts/common/projectmacros.cmake
@@ -0,0 +1,84 @@
1# This script holds macros which are project specific
2
3# Pack a skin xbt file
4# Arguments:
5# input input directory to pack
6# output ouput xbt file
7# On return:
8# xbt is added to ${XBT_FILES}
9function(pack_xbt input output)
10 file(GLOB_RECURSE MEDIA_FILES ${input}/*)
11 get_filename_component(dir ${output} PATH)
12 add_custom_command(OUTPUT ${output}
13 COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}
14 COMMAND TexturePacker::TexturePacker
15 ARGS -input ${input}
16 -output ${output}
17 -dupecheck
18 DEPENDS ${MEDIA_FILES})
19 list(APPEND XBT_FILES ${output})
20 set(XBT_FILES ${XBT_FILES} PARENT_SCOPE)
21endfunction()
22
23# Add a skin to installation list, mirroring it in build tree, packing textures
24# Arguments:
25# skin skin directory
26# relative relative base path in build tree
27# On return:
28# xbt is added to ${XBT_FILES}, data added to ${install_data}, mirror in build tree
29function(copy_skin_to_buildtree skin relative)
30 file(GLOB_RECURSE FILES ${skin}/*)
31 file(GLOB_RECURSE MEDIA_FILES ${skin}/media/*)
32 list(REMOVE_ITEM FILES ${MEDIA_FILES})
33 foreach(file ${FILES})
34 copy_file_to_buildtree(${file} ${relative})
35 endforeach()
36 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${dest}/media)
37 string(REPLACE "${relative}/" "" dest ${skin})
38 pack_xbt(${skin}/media
39 ${CMAKE_BINARY_DIR}/${dest}/media/Textures.xbt
40 ${CMAKE_BINARY_DIR})
41
42 set(XBT_FILES ${XBT_FILES} PARENT_SCOPE)
43 set(install_data ${install_data} PARENT_SCOPE)
44endfunction()
45
46# Get GTest tests as CMake tests.
47# Copied from FindGTest.cmake
48# Thanks to Daniel Blezek <blezek@gmail.com> for the GTEST_ADD_TESTS code
49function(GTEST_ADD_TESTS executable extra_args)
50 if(NOT ARGN)
51 message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS")
52 endif()
53 foreach(source ${ARGN})
54 file(READ "${source}" contents)
55 string(REGEX MATCHALL "TEST_?[F]?\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents})
56 foreach(hit ${found_tests})
57 string(REGEX REPLACE ".*\\( *([A-Za-z_0-9]+), *([A-Za-z_0-9]+) *\\).*" "\\1.\\2" test_name ${hit})
58 add_test(${test_name} ${executable} --gtest_filter=${test_name} ${extra_args})
59 endforeach()
60 # Groups parametrized tests under a single ctest entry
61 string(REGEX MATCHALL "INSTANTIATE_TEST_CASE_P\\(([^,]+), *([^,]+)" found_tests2 ${contents})
62 foreach(hit ${found_tests2})
63 string(SUBSTRING ${hit} 24 -1 test_name)
64 string(REPLACE "," ";" test_name "${test_name}")
65 list(GET test_name 0 filter_name)
66 list(GET test_name 1 test_prefix)
67 string(STRIP ${test_prefix} test_prefix)
68 add_test(${test_prefix}.${filter_name} ${executable} --gtest_filter=${filter_name}* ${extra_args})
69 endforeach()
70 endforeach()
71endfunction()
72
73function(whole_archive output)
74 if(CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
75 set(${output} -Wl,--whole-archive ${ARGN} -Wl,--no-whole-archive PARENT_SCOPE)
76 elseif(CMAKE_CXX_COMPILER_ID STREQUAL AppleClang)
77 foreach(library ${ARGN})
78 list(APPEND ${output} -Wl,-force_load ${library})
79 set(${output} ${${output}} PARENT_SCOPE)
80 endforeach()
81 else()
82 set(${output} ${ARGN} PARENT_SCOPE)
83 endif()
84endfunction()