Skip to content

Commit 8f9a543

Browse files
author
Vano
committed
better syntax, ALL include paths parsing support(TODO include CPPPATH), better headers,
experimental Cmake support
1 parent f2afa2d commit 8f9a543

File tree

7 files changed

+158
-24
lines changed

7 files changed

+158
-24
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@
1010
# Scons specific
1111
*.sconsign.dblite
1212

13+
# Python
14+
*__pycache__

CMakeLists.txt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# TEMPORARILY works only on top of my godot-cpp Cmake rewrite
2+
cmake_minimum_required(VERSION 3.24)
3+
project(scripts)
4+
5+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
6+
include(godot-cppscript)
7+
8+
add_subdirectory(godot-cpp)
9+
10+
# Get Sources
11+
file(GLOB_RECURSE SOURCES ../src/*.c**)
12+
13+
###############################
14+
set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src)
15+
set(GEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../.gen)
16+
set(GEN_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/../src/scripts.gen.h)
17+
18+
file(GLOB_RECURSE CPPSCRIPT_HEADERS ../src/*.hpp)
19+
20+
create_cppscript_target(
21+
cppscript.h
22+
${CMAKE_CURRENT_SOURCE_DIR}
23+
${INCLUDE_DIR}
24+
${GEN_DIR}
25+
${GEN_HEADER}
26+
ON
27+
CPPSCRIPT_MY_SOURCES
28+
)
29+
30+
###############################
31+
# Define our godot-cpp library
32+
message("MY_SOURCES=${CPPSCRIPT_MY_SOURCES}")
33+
add_library(${PROJECT_NAME} SHARED
34+
${SOURCES}
35+
${CPPSCRIPT_MY_SOURCES}
36+
${GEN_HEADER}
37+
${CPPSCRIPT_HEADERS}
38+
src/register_types.cpp
39+
)
40+
41+
#add_dependencies(${PROJECT_NAME} cppscript-target)
42+
target_include_directories(${PROJECT_NAME} PRIVATE ../src src/)
43+
44+
target_link_libraries(${PROJECT_NAME} PUBLIC godot-cpp)
45+
46+
get_directory_property(GODOT_C_FLAGS DIRECTORY godot-cpp DEFINITION GODOT_C_FLAGS)
47+
get_directory_property(GODOT_CXX_FLAGS DIRECTORY godot-cpp DEFINITION GODOT_CXX_FLAGS)
48+
target_compile_options(${PROJECT_NAME} PRIVATE
49+
${GODOT_C_FLAGS}
50+
${GODOT_CXX_FLAGS}
51+
)
52+
53+
get_directory_property(GODOT_LINK_FLAGS DIRECTORY godot-cpp DEFINITION GODOT_LINK_FLAGS)
54+
target_link_options(${PROJECT_NAME} PRIVATE ${GODOT_LINK_FLAGS}) # -Wl,--as-needed -nostdlib++)
55+
56+
57+
get_directory_property(LIBRARY_SUFFIX DIRECTORY godot-cpp DEFINITION LIBRARY_SUFFIX)
58+
set_target_properties(${PROJECT_NAME}
59+
PROPERTIES
60+
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin"
61+
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin"
62+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin"
63+
64+
OUTPUT_NAME "${PROJECT_NAME}${LIBRARY_SUFFIX}"
65+
)
66+

SConstruct

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ scripts = GlobRecursive(SRC_DIR, '*.hpp')
1111

1212
env.Append(CPPPATH=[SRC_DIR, 'src'])
1313
# CppScript config
14+
env['header_name'] = 'cppscript.h' # Name of header to be included to enable cppscript
15+
# (Prefer name unique to your project)
1416
env['src'] = SRC_DIR # Path to C++ source files
1517
env['gen_dir'] = "../.gen" # Path for generated object files
16-
env['defs_file'] = os.path.join(SRC_DIR, 'defs.json') # Path to generated bindings
1718
env['gen_header'] = os.path.join(SRC_DIR, 'scripts.gen.h') # Path to generated header
1819
env['auto_methods'] = True # Generate bindings to public methods automatically
1920
# Or require GMETHOD() before methods

cmake/godot-cppscript.cmake

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
find_package(Python3 3.4 REQUIRED)
2+
3+
#TODO: make it work in parallel
4+
function(create_cppscript_target HEADER_NAME GODOT_CPPSCRIPT_DIR HEADERS_DIR GEN_DIR GEN_HEADER AUTO_METHODS CPPSCRIPT_SOURCES)
5+
if(${AUTO_METHODS})
6+
set(AUTO_METHODS_STR "True")
7+
else()
8+
set(AUTO_METHODS_STR "False")
9+
endif()
10+
11+
file(GLOB_RECURSE HEADERS_LIST RELATIVE ${HEADERS_DIR} ${HEADERS_DIR}/*.hpp)
12+
13+
foreach(PATH ${HEADERS_LIST})
14+
string(REGEX REPLACE "\.hpp$" ".gen.cpp" relative_path "${PATH}")
15+
list(APPEND SOURCES_LIST ${GEN_DIR}/${relative_path})
16+
endforeach()
17+
set(${CPPSCRIPT_SOURCES} ${SOURCES_LIST} PARENT_SCOPE)
18+
19+
add_custom_command(OUTPUT ${GEN_HEADER} ${SOURCES_LIST}
20+
COMMAND ${Python3_EXECUTABLE} "${GODOT_CPPSCRIPT_DIR}/cppscript_bindings.py"
21+
"--header-name" "${HEADER_NAME}"
22+
"--src" "${HEADERS_DIR}"
23+
"--gen-dir" "${GEN_DIR}"
24+
"--gen-header" "${GEN_HEADER}"
25+
"--auto-methods" "${AUTO_METHODS_STR}"
26+
${CPPSCRIPT_HEADERS}
27+
28+
DEPENDS ${CPPSCRIPT_HEADERS}
29+
WORKING_DIRECTORY ${GODOT_CPPSCRIPT_DIR}
30+
VERBATIM
31+
COMMENT "Parsing header files..."
32+
)
33+
34+
#add_custom_target(${TARGET_NAME} DEPENDS ${GEN_HEADER} ${SOURCES_LIST})
35+
#foreach(file ${SOURCES_LIST})
36+
# file(WRITE ${file} "")
37+
# endforeach()
38+
file(REMOVE ${GEN_DIR}/defs.json)
39+
endfunction()
40+

cppscript.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,23 @@ def GlobRecursive(path, pattern, **kwargs):
1717
KEYWORDS = ['GPROPERTY', 'GMETHOD', 'GGROUP', 'GSUBGROUP', 'GBITFIELD', 'GSIGNAL', 'GRPC', 'GVARARG', 'GIGNORE']
1818
INIT_LEVELS = ['GINIT_LEVEL_CORE', 'GINIT_LEVEL_SERVERS', 'GINIT_LEVEL_SCENE', 'GINIT_LEVEL_EDITOR']
1919

20+
CPPSCRIPT_BODY="""#ifndef {0}
21+
#define {0}
22+
#include <cppscript_defs.h>
23+
#include "properties.gen.h"
24+
#endif // {0}
25+
"""
26+
27+
RPC_CONFIG_BODY = """ {{
28+
Dictionary opts;
29+
opts["rpc_mode"] = MultiplayerAPI::{0};
30+
opts["transfer_mode"] = MultiplayerPeer::{1};
31+
opts["call_local"] = {2};
32+
opts["channel"] = {3};
33+
rpc_config("{4}", opts);
34+
}}
35+
"""
36+
2037
# Helpers
2138
class CppScriptException(Exception):
2239
pass
@@ -145,14 +162,15 @@ def generate_header_cmake(target, source, env):
145162

146163
def generate_header(target, source, env, get_file):
147164
index = Index.create()
148-
prop_file_name = os.path.join(env['src'], 'properties.gen.h')
165+
prop_file_name = os.path.join(env['src'], 'properties.gen.h')
149166
try:
150167
shutil.move(prop_file_name, prop_file_name + '.tmp')
151168
except:
152169
pass
153170

154171
try:
155-
cached_defs_all = load_defs_json(env['defs_file'])
172+
defs_file_path = os.path.join(env['gen_dir'], 'defs.json')
173+
cached_defs_all = load_defs_json(defs_file_path)
156174
cached_defs = cached_defs_all.get('files', {})
157175
need_regen = False
158176

@@ -168,6 +186,12 @@ def generate_header(target, source, env, get_file):
168186

169187
new_defs_all = {'hash' : cached_defs_all.get('hash', None), 'files' : new_defs_files}
170188

189+
# Create include header if not exists
190+
path = os.path.join(env['src'], env['header_name'])
191+
if not os.path.exists(path):
192+
with open(path, 'w') as file:
193+
file.write(CPPSCRIPT_BODY.format(env['header_name'].replace(' ', '_').replace('.', '_').upper()))
194+
171195
if write_register_header(new_defs_all, env) or need_regen:
172196
write_property_header(new_defs_all, env)
173197
try:
@@ -180,7 +204,7 @@ def generate_header(target, source, env, get_file):
180204
except:
181205
pass
182206

183-
with open(env['defs_file'], 'w') as file:
207+
with open(defs_file_path, 'w') as file:
184208
json.dump(new_defs_all, file, indent=2, default=lambda x: x if not isinstance(x, set) else list(x))
185209

186210
except CppScriptException as e:
@@ -245,17 +269,17 @@ def add_class(cursor, macros):
245269

246270

247271
for macro in macros:
248-
classes.append((cursor, get_macro_args(filecontent, macro)[1], macro.spelling[1:]))
272+
classes.append((cursor, get_macro_args(filecontent, macro)[1], macro))
249273

250274

251275
collapse_list(found_class, lambda x: x.kind == CursorKind.CLASS_DECL, add_class)
252276

253277
parsed_classes = {}
254-
for cursor, base, type in classes:
278+
for cursor, base, gdclass_macro in classes:
255279
class_defs = {
256280
'class_name' : cursor.spelling,
257281
'base' : base,
258-
'type' : type,
282+
'type' : gdclass_macro.spelling[1:],
259283
'init_level' : 'SCENE',
260284
'methods' : [],
261285
'properties' : [],
@@ -266,6 +290,9 @@ def add_class(cursor, macros):
266290
}
267291
child_cursors = []
268292
parse_class(cursor, child_cursors)
293+
# Exclude cursors added by GCLASS() macro
294+
child_cursors = [i for i in child_cursors if gdclass_macro.extent.start.offset != i.extent.start.offset]
295+
269296
group, subgroup = '', ''
270297
start, end = cursor.extent.start.offset, cursor.extent.end.offset
271298
class_macros = sorted([m for m in keyword_macros if start < m.extent.start.offset < end] + child_cursors, key=lambda x: x.extent.start.offset)
@@ -488,15 +515,13 @@ def write_header(file, defs, env):
488515
Hmethod += f'\tMethod<&{class_name}::{method["name"]}>::bind(D_METHOD("{method["bind_name"]}"{args}){defvals});\n'
489516

490517
if 'rpc_config' in method.keys():
491-
header_rpc_config += f""" {{
492-
Dictionary opts;
493-
opts["rpc_mode"] = MultiplayerAPI::{method['rpc_config']['rpc_mode']};
494-
opts["transfer_mode"] = MultiplayerPeer::{method['rpc_config']['transfer_mode']};
495-
opts["call_local"] = {method['rpc_config']['call_local']};
496-
opts["channel"] = {method['rpc_config']['channel']};
497-
rpc_config("{method["name"]}", opts);
498-
}}
499-
"""
518+
header_rpc_config += RPC_CONFIG_BODY.format(
519+
method['rpc_config']['rpc_mode'],
520+
method['rpc_config']['transfer_mode'],
521+
method['rpc_config']['call_local'],
522+
method['rpc_config']['channel'],
523+
method["name"]
524+
)
500525
else:
501526
args_list = '\n'.join(f'\t\t,MakePropertyInfo<{type}>("{name}")' for type, name in method['varargs'])
502527

cppscript_bindings.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@
88
prog='cppscript_bindings',
99
description='Generates C++ bindings code for GDExtension')
1010

11+
parser.add_argument('--header-name', type=str, nargs=1, required=True)
1112
parser.add_argument('--src', type=str, nargs=1, required=True)
1213
parser.add_argument('--gen-dir', type=str, nargs=1, required=True)
13-
parser.add_argument('--defs-file', type=str, nargs=1, required=True)
1414
parser.add_argument('--gen-header', type=str, nargs=1, required=True)
1515
parser.add_argument('--auto-methods', type=bool, default=True)
1616
parser.add_argument('sources', nargs='*')
1717

1818
args = parser.parse_args(sys.argv[1:])
1919

20-
env = { 'src' : args.src[0],
21-
'gen_dir' : args.gen_dir[0],
22-
'defs_file' : args.defs_file[0],
20+
env = {
21+
'header_name' : args.header_name[0],
22+
'src' : args.src[0],
23+
'gen_dir' : args.gen_dir[0],
2324
'gen_header' : args.gen_header[0],
2425
'auto_methods' : args.auto_methods
2526
}

src/cppscript.h renamed to src/cppscript_defs.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
#ifndef CPPSCRIPT_H
2-
#define CPPSCRIPT_H
3-
#include "properties.gen.h"
1+
#ifndef CPPSCRIPT_HEADER
2+
#define CPPSCRIPT_HEADER
43
#include <godot_cpp/classes/multiplayer_api.hpp>
54
#include <godot_cpp/classes/multiplayer_peer.hpp>
65

@@ -49,4 +48,4 @@ void function(decltype(property) value) { \
4948
#define GINIT_LEVEL_SCENE(...)
5049
#define GINIT_LEVEL_EDITOR(...)
5150

52-
#endif // CPPSCRIPT_H
51+
#endif // CPPSCRIPT_HEADER

0 commit comments

Comments
 (0)