Skip to content

Commit d25d50b

Browse files
committed
Port is now an external port
- since Emscripten 4.0.10, ports can be external => migrated this project to use this feature
1 parent 006f656 commit d25d50b

File tree

6 files changed

+154
-128
lines changed

6 files changed

+154
-128
lines changed

CMakeLists.txt

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
cmake_minimum_required(VERSION 3.10)
22

33
set(emscripten-glfw_RELEASE_YEAR "2025")
4-
set(emscripten-glfw_RELEASE_MONTH "03" )
5-
set(emscripten-glfw_RELEASE_DAY "05" )
4+
set(emscripten-glfw_RELEASE_MONTH "06" )
5+
set(emscripten-glfw_RELEASE_DAY "07" )
66

77
set(emscripten-glfw_GLFW_VERSION "3.4.0")
88

@@ -55,15 +55,8 @@ if(NOT EMSCRIPTEN_GLFW3_DISABLE_JOYSTICK)
5555
list(APPEND glfw3_sources src/cpp/emscripten/glfw3/Joystick.cpp)
5656
endif()
5757

58-
# This is very convoluted, but the only way I found for the zip file
59-
# checksum to not change every time CMake is rerun
60-
configure_file("${CMAKE_CURRENT_LIST_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/emscripten_glfw3_version.h")
61-
set(VERSION_FILE "${CMAKE_CURRENT_LIST_DIR}/include/GLFW/emscripten_glfw3_version.h")
62-
file(SHA256 "${CMAKE_CURRENT_BINARY_DIR}/emscripten_glfw3_version.h" NEW_VERSION_HASH)
63-
file(SHA256 "${VERSION_FILE}" OLD_VERSION_HASH)
64-
if(NOT ${NEW_VERSION_HASH} STREQUAL ${OLD_VERSION_HASH})
65-
configure_file("${CMAKE_CURRENT_BINARY_DIR}/emscripten_glfw3_version.h" "${VERSION_FILE}")
66-
endif()
58+
# Update the version appropriately
59+
configure_file("${CMAKE_CURRENT_LIST_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/emscripten_glfw3_version.h" @ONLY)
6760

6861
macro(add_glfw_lib LIBRARY_NAME)
6962
add_library(${LIBRARY_NAME} ${glfw3_sources})
@@ -94,14 +87,30 @@ target_compile_options(glfw3_pthread PUBLIC "-pthread")
9487
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
9588
### create archive/emscripten-glfw3-${emscripten-glfw_VERSION}.zip for the port
9689
set(ARCHIVE_DIR "${CMAKE_CURRENT_BINARY_DIR}/archive")
90+
set(ARCHIVE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/archive-build")
9791
set(ARCHIVE_NAME "${ARCHIVE_DIR}/emscripten-glfw3-${emscripten-glfw_VERSION}.zip")
92+
93+
# Read the list of files from archive.txt
94+
file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/archive.txt" ARCHIVE_FILES)
95+
set(PROCESSED_FILES "")
96+
97+
# Process each file
98+
foreach(FILE ${ARCHIVE_FILES})
99+
set(ARCHIVE_FILE "${ARCHIVE_BUILD_DIR}/${FILE}")
100+
get_filename_component(FILE_DIR "${ARCHIVE_FILE}" DIRECTORY)
101+
file(MAKE_DIRECTORY "${FILE_DIR}")
102+
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}" "${ARCHIVE_FILE}" @ONLY)
103+
list(APPEND PROCESSED_FILES "${ARCHIVE_FILE}")
104+
endforeach()
105+
98106
add_custom_target("create-archive"
99-
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
107+
WORKING_DIRECTORY "${ARCHIVE_BUILD_DIR}"
100108
COMMAND ${CMAKE_COMMAND} -E remove_directory ${ARCHIVE_DIR}
101109
COMMAND ${CMAKE_COMMAND} -E make_directory ${ARCHIVE_DIR}
102110
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "${ARCHIVE_NAME}" "--format=zip" "--mtime=${emscripten-glfw_RELEASE_DATE}" "--files-from=${CMAKE_CURRENT_LIST_DIR}/archive.txt"
103111
COMMAND ${CMAKE_COMMAND} -E sha512sum "${ARCHIVE_NAME}" > "${ARCHIVE_NAME}.sha512"
104112
COMMAND cat "${ARCHIVE_NAME}.sha512"
113+
DEPENDS ${PROCESSED_FILES}
105114
)
106115

107116
### create a port pointing to archive

archive.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ LICENSE.txt
22
external/GLFW/glfw3.h
33
include/GLFW/emscripten_glfw3.h
44
include/GLFW/emscripten_glfw3_version.h
5+
port/glfw3.py
56
src/cpp/emscripten/glfw3/Clipboard.h
67
src/cpp/emscripten/glfw3/Clipboard.cpp
78
src/cpp/emscripten/glfw3/Config.h

include/GLFW/emscripten_glfw3_version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
// #if EMSCRIPTEN_GLFW_VERSION >= 3'4'0'20240801
2525
// .... code that can be used past a certain release
2626
// #endif
27-
#define EMSCRIPTEN_GLFW_VERSION 3'4'0'20250305
27+
#define EMSCRIPTEN_GLFW_VERSION 3'4'0'20250607
2828

29-
#define EMSCRIPTEN_GLFW_FULL_VERSION_STR "3.4.0.20250305"
29+
#define EMSCRIPTEN_GLFW_FULL_VERSION_STR "3.4.0.20250607"
3030

3131
#endif

port/emscripten-glfw3.py

Lines changed: 5 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2024 pongasoft
1+
# Copyright (c) 2025 pongasoft
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
44
# use this file except in compliance with the License. You may obtain a copy of
@@ -14,118 +14,13 @@
1414
#
1515
# @author Yan Pujante
1616

17-
import os
18-
from typing import Union, Dict
17+
TAG = '3.4.0.20250607'
1918

20-
TAG = '3.4.0.20250305'
21-
HASH = 'd5d1496cf1e05a640c182584a09ed0b43c8d6c42386513e5c2b1e05a2289854a0a0abe085e0a8b64c3a484836a8e63dc5ddb683ce4d2899fccbbf89536d58ee1'
22-
ZIP_URL = f'https://github.com/pongasoft/emscripten-glfw/releases/download/v{TAG}/emscripten-glfw3-{TAG}.zip'
19+
EXTERNAL_PORT = f'https://github.com/pongasoft/emscripten-glfw/releases/download/v{TAG}/emscripten-glfw3-{TAG}.zip'
20+
SHA512 = 'f554ddc22f5b892e3cb9ef63c2f8b0d495f2db237bd3f75ac53a25decb2eb14321db46a1f1de6f58af601d9bd8dc8dd856c5c8837e3e369eedbce5bdb8a8b0e1'
21+
PORT_FILE = 'port/glfw3.py'
2322

2423
# contrib port information (required)
2524
URL = 'https://github.com/pongasoft/emscripten-glfw'
2625
DESCRIPTION = 'This project is an emscripten port of GLFW 3.4 written in C++ for the web/webassembly platform'
2726
LICENSE = 'Apache 2.0 license'
28-
29-
VALID_OPTION_VALUES = {
30-
'disableWarning': ['true', 'false'],
31-
'disableJoystick': ['true', 'false'],
32-
'disableMultiWindow': ['true', 'false'],
33-
'disableWebGL2': ['true', 'false'],
34-
'optimizationLevel': ['0', '1', '2', '3', 'g', 's', 'z'] # all -OX possibilities
35-
}
36-
37-
OPTIONS = {
38-
'disableWarning': 'Boolean to disable warnings emitted by the library',
39-
'disableJoystick': 'Boolean to disable support for joystick entirely',
40-
'disableMultiWindow': 'Boolean to disable multi window support',
41-
'disableWebGL2': 'Boolean to disable WebGL2 support',
42-
'optimizationLevel': f'Optimization level: {VALID_OPTION_VALUES["optimizationLevel"]} (default to 2)',
43-
}
44-
45-
# user options (from --use-port)
46-
opts: Dict[str, Union[str, bool]] = {
47-
'disableWarning': False,
48-
'disableJoystick': False,
49-
'disableMultiWindow': False,
50-
'disableWebGL2': False,
51-
'optimizationLevel': '2'
52-
}
53-
54-
port_name = 'emscripten-glfw3'
55-
56-
57-
def get_lib_name(settings):
58-
return (f'lib_{port_name}_{TAG}-O{opts["optimizationLevel"]}' +
59-
('-nw' if opts['disableWarning'] else '') +
60-
('-nj' if opts['disableJoystick'] else '') +
61-
('-sw' if opts['disableMultiWindow'] else '') +
62-
('-mt' if settings.PTHREADS else '') +
63-
'.a')
64-
65-
66-
def get(ports, settings, shared):
67-
# get the port
68-
ports.fetch_project(port_name, ZIP_URL, sha512hash=HASH)
69-
70-
def create(final):
71-
root_path = os.path.join(ports.get_dir(), port_name)
72-
source_path = os.path.join(root_path, 'src', 'cpp')
73-
source_include_paths = [os.path.join(root_path, 'external'), os.path.join(root_path, 'include')]
74-
75-
flags = [f'-O{opts["optimizationLevel"]}']
76-
77-
if opts['disableWarning']:
78-
flags += ['-DEMSCRIPTEN_GLFW3_DISABLE_WARNING']
79-
80-
if opts['disableJoystick']:
81-
flags += ['-DEMSCRIPTEN_GLFW3_DISABLE_JOYSTICK']
82-
83-
if opts['disableMultiWindow']:
84-
flags += ['-DEMSCRIPTEN_GLFW3_DISABLE_MULTI_WINDOW_SUPPORT']
85-
86-
if settings.PTHREADS:
87-
flags += ['-pthread']
88-
89-
ports.build_port(source_path, final, port_name, includes=source_include_paths, flags=flags)
90-
91-
lib = shared.cache.get_lib(get_lib_name(settings), create, what='port')
92-
if os.path.getmtime(lib) < os.path.getmtime(__file__):
93-
clear(ports, settings, shared)
94-
lib = shared.cache.get_lib(get_lib_name(settings), create, what='port')
95-
return [lib]
96-
97-
98-
def clear(ports, settings, shared):
99-
shared.cache.erase_lib(get_lib_name(settings))
100-
101-
102-
def linker_setup(ports, settings):
103-
root_path = os.path.join(ports.get_dir(), port_name)
104-
source_js_path = os.path.join(root_path, 'src', 'js', 'lib_emscripten_glfw3.js')
105-
settings.JS_LIBRARIES += [source_js_path]
106-
if not opts['disableWebGL2']:
107-
settings.MAX_WEBGL_VERSION = 2
108-
109-
110-
# Makes GLFW includes accessible without installing them (ex: #include <GLFW/glfw3.h>)
111-
def process_args(ports):
112-
root_path = os.path.join(ports.get_dir(), port_name)
113-
args = [
114-
'-I', os.path.join(root_path, 'external'), # <GLFW/glfw3.h>
115-
'-I', os.path.join(root_path, 'include'), # <GLFW/emscripten_glfw3.h>
116-
f'-DEMSCRIPTEN_USE_PORT_CONTRIB_GLFW3={TAG.replace(".", "")}'
117-
]
118-
return args
119-
120-
121-
def check_option(option, value, error_handler):
122-
if value not in VALID_OPTION_VALUES[option]:
123-
error_handler(f'[{option}] can be {list(VALID_OPTION_VALUES[option])}, got [{value}]')
124-
if isinstance(opts[option], bool):
125-
value = value == 'true'
126-
return value
127-
128-
129-
def handle_options(options, error_handler):
130-
for option, value in options.items():
131-
opts[option] = check_option(option, value.lower(), error_handler)

port/glfw3.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Copyright (c) 2024-2025 pongasoft
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
# use this file except in compliance with the License. You may obtain a copy of
5+
# the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations under
13+
# the License.
14+
#
15+
# @author Yan Pujante
16+
17+
import os
18+
from typing import Union, Dict
19+
20+
TAG = '@emscripten-glfw_VERSION@'
21+
22+
# contrib port information (required)
23+
URL = 'https://github.com/pongasoft/emscripten-glfw'
24+
DESCRIPTION = 'This project is an emscripten port of GLFW 3.4 written in C++ for the web/webassembly platform'
25+
LICENSE = 'Apache 2.0 license'
26+
27+
VALID_OPTION_VALUES = {
28+
'disableWarning': ['true', 'false'],
29+
'disableJoystick': ['true', 'false'],
30+
'disableMultiWindow': ['true', 'false'],
31+
'disableWebGL2': ['true', 'false'],
32+
'optimizationLevel': ['0', '1', '2', '3', 'g', 's', 'z'] # all -OX possibilities
33+
}
34+
35+
OPTIONS = {
36+
'disableWarning': 'Boolean to disable warnings emitted by the library',
37+
'disableJoystick': 'Boolean to disable support for joystick entirely',
38+
'disableMultiWindow': 'Boolean to disable multi window support',
39+
'disableWebGL2': 'Boolean to disable WebGL2 support',
40+
'optimizationLevel': f'Optimization level: {VALID_OPTION_VALUES["optimizationLevel"]} (default to 2)',
41+
}
42+
43+
# user options (from --use-port)
44+
opts: Dict[str, Union[str, bool]] = {
45+
'disableWarning': False,
46+
'disableJoystick': False,
47+
'disableMultiWindow': False,
48+
'disableWebGL2': False,
49+
'optimizationLevel': '2'
50+
}
51+
52+
port_name = 'emscripten-glfw3'
53+
54+
# parent folder of where this file is located port/emscripten-glfw3.py
55+
root_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
56+
57+
def get_lib_name(settings):
58+
return (f'lib_{port_name}_{TAG}-O{opts["optimizationLevel"]}' +
59+
('-nw' if opts['disableWarning'] else '') +
60+
('-nj' if opts['disableJoystick'] else '') +
61+
('-sw' if opts['disableMultiWindow'] else '') +
62+
('-mt' if settings.PTHREADS else '') +
63+
'.a')
64+
65+
66+
def get(ports, settings, shared):
67+
def create(final):
68+
source_path = os.path.join(root_path, 'src', 'cpp')
69+
source_include_paths = [os.path.join(root_path, 'external'), os.path.join(root_path, 'include')]
70+
71+
flags = [f'-O{opts["optimizationLevel"]}']
72+
73+
if opts['disableWarning']:
74+
flags += ['-DEMSCRIPTEN_GLFW3_DISABLE_WARNING']
75+
76+
if opts['disableJoystick']:
77+
flags += ['-DEMSCRIPTEN_GLFW3_DISABLE_JOYSTICK']
78+
79+
if opts['disableMultiWindow']:
80+
flags += ['-DEMSCRIPTEN_GLFW3_DISABLE_MULTI_WINDOW_SUPPORT']
81+
82+
if settings.PTHREADS:
83+
flags += ['-pthread']
84+
85+
ports.build_port(source_path, final, port_name, includes=source_include_paths, flags=flags)
86+
87+
return [shared.cache.get_lib(get_lib_name(settings), create, what='port')]
88+
89+
90+
def clear(ports, settings, shared):
91+
shared.cache.erase_lib(get_lib_name(settings))
92+
93+
94+
def linker_setup(ports, settings):
95+
source_js_path = os.path.join(root_path, 'src', 'js', 'lib_emscripten_glfw3.js')
96+
settings.JS_LIBRARIES += [source_js_path]
97+
if not opts['disableWebGL2']:
98+
settings.MAX_WEBGL_VERSION = 2
99+
100+
101+
# Makes GLFW includes accessible without installing them (ex: #include <GLFW/glfw3.h>)
102+
def process_args(ports):
103+
args = [
104+
'-I', os.path.join(root_path, 'external'), # <GLFW/glfw3.h>
105+
'-I', os.path.join(root_path, 'include'), # <GLFW/emscripten_glfw3.h>
106+
f'-DEMSCRIPTEN_USE_PORT_CONTRIB_GLFW3={TAG.replace(".", "")}'
107+
]
108+
return args
109+
110+
111+
def check_option(option, value, error_handler):
112+
if value not in VALID_OPTION_VALUES[option]:
113+
error_handler(f'[{option}] can be {list(VALID_OPTION_VALUES[option])}, got [{value}]')
114+
if isinstance(opts[option], bool):
115+
value = value == 'true'
116+
return value
117+
118+
119+
def handle_options(options, error_handler):
120+
for option, value in options.items():
121+
opts[option] = check_option(option, value.lower(), error_handler)

tools/create_local_port.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@
2222
lines = file.readlines()
2323
file.seek(0)
2424
for line in lines:
25-
if 'HASH = ' in line:
26-
file.write(line.replace(line, f"HASH = '{sha512_sum}'\n"))
25+
if 'SHA512 = ' in line:
26+
file.write(line.replace(line, f"SHA512 = '{sha512_sum}'\n"))
2727
elif 'TAG = ' in line:
2828
file.write(line.replace(line, f"TAG = '{version}'\n"))
29-
elif 'ZIP_URL = ' in line:
29+
elif 'EXTERNAL_PORT = ' in line:
3030
zip_file = os.path.join(binary_dir, 'archive', f'emscripten-glfw3-{version}.zip')
3131
zip_url = pathlib.Path(zip_file).as_uri()
3232
file.write(f'# {line}')
33-
file.write(line.replace(line, f"ZIP_URL = '{zip_url}'\n"))
33+
file.write(line.replace(line, f"EXTERNAL_PORT = '{zip_url}'\n"))
3434
else:
3535
file.write(line)
3636
file.truncate()

0 commit comments

Comments
 (0)