Skip to content

Commit cb0db65

Browse files
author
Vano
committed
SCons/CMake single function setup
1 parent d7fb2d1 commit cb0db65

File tree

4 files changed

+116
-46
lines changed

4 files changed

+116
-46
lines changed

CMakeLists.txt

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,27 +66,47 @@ if(${GODOT_CPP_WARNING_AS_ERROR})
6666
endif()
6767

6868
###############################
69+
# godot-cppscript creation
70+
71+
# include module
6972
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
7073
include(godot-cppscript)
7174

72-
set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src)
73-
set(GEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../.gen)
74-
75+
# Get header files (.hpp only)
7576
file(GLOB_RECURSE CPPSCRIPT_HEADERS ../src/*.hpp)
7677

77-
get_target_property(DEFS ${PROJECT_NAME} COMPILE_DEFINITIONS)
78-
get_target_property(INC_PATHS ${PROJECT_NAME} INCLUDE_DIRECTORIES)
78+
# Optional
79+
80+
# C++ defines (TOOLS_ENABLED, DEBUG_METHODS etc.)
81+
# enable, if you conditionally enable classes/members
82+
# based on definitions
83+
#get_target_property(DEFS ${PROJECT_NAME} COMPILE_DEFINITIONS)
84+
85+
# Include paths
86+
# (try to avoid godot-cpp headers paths,
87+
# it slows parsing drastically)
88+
#get_target_property(INC_PATHS ${PROJECT_NAME} INCLUDE_DIRECTORIES)
7989
create_cppscript_target(
90+
# Name of your main target
91+
${PROJECT_NAME}
92+
93+
# Name of header to be included to enable cppscript
94+
# (Prefer name unique to your project)
8095
cppscript.h
81-
${INCLUDE_DIR}
82-
${GEN_DIR}
96+
97+
# FULL PATH to C++ header files
98+
${CMAKE_CURRENT_SOURCE_DIR}/../src
99+
100+
# FULL PATH to generated object files
101+
${CMAKE_CURRENT_SOURCE_DIR}/../.gen
102+
103+
# Generate bindings to public methods automatically
104+
# or require GMETHOD() before methods
83105
ON
84-
"${INC_PATHS}"
85-
"${DEFS}"
86-
CPPSCRIPT_MY_SOURCES
87-
)
88106

89-
target_sources(${PROJECT_NAME} PRIVATE ${CPPSCRIPT_MY_SOURCES})
90-
target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIR} src)
107+
# Optional
108+
"" # OR "${INC_PATHS}"
109+
"" # OR "${DEFS}"
110+
)
91111
###############################
92112

SConstruct

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from cppscript import GlobRecursive, generate_header_scons, generate_header_emitter
1+
from cppscript import create_cppscript_target, GlobRecursive
22
import os
33

44
SRC_DIR = '../src'
@@ -9,37 +9,56 @@ env = SConscript('godot-cpp/SConstruct').Clone()
99
sources = GlobRecursive(SRC_DIR, '*.cpp')
1010
scripts = GlobRecursive(SRC_DIR, '*.hpp')
1111

12-
env.Append(CPPPATH=[SRC_DIR, 'src'])
13-
# CppScript config
14-
env['header_name'] = 'cppscript.h' # Name of header to be included to enable cppscript
15-
# (Prefer name unique to your project)
16-
env['header_dir'] = SRC_DIR # Path to C++ header files
17-
env['gen_dir'] = "../.gen" # Path for generated object files
18-
env['auto_methods'] = True # Generate bindings to public methods automatically
19-
# Or require GMETHOD() before methods
2012
env.Append(CXXFLAGS='-fdiagnostics-color=always')
21-
env.Append(BUILDERS={'CppScript' : Builder(
22-
action=generate_header_scons,
23-
emitter=generate_header_emitter)})
2413

25-
generated = env.CppScript(scripts)
26-
header, *bindings = generated
14+
generated = create_cppscript_target(
15+
env, # SCons env, env.Clone() for different projects
16+
scripts, # Header files to parse (.hpp only)
2717

28-
env.Precious(generated)
18+
# CppScript config
19+
{
20+
# Name of header to be included to enable cppscript
21+
# (Prefer name unique to your project)
22+
'header_name' : 'cppscript.h',
23+
24+
# Path to C++ header files
25+
'header_dir' : SRC_DIR,
26+
27+
# Path to generated object files
28+
'gen_dir' : "../.gen",
29+
30+
# Generate bindings to public methods automatically
31+
# or require GMETHOD() before methods
32+
'auto_methods' : True,
33+
34+
# Optional
35+
36+
## C++ defines (TOOLS_ENABLED, DEBUG_METHODS etc.)
37+
## enable, if you conditionally enable classes/members
38+
## based on definitions
39+
#'compile_defs' : env['CPPDEFINES'],
40+
#
41+
## Include paths
42+
## (try to avoid godot-cpp headers paths,
43+
## it slows parsing drastically)
44+
#'include_paths' : env['CPPPATH']
45+
}
46+
)
2947

3048
if env["platform"] == "macos":
3149
library = env.SharedLibrary(
3250
"../bin/lib{}.{}.{}.framework/lib{}.{}.{}".format(
3351
library_name, env["platform"], env["target"], library_name, env["platform"], env["target"]
3452
),
35-
source=sources + bindings,
53+
source=sources + generated, # Add generated source files to target
3654
)
3755
else:
3856
library = env.SharedLibrary(
3957
"../bin/lib{}{}{}".format(library_name, env["suffix"], env["SHLIBSUFFIX"]),
40-
source=sources + bindings,
58+
source=sources + generated, # Add generated source files to target
4159
)
4260

61+
# Rebuild after headers change
4362
env.Depends(library[0].sources, generated)
4463

4564
Default(library)

cmake/godot-cppscript.cmake

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ find_package(Python3 3.4 REQUIRED)
33
set(CPPSCRIPT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
44

55
#TODO: make it work in parallel
6-
function(create_cppscript_target HEADER_NAME HEADERS_DIR GEN_DIR AUTO_METHODS INCLUDE_PATHS COMPILE_DEFS CPPSCRIPT_SOURCES)
6+
function(create_cppscript_target TARGET_NAME HEADER_NAME HEADERS_DIR GEN_DIR AUTO_METHODS INCLUDE_PATHS COMPILE_DEFS)
7+
# Handle empty lists
78
if("${COMPILE_DEFS}" STREQUAL "DEFS-NOTFOUND")
89
set(COMPILE_DEFS "")
910
endif()
11+
if("${INCLUDE_PATHS}" STREQUAL "INC_PATHS-NOTFOUND")
12+
set(INCLUDE_PATHS "")
13+
endif()
14+
1015
if(${AUTO_METHODS})
1116
set(AUTO_METHODS_STR "True")
1217
else()
@@ -19,7 +24,6 @@ function(create_cppscript_target HEADER_NAME HEADERS_DIR GEN_DIR AUTO_METHODS IN
1924
string(REGEX REPLACE "\.hpp$" ".gen.cpp" relative_path "${PATH}")
2025
list(APPEND SOURCES_LIST ${GEN_DIR}/${relative_path})
2126
endforeach()
22-
set(${CPPSCRIPT_SOURCES} ${SOURCES_LIST} PARENT_SCOPE)
2327

2428
add_custom_command(
2529
OUTPUT
@@ -44,5 +48,8 @@ function(create_cppscript_target HEADER_NAME HEADERS_DIR GEN_DIR AUTO_METHODS IN
4448
VERBATIM
4549
COMMENT "Parsing header files..."
4650
)
51+
52+
target_sources(${TARGET_NAME} PRIVATE ${SOURCES_LIST})
53+
target_include_directories(${TARGET_NAME} PUBLIC ${HEADERS_DIR} ${CPPSCRIPT_DIR}/src)
4754
endfunction()
4855

cppscript.py

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,36 @@
33

44
if 'NOT_SCONS' not in os.environ.keys():
55
from SCons.Script import Glob
6+
from SCons.Builder import Builder
7+
8+
def create_cppscript_target(env, sources, cppscript_env, *args, **kwargs):
9+
if not 'CppScript' in env['BUILDERS'].keys():
10+
env.Append(BUILDERS={'CppScript' : CppScriptBuilder()})
11+
12+
return env.CppScript(sources, cppscript_env, *args, **kwargs)
13+
14+
class CppScriptBuilder():
15+
def __init__(self, *args, **kwargs):
16+
self.builder = Builder(action=generate_header_scons, emitter=generate_header_emitter, *args, **kwargs)
17+
18+
def __call__(self, scons_env, source, call_args, *args, **kwargs):
19+
env, *other = call_args
20+
cppscript_src = os.path.join(os.path.dirname(__file__), 'src')
21+
# Convert scons variables to cppscript's env
22+
scons_env['cppscript_env'] = {
23+
'header_name' : env['header_name'],
24+
'header_dir' : env['header_dir'],
25+
'gen_dir' : env['gen_dir'],
26+
'compile_defs' : [f'{i[0]}={i[1]}' if type(i) is tuple else str(i) for i in env.get('compile_defs', [])],
27+
'include_paths' : [cppscript_src] + env.get('include_paths', []),
28+
'auto_methods' : env['auto_methods']
29+
}
30+
31+
# Append needed directories
32+
scons_env.Append(CPPPATH=[cppscript_src, env['header_dir']])
33+
return self.builder(scons_env, source=source, *other, *args, **kwargs)
34+
35+
636
def GlobRecursive(path, pattern, **kwargs):
737
found = []
838
for root, dirs, files in os.walk(path):
@@ -151,29 +181,23 @@ def is_virtual_method(cursor):
151181

152182
# Builder
153183
def generate_header_emitter(target, source, env):
154-
return [env.File(os.path.join(env['header_dir'], 'scripts.gen.h'))] + [env.File(filename_to_gen_filename(str(i), env)) for i in source], source
184+
generated = [env.File(filename_to_gen_filename(str(i), env['cppscript_env'])) for i in source]
155185

186+
# To avoid generated sources deletion and re-parsing
187+
env.Precious(generated)
156188

157-
def generate_header_scons(target, source, env):
158-
# Convert scons variables to cppscript's env
159-
cppscript_env = {
160-
'header_name' : env['header_name'],
161-
'header_dir' : env['header_dir'],
162-
'gen_dir' : env['gen_dir'],
163-
'compile_defs' : [f'{i[0]}={i[1]}' if type(i) is tuple else str(i) for i in env['CPPDEFINES']],
164-
'include_paths' : env['CPPPATH'],
165-
'auto_methods' : env['auto_methods']
166-
}
189+
return generated, source
167190

168191

169-
return generate_header(target, source, cppscript_env, get_file_scons)
192+
def generate_header_scons(target, source, env):
193+
return generate_header(source, env['cppscript_env'], get_file_scons)
170194

171195

172196
def generate_header_cmake(source, env):
173-
return generate_header(None, source, env, get_file_cmake)
197+
return generate_header(source, env, get_file_cmake)
174198

175199

176-
def generate_header(target, source, env, get_file):
200+
def generate_header(source, env, get_file):
177201
index = Index.create()
178202
prop_file_name = os.path.join(env['header_dir'], 'properties.gen.h')
179203

0 commit comments

Comments
 (0)