mirror of
https://github.com/apple/foundationdb.git
synced 2026-01-24 20:08:38 +00:00
Make FDB_USE_CSHARP_TOOLS authoritative and consistently honored across the build (#12615)
* Make FDB_USE_CSHARP_TOOLS authoritative across the build Historically, FDB_USE_CSHARP_TOOLS acted as a preference hint, and parts of the build could still probe for or assume the presence of C# tooling even when it was disabled. This change makes the option authoritative and consistently honored across the build system. C# tooling is now used only when explicitly enabled and available, and all downstream assumptions are gated accordingly. The default configuration and tool preference order remain unchanged. * cmake files changes * WIP: tmp test * Honor reviewer feedback on C# toolchain detection and actor comparison - Stop assuming C# tooling availability on Windows; explicitly probe for .NET using find_program. - Prefer .NET over mono on all platforms, with mono used only as a fallback. - Fail explicitly when FDB_USE_CSHARP_TOOLS=ON but no C# toolchain is found. - Preserve Python/C# actor output comparison when C# tooling is available, skipping it only when C# is explicitly disabled or unavailable. - Simplify Python argument parsing and remove unnecessary textwrap usage.
This commit is contained in:
@@ -169,24 +169,68 @@ endif()
|
||||
|
||||
include(utils)
|
||||
|
||||
# Flow and other tools are written in C# - so we need that dependency
|
||||
include(EnableCsharp)
|
||||
# First thing we need is the actor compiler
|
||||
option(
|
||||
WITH_CSHARP
|
||||
"Prefer C# build tools (actor compiler, coverage tool, vexillographer) when a toolchain is available"
|
||||
ON)
|
||||
|
||||
set(FDB_USE_CSHARP_TOOLS_EXPLICIT FALSE)
|
||||
if(DEFINED FDB_USE_CSHARP_TOOLS)
|
||||
set(FDB_USE_CSHARP_TOOLS_EXPLICIT TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FDB_USE_CSHARP_TOOLS)
|
||||
set(FDB_USE_CSHARP_TOOLS ${WITH_CSHARP})
|
||||
else()
|
||||
set(WITH_CSHARP ${FDB_USE_CSHARP_TOOLS})
|
||||
endif()
|
||||
|
||||
set(CSHARP_TOOLCHAIN_FOUND FALSE)
|
||||
set(COVERAGETOOL_AVAILABLE FALSE)
|
||||
if(FDB_USE_CSHARP_TOOLS)
|
||||
if(WIN32)
|
||||
find_program(dotnet_EXECUTABLE NAMES dotnet dotnet.exe)
|
||||
if(dotnet_EXECUTABLE)
|
||||
set(CSHARP_TOOLCHAIN_FOUND TRUE)
|
||||
endif()
|
||||
else()
|
||||
find_package(dotnet)
|
||||
if(dotnet_FOUND)
|
||||
set(CSHARP_TOOLCHAIN_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CSHARP_TOOLCHAIN_FOUND)
|
||||
find_package(mono)
|
||||
if(mono_FOUND)
|
||||
set(CSHARP_TOOLCHAIN_FOUND TRUE)
|
||||
set(CSHARP_USE_MONO TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FDB_USE_CSHARP_TOOLS_EXPLICIT AND FDB_USE_CSHARP_TOOLS
|
||||
AND NOT CSHARP_TOOLCHAIN_FOUND)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"FDB_USE_CSHARP_TOOLS is enabled, but CSHARP_TOOLCHAIN_FOUND is FALSE. Install .NET (dotnet) or Mono, or set WITH_CSHARP=OFF.")
|
||||
endif()
|
||||
|
||||
# First thing we need is the actor compiler - and to compile and run the actor
|
||||
# compiler, we need mono
|
||||
include(CompileActorCompiler)
|
||||
|
||||
include(CompileCoverageTool)
|
||||
if(FDB_USE_CSHARP_TOOLS AND CSHARP_TOOLCHAIN_FOUND)
|
||||
include(CompileCoverageTool)
|
||||
set(COVERAGETOOL_AVAILABLE TRUE)
|
||||
else()
|
||||
message(STATUS "C# tooling disabled or not found; skipping coverage tool build")
|
||||
endif()
|
||||
# Vexilographer generation is configured inside fdbclient
|
||||
include(CompileVexillographer)
|
||||
|
||||
# with the actor compiler, we can now make the flow commands available
|
||||
include(FlowCommands)
|
||||
|
||||
###############################################################################
|
||||
# Vexilographer
|
||||
###############################################################################
|
||||
|
||||
include(CompileVexillographer)
|
||||
|
||||
###############################################################################
|
||||
# Generate config file
|
||||
###############################################################################
|
||||
@@ -266,7 +310,7 @@ if(WITH_PYTHON AND WITH_C_BINDING)
|
||||
endif()
|
||||
if(WITH_DOCUMENTATION)
|
||||
add_subdirectory(documentation)
|
||||
if(BUILD_JAVA_BINDING)
|
||||
if(BUILD_JAVA_BINDING AND TARGET CopyJavadoc)
|
||||
add_dependencies(html CopyJavadoc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -225,29 +225,33 @@ function(stage_correctness_package)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
list(APPEND package_files ${STAGE_OUT_DIR}/bin/fdbserver
|
||||
${STAGE_OUT_DIR}/bin/coverage.fdbserver.xml
|
||||
${STAGE_OUT_DIR}/bin/coverage.fdbclient.xml
|
||||
${STAGE_OUT_DIR}/bin/coverage.fdbrpc.xml
|
||||
${STAGE_OUT_DIR}/bin/coverage.flow.xml
|
||||
${STAGE_OUT_DIR}/CMakeCache.txt
|
||||
)
|
||||
set(package_files ${STAGE_OUT_DIR}/bin/fdbserver
|
||||
${STAGE_OUT_DIR}/CMakeCache.txt)
|
||||
|
||||
set(package_dependencies ${CMAKE_BINARY_DIR}/CMakeCache.txt
|
||||
${CMAKE_BINARY_DIR}/packages/bin/fdbserver)
|
||||
|
||||
set(copy_sources ${CMAKE_BINARY_DIR}/packages/bin/fdbserver)
|
||||
if(COVERAGETOOL_AVAILABLE)
|
||||
list(APPEND package_files ${STAGE_OUT_DIR}/bin/coverage.fdbserver.xml
|
||||
${STAGE_OUT_DIR}/bin/coverage.fdbclient.xml
|
||||
${STAGE_OUT_DIR}/bin/coverage.fdbrpc.xml
|
||||
${STAGE_OUT_DIR}/bin/coverage.flow.xml)
|
||||
list(APPEND package_dependencies ${CMAKE_BINARY_DIR}/bin/coverage.fdbserver.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbclient.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbrpc.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.flow.xml)
|
||||
list(APPEND copy_sources ${CMAKE_BINARY_DIR}/bin/coverage.fdbserver.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbclient.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbrpc.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.flow.xml)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${package_files}
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/CMakeCache.txt
|
||||
${CMAKE_BINARY_DIR}/packages/bin/fdbserver
|
||||
${CMAKE_BINARY_DIR}/bin/coverage.fdbserver.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbclient.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbrpc.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.flow.xml
|
||||
DEPENDS ${package_dependencies}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/CMakeCache.txt ${STAGE_OUT_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/packages/bin/fdbserver
|
||||
${CMAKE_BINARY_DIR}/bin/coverage.fdbserver.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbclient.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.fdbrpc.xml
|
||||
${CMAKE_BINARY_DIR}/lib/coverage.flow.xml
|
||||
${STAGE_OUT_DIR}/bin
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${copy_sources} ${STAGE_OUT_DIR}/bin
|
||||
COMMENT "Copying files for ${STAGE_CONTEXT} package"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
find_program(MCS_EXECUTABLE mcs)
|
||||
find_program(MONO_EXECUTABLE mono)
|
||||
if(NOT DEFINED FDB_USE_CSHARP_TOOLS)
|
||||
set(FDB_USE_CSHARP_TOOLS TRUE)
|
||||
endif()
|
||||
|
||||
set(ACTORCOMPILER_PY_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/actorcompiler_py/__main__.py
|
||||
@@ -12,7 +13,7 @@ set(ACTORCOMPILER_PY_SRCS
|
||||
set(ACTORCOMPILER_CSPROJ
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/actorcompiler/actorcompiler.csproj)
|
||||
|
||||
set(ACTORCOMPILER_SRCS
|
||||
set(ACTORCOMPILER_LEGACY_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/actorcompiler/ActorCompiler.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/actorcompiler/ActorParser.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/actorcompiler/ParseTree.cs
|
||||
@@ -25,48 +26,63 @@ set(ACTOR_COMPILER_REFERENCES
|
||||
|
||||
add_custom_target(actorcompiler_py DEPENDS ${ACTORCOMPILER_PY_SRCS})
|
||||
|
||||
if(WIN32)
|
||||
add_executable(actorcompiler_csharp ${ACTORCOMPILER_SRCS})
|
||||
target_compile_options(actorcompiler_csharp PRIVATE "/langversion:6")
|
||||
set_property(
|
||||
TARGET actorcompiler_csharp
|
||||
PROPERTY VS_DOTNET_REFERENCES
|
||||
"System"
|
||||
"System.Core"
|
||||
"System.Xml.Linq"
|
||||
"System.Data.DataSetExtensions"
|
||||
"Microsoft.CSharp"
|
||||
"System.Data"
|
||||
"System.Xml")
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND $<TARGET_FILE:actorcompiler_csharp>
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
add_custom_target(actorcompiler)
|
||||
add_dependencies(actorcompiler actorcompiler_csharp actorcompiler_py)
|
||||
elseif(CSHARP_USE_MONO)
|
||||
add_custom_command(
|
||||
OUTPUT actorcompiler.exe
|
||||
COMMAND ${CSHARP_COMPILER_EXECUTABLE} ARGS ${ACTOR_COMPILER_REFERENCES}
|
||||
${ACTORCOMPILER_SRCS} "-target:exe" "-out:actorcompiler.exe"
|
||||
DEPENDS ${ACTORCOMPILER_SRCS}
|
||||
COMMENT "Compile actor compiler"
|
||||
VERBATIM)
|
||||
add_custom_target(actorcompiler_csharp
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/actorcompiler.exe)
|
||||
set(actor_exe "${CMAKE_CURRENT_BINARY_DIR}/actorcompiler.exe")
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND ${MONO_EXECUTABLE} ${actor_exe}
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
add_custom_target(actorcompiler)
|
||||
add_dependencies(actorcompiler actorcompiler_csharp actorcompiler_py)
|
||||
else()
|
||||
dotnet_build(${ACTORCOMPILER_CSPROJ} SOURCE ${ACTORCOMPILER_SRCS})
|
||||
set(actor_exe "${actorcompiler_EXECUTABLE_PATH}")
|
||||
message(STATUS "Actor compiler path: ${actor_exe}")
|
||||
# dotnet_build already creates a target named 'actorcompiler', so we just add Python dependency
|
||||
add_dependencies(actorcompiler actorcompiler_py)
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND ${actor_exe}
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
set(ACTORCOMPILER_PY_COMMAND
|
||||
${Python3_EXECUTABLE} -m flow.actorcompiler_py
|
||||
CACHE INTERNAL "Command to run the Python actor compiler")
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND ""
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
|
||||
set(ACTORCOMPILER_COMMAND ${ACTORCOMPILER_PY_COMMAND}
|
||||
CACHE INTERNAL "Command to run the actor compiler")
|
||||
|
||||
set(actorcompiler_dependencies actorcompiler_py)
|
||||
|
||||
if(FDB_USE_CSHARP_TOOLS AND CSHARP_TOOLCHAIN_FOUND)
|
||||
if(WIN32)
|
||||
add_executable(actorcompiler_csharp ${ACTORCOMPILER_LEGACY_SRCS})
|
||||
target_compile_options(actorcompiler_csharp PRIVATE "/langversion:6")
|
||||
set_property(
|
||||
TARGET actorcompiler_csharp
|
||||
PROPERTY VS_DOTNET_REFERENCES
|
||||
"System"
|
||||
"System.Core"
|
||||
"System.Xml.Linq"
|
||||
"System.Data.DataSetExtensions"
|
||||
"Microsoft.CSharp"
|
||||
"System.Data"
|
||||
"System.Xml")
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND $<TARGET_FILE:actorcompiler_csharp>
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
list(APPEND actorcompiler_dependencies actorcompiler_csharp)
|
||||
elseif(CSHARP_USE_MONO)
|
||||
add_custom_command(
|
||||
OUTPUT actorcompiler.exe
|
||||
COMMAND ${CSHARP_COMPILER_EXECUTABLE} ARGS ${ACTOR_COMPILER_REFERENCES}
|
||||
${ACTORCOMPILER_LEGACY_SRCS} "-target:exe" "-out:actorcompiler.exe"
|
||||
DEPENDS ${ACTORCOMPILER_LEGACY_SRCS}
|
||||
COMMENT "Compile actor compiler"
|
||||
VERBATIM)
|
||||
add_custom_target(actorcompiler_csharp
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/actorcompiler.exe)
|
||||
set(actor_exe "${CMAKE_CURRENT_BINARY_DIR}/actorcompiler.exe")
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND ${MONO_EXECUTABLE} ${actor_exe}
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
list(APPEND actorcompiler_dependencies actorcompiler_csharp)
|
||||
else()
|
||||
dotnet_build(${ACTORCOMPILER_CSPROJ} SOURCE ${ACTORCOMPILER_LEGACY_SRCS})
|
||||
set(actor_exe "${actorcompiler_EXECUTABLE_PATH}")
|
||||
message(STATUS "Actor compiler path: ${actor_exe}")
|
||||
set(ACTORCOMPILER_CSHARP_COMMAND ${dotnet_EXECUTABLE} ${actor_exe}
|
||||
CACHE INTERNAL "Command to run the C# actor compiler")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ACTORCOMPILER_COMMAND
|
||||
${Python3_EXECUTABLE} -m flow.actorcompiler_py
|
||||
CACHE INTERNAL "Command to run the actor compiler")
|
||||
if(NOT TARGET actorcompiler)
|
||||
add_custom_target(actorcompiler)
|
||||
endif()
|
||||
add_dependencies(actorcompiler ${actorcompiler_dependencies})
|
||||
|
||||
if(ACTORCOMPILER_CSHARP_COMMAND)
|
||||
set(ACTORCOMPILER_COMMAND ${ACTORCOMPILER_CSHARP_COMMAND}
|
||||
CACHE INTERNAL "Command to run the actor compiler" FORCE)
|
||||
endif()
|
||||
|
||||
@@ -4,6 +4,8 @@ set(COVERAGETOOL_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/coveragetool/Program.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flow/coveragetool/Properties/AssemblyInfo.cs)
|
||||
|
||||
set(coveragetool_command "")
|
||||
|
||||
if(WIN32)
|
||||
add_executable(coveragetool ${COVERAGETOOL_SRCS})
|
||||
target_compile_options(coveragetool PRIVATE "/langversion:6")
|
||||
@@ -32,7 +34,16 @@ elseif(CSHARP_USE_MONO)
|
||||
add_custom_target(coveragetool
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/coveragetool.exe)
|
||||
set(coveragetool_exe "${CMAKE_CURRENT_BINARY_DIR}/coveragetool.exe")
|
||||
set(coveragetool_command ${MONO_EXECUTABLE} ${coveragetool_exe})
|
||||
else()
|
||||
dotnet_build(${COVERAGETOOL_CSPROJ} SOURCE ${COVERAGETOOL_SRCS})
|
||||
set(coveragetool_exe "${coveragetool_EXECUTABLE_PATH}")
|
||||
set(coveragetool_command ${dotnet_EXECUTABLE} ${coveragetool_exe})
|
||||
endif()
|
||||
|
||||
if(NOT coveragetool_command)
|
||||
set(coveragetool_command ${coveragetool_exe})
|
||||
endif()
|
||||
set(coveragetool_command
|
||||
${coveragetool_command}
|
||||
CACHE INTERNAL "Command to run coveragetool")
|
||||
|
||||
@@ -7,28 +7,45 @@ set(VEXILLOGRAPHER_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fdbclient/vexillographer/python.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fdbclient/vexillographer/ruby.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fdbclient/vexillographer/vexillographer.cs)
|
||||
set(VEXILLOGRAPHER_PY ${CMAKE_CURRENT_SOURCE_DIR}/fdbclient/vexillographer/vexillographer.py)
|
||||
|
||||
if(WIN32)
|
||||
if(NOT DEFINED FDB_USE_CSHARP_TOOLS)
|
||||
set(FDB_USE_CSHARP_TOOLS TRUE)
|
||||
endif()
|
||||
set(VEXILLOGRAPHER_COMMAND "")
|
||||
|
||||
if(WIN32 AND FDB_USE_CSHARP_TOOLS)
|
||||
add_executable(vexillographer ${VEXILLOGRAPHER_SRCS})
|
||||
target_compile_options(vexillographer PRIVATE "/langversion:6")
|
||||
set_property(
|
||||
TARGET vexillographer PROPERTY VS_DOTNET_REFERENCES "System" "System.Core"
|
||||
"System.Data" "System.Xml" "System.Xml.Linq")
|
||||
elseif(CSHARP_USE_MONO)
|
||||
set(VEXILLOGRAPHER_REFERENCES
|
||||
"-r:System,System.Core,System.Data,System.Xml,System.Xml.Linq")
|
||||
set(VEXILLOGRAPHER_EXE "${CMAKE_CURRENT_BINARY_DIR}/vexillographer.exe")
|
||||
add_custom_command(
|
||||
OUTPUT ${VEXILLOGRAPHER_EXE}
|
||||
COMMAND ${CSHARP_COMPILER_EXECUTABLE} ARGS ${VEXILLOGRAPHER_REFERENCES}
|
||||
${VEXILLOGRAPHER_SRCS} -target:exe -out:${VEXILLOGRAPHER_EXE}
|
||||
DEPENDS ${VEXILLOGRAPHER_SRCS}
|
||||
COMMENT "Compile Vexillographer")
|
||||
add_custom_target(vexillographer DEPENDS ${VEXILLOGRAPHER_EXE})
|
||||
set(VEXILLOGRAPHER_DEPENDS vexillographer)
|
||||
elseif(FDB_USE_CSHARP_TOOLS AND CSHARP_TOOLCHAIN_FOUND)
|
||||
if(CSHARP_USE_MONO)
|
||||
set(VEXILLOGRAPHER_REFERENCES
|
||||
"-r:System,System.Core,System.Data,System.Xml,System.Xml.Linq")
|
||||
set(VEXILLOGRAPHER_EXE "${CMAKE_CURRENT_BINARY_DIR}/vexillographer.exe")
|
||||
add_custom_command(
|
||||
OUTPUT ${VEXILLOGRAPHER_EXE}
|
||||
COMMAND ${CSHARP_COMPILER_EXECUTABLE} ARGS ${VEXILLOGRAPHER_REFERENCES}
|
||||
${VEXILLOGRAPHER_SRCS} -target:exe -out:${VEXILLOGRAPHER_EXE}
|
||||
DEPENDS ${VEXILLOGRAPHER_SRCS}
|
||||
COMMENT "Compile Vexillographer")
|
||||
add_custom_target(vexillographer DEPENDS ${VEXILLOGRAPHER_EXE})
|
||||
set(VEXILLOGRAPHER_DEPENDS vexillographer)
|
||||
set(VEXILLOGRAPHER_COMMAND ${MONO_EXECUTABLE} ${VEXILLOGRAPHER_EXE})
|
||||
else()
|
||||
dotnet_build(${VEXILLOGRAPHER_CSPROJ} SOURCE ${VEXILLOGRAPHER_SRCS})
|
||||
message(STATUS "Generated executable: ${vexillographer_EXECUTABLE_PATH}")
|
||||
set(VEXILLOGRAPHER_EXE ${vexillographer_EXECUTABLE_PATH})
|
||||
set(VEXILLOGRAPHER_COMMAND ${dotnet_EXECUTABLE} ${vexillographer_EXECUTABLE_PATH})
|
||||
set(VEXILLOGRAPHER_DEPENDS ${vexillographer_EXECUTABLE_PATH})
|
||||
endif()
|
||||
else()
|
||||
dotnet_build(${VEXILLOGRAPHER_CSPROJ} SOURCE ${VEXILLOGRAPHER_SRCS})
|
||||
message(STATUS "Generated executable: ${vexillographer_EXECUTABLE_PATH}")
|
||||
set(VEXILLOGRAPHER_EXE ${vexillographer_EXECUTABLE_PATH})
|
||||
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||
set(VEXILLOGRAPHER_COMMAND ${Python3_EXECUTABLE} ${VEXILLOGRAPHER_PY})
|
||||
set(VEXILLOGRAPHER_DEPENDS ${VEXILLOGRAPHER_PY})
|
||||
endif()
|
||||
|
||||
function(vexillographer_compile)
|
||||
@@ -41,21 +58,19 @@ function(vexillographer_compile)
|
||||
set(VX_OUTPUT ${VX_OUT})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(WIN32 AND FDB_USE_CSHARP_TOOLS)
|
||||
add_custom_command(
|
||||
OUTPUT ${VX_OUTPUT}
|
||||
COMMAND
|
||||
$<TARGET_FILE:vexillographer>
|
||||
COMMAND $<TARGET_FILE:vexillographer>
|
||||
${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options ${VX_LANG}
|
||||
${VX_OUT}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options
|
||||
vexillographer
|
||||
COMMENT "Generate FDBOptions ${VX_LANG} files")
|
||||
elseif(CSHARP_USE_MONO)
|
||||
elseif(FDB_USE_CSHARP_TOOLS AND CSHARP_TOOLCHAIN_FOUND AND CSHARP_USE_MONO)
|
||||
add_custom_command(
|
||||
OUTPUT ${VX_OUTPUT}
|
||||
COMMAND
|
||||
${MONO_EXECUTABLE} ${VEXILLOGRAPHER_EXE}
|
||||
COMMAND ${VEXILLOGRAPHER_COMMAND}
|
||||
${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options ${VX_LANG}
|
||||
${VX_OUT}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options
|
||||
@@ -64,12 +79,11 @@ function(vexillographer_compile)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${VX_OUTPUT}
|
||||
COMMAND
|
||||
${VEXILLOGRAPHER_EXE}
|
||||
COMMAND ${VEXILLOGRAPHER_COMMAND}
|
||||
${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options ${VX_LANG}
|
||||
${VX_OUT}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options
|
||||
vexillographer
|
||||
${VEXILLOGRAPHER_DEPENDS}
|
||||
COMMENT "Generate FDBOptions ${VX_LANG} files")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ function(dotnet_build project_file_path)
|
||||
cmake_path(APPEND project_root_directory "bin" OUTPUT_VARIABLE
|
||||
project_binary_directory)
|
||||
cmake_path(APPEND project_binary_directory "${project}" OUTPUT_VARIABLE
|
||||
project_binary_directory)
|
||||
cmake_path(APPEND project_binary_directory "${project}.dll" OUTPUT_VARIABLE
|
||||
project_binary_path)
|
||||
message(
|
||||
STATUS "Building project ${project} using dotnet, in ${configuration} mode")
|
||||
@@ -80,6 +82,7 @@ function(dotnet_build project_file_path)
|
||||
COMMAND
|
||||
${dotnet_EXECUTABLE} ARGS build ${project_file_path} --configuration
|
||||
"${configuration}" --output "${project_binary_directory}" --self-contained
|
||||
"false" -p:UseAppHost=false -p:PublishSingleFile=false
|
||||
DEPENDS ${ARG_SOURCE}
|
||||
WORKING_DIRECTORY "${project_root_directory}"
|
||||
COMMENT "Build ${project} using .NET framework")
|
||||
|
||||
@@ -29,6 +29,9 @@ set(PASS_COMPILATION_UNIT
|
||||
)
|
||||
|
||||
function(generate_coverage_xml)
|
||||
if(NOT COVERAGETOOL_AVAILABLE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT (${ARGC} EQUAL "1"))
|
||||
message(FATAL_ERROR "generate_coverage_xml expects one argument")
|
||||
endif()
|
||||
@@ -85,7 +88,7 @@ function(generate_coverage_xml)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${target_file}
|
||||
COMMAND ${coveragetool_exe} ${target_file} ${in_files}
|
||||
COMMAND ${coveragetool_command} ${target_file} ${in_files}
|
||||
DEPENDS ${in_files}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generate coverage xml")
|
||||
@@ -268,9 +271,11 @@ function(add_flow_target)
|
||||
set(cs_out_file "${out_file}.cs_gen")
|
||||
add_custom_command(OUTPUT "${out_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_SOURCE_DIR}"
|
||||
${ACTORCOMPILER_COMMAND} "${in_file}" "${py_out_file}" ${actor_compiler_flags}
|
||||
${ACTORCOMPILER_PY_COMMAND} "${in_file}" "${py_out_file}" ${actor_compiler_flags}
|
||||
COMMAND ${ACTORCOMPILER_CSHARP_COMMAND} "${in_file}" "${cs_out_file}" ${actor_compiler_flags}
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/flow/actorcompiler_py/compare_actor_output.py "${cs_out_file}" "${py_out_file}"
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/flow/actorcompiler_py/compare_actor_output.py
|
||||
"${cs_out_file}" "${py_out_file}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${py_out_file}" "${out_file}"
|
||||
DEPENDS "${in_file}" actorcompiler
|
||||
COMMENT "Compile and compare actor: ${src}")
|
||||
@@ -327,6 +332,17 @@ function(add_flow_target)
|
||||
set_property(TARGET ${AFT_NAME} PROPERTY COVERAGE_FILTERS ${AFT_SRCS})
|
||||
|
||||
add_custom_target(${AFT_NAME}_actors DEPENDS ${generated_files})
|
||||
if(TARGET fdboptions AND NOT "${AFT_NAME}" STREQUAL "fdboptions")
|
||||
if(DEFINED FDB_OPTIONS_H)
|
||||
set_source_files_properties(${sources} ${AFT_ADDL_SRCS}
|
||||
APPEND PROPERTY OBJECT_DEPENDS ${FDB_OPTIONS_H})
|
||||
endif()
|
||||
add_dependencies(${AFT_NAME}_actors fdboptions)
|
||||
add_dependencies(${AFT_NAME} fdboptions)
|
||||
if(TARGET fdboptions_vex)
|
||||
add_dependencies(${AFT_NAME}_actors fdboptions_vex)
|
||||
endif()
|
||||
endif()
|
||||
add_dependencies(${AFT_NAME} ${AFT_NAME}_actors)
|
||||
generate_coverage_xml(${AFT_NAME})
|
||||
if(strip_target)
|
||||
|
||||
@@ -4,21 +4,42 @@ list(APPEND FDBCLIENT_SRCS sha1/SHA1.cpp)
|
||||
message(STATUS "FDB version is ${FDB_VERSION}")
|
||||
message(STATUS "FDB package name is ${FDB_PACKAGE_NAME}")
|
||||
|
||||
set(options_srcs ${CMAKE_CURRENT_BINARY_DIR}/FDBOptions.g.cpp)
|
||||
if(NOT VEXILLOGRAPHER_COMMAND)
|
||||
message(FATAL_ERROR "VEXILLOGRAPHER_COMMAND is undefined; ensure CompileVexillographer.cmake is included")
|
||||
endif()
|
||||
|
||||
make_directory(${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/)
|
||||
vexillographer_compile(TARGET fdboptions_vex LANG cpp OUT ${CMAKE_CURRENT_BINARY_DIR}/FDBOptions.g
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/FDBOptions.g.h ${CMAKE_CURRENT_BINARY_DIR}/FDBOptions.g.cpp)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/FDBOptions.g.h
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/FDBOptions.g.h
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/FDBOptions.g.h ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/FDBOptions.g.h)
|
||||
set(FDBOPTIONS_GEN_BASE ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/FDBOptions.g)
|
||||
set(FDBOPTIONS_GEN_H ${FDBOPTIONS_GEN_BASE}.h)
|
||||
set(FDBOPTIONS_GEN_CPP ${FDBOPTIONS_GEN_BASE}.cpp)
|
||||
|
||||
vexillographer_compile(TARGET fdboptions_c LANG c OUT ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/fdb_c_options.g.h
|
||||
# Generate the C++ option bindings directly into the final include directory so
|
||||
# the header and source exist before any staging or actor compilation.
|
||||
add_custom_command(
|
||||
OUTPUT ${FDBOPTIONS_GEN_H} ${FDBOPTIONS_GEN_CPP}
|
||||
COMMAND ${VEXILLOGRAPHER_COMMAND}
|
||||
${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options
|
||||
cpp
|
||||
${FDBOPTIONS_GEN_BASE}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/fdbclient/vexillographer/fdb.options
|
||||
${VEXILLOGRAPHER_DEPENDS}
|
||||
COMMENT "Generate FDBOptions (C++)"
|
||||
VERBATIM)
|
||||
|
||||
vexillographer_compile(
|
||||
TARGET fdboptions_c
|
||||
LANG c
|
||||
OUT ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/fdb_c_options.g.h
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/fdb_c_options.g.h)
|
||||
|
||||
add_custom_target(fdboptions DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/include/fdbclient/FDBOptions.g.h)
|
||||
add_dependencies(fdboptions fdboptions_c)
|
||||
set(FDB_OPTIONS_H ${FDBOPTIONS_GEN_H} CACHE INTERNAL "FDB options header")
|
||||
set(options_srcs ${FDBOPTIONS_GEN_CPP})
|
||||
|
||||
add_custom_target(fdboptions ALL
|
||||
DEPENDS ${FDBOPTIONS_GEN_H}
|
||||
${FDBOPTIONS_GEN_CPP}
|
||||
fdboptions_c)
|
||||
|
||||
################################################################################
|
||||
# Build information
|
||||
|
||||
419
fdbclient/vexillographer/vexillographer.py
Normal file
419
fdbclient/vexillographer/vexillographer.py
Normal file
@@ -0,0 +1,419 @@
|
||||
import argparse
|
||||
import enum
|
||||
import pathlib
|
||||
import sys
|
||||
import textwrap
|
||||
import xml.etree.ElementTree as ET
|
||||
from dataclasses import dataclass
|
||||
from typing import Iterable, List, Optional
|
||||
|
||||
|
||||
class Scope(enum.Enum):
|
||||
NetworkOption = "NetworkOption"
|
||||
DatabaseOption = "DatabaseOption"
|
||||
TransactionOption = "TransactionOption"
|
||||
StreamingMode = "StreamingMode"
|
||||
MutationType = "MutationType"
|
||||
ConflictRangeType = "ConflictRangeType"
|
||||
ErrorPredicate = "ErrorPredicate"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return {
|
||||
Scope.NetworkOption: "NET_OPTION",
|
||||
Scope.DatabaseOption: "DB_OPTION",
|
||||
Scope.TransactionOption: "TR_OPTION",
|
||||
Scope.StreamingMode: "STREAMING_MODE",
|
||||
Scope.MutationType: "MUTATION_TYPE",
|
||||
Scope.ConflictRangeType: "CONFLICT_RANGE_TYPE",
|
||||
Scope.ErrorPredicate: "ERROR_PREDICATE",
|
||||
}[self]
|
||||
|
||||
|
||||
class ParamType(enum.Enum):
|
||||
NoneType = "None"
|
||||
String = "String"
|
||||
Int = "Int"
|
||||
Bytes = "Bytes"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Option:
|
||||
scope: Scope
|
||||
name: str
|
||||
code: int
|
||||
param_type: ParamType
|
||||
param_desc: Optional[str]
|
||||
comment: str
|
||||
hidden: bool
|
||||
persistent: bool
|
||||
sensitive: bool
|
||||
default_for: int
|
||||
|
||||
def parameter_comment(self) -> str:
|
||||
return "Option takes no parameter" if self.param_desc is None else f"({self.param_type.value}) {self.param_desc}"
|
||||
|
||||
def is_deprecated(self) -> bool:
|
||||
return self.comment.startswith("Deprecated")
|
||||
|
||||
|
||||
HEADER_NOTICE_C = textwrap.dedent(
|
||||
"""
|
||||
#ifndef FDB_C_OPTIONS_G_H
|
||||
#define FDB_C_OPTIONS_G_H
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* FoundationDB C API
|
||||
*
|
||||
* This source file is part of the FoundationDB open source project
|
||||
*
|
||||
* Copyright 2013-2024 Apple Inc. and the FoundationDB project authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Do not include this file directly.
|
||||
*/
|
||||
"""
|
||||
).strip()
|
||||
|
||||
HEADER_NOTICE_CPP = """\
|
||||
#ifndef FDBCLIENT_FDBOPTIONS_G_H
|
||||
#define FDBCLIENT_FDBOPTIONS_G_H
|
||||
#pragma once
|
||||
|
||||
#include "fdbclient/FDBOptions.h"
|
||||
""".strip()
|
||||
|
||||
LICENSE_PY = textwrap.dedent(
|
||||
"""
|
||||
# FoundationDB Python API
|
||||
# Copyright (c) 2013-2017 Apple Inc.
|
||||
|
||||
# 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.
|
||||
|
||||
import types
|
||||
"""
|
||||
).strip()
|
||||
|
||||
LICENSE_RB = textwrap.dedent(
|
||||
"""
|
||||
# FoundationDB Ruby API
|
||||
# Copyright (c) 2013-2017 Apple Inc.
|
||||
|
||||
# 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.
|
||||
|
||||
# Documentation for this API can be found at
|
||||
# https://apple.github.io/foundationdb/api-ruby.html
|
||||
|
||||
module FDB
|
||||
"""
|
||||
).strip()
|
||||
|
||||
LICENSE_JAVA = textwrap.dedent(
|
||||
"""
|
||||
/*
|
||||
* FoundationDB Java API
|
||||
* Copyright (c) 2013-2024 Apple Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
"""
|
||||
).strip()
|
||||
|
||||
|
||||
def parse_options(xml_path: pathlib.Path, binding: str) -> List[Option]:
|
||||
tree = ET.parse(xml_path)
|
||||
options_root = tree.getroot()
|
||||
options: List[Option] = []
|
||||
for scope_elem in options_root.findall("Scope"):
|
||||
scope = Scope(scope_elem.get("name"))
|
||||
for opt_elem in scope_elem.findall("Option"):
|
||||
disable_on = opt_elem.get("disableOn")
|
||||
if disable_on:
|
||||
if binding in [item.strip() for item in disable_on.split(",") if item.strip()]:
|
||||
continue
|
||||
param_type = ParamType(opt_elem.get("paramType", "None"))
|
||||
options.append(
|
||||
Option(
|
||||
scope=scope,
|
||||
name=opt_elem.get("name"),
|
||||
code=int(opt_elem.get("code")),
|
||||
param_type=param_type,
|
||||
param_desc=opt_elem.get("paramDescription"),
|
||||
comment=opt_elem.get("description", ""),
|
||||
hidden=opt_elem.get("hidden") == "true",
|
||||
persistent=opt_elem.get("persistent") == "true",
|
||||
sensitive=opt_elem.get("sensitive") == "true",
|
||||
default_for=int(opt_elem.get("defaultFor", "-1")),
|
||||
)
|
||||
)
|
||||
return options
|
||||
|
||||
|
||||
def indent(text: str, prefix: str) -> str:
|
||||
return "\n".join(prefix + line if line else prefix for line in text.split("\n"))
|
||||
|
||||
|
||||
def write_c(file_path: pathlib.Path, options: Iterable[Option]) -> None:
|
||||
def option_line(opt: Option, prefix: str) -> str:
|
||||
parameter_comment = ""
|
||||
if opt.scope.name.endswith("Option"):
|
||||
hidden_note = (
|
||||
"This is a hidden parameter and should not be used directly by applications."
|
||||
if opt.hidden
|
||||
else ""
|
||||
)
|
||||
parameter_comment = f" /* Parameter: {opt.parameter_comment()} {hidden_note}*/\n"
|
||||
return f"{parameter_comment} /* {opt.comment} */\n {prefix}{opt.name.upper()}={opt.code}"
|
||||
|
||||
with file_path.open("w", newline="\n") as handle:
|
||||
handle.write(HEADER_NOTICE_C + "\n")
|
||||
for scope in Scope:
|
||||
scoped = [o for o in options if o.scope is scope]
|
||||
if not scoped:
|
||||
scoped = [
|
||||
Option(scope, "DUMMY_DO_NOT_USE", -1, ParamType.NoneType, None,
|
||||
"This option is only a placeholder for C compatibility and should not be used", False, False, False, -1)
|
||||
]
|
||||
prefix = f"FDB_{scope.description}_"
|
||||
handle.write("typedef enum {\n")
|
||||
handle.write(",\n\n".join(option_line(o, prefix) for o in scoped))
|
||||
handle.write(f"\n}} FDB{scope.name};\n\n")
|
||||
handle.write("#endif\n")
|
||||
|
||||
|
||||
def write_cpp(base_path: pathlib.Path, options: Iterable[Option]) -> None:
|
||||
options = list(options)
|
||||
# Keep the ".g" stem for generated C++ option artifacts
|
||||
header_path = base_path.parent / (base_path.name + ".h")
|
||||
source_path = base_path.parent / (base_path.name + ".cpp")
|
||||
|
||||
def option_enum(opt: Option, indent_level: str) -> str:
|
||||
return f"{indent_level}/* {opt.comment} */\n{indent_level}{opt.name.upper()}={opt.code}"
|
||||
|
||||
def option_info(opt: Option, indent_level: str, struct_name: str) -> str:
|
||||
return (
|
||||
f"{indent_level}ADD_OPTION_INFO({struct_name}, {opt.name.upper()}, \"{opt.name.upper()}\", "
|
||||
f"\"{opt.comment}\", \"{opt.parameter_comment()}\", "
|
||||
f"{str(opt.param_desc is not None).lower()}, {str(opt.hidden).lower()}, "
|
||||
f"{str(opt.persistent).lower()}, {str(opt.sensitive).lower()}, {opt.default_for}, "
|
||||
f"FDBOptionInfo::ParamType::{opt.param_type.value})"
|
||||
)
|
||||
|
||||
with header_path.open("w", newline="\n") as header:
|
||||
header.write(HEADER_NOTICE_CPP + "\n\n")
|
||||
for scope in Scope:
|
||||
scoped = [o for o in options if o.scope is scope]
|
||||
header.write(f"struct FDB{scope.name}s {{\n")
|
||||
header.write("\tfriend class FDBOptionInfoMap<FDB{0}s>;\n\n".format(scope.name))
|
||||
header.write("\tenum Option : int {\n")
|
||||
header.write(",\n\n".join(option_enum(o, "\t\t") for o in scoped))
|
||||
header.write("\n\t};\n\n")
|
||||
header.write(f"\tstatic FDBOptionInfoMap<FDB{scope.name}s> optionInfo;\n\n")
|
||||
header.write("private:\n")
|
||||
header.write("\tstatic void init();\n")
|
||||
header.write("};\n\n")
|
||||
header.write("#endif\n")
|
||||
|
||||
with source_path.open("w", newline="\n") as source:
|
||||
source.write('#include "fdbclient/FDBOptions.g.h"\n\n')
|
||||
for scope in Scope:
|
||||
scoped = [o for o in options if o.scope is scope]
|
||||
source.write(f"FDBOptionInfoMap<FDB{scope.name}s> FDB{scope.name}s::optionInfo;\n\n")
|
||||
source.write(f"void FDB{scope.name}s::init() {{\n")
|
||||
source.write("\n".join(option_info(o, "\t", f"FDB{scope.name}s") for o in scoped))
|
||||
source.write("\n}\n\n")
|
||||
|
||||
|
||||
def write_python(file_path: pathlib.Path, options: Iterable[Option]) -> None:
|
||||
type_map = {
|
||||
ParamType.NoneType: "type(None)",
|
||||
ParamType.Int: "type(0)",
|
||||
ParamType.String: "type('')",
|
||||
ParamType.Bytes: "type(b'')",
|
||||
}
|
||||
with file_path.open("w", newline="\n") as handle:
|
||||
handle.write(LICENSE_PY + "\n")
|
||||
for scope in Scope:
|
||||
scoped = [o for o in options if o.scope is scope and not o.hidden]
|
||||
handle.write(f"{scope.name} = {{\n")
|
||||
lines = []
|
||||
for o in scoped:
|
||||
param_desc = "None" if o.param_desc is None else f"\"{o.param_desc}\""
|
||||
lines.append(
|
||||
f" \"{o.name}\" : ({o.code}, \"{o.comment}\", {type_map[o.param_type]}, {param_desc}),"
|
||||
)
|
||||
handle.write("\n".join(lines))
|
||||
handle.write("\n}\n\n")
|
||||
|
||||
|
||||
def write_ruby(file_path: pathlib.Path, options: Iterable[Option]) -> None:
|
||||
type_map = {
|
||||
ParamType.NoneType: "nil",
|
||||
ParamType.Int: "0",
|
||||
ParamType.String: "''",
|
||||
ParamType.Bytes: "''",
|
||||
}
|
||||
with file_path.open("w", newline="\n") as handle:
|
||||
handle.write(LICENSE_RB + "\n")
|
||||
for scope in Scope:
|
||||
if scope is Scope.ErrorPredicate:
|
||||
continue
|
||||
scoped = [o for o in options if o.scope is scope and not o.hidden]
|
||||
handle.write(f" @@{scope.name} = {{\n")
|
||||
lines = []
|
||||
for o in scoped:
|
||||
param_desc = "nil" if o.param_desc is None else f"\"{o.param_desc}\""
|
||||
lines.append(
|
||||
f" \"{o.name.upper()}\" => [{o.code}, \"{o.comment}\", {type_map[o.param_type]}, {param_desc}],"
|
||||
)
|
||||
handle.write("\n".join(lines))
|
||||
handle.write("\n }\n\n")
|
||||
handle.write("end\n")
|
||||
|
||||
|
||||
def write_java(file_path: pathlib.Path, options: Iterable[Option]) -> None:
|
||||
with file_path.open("w", newline="\n") as handle:
|
||||
handle.write(LICENSE_JAVA + "\n")
|
||||
handle.write("package com.apple.foundationdb;\n\n")
|
||||
handle.write("@SuppressWarnings(\"unused\")\n")
|
||||
handle.write("public class FDBOptions {\n")
|
||||
handle.write(" private FDBOptions() { }\n")
|
||||
|
||||
# Enums
|
||||
for scope in Scope:
|
||||
scoped = [o for o in options if o.scope is scope]
|
||||
enum_name = scope.name
|
||||
handle.write(f" public enum {enum_name} {{\n")
|
||||
handle.write(",\n".join(
|
||||
f" {o.name}({o.code})" for o in scoped
|
||||
))
|
||||
handle.write(";\n\n")
|
||||
handle.write(" private final int code;\n")
|
||||
handle.write(f" {enum_name}(int c) {{ this.code = c; }}\n")
|
||||
handle.write(" public int code() { return this.code; }\n")
|
||||
handle.write(" }\n\n")
|
||||
|
||||
# Options info helper
|
||||
handle.write(" static final class OptionInfo {\n")
|
||||
handle.write(" enum ParamType { NONE, INT, STRING, BYTES }\n")
|
||||
handle.write(" public final String description;\n")
|
||||
handle.write(" public final String parameterDescription;\n")
|
||||
handle.write(" public final boolean hasParameter;\n")
|
||||
handle.write(" public final boolean isDeprecated;\n")
|
||||
handle.write(" public final boolean isPersistent;\n")
|
||||
handle.write(" public final boolean isSensitive;\n")
|
||||
handle.write(" public final int defaultFor;\n")
|
||||
handle.write(" public final ParamType parameterType;\n")
|
||||
handle.write(" OptionInfo(String desc, String paramDesc, boolean hasParam, boolean deprecated, boolean persistent, boolean sensitive, int defaultFor, ParamType parameterType) {\n")
|
||||
handle.write(" this.description = desc;\n")
|
||||
handle.write(" this.parameterDescription = paramDesc;\n")
|
||||
handle.write(" this.hasParameter = hasParam;\n")
|
||||
handle.write(" this.isDeprecated = deprecated;\n")
|
||||
handle.write(" this.isPersistent = persistent;\n")
|
||||
handle.write(" this.isSensitive = sensitive;\n")
|
||||
handle.write(" this.defaultFor = defaultFor;\n")
|
||||
handle.write(" this.parameterType = parameterType;\n")
|
||||
handle.write(" }\n")
|
||||
handle.write(" }\n\n")
|
||||
|
||||
# Maps
|
||||
handle.write(" static final class OptionInfoMap {\n")
|
||||
for scope in Scope:
|
||||
scoped = [o for o in options if o.scope is scope]
|
||||
map_entries_list = []
|
||||
for o in scoped:
|
||||
map_entries_list.append(
|
||||
" new OptionInfo(\"{}\", \"{}\", {}, {}, {}, {}, {}, OptionInfo.ParamType.{})".format(
|
||||
o.comment,
|
||||
o.parameter_comment(),
|
||||
str(o.param_desc is not None).lower(),
|
||||
str(o.is_deprecated()).lower(),
|
||||
str(o.persistent).lower(),
|
||||
str(o.sensitive).lower(),
|
||||
o.default_for,
|
||||
o.param_type.value.upper(),
|
||||
)
|
||||
)
|
||||
map_entries = ",\n".join(map_entries_list)
|
||||
handle.write(f" static final OptionInfo[] {scope.name} = new OptionInfo[] {{\n{map_entries}\n }};\n\n")
|
||||
handle.write(" }\n")
|
||||
handle.write("}\n")
|
||||
|
||||
|
||||
WRITERS = {
|
||||
"c": write_c,
|
||||
"cpp": write_cpp,
|
||||
"python": write_python,
|
||||
"ruby": write_ruby,
|
||||
"java": write_java,
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("input")
|
||||
parser.add_argument("lang", choices=WRITERS.keys())
|
||||
parser.add_argument("output")
|
||||
args = parser.parse_args()
|
||||
|
||||
options = parse_options(pathlib.Path(args.input), args.lang)
|
||||
writer = WRITERS[args.lang]
|
||||
writer(pathlib.Path(args.output), options)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user