no message
This commit is contained in:
392
cmake/predefine.cmake
Normal file
392
cmake/predefine.cmake
Normal file
@@ -0,0 +1,392 @@
|
||||
|
||||
set(CC_PLATFORM_IOS 1)
|
||||
set(CC_PLATFORM_WINDOWS 2)
|
||||
set(CC_PLATFORM_ANDROID 3)
|
||||
set(CC_PLATFORM_MACOS 4)
|
||||
set(CC_PLATFORM_OHOS 5)
|
||||
set(CC_PLATFORM_LINUX 6)
|
||||
set(CC_PLATFORM_QNX 7)
|
||||
set(CC_PLATFORM_NX 8)
|
||||
set(CC_PLATFORM_EMSCRIPTEN 9)
|
||||
set(CC_PLATFORM_OPENHARMONY 10)
|
||||
set(CC_PLATFORM 1)
|
||||
|
||||
if(NX)
|
||||
if(NOT DEFINED ENV{NINTENDO_SDK_ROOT})
|
||||
message(FATAL_ERROR "Nintendo SDK not found")
|
||||
return()
|
||||
endif()
|
||||
if(NOT IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../platform-nx)
|
||||
message(FATAL_ERROR "platform adaptation package not found")
|
||||
return()
|
||||
endif()
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
message(FATAL_ERROR "Only windows environment is supported")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (CC_NX_WINDOWS) # windows reference
|
||||
set(WINDOWS TRUE)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_WINDOWS})
|
||||
else()
|
||||
set(CC_PLATFORM ${CC_PLATFORM_NX})
|
||||
endif()
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(WINDOWS TRUE)
|
||||
set(PLATFORM_FOLDER windows)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_WINDOWS})
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
|
||||
set(PLATFORM_FOLDER android)
|
||||
set(ANDROID TRUE)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_ANDROID})
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(APPLE TRUE)
|
||||
set(MACOSX TRUE)
|
||||
set(PLATFORM_FOLDER mac)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_MACOS})
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(LINUX TRUE)
|
||||
set(PLATFORM_FOLDER linux)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_LINUX})
|
||||
add_definitions(-D__LINUX__=1)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "iOS")
|
||||
set(APPLE TRUE)
|
||||
set(IOS TRUE)
|
||||
set(PLATFORM_FOLDER ios)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_IOS})
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "QNX")
|
||||
if(NOT IS_DIRECTORY ${QNX_PATH})
|
||||
message(FATAL_ERROR "platform adaptation package not found")
|
||||
return()
|
||||
endif()
|
||||
set(QNX TRUE)
|
||||
set(PLATFORM_FOLDER qnx)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_QNX})
|
||||
add_definitions(-D__QNX__=1)
|
||||
elseif(OPENHARMONY)
|
||||
set(OPENHARMONY TRUE)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_OPENHARMONY})
|
||||
add_definitions(-D__OPENHARMONY__=1)
|
||||
set(PLATFORM_FOLDER openharmony)
|
||||
set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden ${CMAKE_CXX_FLAGS}")
|
||||
if("${OHOS_ARCH}" STREQUAL "armeabi-v7a")
|
||||
set(CMAKE_CXX_FLAGS "-march=armv7a ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
set(CC_WGPU_WASM TRUE)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_EMSCRIPTEN})
|
||||
set(EMSCRIPTEN TRUE)
|
||||
add_definitions(-DCC_WGPU_WASM=1)
|
||||
elseif(OHOS)
|
||||
set(OHOS TRUE)
|
||||
set(CC_PLATFORM ${CC_PLATFORM_OHOS})
|
||||
add_definitions(-D__OHOS__=1)
|
||||
set(PLATFORM_FOLDER ohos)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported platform '${CMAKE_SYSTEM_NAME}', CMake will exit!")
|
||||
return()
|
||||
endif()
|
||||
|
||||
MESSAGE(STATUS "platform: ${CMAKE_SYSTEM_NAME}")
|
||||
|
||||
# platform macros
|
||||
add_definitions(-DCC_PLATFORM_WINDOWS=${CC_PLATFORM_WINDOWS})
|
||||
add_definitions(-DCC_PLATFORM_MACOS=${CC_PLATFORM_MACOS})
|
||||
add_definitions(-DCC_PLATFORM_IOS=${CC_PLATFORM_IOS})
|
||||
add_definitions(-DCC_PLATFORM_MAC_OSX=${CC_PLATFORM_MACOS}) # keep compatible
|
||||
add_definitions(-DCC_PLATFORM_MAC_IOS=${CC_PLATFORM_IOS}) # keep compatible
|
||||
add_definitions(-DCC_PLATFORM_ANDROID=${CC_PLATFORM_ANDROID})
|
||||
add_definitions(-DCC_PLATFORM_OHOS=${CC_PLATFORM_OHOS})
|
||||
add_definitions(-DCC_PLATFORM_LINUX=${CC_PLATFORM_LINUX})
|
||||
add_definitions(-DCC_PLATFORM_QNX=${CC_PLATFORM_QNX})
|
||||
add_definitions(-DCC_PLATFORM_NX=${CC_PLATFORM_NX})
|
||||
add_definitions(-DCC_PLATFORM_OPENHARMONY=${CC_PLATFORM_OPENHARMONY})
|
||||
add_definitions(-DCC_PLATFORM_EMSCRIPTEN=${CC_PLATFORM_EMSCRIPTEN})
|
||||
add_definitions(-DCC_PLATFORM=${CC_PLATFORM})
|
||||
|
||||
|
||||
# simplify generator condition, please use them everywhere
|
||||
if(CMAKE_GENERATOR STREQUAL Xcode)
|
||||
set(XCODE TRUE)
|
||||
elseif(CMAKE_GENERATOR MATCHES Visual)
|
||||
set(VS TRUE)
|
||||
endif()
|
||||
|
||||
# generators that are capable of organizing into a hierarchy of folders
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# set c++ standard
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if("$ENV{COCOS_ENGINE_DEV}" EQUAL "1")
|
||||
set(WERROR_FLAGS "-Werror -Werror=return-type") # -Wshorten-64-to-32 -Werror=return-type
|
||||
|
||||
if(APPLE)
|
||||
set(WERROR_FLAGS " ${WERROR_FLAGS} -Wno-deprecated-declarations")
|
||||
elseif(LINUX)
|
||||
set(WERROR_FLAGS " ${WERROR_FLAGS} -Wno-nullability-completeness -Wno-deprecated-declarations")
|
||||
elseif(ANDROID)
|
||||
set(WERROR_FLAGS " ${WERROR_FLAGS} -Wno-deprecated-declarations -Wno-unknown-warning-option -Wno-deprecated-builtins")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(WERROR_FLAGS " ${WERROR_FLAGS} -Wno-invalid-offsetof")
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(WERROR_FLAGS "/WX")
|
||||
endif()
|
||||
message(STATUS "Enable NO_WERROR")
|
||||
else()
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(WERROR_FLAGS "")
|
||||
else()
|
||||
set(WERROR_FLAGS "-Werror=return-type")
|
||||
endif()
|
||||
message(STATUS "Ignore NO_WERROR")
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
if("${ANDROID_ABI}" STREQUAL "armeabi-v7a")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon-fp16")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon-fp16")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsigned-char -ffunction-sections -fdata-sections -fstrict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char -ffunction-sections -fdata-sections -fstrict-aliasing -frtti -fexceptions")
|
||||
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -fno-omit-frame-pointer")
|
||||
else()
|
||||
if(NOT DEFINED HIDE_SYMBOLS OR HIDE_SYMBOLS) # hidden by default
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(cc_enable_werror source_list)
|
||||
foreach(src IN LISTS source_list)
|
||||
if("${src}" MATCHES "\\.(cpp|mm|c|m)\$")
|
||||
set_source_files_properties("${src}" PROPERTIES
|
||||
COMPILE_FLAGS "${WERROR_FLAGS}"
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
################################# cc_set_if_undefined ###################################
|
||||
macro(cc_set_if_undefined varname value)
|
||||
if(NOT DEFINED ${varname})
|
||||
set(${varname} ${value})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
################################# cocos_source_files ###################################
|
||||
macro(cocos_source_files)
|
||||
set(list_var "${ARGN}")
|
||||
set(TWAE ON)
|
||||
set(ACCEPT_MN OFF)
|
||||
set(MODULE_NAME "COCOS")
|
||||
set(NO_UBUILD OFF)
|
||||
foreach(src IN LISTS list_var)
|
||||
if(ACCEPT_MN)
|
||||
set(MODULE_NAME "${src}")
|
||||
set(ACCEPT_MN OFF)
|
||||
elseif("NO_WERROR" STREQUAL "${src}")
|
||||
set(TWAE OFF)
|
||||
elseif("MODULE" STREQUAL "${src}")
|
||||
set(ACCEPT_MN ON)
|
||||
elseif("NO_UBUILD" STREQUAL "${src}")
|
||||
set(NO_UBUILD ON)
|
||||
else()
|
||||
if(IS_ABSOLUTE "${src}")
|
||||
set(fp "${src}")
|
||||
else()
|
||||
set(fp "${CWD}/${src}")
|
||||
endif()
|
||||
get_source_file_property(IS_GENERATED ${fp} GENERATED)
|
||||
if(EXISTS ${fp} OR ${IS_GENERATED})
|
||||
if("${fp}" MATCHES "\\.(cpp|mm|c|m)\$" AND TWAE)
|
||||
set_source_files_properties("${fp}" PROPERTIES
|
||||
COMPILE_FLAGS "${WERROR_FLAGS}"
|
||||
)
|
||||
endif()
|
||||
if("${fp}" MATCHES "\\.(cpp|mm|c|m)\$" AND NO_UBUILD)
|
||||
set_source_files_properties("${fp}" PROPERTIES
|
||||
SKIP_UNITY_BUILD_INCLUSION ON
|
||||
)
|
||||
endif()
|
||||
list(APPEND ${MODULE_NAME}_SOURCE_LIST "${fp}")
|
||||
else()
|
||||
message(FATAL_ERROR "Cocos souce file not exists: \"${src}\", is generated ${IS_GENERATED}")
|
||||
endif()
|
||||
set(TWAE ON)
|
||||
set(NO_UBUILD OFF)
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
################################# inspect_values ###################################
|
||||
function(cc_inspect_values)
|
||||
set(list_var "${ARGN}")
|
||||
foreach(src IN LISTS list_var)
|
||||
set(opv ${${src}})
|
||||
message(STATUS "OPTION ${src}:\t${opv}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(cc_parse_cfg_include_files cfg_file output_var)
|
||||
file(STRINGS ${cfg_file} my_lines)
|
||||
set(include_pattern "^%include *\"([^\"]*)\" *$")
|
||||
set(include_files "")
|
||||
foreach(line ${my_lines})
|
||||
if(line MATCHES ${include_pattern})
|
||||
# keep syncing with SWIG_ARGS
|
||||
set(include_file ${CMAKE_CURRENT_LIST_DIR}/cocos/${CMAKE_MATCH_1})
|
||||
set(include_file2 ${CMAKE_CURRENT_LIST_DIR}/${CMAKE_MATCH_1})
|
||||
if(EXISTS ${include_file})
|
||||
list(APPEND include_files ${include_file})
|
||||
elseif(EXISTS ${include_file2})
|
||||
list(APPEND include_files ${include_file2})
|
||||
else()
|
||||
message(FATAL_ERROR "%include ${include_file}: file not found")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(${output_var} ${include_files} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(cc_gen_swig_files cfg_directory output_dir)
|
||||
file(MAKE_DIRECTORY "${output_dir}")
|
||||
if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(SWIG_DIR ${EXTERNAL_ROOT}/win64/bin/swig)
|
||||
set(SWIG_EXEC ${SWIG_DIR}/bin/swig.exe)
|
||||
elseif(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(SWIG_DIR ${EXTERNAL_ROOT}/mac/bin/swig)
|
||||
set(SWIG_EXEC ${SWIG_DIR}/bin/swig)
|
||||
elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(SWIG_DIR ${EXTERNAL_ROOT}/linux/bin/swig)
|
||||
set(SWIG_EXEC ${SWIG_DIR}/bin/swig)
|
||||
else()
|
||||
message(FATAL_ERROR "swig is not supported on current platform!")
|
||||
endif()
|
||||
|
||||
set(SWIG_ARGS
|
||||
-c++
|
||||
-cocos
|
||||
-fvirtual
|
||||
-noexcept
|
||||
-cpperraswarn
|
||||
-D__clang__
|
||||
-Dfinal=
|
||||
-DCC_PLATFORM=3
|
||||
-Dconstexpr=const
|
||||
-DCC_PLATFORM_ANDROID=3
|
||||
-I${SWIG_DIR}/share/swig/4.1.0/javascript/cocos
|
||||
-I${SWIG_DIR}/share/swig/4.1.0
|
||||
-I${CMAKE_CURRENT_LIST_DIR}/
|
||||
-I${CMAKE_CURRENT_LIST_DIR}/cocos
|
||||
-o
|
||||
)
|
||||
file(GLOB cfg_files ${cfg_directory}/*.i)
|
||||
|
||||
list(FILTER cfg_files EXCLUDE REGEX ".*template.*")
|
||||
foreach(cfg ${cfg_files})
|
||||
|
||||
set(dep_files)
|
||||
get_filename_component(mod_name ${cfg} NAME_WE)
|
||||
set(output_file_tmp ${output_dir}/temp/jsb_${mod_name}_auto.cpp)
|
||||
set(output_file ${output_dir}/jsb_${mod_name}_auto.cpp)
|
||||
|
||||
set(output_hfile_tmp ${output_dir}/temp/jsb_${mod_name}_auto.h)
|
||||
set(output_hfile ${output_dir}/jsb_${mod_name}_auto.h)
|
||||
|
||||
cc_parse_cfg_include_files(${cfg} dep_files)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${output_hfile}
|
||||
${output_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running swig with config file ${cfg} ..."
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir}/temp
|
||||
COMMAND ${SWIG_EXEC} ${SWIG_ARGS}
|
||||
${output_file_tmp}
|
||||
${cfg}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${output_file_tmp} ${output_file}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${output_hfile_tmp} ${output_hfile}
|
||||
DEPENDS ${cfg} ${dep_files}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
|
||||
)
|
||||
set_source_files_properties(${output_file}
|
||||
PROPERTIES
|
||||
GENERATED TRUE
|
||||
LOCATION ${output_file}
|
||||
)
|
||||
get_source_file_property(IS_GENERATED ${output_file} GENERATED)
|
||||
|
||||
endforeach()
|
||||
endfunction(cc_gen_swig_files)
|
||||
|
||||
function(cc_set_target_property target_name property value)
|
||||
set_target_properties(${target_name} PROPERTIES CC_${property} ${value})
|
||||
endfunction()
|
||||
|
||||
function(cc_get_target_property output target_name property)
|
||||
get_target_property(output ${target_name} ${property})
|
||||
endfunction()
|
||||
|
||||
function(cc_redirect_property target from_property to_property)
|
||||
cc_get_target_property(output ${target} ${from_property})
|
||||
if(output)
|
||||
set_target_properties(${target_name} PROPERTIES
|
||||
${to_property} ${output}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(NOT DEFINED NODE_EXECUTABLE)
|
||||
if(DEFINED EDITOR_NODEJS)
|
||||
set(NODE_EXECUTABLE ${EDITOR_NODEJS})
|
||||
elseif(DEFINED ENV{NODE_EXECUTABLE})
|
||||
set(NODE_EXECUTABLE $ENV{NODE_EXECUTABLE})
|
||||
message(STATUS "set NODE_EXECUTABLE by env")
|
||||
else()
|
||||
find_program(NODE_EXECUTABLE NAMES node)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT DEFINED TSC_EXECUTABLE)
|
||||
find_program(TSC_EXECUTABLE NAMES tsc)
|
||||
endif()
|
||||
if(NOT DEFINED CCACHE_EXECUTABLE)
|
||||
find_program(CCACHE_EXECUTABLE NAMES ccache)
|
||||
endif()
|
||||
|
||||
## predefined configurations for game applications
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../templates/cmake/common.cmake)
|
||||
if(APPLE)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../templates/cmake/apple.cmake)
|
||||
elseif(WINDOWS)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../emplates/cmake/windows.cmake)
|
||||
elseif(LINUX)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../templates/cmake/linux.cmake)
|
||||
elseif(ANDROID)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../templates/cmake/android.cmake)
|
||||
elseif(OPENHARMONY)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../templates/cmake/openharmony.cmake)
|
||||
elseif(OHOS)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../templates/cmake/ohos.cmake)
|
||||
elseif(QNX)
|
||||
elseif(EMSCRIPTEN)
|
||||
else()
|
||||
message(FATAL_ERROR "Unhandled platform specified cmake utils!")
|
||||
endif()
|
||||
96
cmake/scripts/engine-version.js
Normal file
96
cmake/scripts/engine-version.js
Normal file
@@ -0,0 +1,96 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
|
||||
const pkgCfg = path.join(__dirname, '../../../package.json');
|
||||
|
||||
if (!fs.existsSync(pkgCfg)) {
|
||||
console.error(`Can not find package.json: ${pkgCfg}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let pkgJson = {};
|
||||
try {
|
||||
pkgJson = JSON.parse(fs.readFileSync(pkgCfg, 'utf8'));
|
||||
} catch (err) {
|
||||
console.error(`Error parsing ${pkgCfg}`);
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!pkgJson.version) {
|
||||
console.error(`Can not find field 'version' in file ${pkgCfg}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const version_regex = /(\d+)\.(\d+)(\.(\d+))?(-(\w+))?/;
|
||||
const version_str = pkgJson.version;
|
||||
const version_result = version_str.match(version_regex);
|
||||
|
||||
if (!version_result) {
|
||||
console.error(`Failed to parse version string: '${version_str}'`);
|
||||
process.exit(1);
|
||||
}
|
||||
const majorVersion = parseInt(version_result[1]);
|
||||
const minorVersion = parseInt(version_result[2]);
|
||||
const patchVersion = version_result[4] ? parseInt(version_result[4]) : 0;
|
||||
const preRelease = version_result[6] ? version_result[6] : 'release';
|
||||
const versionIntValue = majorVersion * 10000 + minorVersion * 100 + patchVersion;
|
||||
const fullYear = (new Date).getFullYear();
|
||||
const version_header = `/****************************************************************************
|
||||
Copyright (c) ${fullYear <= 2022 ? "2022" : "2022-"+fullYear} Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#define COCOS_MAJOR_VERSION ${majorVersion}
|
||||
#define COCOS_MINJOR_VERSION ${minorVersion}
|
||||
#define COCOS_PATCH_VERSION ${patchVersion}
|
||||
#define COCOS_VERSION_STRING "${majorVersion}.${minorVersion}.${patchVersion}"
|
||||
#define COCOS_VERSION_DEFINED 1
|
||||
#define COCOS_VERSION ${versionIntValue}
|
||||
|
||||
// #define COCOS_PRE_RELEASE "${preRelease}"
|
||||
`;
|
||||
|
||||
const outputVersionFile = path.join(__dirname, '../../cocos/cocos-version.h');
|
||||
|
||||
if(!fs.existsSync(outputVersionFile) || !compareFileContent(outputVersionFile, version_header)) {
|
||||
console.log(`Update cocos-version.h to ${version_str}`);
|
||||
fs.writeFileSync(outputVersionFile, version_header);
|
||||
} else {
|
||||
console.log(`cocos-version.h is up to date`);
|
||||
}
|
||||
|
||||
function compareFileContent(file, content) {
|
||||
const srcLines = fs.readFileSync(file, 'utf8').split('\n').map(x=>x.trim());
|
||||
const dstLines = content.split('\n').map(x => x.trim());
|
||||
if(srcLines.length !== dstLines.length) {
|
||||
return false;
|
||||
}
|
||||
for(let i = 0, l = srcLines.length; i < l; i++) {
|
||||
if(srcLines[i] != dstLines[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
47
cmake/scripts/gen_debugInfos.js
Normal file
47
cmake/scripts/gen_debugInfos.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const Fs = require('fs');
|
||||
const process = require('process');
|
||||
const writeIfDifferent = require('./utils').writeIfDifferent;
|
||||
|
||||
if (process.argv.length !== 5) {
|
||||
console.error('bad argument');
|
||||
console.error(' - input file');
|
||||
console.error(' - template file');
|
||||
console.error(' - output file');
|
||||
process.exit(-1);
|
||||
}
|
||||
|
||||
const inputFile = process.argv[2];
|
||||
const template = process.argv[3];
|
||||
const outputFile = process.argv[4];
|
||||
|
||||
let buildDebugInfos = function() {
|
||||
let readContent = Fs.readFileSync(inputFile, 'utf-8');
|
||||
let titleRegExp = /### \d+/g;
|
||||
let debugInfos = "";
|
||||
|
||||
let result1 = titleRegExp.exec(readContent);
|
||||
while (result1) {
|
||||
let result2 = titleRegExp.exec(readContent);
|
||||
let errInfoHead = result1.index + result1[0].length;
|
||||
let errInfoTail = result2? result2.index: readContent.length;
|
||||
|
||||
let errCode = /\d+/.exec(result1[0])[0];
|
||||
let errInfo = readContent.slice(errInfoHead, errInfoTail);
|
||||
errInfo = errInfo.replace(/```/g, ' ');
|
||||
errInfo = errInfo.trim();
|
||||
errInfo = errInfo.replace(/\r\n/g, '\n');
|
||||
|
||||
if (!errInfo.includes('<!-- DEPRECATED -->')) {
|
||||
errInfo = errInfo.replace(/\n/g, "\\n").replace(/\"/g, "'").replace(/\\`/g, "`");
|
||||
debugInfos = debugInfos.concat("{ ", errCode, ", \"", errInfo, "\" },\n");
|
||||
}
|
||||
|
||||
result1 = result2;
|
||||
}
|
||||
|
||||
let replaceData = Fs.readFileSync(template).toString('utf-8').replace("${PLACE_HOLDER}", debugInfos);
|
||||
writeIfDifferent(outputFile, replaceData, { encoding: 'utf-8' });
|
||||
};
|
||||
|
||||
buildDebugInfos();
|
||||
process.exit(0);
|
||||
846
cmake/scripts/plugin_support/plugin_cfg.js
Normal file
846
cmake/scripts/plugin_support/plugin_cfg.js
Normal file
@@ -0,0 +1,846 @@
|
||||
/*
|
||||
* Generated by PEG.js 0.10.0.
|
||||
*
|
||||
* http://pegjs.org/
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
function peg$subclass(child, parent) {
|
||||
function ctor() { this.constructor = child; }
|
||||
ctor.prototype = parent.prototype;
|
||||
child.prototype = new ctor();
|
||||
}
|
||||
|
||||
function peg$SyntaxError(message, expected, found, location) {
|
||||
this.message = message;
|
||||
this.expected = expected;
|
||||
this.found = found;
|
||||
this.location = location;
|
||||
this.name = "SyntaxError";
|
||||
|
||||
if (typeof Error.captureStackTrace === "function") {
|
||||
Error.captureStackTrace(this, peg$SyntaxError);
|
||||
}
|
||||
}
|
||||
|
||||
peg$subclass(peg$SyntaxError, Error);
|
||||
|
||||
peg$SyntaxError.buildMessage = function(expected, found) {
|
||||
var DESCRIBE_EXPECTATION_FNS = {
|
||||
literal: function(expectation) {
|
||||
return "\"" + literalEscape(expectation.text) + "\"";
|
||||
},
|
||||
|
||||
"class": function(expectation) {
|
||||
var escapedParts = "",
|
||||
i;
|
||||
|
||||
for (i = 0; i < expectation.parts.length; i++) {
|
||||
escapedParts += expectation.parts[i] instanceof Array
|
||||
? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])
|
||||
: classEscape(expectation.parts[i]);
|
||||
}
|
||||
|
||||
return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
|
||||
},
|
||||
|
||||
any: function(expectation) {
|
||||
return "any character";
|
||||
},
|
||||
|
||||
end: function(expectation) {
|
||||
return "end of input";
|
||||
},
|
||||
|
||||
other: function(expectation) {
|
||||
return expectation.description;
|
||||
}
|
||||
};
|
||||
|
||||
function hex(ch) {
|
||||
return ch.charCodeAt(0).toString(16).toUpperCase();
|
||||
}
|
||||
|
||||
function literalEscape(s) {
|
||||
return s
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\0/g, '\\0')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
|
||||
}
|
||||
|
||||
function classEscape(s) {
|
||||
return s
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/\]/g, '\\]')
|
||||
.replace(/\^/g, '\\^')
|
||||
.replace(/-/g, '\\-')
|
||||
.replace(/\0/g, '\\0')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
|
||||
}
|
||||
|
||||
function describeExpectation(expectation) {
|
||||
return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
|
||||
}
|
||||
|
||||
function describeExpected(expected) {
|
||||
var descriptions = new Array(expected.length),
|
||||
i, j;
|
||||
|
||||
for (i = 0; i < expected.length; i++) {
|
||||
descriptions[i] = describeExpectation(expected[i]);
|
||||
}
|
||||
|
||||
descriptions.sort();
|
||||
|
||||
if (descriptions.length > 0) {
|
||||
for (i = 1, j = 1; i < descriptions.length; i++) {
|
||||
if (descriptions[i - 1] !== descriptions[i]) {
|
||||
descriptions[j] = descriptions[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
descriptions.length = j;
|
||||
}
|
||||
|
||||
switch (descriptions.length) {
|
||||
case 1:
|
||||
return descriptions[0];
|
||||
|
||||
case 2:
|
||||
return descriptions[0] + " or " + descriptions[1];
|
||||
|
||||
default:
|
||||
return descriptions.slice(0, -1).join(", ")
|
||||
+ ", or "
|
||||
+ descriptions[descriptions.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
function describeFound(found) {
|
||||
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
|
||||
}
|
||||
|
||||
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
|
||||
};
|
||||
|
||||
function peg$parse(input, options) {
|
||||
options = options !== void 0 ? options : {};
|
||||
|
||||
var peg$FAILED = {},
|
||||
|
||||
peg$startRuleIndices = { Expression: 0 },
|
||||
peg$startRuleIndex = 0,
|
||||
|
||||
peg$consts = [
|
||||
"||",
|
||||
peg$literalExpectation("||", false),
|
||||
function(head, tail) {
|
||||
let s = [head];
|
||||
s = s.concat(tail.map(x=>x[1]));
|
||||
return new VersionSet(s);
|
||||
},
|
||||
peg$otherExpectation("Condition Items"),
|
||||
function(head, tail) {
|
||||
let s = [head];
|
||||
s = s.concat(tail.map(x=> x[1]));
|
||||
return s;
|
||||
},
|
||||
function(head) {
|
||||
return [head];
|
||||
},
|
||||
">=",
|
||||
peg$literalExpectation(">=", false),
|
||||
function(v) {
|
||||
v.op = OP_GE;
|
||||
return v;
|
||||
},
|
||||
"<=",
|
||||
peg$literalExpectation("<=", false),
|
||||
function(v) {
|
||||
v.op = OP_LE;
|
||||
return v;
|
||||
},
|
||||
"!=",
|
||||
peg$literalExpectation("!=", false),
|
||||
function(v) {
|
||||
v.op = OP_NOT;
|
||||
return v;
|
||||
},
|
||||
"!",
|
||||
peg$literalExpectation("!", false),
|
||||
"=",
|
||||
peg$literalExpectation("=", false),
|
||||
function(v) {
|
||||
v.op = OP_EQ;
|
||||
return v;
|
||||
},
|
||||
"<",
|
||||
peg$literalExpectation("<", false),
|
||||
function(v) {
|
||||
v.op = OP_LT;
|
||||
return v;
|
||||
},
|
||||
">",
|
||||
peg$literalExpectation(">", false),
|
||||
function(v) {
|
||||
v.op = OP_GT;
|
||||
return v;
|
||||
},
|
||||
function(head) {
|
||||
head.op = OP_IS;
|
||||
return head;
|
||||
},
|
||||
peg$otherExpectation("version"),
|
||||
peg$otherExpectation("major.minor.patch"),
|
||||
".",
|
||||
peg$literalExpectation(".", false),
|
||||
function(v, n) { v.patch = n; return v},
|
||||
peg$otherExpectation("major.minor"),
|
||||
function(v, n) {v.minor = n; return v},
|
||||
peg$otherExpectation("major"),
|
||||
function(n) {let v = new Version; v.major = n; return v},
|
||||
"*",
|
||||
peg$literalExpectation("*", false),
|
||||
"x",
|
||||
peg$literalExpectation("x", false),
|
||||
"X",
|
||||
peg$literalExpectation("X", false),
|
||||
function() {return '*';},
|
||||
peg$otherExpectation("integer"),
|
||||
/^[0-9]/,
|
||||
peg$classExpectation([["0", "9"]], false, false),
|
||||
function() { return parseInt(text(), 10); },
|
||||
peg$otherExpectation("whitespace"),
|
||||
/^[ \t\n\r]/,
|
||||
peg$classExpectation([" ", "\t", "\n", "\r"], false, false)
|
||||
],
|
||||
|
||||
peg$bytecode = [
|
||||
peg$decode("%;!/k#$%2 \"\"6 7!/,#;!/#$+\")(\"'#&'#0<*%2 \"\"6 7!/,#;!/#$+\")(\"'#&'#&/)$8\":\"\"\"! )(\"'#&'#"),
|
||||
peg$decode("<%;*/w#;\"/n$$%;)/,#;\"/#$+\")(\"'#&'#/9#06*%;)/,#;\"/#$+\")(\"'#&'#&&&#/2$;*/)$8$:$$\"\"!)($'#(#'#(\"'#&'#.D &%;*/:#;\"/1$;*/($8#:%#!!)(#'#(\"'#&'#=.\" 7#"),
|
||||
peg$decode("%2&\"\"6&7'/:#;*/1$;#/($8#:(#! )(#'#(\"'#&'#.\u013D &%2)\"\"6)7*/:#;*/1$;#/($8#:+#! )(#'#(\"'#&'#.\u0110 &%2,\"\"6,7-/:#;*/1$;#/($8#:.#! )(#'#(\"'#&'#.\xE3 &%2/\"\"6/70/:#;*/1$;#/($8#:.#! )(#'#(\"'#&'#.\xB6 &%21\"\"6172/:#;*/1$;#/($8#:3#! )(#'#(\"'#&'#.\x89 &%24\"\"6475/:#;*/1$;#/($8#:6#! )(#'#(\"'#&'#.\\ &%27\"\"6778/:#;*/1$;#/($8#:9#! )(#'#(\"'#&'#./ &%;#/' 8!::!! )"),
|
||||
peg$decode("<;$.) &;%.# &;&=.\" 7;"),
|
||||
peg$decode("<%;%/A#2=\"\"6=7>/2$;'/)$8#:?#\"\" )(#'#(\"'#&'#=.\" 7<"),
|
||||
peg$decode("<%;&/A#2=\"\"6=7>/2$;'/)$8#:A#\"\" )(#'#(\"'#&'#=.\" 7@"),
|
||||
peg$decode("<%;'/' 8!:C!! )=.\" 7B"),
|
||||
peg$decode("%2D\"\"6D7E.5 &2F\"\"6F7G.) &2H\"\"6H7I/& 8!:J! ).# &;("),
|
||||
peg$decode("<%$4L\"\"5!7M/,#0)*4L\"\"5!7M&&&#/& 8!:N! )=.\" 7K"),
|
||||
peg$decode("<$4P\"\"5!7Q/,#0)*4P\"\"5!7Q&&&#=.\" 7O"),
|
||||
peg$decode("<$4P\"\"5!7Q0)*4P\"\"5!7Q&=.\" 7O")
|
||||
],
|
||||
|
||||
peg$currPos = 0,
|
||||
peg$savedPos = 0,
|
||||
peg$posDetailsCache = [{ line: 1, column: 1 }],
|
||||
peg$maxFailPos = 0,
|
||||
peg$maxFailExpected = [],
|
||||
peg$silentFails = 0,
|
||||
|
||||
peg$result;
|
||||
|
||||
if ("startRule" in options) {
|
||||
if (!(options.startRule in peg$startRuleIndices)) {
|
||||
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
||||
}
|
||||
|
||||
peg$startRuleIndex = peg$startRuleIndices[options.startRule];
|
||||
}
|
||||
|
||||
function text() {
|
||||
return input.substring(peg$savedPos, peg$currPos);
|
||||
}
|
||||
|
||||
function location() {
|
||||
return peg$computeLocation(peg$savedPos, peg$currPos);
|
||||
}
|
||||
|
||||
function expected(description, location) {
|
||||
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
|
||||
|
||||
throw peg$buildStructuredError(
|
||||
[peg$otherExpectation(description)],
|
||||
input.substring(peg$savedPos, peg$currPos),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function error(message, location) {
|
||||
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
|
||||
|
||||
throw peg$buildSimpleError(message, location);
|
||||
}
|
||||
|
||||
function peg$literalExpectation(text, ignoreCase) {
|
||||
return { type: "literal", text: text, ignoreCase: ignoreCase };
|
||||
}
|
||||
|
||||
function peg$classExpectation(parts, inverted, ignoreCase) {
|
||||
return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
|
||||
}
|
||||
|
||||
function peg$anyExpectation() {
|
||||
return { type: "any" };
|
||||
}
|
||||
|
||||
function peg$endExpectation() {
|
||||
return { type: "end" };
|
||||
}
|
||||
|
||||
function peg$otherExpectation(description) {
|
||||
return { type: "other", description: description };
|
||||
}
|
||||
|
||||
function peg$computePosDetails(pos) {
|
||||
var details = peg$posDetailsCache[pos], p;
|
||||
|
||||
if (details) {
|
||||
return details;
|
||||
} else {
|
||||
p = pos - 1;
|
||||
while (!peg$posDetailsCache[p]) {
|
||||
p--;
|
||||
}
|
||||
|
||||
details = peg$posDetailsCache[p];
|
||||
details = {
|
||||
line: details.line,
|
||||
column: details.column
|
||||
};
|
||||
|
||||
while (p < pos) {
|
||||
if (input.charCodeAt(p) === 10) {
|
||||
details.line++;
|
||||
details.column = 1;
|
||||
} else {
|
||||
details.column++;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
peg$posDetailsCache[pos] = details;
|
||||
return details;
|
||||
}
|
||||
}
|
||||
|
||||
function peg$computeLocation(startPos, endPos) {
|
||||
var startPosDetails = peg$computePosDetails(startPos),
|
||||
endPosDetails = peg$computePosDetails(endPos);
|
||||
|
||||
return {
|
||||
start: {
|
||||
offset: startPos,
|
||||
line: startPosDetails.line,
|
||||
column: startPosDetails.column
|
||||
},
|
||||
end: {
|
||||
offset: endPos,
|
||||
line: endPosDetails.line,
|
||||
column: endPosDetails.column
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function peg$fail(expected) {
|
||||
if (peg$currPos < peg$maxFailPos) { return; }
|
||||
|
||||
if (peg$currPos > peg$maxFailPos) {
|
||||
peg$maxFailPos = peg$currPos;
|
||||
peg$maxFailExpected = [];
|
||||
}
|
||||
|
||||
peg$maxFailExpected.push(expected);
|
||||
}
|
||||
|
||||
function peg$buildSimpleError(message, location) {
|
||||
return new peg$SyntaxError(message, null, null, location);
|
||||
}
|
||||
|
||||
function peg$buildStructuredError(expected, found, location) {
|
||||
return new peg$SyntaxError(
|
||||
peg$SyntaxError.buildMessage(expected, found),
|
||||
expected,
|
||||
found,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function peg$decode(s) {
|
||||
var bc = new Array(s.length), i;
|
||||
|
||||
for (i = 0; i < s.length; i++) {
|
||||
bc[i] = s.charCodeAt(i) - 32;
|
||||
}
|
||||
|
||||
return bc;
|
||||
}
|
||||
|
||||
function peg$parseRule(index) {
|
||||
var bc = peg$bytecode[index],
|
||||
ip = 0,
|
||||
ips = [],
|
||||
end = bc.length,
|
||||
ends = [],
|
||||
stack = [],
|
||||
params, i;
|
||||
|
||||
while (true) {
|
||||
while (ip < end) {
|
||||
switch (bc[ip]) {
|
||||
case 0:
|
||||
stack.push(peg$consts[bc[ip + 1]]);
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
stack.push(void 0);
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
stack.push(null);
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
stack.push(peg$FAILED);
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
stack.push([]);
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
stack.push(peg$currPos);
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
stack.pop();
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
peg$currPos = stack.pop();
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
stack.length -= bc[ip + 1];
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
stack.splice(-2, 1);
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
stack[stack.length - 2].push(stack.pop());
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 11:
|
||||
stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1]));
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
stack.push(input.substring(stack.pop(), peg$currPos));
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
ends.push(end);
|
||||
ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
|
||||
|
||||
if (stack[stack.length - 1]) {
|
||||
end = ip + 3 + bc[ip + 1];
|
||||
ip += 3;
|
||||
} else {
|
||||
end = ip + 3 + bc[ip + 1] + bc[ip + 2];
|
||||
ip += 3 + bc[ip + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 14:
|
||||
ends.push(end);
|
||||
ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
|
||||
|
||||
if (stack[stack.length - 1] === peg$FAILED) {
|
||||
end = ip + 3 + bc[ip + 1];
|
||||
ip += 3;
|
||||
} else {
|
||||
end = ip + 3 + bc[ip + 1] + bc[ip + 2];
|
||||
ip += 3 + bc[ip + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 15:
|
||||
ends.push(end);
|
||||
ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
|
||||
|
||||
if (stack[stack.length - 1] !== peg$FAILED) {
|
||||
end = ip + 3 + bc[ip + 1];
|
||||
ip += 3;
|
||||
} else {
|
||||
end = ip + 3 + bc[ip + 1] + bc[ip + 2];
|
||||
ip += 3 + bc[ip + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 16:
|
||||
if (stack[stack.length - 1] !== peg$FAILED) {
|
||||
ends.push(end);
|
||||
ips.push(ip);
|
||||
|
||||
end = ip + 2 + bc[ip + 1];
|
||||
ip += 2;
|
||||
} else {
|
||||
ip += 2 + bc[ip + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 17:
|
||||
ends.push(end);
|
||||
ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
|
||||
|
||||
if (input.length > peg$currPos) {
|
||||
end = ip + 3 + bc[ip + 1];
|
||||
ip += 3;
|
||||
} else {
|
||||
end = ip + 3 + bc[ip + 1] + bc[ip + 2];
|
||||
ip += 3 + bc[ip + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 18:
|
||||
ends.push(end);
|
||||
ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);
|
||||
|
||||
if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === peg$consts[bc[ip + 1]]) {
|
||||
end = ip + 4 + bc[ip + 2];
|
||||
ip += 4;
|
||||
} else {
|
||||
end = ip + 4 + bc[ip + 2] + bc[ip + 3];
|
||||
ip += 4 + bc[ip + 2];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 19:
|
||||
ends.push(end);
|
||||
ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);
|
||||
|
||||
if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLowerCase() === peg$consts[bc[ip + 1]]) {
|
||||
end = ip + 4 + bc[ip + 2];
|
||||
ip += 4;
|
||||
} else {
|
||||
end = ip + 4 + bc[ip + 2] + bc[ip + 3];
|
||||
ip += 4 + bc[ip + 2];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 20:
|
||||
ends.push(end);
|
||||
ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);
|
||||
|
||||
if (peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))) {
|
||||
end = ip + 4 + bc[ip + 2];
|
||||
ip += 4;
|
||||
} else {
|
||||
end = ip + 4 + bc[ip + 2] + bc[ip + 3];
|
||||
ip += 4 + bc[ip + 2];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 21:
|
||||
stack.push(input.substr(peg$currPos, bc[ip + 1]));
|
||||
peg$currPos += bc[ip + 1];
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 22:
|
||||
stack.push(peg$consts[bc[ip + 1]]);
|
||||
peg$currPos += peg$consts[bc[ip + 1]].length;
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 23:
|
||||
stack.push(peg$FAILED);
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$consts[bc[ip + 1]]);
|
||||
}
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
peg$savedPos = stack[stack.length - 1 - bc[ip + 1]];
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 25:
|
||||
peg$savedPos = peg$currPos;
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 26:
|
||||
params = bc.slice(ip + 4, ip + 4 + bc[ip + 3]);
|
||||
for (i = 0; i < bc[ip + 3]; i++) {
|
||||
params[i] = stack[stack.length - 1 - params[i]];
|
||||
}
|
||||
|
||||
stack.splice(
|
||||
stack.length - bc[ip + 2],
|
||||
bc[ip + 2],
|
||||
peg$consts[bc[ip + 1]].apply(null, params)
|
||||
);
|
||||
|
||||
ip += 4 + bc[ip + 3];
|
||||
break;
|
||||
|
||||
case 27:
|
||||
stack.push(peg$parseRule(bc[ip + 1]));
|
||||
ip += 2;
|
||||
break;
|
||||
|
||||
case 28:
|
||||
peg$silentFails++;
|
||||
ip++;
|
||||
break;
|
||||
|
||||
case 29:
|
||||
peg$silentFails--;
|
||||
ip++;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Invalid opcode: " + bc[ip] + ".");
|
||||
}
|
||||
}
|
||||
|
||||
if (ends.length > 0) {
|
||||
end = ends.pop();
|
||||
ip = ips.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return stack[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const OP_EQ = "equal";
|
||||
const OP_IS = OP_EQ;
|
||||
const OP_GT = "greater";
|
||||
const OP_GE= "greaterequal";
|
||||
const OP_LT= "less";
|
||||
const OP_LE= "lessequal";
|
||||
const OP_NOT = "not";
|
||||
|
||||
const VERBOSE = false;
|
||||
|
||||
function Version(){
|
||||
this.major = null;
|
||||
this.minor = null;
|
||||
this.patch = null;
|
||||
this.op = null;
|
||||
}
|
||||
|
||||
const P = Version.prototype;
|
||||
|
||||
P.toString = function() {
|
||||
return `[${this.op ? this.op : "?"}]/v${this.major}.${this.minor}.${this.patch}`;
|
||||
}
|
||||
|
||||
Object.defineProperty(Version.prototype, 'wildcard', {
|
||||
get: function() {
|
||||
return this.major === '*' || this.minor === '*' || this.patch === '*';
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Version.prototype, 'anyMajor', {
|
||||
get: function() { return this.major === '*';}
|
||||
});
|
||||
Object.defineProperty(Version.prototype, 'anyMinor', {
|
||||
get: function() { return this.minor === '*';}
|
||||
});
|
||||
Object.defineProperty(Version.prototype, 'anyPatch', {
|
||||
get: function() { return this.patch === '*';}
|
||||
});
|
||||
P.toArray = function() {
|
||||
const r = [];
|
||||
if(this.major !== null) {
|
||||
r.push(this.major);
|
||||
}
|
||||
if(this.minor !== null) {
|
||||
r.push(this.minor);
|
||||
}
|
||||
if(this.patch !== null) {
|
||||
r.push(this.patch);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
P.assertNotWildcard = function() {
|
||||
if(this.wildcard) {
|
||||
throw new Error("Source version should not be wildcard: "+this.toString());
|
||||
}
|
||||
}
|
||||
|
||||
P.compareTo = function(o) {
|
||||
this.assertNotWildcard();
|
||||
if(o.wildcard) {
|
||||
throw new Error("Reference version should not be wildcard when comparing!");
|
||||
}
|
||||
const va = this.toArray();
|
||||
const vb = o.toArray();
|
||||
const l = Math.min(va.length, vb.length);
|
||||
let fillZeros = (a, l, ml) =>{ for(let i = l; i < ml; i++) a[i] = 0;}
|
||||
fillZeros(va, l, 3);
|
||||
fillZeros(vb, l, 3);
|
||||
let toFactor = (v) => {return (v[0] << 20) + (v[1] << 10) + (v[2]);}
|
||||
return toFactor(va) - toFactor(vb);
|
||||
};
|
||||
P.match = function(o) {
|
||||
if(VERBOSE) {
|
||||
console.log(`try match ${o}`);
|
||||
}
|
||||
this.assertNotWildcard();
|
||||
if(!o.wildcard) {
|
||||
throw new Error("Reference version should be wildcard when matching!");
|
||||
}
|
||||
|
||||
if(VERBOSE) {
|
||||
console.log(` match major ${o.major}, any ${o.anyMajor}, ${this.major} <> ${o.major}`);
|
||||
}
|
||||
if(o.anyMajor) return true;
|
||||
if(this.major !== o.major) return false;
|
||||
|
||||
if(VERBOSE) {
|
||||
console.log(` match minor ${o.minor}, any ${o.anyMinor}, ${this.minor} <> ${o.minor}`);
|
||||
}
|
||||
if(o.anyMinor) return true;
|
||||
if(this.minor !== o.minor) return false;
|
||||
|
||||
if(VERBOSE) {
|
||||
console.log(` match patch ${o.patch}, any ${o.anyPatch}`);
|
||||
}
|
||||
if(o.anyPatch) return true;
|
||||
return this.patch == o.patch;
|
||||
};
|
||||
|
||||
P.test = function(o) {
|
||||
let op = o.op;
|
||||
if(op === OP_EQ) {
|
||||
return o.wildcard ? this.match(o) : this.compareTo(o) === 0;
|
||||
}
|
||||
if(op === OP_NOT) {
|
||||
return o.wildcard ? !this.match(o) : this.compareTo(o) !== 0;
|
||||
}
|
||||
if(o.wildcard){
|
||||
throw new Error("Can not compare to wildcard version");
|
||||
}
|
||||
const R = this.compareTo(o);
|
||||
if(op === OP_GE) {
|
||||
return R >= 0;
|
||||
}
|
||||
if(op === OP_LE) {
|
||||
return R <= 0;
|
||||
}
|
||||
if(op === OP_GT) {
|
||||
return R > 0;
|
||||
}
|
||||
if(op === OP_LT) {
|
||||
return R < 0;
|
||||
}
|
||||
throw new Error("invalidate operation " + op);
|
||||
};
|
||||
|
||||
function VersionSet(data) {
|
||||
this.conds = data;
|
||||
}
|
||||
|
||||
function allMatch(v, versions) {
|
||||
let t;
|
||||
let r = true;
|
||||
for(let c of versions) {
|
||||
t = v.test(c);
|
||||
if(VERBOSE) {
|
||||
console.log(`test ${v} with ${c} => ${t}`);
|
||||
}
|
||||
if(!t){
|
||||
r = false;
|
||||
if(!VERBOSE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function arrElmOr(arr, idx, dft){
|
||||
if(arr[idx] === undefined) return dft;
|
||||
return arr[idx];
|
||||
}
|
||||
|
||||
VersionSet.prototype.match = function(o) {
|
||||
let ps = o.split('.');
|
||||
let v = new Version;
|
||||
v.major = parseInt(arrElmOr(ps, 0, 0), 10);
|
||||
v.minor = parseInt(arrElmOr(ps, 1, 0), 10);
|
||||
v.patch = parseInt(arrElmOr(ps, 2, 0), 10);
|
||||
if(VERBOSE) {
|
||||
console.log(`match version ${v}`);
|
||||
}
|
||||
for(let c of this.conds){
|
||||
if(allMatch(v, c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
peg$result = peg$parseRule(peg$startRuleIndex);
|
||||
|
||||
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
|
||||
return peg$result;
|
||||
} else {
|
||||
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
|
||||
peg$fail(peg$endExpectation());
|
||||
}
|
||||
|
||||
throw peg$buildStructuredError(
|
||||
peg$maxFailExpected,
|
||||
peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
|
||||
peg$maxFailPos < input.length
|
||||
? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
|
||||
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SyntaxError: peg$SyntaxError,
|
||||
parse: peg$parse
|
||||
};
|
||||
251
cmake/scripts/plugin_support/plugin_cfg.pegjs
Normal file
251
cmake/scripts/plugin_support/plugin_cfg.pegjs
Normal file
@@ -0,0 +1,251 @@
|
||||
// Simple Version Grammar
|
||||
|
||||
{
|
||||
|
||||
const OP_EQ = "equal";
|
||||
const OP_IS = OP_EQ;
|
||||
const OP_GT = "greater";
|
||||
const OP_GE= "greaterequal";
|
||||
const OP_LT= "less";
|
||||
const OP_LE= "lessequal";
|
||||
const OP_NOT = "not";
|
||||
|
||||
const VERBOSE = false;
|
||||
|
||||
function Version(){
|
||||
this.major = null;
|
||||
this.minor = null;
|
||||
this.patch = null;
|
||||
this.op = null;
|
||||
}
|
||||
|
||||
const P = Version.prototype;
|
||||
|
||||
P.toString = function() {
|
||||
return `[${this.op ? this.op : "?"}]/v${this.major}.${this.minor}.${this.patch}`;
|
||||
}
|
||||
|
||||
Object.defineProperty(Version.prototype, 'wildcard', {
|
||||
get: function() {
|
||||
return this.major === '*' || this.minor === '*' || this.patch === '*';
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Version.prototype, 'anyMajor', {
|
||||
get: function() { return this.major === '*';}
|
||||
});
|
||||
Object.defineProperty(Version.prototype, 'anyMinor', {
|
||||
get: function() { return this.minor === '*';}
|
||||
});
|
||||
Object.defineProperty(Version.prototype, 'anyPatch', {
|
||||
get: function() { return this.patch === '*';}
|
||||
});
|
||||
P.toArray = function() {
|
||||
const r = [];
|
||||
if(this.major !== null) {
|
||||
r.push(this.major);
|
||||
}
|
||||
if(this.minor !== null) {
|
||||
r.push(this.minor);
|
||||
}
|
||||
if(this.patch !== null) {
|
||||
r.push(this.patch);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
P.assertNotWildcard = function() {
|
||||
if(this.wildcard) {
|
||||
throw new Error("Source version should not be wildcard: "+this.toString());
|
||||
}
|
||||
}
|
||||
|
||||
P.compareTo = function(o) {
|
||||
this.assertNotWildcard();
|
||||
if(o.wildcard) {
|
||||
throw new Error("Reference version should not be wildcard when comparing!");
|
||||
}
|
||||
const va = this.toArray();
|
||||
const vb = o.toArray();
|
||||
const l = Math.min(va.length, vb.length);
|
||||
let fillZeros = (a, l, ml) =>{ for(let i = l; i < ml; i++) a[i] = 0;}
|
||||
fillZeros(va, l, 3);
|
||||
fillZeros(vb, l, 3);
|
||||
let toFactor = (v) => {return (v[0] << 20) + (v[1] << 10) + (v[2]);}
|
||||
return toFactor(va) - toFactor(vb);
|
||||
};
|
||||
P.match = function(o) {
|
||||
if(VERBOSE) {
|
||||
console.log(`try match ${o}`);
|
||||
}
|
||||
this.assertNotWildcard();
|
||||
if(!o.wildcard) {
|
||||
throw new Error("Reference version should be wildcard when matching!");
|
||||
}
|
||||
|
||||
if(VERBOSE) {
|
||||
console.log(` match major ${o.major}, any ${o.anyMajor}, ${this.major} <> ${o.major}`);
|
||||
}
|
||||
if(o.anyMajor) return true;
|
||||
if(this.major !== o.major) return false;
|
||||
|
||||
if(VERBOSE) {
|
||||
console.log(` match minor ${o.minor}, any ${o.anyMinor}, ${this.minor} <> ${o.minor}`);
|
||||
}
|
||||
if(o.anyMinor) return true;
|
||||
if(this.minor !== o.minor) return false;
|
||||
|
||||
if(VERBOSE) {
|
||||
console.log(` match patch ${o.patch}, any ${o.anyPatch}`);
|
||||
}
|
||||
if(o.anyPatch) return true;
|
||||
return this.patch == o.patch;
|
||||
};
|
||||
|
||||
P.test = function(o) {
|
||||
let op = o.op;
|
||||
if(op === OP_EQ) {
|
||||
return o.wildcard ? this.match(o) : this.compareTo(o) === 0;
|
||||
}
|
||||
if(op === OP_NOT) {
|
||||
return o.wildcard ? !this.match(o) : this.compareTo(o) !== 0;
|
||||
}
|
||||
if(o.wildcard){
|
||||
throw new Error("Can not compare to wildcard version");
|
||||
}
|
||||
const R = this.compareTo(o);
|
||||
if(op === OP_GE) {
|
||||
return R >= 0;
|
||||
}
|
||||
if(op === OP_LE) {
|
||||
return R <= 0;
|
||||
}
|
||||
if(op === OP_GT) {
|
||||
return R > 0;
|
||||
}
|
||||
if(op === OP_LT) {
|
||||
return R < 0;
|
||||
}
|
||||
throw new Error("invalidate operation " + op);
|
||||
};
|
||||
|
||||
function VersionSet(data) {
|
||||
this.conds = data;
|
||||
}
|
||||
|
||||
function allMatch(v, versions) {
|
||||
let t;
|
||||
let r = true;
|
||||
for(let c of versions) {
|
||||
t = v.test(c);
|
||||
if(VERBOSE) {
|
||||
console.log(`test ${v} with ${c} => ${t}`);
|
||||
}
|
||||
if(!t){
|
||||
r = false;
|
||||
if(!VERBOSE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function arrElmOr(arr, idx, dft){
|
||||
if(arr[idx] === undefined) return dft;
|
||||
return arr[idx];
|
||||
}
|
||||
|
||||
VersionSet.prototype.match = function(o) {
|
||||
let ps = o.split('.');
|
||||
let v = new Version;
|
||||
v.major = parseInt(arrElmOr(ps, 0, 0), 10);
|
||||
v.minor = parseInt(arrElmOr(ps, 1, 0), 10);
|
||||
v.patch = parseInt(arrElmOr(ps, 2, 0), 10);
|
||||
if(VERBOSE) {
|
||||
console.log(`match version ${v}`);
|
||||
}
|
||||
for(let c of this.conds){
|
||||
if(allMatch(v, c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Expression
|
||||
= head:Conds tail:('||' Conds)* {
|
||||
let s = [head];
|
||||
s = s.concat(tail.map(x=>x[1]));
|
||||
return new VersionSet(s);
|
||||
}
|
||||
|
||||
Conds "Condition Items"
|
||||
= _ head:Cond tail:(S Cond)+ _ {
|
||||
let s = [head];
|
||||
s = s.concat(tail.map(x=> x[1]));
|
||||
return s;
|
||||
}
|
||||
/ _ head: Cond _ {
|
||||
return [head];
|
||||
}
|
||||
|
||||
Cond
|
||||
= '>=' _ v:Version {
|
||||
v.op = OP_GE;
|
||||
return v;
|
||||
}
|
||||
/ '<=' _ v:Version {
|
||||
v.op = OP_LE;
|
||||
return v;
|
||||
}
|
||||
/ '!=' _ v:Version {
|
||||
v.op = OP_NOT;
|
||||
return v;
|
||||
}
|
||||
/ '!' _ v:Version {
|
||||
v.op = OP_NOT;
|
||||
return v;
|
||||
}
|
||||
/ '=' _ v:Version {
|
||||
v.op = OP_EQ;
|
||||
return v;
|
||||
}
|
||||
/ '<' _ v:Version {
|
||||
v.op = OP_LT;
|
||||
return v;
|
||||
}
|
||||
/ '>'_ v:Version {
|
||||
v.op = OP_GT;
|
||||
return v;
|
||||
}
|
||||
/ head:Version {
|
||||
head.op = OP_IS;
|
||||
return head;
|
||||
}
|
||||
|
||||
Version "version"
|
||||
= V3 / V2 / V1
|
||||
|
||||
V3 "major.minor.patch"
|
||||
= v:V2 '.' n:Factor { v.patch = n; return v}
|
||||
|
||||
V2 "major.minor"
|
||||
= v:V1 '.' n:Factor {v.minor = n; return v}
|
||||
|
||||
V1 "major"
|
||||
= n:Factor {let v = new Version; v.major = n; return v}
|
||||
|
||||
|
||||
Factor
|
||||
= ('*' / 'x' / 'X') {return '*';}
|
||||
/ Integer
|
||||
|
||||
Integer "integer"
|
||||
= [0-9]+ { return parseInt(text(), 10); }
|
||||
|
||||
S "whitespace"
|
||||
= [ \t\n\r]+
|
||||
|
||||
_ "whitespace"
|
||||
= [ \t\n\r]*
|
||||
133
cmake/scripts/plugin_support/test_parse.js
Normal file
133
cmake/scripts/plugin_support/test_parse.js
Normal file
@@ -0,0 +1,133 @@
|
||||
|
||||
|
||||
const parser = require('./plugin_cfg.js');
|
||||
const input_text = `3.4.x 3.5 3 3.* * 6.2.* || > 3.5 <= 3.2 > 2.4 <= 33.2 >=133.222.2 !333 != 22 || 4`;
|
||||
|
||||
// let r = parser.parse(input_text);
|
||||
|
||||
|
||||
|
||||
function assert(label, blk) {
|
||||
console.log(`run ${label}`);
|
||||
let r = blk();
|
||||
if (!r) {
|
||||
console.error(` failed!`);
|
||||
}
|
||||
}
|
||||
|
||||
// r.match("3.2");
|
||||
// r.match("3.4");
|
||||
{
|
||||
let vs = ["3.4", "3.4.*", "3.4.x", "3.4.X"];
|
||||
for (let v of vs) {
|
||||
let s = parser.parse(v);
|
||||
let label = `Simple match ${v}`;
|
||||
assert(`${label} 1`, () => {
|
||||
return s.match("3.4");
|
||||
});
|
||||
assert(`${label} 2`, () => {
|
||||
return !s.match("3.2");
|
||||
});
|
||||
assert(`${label} 2`, () => {
|
||||
return s.match("3.4.3");
|
||||
});
|
||||
assert(`${label} 3`, () => {
|
||||
return s.match("3.4.6");
|
||||
});
|
||||
assert(`${label} 4`, () => {
|
||||
return !s.match("3.444");
|
||||
});
|
||||
assert("dont match", () => {
|
||||
let cases = [
|
||||
"2.4",
|
||||
"2.4.2",
|
||||
"6.4",
|
||||
"3"
|
||||
]
|
||||
return !cases.reduce((p, cs) => p || s.match(cs), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
let s = parser.parse("*");
|
||||
assert("match all", () => {
|
||||
let cases = [
|
||||
"2.4",
|
||||
"2.4.2",
|
||||
"6.4",
|
||||
"3"
|
||||
]
|
||||
return cases.reduce((p, cs) => p && s.match(cs), true);
|
||||
});
|
||||
}
|
||||
{
|
||||
function assert_match(target, versions, bad_versions) {
|
||||
let s = parser.parse(target);
|
||||
for (let v of versions) {
|
||||
assert(`test ${v}`, () => {
|
||||
return s.match(v);
|
||||
});
|
||||
}
|
||||
for (let v of bad_versions) {
|
||||
assert(`test not match ${v}`, () => {
|
||||
return !s.match(v);
|
||||
});
|
||||
}
|
||||
}
|
||||
assert_match(">3.3 <3.6", [
|
||||
'3.4',
|
||||
'3.4.1',
|
||||
'3.4.2',
|
||||
'3.5',
|
||||
'3.5.0',
|
||||
'3.5.1',
|
||||
'3.5.2',
|
||||
],
|
||||
[
|
||||
'3.3',
|
||||
'3.3.2',
|
||||
'2.3',
|
||||
'3.6.0',
|
||||
'3.6',
|
||||
]
|
||||
);
|
||||
assert_match(">=3.3 <= 3.6.0", [
|
||||
'3.3.0',
|
||||
'3.3.1',
|
||||
'3.4',
|
||||
'3.4.1',
|
||||
'3.4.2',
|
||||
'3.5',
|
||||
'3.5.0',
|
||||
'3.5.1',
|
||||
'3.5.2',
|
||||
'3.6.0'
|
||||
],
|
||||
[
|
||||
'3.2.9',
|
||||
'2.3',
|
||||
'3.6.1',
|
||||
]
|
||||
);
|
||||
assert_match(">=3.3 <= 3.6.0 !3.5.2|| 4.x", [
|
||||
'3.3.0',
|
||||
'3.3.1',
|
||||
'3.4',
|
||||
'3.4.1',
|
||||
'3.4.2',
|
||||
'3.5',
|
||||
'3.5.0',
|
||||
'4.0',
|
||||
'4.1',
|
||||
'4.2',
|
||||
'3.5.1',
|
||||
'3.6.0'
|
||||
],
|
||||
[
|
||||
'3.2.9',
|
||||
'2.3',
|
||||
'3.6.1',
|
||||
'3.5.2'
|
||||
]
|
||||
);
|
||||
}
|
||||
271
cmake/scripts/plugins_parser.js
Normal file
271
cmake/scripts/plugins_parser.js
Normal file
@@ -0,0 +1,271 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const version_parser = require('./plugin_support/plugin_cfg');
|
||||
|
||||
const MAX_SEARCH_LEVEL = 7;
|
||||
const CC_PLUGIN_JSON_STR = 'cc_plugin.json';
|
||||
|
||||
const node_path = process.argv.shift();
|
||||
const script_path = process.argv.shift();
|
||||
const search_path_input_file = process.argv.shift();
|
||||
const plugin_cmake_output_file = process.argv.shift();
|
||||
const PLATFORM_NAME_FROM_CMAKE = process.argv.shift();
|
||||
|
||||
const PROJ_SEARCH_PATHS = fs.readFileSync(search_path_input_file, 'utf8').
|
||||
split('\n').
|
||||
map(x => x.trim()).
|
||||
filter(x => x.length > 0 && !x.startsWith("#"));
|
||||
|
||||
const cc_config_json_list = [];
|
||||
|
||||
function search_cc_config_json_levels(dir, depth) {
|
||||
// console.log(`[searching plugins] search dir ${dir}`);
|
||||
if (depth > MAX_SEARCH_LEVEL) return;
|
||||
const st = fs.statSync(dir);
|
||||
if (!st.isDirectory()) return;
|
||||
|
||||
let subfiles = fs.readdirSync(dir);
|
||||
let subdirs = [];
|
||||
for (let item of subfiles) {
|
||||
if (item === "." || item === "..") continue;
|
||||
let fp = path.join(dir, item);
|
||||
const subst = fs.statSync(fp);
|
||||
if (subst.isFile() && item === CC_PLUGIN_JSON_STR) {
|
||||
cc_config_json_list.push(dir);
|
||||
return;
|
||||
}
|
||||
if (subst.isDirectory()) {
|
||||
subdirs.push(fp);
|
||||
}
|
||||
}
|
||||
for (let sd of subdirs) {
|
||||
search_cc_config_json_levels(sd, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (let searchPath of PROJ_SEARCH_PATHS) {
|
||||
if (!fs.existsSync(searchPath)) {
|
||||
console.log(`[searching plugins] directory ${searchPath} does not exist`);
|
||||
continue;
|
||||
}
|
||||
search_cc_config_json_levels(searchPath, 1);
|
||||
}
|
||||
|
||||
|
||||
if (cc_config_json_list.length === 0) {
|
||||
console.log("[searching plugins] no plugins found!");
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
for (let dir of cc_config_json_list) {
|
||||
console.log(`[searching plugins] plugin dir found: ${dir}`)
|
||||
}
|
||||
|
||||
function read_engine_version() {
|
||||
const pkg = path.join(__dirname, '../../../package.json');
|
||||
return require(pkg).version;
|
||||
}
|
||||
|
||||
function parse_package_dependency(info) {
|
||||
let pkgs = [];
|
||||
for (let m of info.modules) {
|
||||
if (m.platforms && m.platforms.indexOf(PLATFORM_NAME_FROM_CMAKE) < 0) {
|
||||
continue;
|
||||
}
|
||||
pkgs.push({ target: m.target, depends: typeof m.depends === 'string' ? [m.depends] : (m.depends || []) });
|
||||
}
|
||||
return pkgs;
|
||||
}
|
||||
|
||||
function get_property_variants(obj, ...names) {
|
||||
for (let n of names) {
|
||||
if (obj.hasOwnProperty(n)) {
|
||||
return obj[n];
|
||||
}
|
||||
if (n.indexOf('_') >= 0) {
|
||||
const k = n.replace(/_/g, '-');
|
||||
if (obj.hasOwnProperty(k)) {
|
||||
return obj[k];
|
||||
}
|
||||
}
|
||||
if (n.indexOf('-') >= 0) {
|
||||
const k = n.replace(/-/g, '_');
|
||||
if (obj.hasOwnProperty(k)) {
|
||||
return obj[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
function test_enable_by_configurations(config) {
|
||||
const support_platforms = get_property_variants(config, "platforms") || [];
|
||||
const enabled_default = get_property_variants(config, "enable", "enabled");
|
||||
const enable_all = enabled_default === undefined ? true : enabled_default;
|
||||
const disable_all = (get_property_variants(config, "disable", "disabled") || false) || !enable_all;
|
||||
const disabled_platforms = get_property_variants(config, "disable-by-platforms", "disabled-by-platforms") || [];
|
||||
const engine_version_value = get_property_variants(config, "engine-version");
|
||||
if (disable_all) {
|
||||
// all disabled
|
||||
console.log(` plugin is disabled.`);
|
||||
return false;
|
||||
}
|
||||
if (support_platforms.length > 0 && support_platforms.indexOf(PLATFORM_NAME_FROM_CMAKE) < 0) {
|
||||
// unsupported platform
|
||||
console.log(` plugin is not supported by current platform ${PLATFORM_NAME_FROM_CMAKE}.`);
|
||||
return false;
|
||||
}
|
||||
if (disabled_platforms.indexOf(PLATFORM_NAME_FROM_CMAKE) > -1) {
|
||||
// disable by user settings
|
||||
console.log(` plugin is disabled by setting.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const ENGINE_VERSION = read_engine_version().replace(/^(v|V)/, '');
|
||||
try {
|
||||
const version_filter = version_parser.parse(engine_version_value);
|
||||
const version_valid = version_filter.match(ENGINE_VERSION);
|
||||
if (!version_valid) {
|
||||
console.warn(` Engine version '${ENGINE_VERSION}' mismatch '${engine_version_value}'`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(` Failed to parse 'engine-version', value: '${engine_version_value}'`);
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function validate_cc_plugin_json_format(tag, content) {
|
||||
const field_required = (obj, field_name) => {
|
||||
if (Object.hasOwnProperty(obj, field_name)) {
|
||||
console.warn(`${tag} field '${field_name}' is not set`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const required_fields = ["name", "version", "engine-version", "author", "description", "modules", "platforms"];
|
||||
for (const f of required_fields) {
|
||||
if (!field_required(content, f)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const modules = content["modules"];
|
||||
if (modules.length == 0) {
|
||||
console.warn(`${tag} modules field is empty`);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let m of modules) {
|
||||
const mod_fields = ["target"];
|
||||
for (const f of mod_fields) {
|
||||
if (!field_required(m, f)) {
|
||||
console.warn(`${tag} module field ${f} is not set`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function add_search_path_suffix(dir, platform) {
|
||||
if (platform.match(/^android/i)) {
|
||||
return [`${dir}/android/\${ANDROID_ABI}`, `${dir}/android`];
|
||||
} else if (platform.match(/^win/i)) {
|
||||
return [`${dir}/windows/x86_64`, `${dir}/windows`];
|
||||
} else if (platform.match(/^iphonesimulator/i)) {
|
||||
return [`${dir}/iphonesimulator`, `${dir}/ios`];
|
||||
} else if (platform.match(/^ios/i)) {
|
||||
return [`${dir}/ios`];
|
||||
} else if (platform.match(/^mac/i) || platform.match(/^darwin/i)) {
|
||||
return [`${dir}/mac/\${CMAKE_SYSTEM_PROCESSOR}`, `${dir}/mac`];
|
||||
} else {
|
||||
console.warn(`Don't knowm suffix for '${platform}`)
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Engine version: ${read_engine_version()}`);
|
||||
|
||||
/// Generate Pre-AutoLoadPlugins.cmake
|
||||
|
||||
let output_lines = ["# plugins found & enabled in search path",
|
||||
"# To disable automatic update of this file, set SKIP_SCAN_PLUGINS to ON.",
|
||||
""];
|
||||
for (let plugin_dir of cc_config_json_list) {
|
||||
let load_plugins = [];
|
||||
try {
|
||||
let maybe_plugin_name = path.basename(plugin_dir);
|
||||
console.log(`Parsing plugin directory ${maybe_plugin_name}`);
|
||||
let cc_plugin_file = path.join(plugin_dir, CC_PLUGIN_JSON_STR);
|
||||
let cc_plugin_content = fs.readFileSync(cc_plugin_file, { encoding: 'utf8' });
|
||||
let cc_plugin_json = JSON.parse(cc_plugin_content);
|
||||
if (!validate_cc_plugin_json_format(`Parsing module ${maybe_plugin_name}:`, cc_plugin_json)) {
|
||||
continue;
|
||||
}
|
||||
if (!test_enable_by_configurations(cc_plugin_json)) {
|
||||
console.log(` ${maybe_plugin_name} disabled by configuration`);
|
||||
continue;
|
||||
}
|
||||
const plugin_name = cc_plugin_json.name;
|
||||
const module_type = get_property_variants(cc_plugin_json, "module_type")
|
||||
if (module_type !== undefined && module_type !== 'release') {
|
||||
console.log(` plugin ${plugin_name} is not a release, should be include or add_subdirectory in dev env.`);
|
||||
continue;
|
||||
}
|
||||
const packages = parse_package_dependency(cc_plugin_json);
|
||||
const cc_project_dir = path.dirname(plugin_cmake_output_file);
|
||||
let project_to_plugin_dir = path.relative(cc_project_dir, plugin_dir).replace(/\\/g, '/');
|
||||
project_to_plugin_dir = `\${CC_PROJECT_DIR}/${project_to_plugin_dir}`;
|
||||
const plugin_root_path_for_platform = add_search_path_suffix(project_to_plugin_dir, PLATFORM_NAME_FROM_CMAKE);
|
||||
for (let pkg of packages) {
|
||||
const [target_name, target_version] = pkg.target.split('@');
|
||||
output_lines.push(`set(${target_name}_ROOT\n${plugin_root_path_for_platform.map(x => ` "${x}"`).join("\n")}\n)`, "");
|
||||
output_lines.push(`list(APPEND CMAKE_FIND_ROOT_PATH \${${target_name}_ROOT})`)
|
||||
load_plugins = load_plugins.concat([...pkg.depends, target_name + (target_version !== undefined ? '@' + target_version : '')]);
|
||||
output_lines.push(`list(APPEND CC_REGISTERED_PLUGINS`);
|
||||
output_lines = output_lines.concat(` ${target_name}`);
|
||||
output_lines.push(`)`);
|
||||
}
|
||||
let plugin_names = load_plugins.map(x => x.split(/@/));
|
||||
for (let plg of plugin_names) {
|
||||
output_lines.push("");
|
||||
if (plg[1] && plg.length > 0) {
|
||||
output_lines.push(`find_package(${plg[0]} ${plg[1]}`);
|
||||
} else {
|
||||
output_lines.push(`find_package(${plg[0]}`);
|
||||
}
|
||||
output_lines.push(` REQUIRED`);
|
||||
output_lines.push(` NAMES "${plg[0]}"`);
|
||||
output_lines.push(`# NO_DEFAULT_PATH`);
|
||||
output_lines.push(`)`);
|
||||
}
|
||||
if (packages.length > 0) {
|
||||
console.log(` record plugin ${plugin_name}`);
|
||||
} else {
|
||||
console.log(` no sub module found`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Parsing plugin directory: ${plugin_dir}`)
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (cc_config_json_list.length == 0) {
|
||||
console.log(`Try unlink file ${out_file}`)
|
||||
if (fs.existsSync(out_file)) {
|
||||
fs.unlinkSync(out_file);
|
||||
}
|
||||
} else {
|
||||
let old_content = null;
|
||||
let new_content = output_lines.join("\n") + "\n";
|
||||
if (fs.existsSync(plugin_cmake_output_file)) {
|
||||
old_content = fs.readFileSync(plugin_cmake_output_file);
|
||||
}
|
||||
if (old_content !== new_content) {
|
||||
fs.writeFileSync(plugin_cmake_output_file, output_lines.join("\n") + "\n", { encoding: 'utf8' });
|
||||
}
|
||||
}
|
||||
process.exit(0);
|
||||
38
cmake/scripts/utils.js
Normal file
38
cmake/scripts/utils.js
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
|
||||
function all_eql(a, b) {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
const l = a.length;
|
||||
for (let i = 0; i < l; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function equals_ignore_spaces(a, b) {
|
||||
const lines_a = a.split('\n').map(x => x.trim());
|
||||
const lines_b = b.split('\n').map(x => x.trim());
|
||||
return all_eql(lines_a, lines_b);
|
||||
}
|
||||
|
||||
|
||||
function writeIfDifferent(file, data, args) {
|
||||
if (fs.existsSync(file)) {
|
||||
let content = fs.readFileSync(file, args).toString(args.encoding);
|
||||
if (equals_ignore_spaces(content, data)) {
|
||||
console.log(`Skip update ${file}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(file, data, args);
|
||||
console.log(` write to file ${file}`);
|
||||
}
|
||||
|
||||
exports.writeIfDifferent = writeIfDifferent;
|
||||
Reference in New Issue
Block a user