1
2version_deps += custom_target('version information',
3    command : [preprocess_command, '@INPUT@', '@OUTPUT@'],
4    build_by_default : true,
5    build_always_stale : true,
6    input : 'version_auto.c.in',
7    output : 'version_auto.c',
8)
9
10if host_machine.system() == 'windows'
11    winmod = import('windows')
12
13    rcpath = join_paths(meson.current_build_dir(), 'taisei.rc')
14    icons_dir = join_paths(meson.source_root(), 'misc', 'icons')
15    icon_main = join_paths(icons_dir, 'taisei.ico')
16    icon_replay = join_paths(icons_dir, 'taisei-replay.ico')
17    manifest = join_paths(meson.current_source_dir(), 'taisei.manifest')
18
19    rcdefs = [
20        '-DICON_MAIN=@0@'.format(icon_main),
21        '-DICON_REPLAY=@0@'.format(icon_replay),
22        '-DMANIFEST=@0@'.format(manifest),
23    ]
24
25    if is_debug_build
26        rcdefs += ['-DBUILDTYPE_DEFINE=#define DEBUG_BUILD']
27    else
28        rcdefs += ['-DBUILDTYPE_DEFINE=#define RELEASE_BUILD']
29    endif
30
31    # https://github.com/mesonbuild/meson/issues/4301
32    rc_target = custom_target('windows-resource',
33        command : [preprocess_command, rcdefs, '@INPUT@', '@OUTPUT@'],
34        build_always_stale : true,
35        build_by_default : true,
36        input : 'taisei.rc.in',
37        output : 'taisei.rc',
38    )
39
40    version_deps += winmod.compile_resources(
41        rc_target,
42        depend_files : files(
43            'taisei.manifest',
44            icon_main,
45            icon_replay,
46        )
47    )
48
49    # msvcrt is dumb and only supports up to c89.
50    # with this defined, alternative implementations from mingw for e.g. the
51    # printf family of functions will be used, which conform to c11.
52    config.set('__USE_MINGW_ANSI_STDIO', 1)
53endif
54
55taisei_src = files(
56    'aniplayer.c',
57    'boss.c',
58    'cli.c',
59    'color.c',
60    'color.c',
61    'config.c',
62    'credits.c',
63    'dialog.c',
64    'difficulty.c',
65    'dynarray.c',
66    'ending.c',
67    'enemy.c',
68    'entity.c',
69    'events.c',
70    'framerate.c',
71    'gamepad.c',
72    'global.c',
73    'hashtable.c',
74    'hirestime.c',
75    'item.c',
76    'laser.c',
77    'list.c',
78    'log.c',
79    'main.c',
80    'player.c',
81    'plrmodes.c',
82    'progress.c',
83    'projectile.c',
84    'projectile_prototypes.c',
85    'random.c',
86    'refs.c',
87    'replay.c',
88    'stage.c',
89    'stagedraw.c',
90    'stageobjects.c',
91    'stagetext.c',
92    'stageutils.c',
93    'taskmanager.c',
94    'transition.c',
95    'version.c',
96    'video.c',
97    'video_postprocess.c',
98)
99
100if get_option('objpools')
101    taisei_src += files(
102        'objectpool.c',
103    )
104else
105    taisei_src += files(
106        'objectpool_fake.c',
107    )
108endif
109
110if host_machine.system() == 'nx'
111    taisei_src += files(
112        'arch_switch.c',
113    )
114endif
115
116subdir('audio')
117subdir('dialog')
118subdir('eventloop')
119subdir('menu')
120subdir('plrmodes')
121subdir('renderer')
122subdir('resource')
123subdir('rwops')
124subdir('stages')
125subdir('util')
126subdir('vfs')
127
128configure_file(configuration : config, output : 'build_config.h')
129
130taisei_src += [
131    audio_src,
132    dialog_src,
133    eventloop_src,
134    menu_src,
135    plrmodes_src,
136    renderer_src,
137    resource_src,
138    rwops_src,
139    stages_src,
140    util_src,
141    vfs_src,
142]
143
144taisei_deps += [
145    audio_deps,
146    renderer_deps,
147    util_deps,
148]
149
150if taisei_deps.contains(dep_opusfile)
151    taisei_src += util_opus_src
152endif
153
154taisei_basename = (macos_app_bundle ? 'Taisei' : 'taisei')
155
156if host_machine.system() == 'emscripten'
157    if get_option('b_staticpic')
158        warning('b_staticpic is not compatible with the LLVM WebAssembly backend')
159    endif
160
161    em_debug = is_debug_build
162    em_link_outputs = []
163    em_link_output_suffixes = ['html', 'wasm', 'js']  # first element is significant
164    em_data_dir = config.get_unquoted('TAISEI_BUILDCONF_DATA_PATH')
165    em_common_args = [
166        '-s', 'STRICT=1',
167    ]
168    em_link_args = [
169        '-O@0@'.format(get_option('optimization')),
170        '-s', 'ALLOW_MEMORY_GROWTH=1',
171        '-s', 'DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=["$autoResumeAudioContext"]',
172        '-s', 'ENVIRONMENT=web',
173        '-s', 'EXIT_RUNTIME=0',
174        '-s', 'EXPORTED_FUNCTIONS=["_main", "_vfs_sync_callback"]',
175        '-s', 'EXPORTED_RUNTIME_METHODS=["ccall"]',
176        '-s', 'FILESYSTEM=1',
177        '-s', 'FORCE_FILESYSTEM=1',
178        '-s', 'GL_POOL_TEMP_BUFFERS=0',
179        '-s', 'GL_PREINITIALIZED_CONTEXT=1',
180        '-s', 'INITIAL_MEMORY=268435456',
181        '-s', 'LLD_REPORT_UNDEFINED',
182        '-s', 'LZ4=1',
183        '-s', 'MAX_WEBGL_VERSION=2',
184        '-s', 'MIN_WEBGL_VERSION=2',
185        '-s', 'MODULARIZE=0',
186        '-s', 'WASM=1',
187        '-lGL',
188        '-lgl',
189        '-legl.js',
190        '-lidbfs.js',
191    ]
192
193    taisei_c_args += ['-s', 'STRICT=1']
194
195    if em_debug
196        em_link_output_suffixes += ['wasm.map']
197        em_link_args += [
198            '--emrun',
199            '--profiling',
200            '-g3',
201            '-gsource-map',
202            '--source-map-base', meson.get_cross_property('source_map_base', 'http://0.0.0.0:6931/'),
203            '-s', 'ASSERTIONS=2',
204            '-s', 'GL_DEBUG=1',
205            '-s', 'GL_ASSERTIONS=1',
206            '-s', 'GL_TRACK_ERRORS=1',
207        ]
208    else
209        em_link_args += [
210            '-O@0@'.format(get_option('optimization')),
211            '-g0',
212            '-s', 'ASSERTIONS=0',
213            '-s', 'GL_TRACK_ERRORS=0',
214        ]
215
216        if get_option('optimization') != '0'
217            em_link_args += ['--closure', '1']
218        endif
219    endif
220
221    foreach suffix : em_link_output_suffixes
222        em_link_outputs += ['@0@.@1@'.format(taisei_basename, suffix)]
223    endforeach
224
225    libtaisei = static_library(taisei_basename, taisei_src, version_deps,
226        dependencies : taisei_deps,
227        c_pch : 'pch/taisei_pch.h',
228        c_args : [em_common_args, taisei_c_args],
229        install : false,
230    )
231
232    taisei = static_library(taisei_basename + '-full',
233        link_whole : libtaisei,
234    )
235
236    taisei_html = custom_target(em_link_outputs[0],
237        command : [
238            meson.get_compiler('cpp').cmd_array(),
239            taisei,
240            '--pre-js', em_preamble,
241            em_bundle_link_args,
242            '--shell-file', em_shell,
243            get_option('c_args'),
244            get_option('c_link_args'),
245            em_common_args,
246            em_link_args,
247            '-o', '@OUTPUT0@',
248        ],
249        build_by_default : true,
250        output : em_link_outputs,
251        install : true,
252        install_dir : bindir,
253        console : true,
254    )
255
256    bindist_deps += taisei_html
257elif host_machine.system() == 'nx'
258    taisei_elf_name = '@0@.elf'.format(taisei_basename)
259    taisei_elf = executable(taisei_elf_name, taisei_src, version_deps,
260        dependencies : taisei_deps,
261        c_args : taisei_c_args,
262        c_pch : 'pch/taisei_pch.h',
263        install : is_debug_build,
264        install_dir : bindir,
265        override_options: ['strip=false'],
266    )
267    bindist_deps += taisei_elf
268
269    taisei_nacp_name = '@0@.nacp'.format(taisei_basename)
270    taisei_nacp = custom_target(taisei_nacp_name,
271        command : [
272            find_program('nacptool'),
273            '--create',
274            nx_app_title,
275            nx_app_author,
276            taisei_version_string,
277            '@OUTPUT@',
278        ],
279        build_by_default : true,
280        install : false,
281        output : taisei_nacp_name,
282    )
283
284    taisei_nro_name = '@0@.nro'.format(taisei_basename)
285    taisei_nro = custom_target(taisei_nro_name,
286        # NOTE: Unfortunately we can't just put 'taisei_elf' directly into the command array.
287        # Meson then makes an invalid assumption that we are going to execute it ("use as a generator"),
288        # and aborts because there's no exe wrapper in the cross file (which wouldn't make sense to have).
289
290        command : [
291            find_program('elf2nro'),
292            taisei_elf.full_path(),   # workaround for the above issue
293            '@OUTPUT@',
294            '--nacp=@0@'.format(taisei_nacp.full_path()),   # if we could pass the path in a standalone argument, we could have meson generate an implicit dependency here...
295            '--icon=@0@'.format(nx_icon_path),
296        ],
297        build_by_default : true,
298        depends : [taisei_elf, taisei_nacp],
299        install : true,
300        install_dir : bindir,
301        output : taisei_nro_name,
302    )
303    bindist_deps += taisei_nro
304else
305    taisei = executable(taisei_basename, taisei_src, version_deps,
306        dependencies : taisei_deps,
307        c_args : taisei_c_args,
308        gui_app : not get_option('win_console'),
309        install : true,
310        install_dir : bindir,
311    )
312    bindist_deps += taisei
313endif
314