Skip to content

Commit

Permalink
Small updates (#21)
Browse files Browse the repository at this point in the history
* Allow stripping binaries when distribution of wheels is enabled
* Added emoji component and PIL image to JUCE image
* Added more juce_core bindings
* Allow embedding the python standard library in a juce app
* Improved hotreloading
* More unit tests
* Fix Justification class failures
* Fix problems with KeyPress
* Bump to JUCE 7.0.10
* Improved exception handling
* Avoid memory leaks
  • Loading branch information
kunitoki authored Feb 21, 2024
1 parent 11399c6 commit 97d1357
Show file tree
Hide file tree
Showing 61 changed files with 3,648 additions and 417 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
CIBW_ARCHS: ${{matrix.cibw_archs}}
CIBW_BUILD: cp${{ matrix.python }}-${{ matrix.platform_id }}
CIBW_TEST_SKIP: "*-manylinux_aarch64 *-macosx_universal2:arm64 *-win_arm64"
CIBW_ENVIRONMENT: POPSICLE_LTO=${{matrix.lto}}
CIBW_ENVIRONMENT: POPSICLE_LTO=${{matrix.lto}} POPSICLE_DISTRIBUTION=1

- name: Upload all the dists
uses: actions/upload-artifact@v4
Expand Down
19 changes: 16 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ project (${PROJECT_NAME} VERSION ${VERSION_NUMBER})

# Find python
if ("${Python_INCLUDE_DIRS}" STREQUAL "")
set (Python_ROOT_DIR "/Library/Frameworks/Python.framework/Versions/Current")
#set (Python_ROOT_DIR "/Library/Frameworks/Python.framework/Versions/Current")
set (Python_USE_STATIC_LIBS TRUE)
find_package (Python REQUIRED Development)
else()
Expand Down Expand Up @@ -46,7 +46,6 @@ set_target_properties (${PROJECT_NAME} PROPERTIES PREFIX "")

if (APPLE)
set_target_properties (${PROJECT_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
set_target_properties (${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE "-s")
set_target_properties (${PROJECT_NAME} PROPERTIES SUFFIX ".so")
target_link_options (${PROJECT_NAME} PRIVATE "-Wl,-weak_reference_mismatches,weak")
elseif (WIN32)
Expand All @@ -57,6 +56,20 @@ elseif (WIN32)
endif()
endif()

if (ENABLE_DISTRIBUTION)
if (APPLE)
add_custom_command(
TARGET "${PROJECT_NAME}" POST_BUILD DEPENDS "${PROJECT_NAME}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS -x $<TARGET_FILE:${PROJECT_NAME}>)
elseif (UNIX)
add_custom_command(
TARGET "${PROJECT_NAME}" POST_BUILD DEPENDS "${PROJECT_NAME}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS --strip-all $<TARGET_FILE:${PROJECT_NAME}>)
endif()
endif()

if (ENABLE_LTO)
set (LTO_CONFIGURATION "juce::juce_recommended_lto_flags")
else()
Expand All @@ -73,7 +86,7 @@ target_compile_definitions (${PROJECT_NAME} PRIVATE
JUCE_DISPLAY_SPLASH_SCREEN=0
JUCE_DISABLE_JUCE_VERSION_PRINTING=1
JUCE_MODAL_LOOPS_PERMITTED=1
JUCE_CATCH_UNHANDLED_EXCEPTIONS=0
JUCE_CATCH_UNHANDLED_EXCEPTIONS=1
JUCE_LOG_ASSERTIONS=1
JUCE_ALLOW_STATIC_NULL_VARIABLES=0
JUCE_STRICT_REFCOUNTEDPOINTER=1
Expand Down
2 changes: 1 addition & 1 deletion JUCE
Submodule JUCE updated 450 files
40 changes: 25 additions & 15 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,59 +188,59 @@ Supported Modules
- Not Planned
* - juce_audio_basics
- ✅
- 0.0%
- 0.87%
- In Progress
* - juce_audio_devices
- ✅
- 0.0%
- In Progress
* - juce_audio_formats
- ⛔️
- N/A
- Planned
-
- 0.0%
- In Progress
* - juce_audio_plugin_client
- ⛔️
- N/A
- Not planned
* - juce_audio_processors
- ⛔️
- N/A
- Planned
-
- 0.0%
- In Progress
* - juce_audio_utils
- ⛔️
- N/A
- Planned
-
- 0.0%
- In Progress
* - juce_box2d
- ⛔️
- N/A
- Planned
* - juce_core
- ✅
- 36.66%
- 44.82%
- Ready
* - juce_cryptography
- ⛔️
- N/A
- Planned
* - juce_data_structures
- ✅
- 25.72%
- 55.61%
- Ready
* - juce_dsp
- ⛔️
- N/A
- Planned
* - juce_events
- ✅
- 50.97%
- 49.68%
- Ready
* - juce_graphics
- ✅
- 15.76%
- In Progress
* - juce_gui_basics
- ✅
- 9.53%
- 9.77%
- In Progress, Basic Components Available
* - juce_gui_extra
- ✅
Expand Down Expand Up @@ -309,6 +309,11 @@ Some images of JUCE tutorials and other small apps ported to *popsicle*.
.. image:: images/audio_player.png
:target: examples/audio_player.py

- Audio Player with waveform (https://docs.juce.com/master/tutorial_audio_thumbnail.html)

.. image:: images/audio_player_waveform.png
:target: examples/audio_player_waveform.py

- OpenCV Integration

.. image:: images/opencv_integration.png
Expand All @@ -319,6 +324,11 @@ Some images of JUCE tutorials and other small apps ported to *popsicle*.
.. image:: images/matplotlib_integration.png
:target: examples/matplotlib_integration.py

- Emojis Components (`emojis_component.py <examples/emojis_component.py>`_ and `emojis_font_component.py <examples/emojis_font_component.py>`_)

.. image:: images/emojis_component.png
:target: examples/emojis_font_component.py


-------------
Code Coverage
Expand Down Expand Up @@ -380,7 +390,7 @@ Install python dependencies.
.. code-block:: bash
# Build the binary distribution
python -m build --wheel
python3 -m build --wheel
# Install the local wheel
pip3 install dist/popsicle-*.whl
Expand Down
97 changes: 97 additions & 0 deletions cmake/ArchivePythonStdlib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import os
import stat
import shutil
import hashlib
import zipfile
from pathlib import Path
from argparse import ArgumentParser


def file_hash(file):
h = hashlib.md5()

with open(file, "rb") as f:
h.update(f.read())

return h.hexdigest()


def make_archive(file, directory):
archived_files = []
for dirname, _, files in os.walk(directory):
for filename in files:
path = os.path.join(dirname, filename)
archived_files.append((path, os.path.relpath(path, directory)))

with zipfile.ZipFile(file, "w") as zf:
for path, archive_path in sorted(archived_files):
permission = 0o555 if os.access(path, os.X_OK) else 0o444

zip_info = zipfile.ZipInfo.from_file(path, archive_path)
zip_info.date_time = (1999, 1, 1, 0, 0, 0)
zip_info.external_attr = (stat.S_IFREG | permission) << 16

with open(path, "rb") as fp:
zf.writestr(zip_info, fp.read(), compress_type=zipfile.ZIP_DEFLATED, compresslevel=9)


if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("-b", "--base-folder", type=Path, help="Path to the base folder.")
parser.add_argument("-o", "--output-folder", type=Path, help="Path to the output folder.")
parser.add_argument("-M", "--version-major", type=int, help="Major version number (integer).")
parser.add_argument("-m", "--version-minor", type=int, help="Minor version number (integer).")
parser.add_argument("-i", "--ignore-patterns", type=str, default=None, help="Ignored patterns (semicolon separated list).")

args = parser.parse_args()

version = f"{args.version_major}.{args.version_minor}"
version_nodot = f"{args.version_major}{args.version_minor}"

final_location: Path = args.output_folder / "python"
site_packages = final_location / "site-packages"
base_python: Path = args.base_folder / "lib" / f"python{version}"
final_archive = args.output_folder / f"python{version_nodot}.zip"
temp_archive = args.output_folder / f"temp{version_nodot}.zip"

base_patterns = [
"*.pyc",
"__pycache__",
"__phello__",
"*config-3*",
"*tcl*",
"*tdbc*",
"*tk*",
"Tk*",
"_tk*",
"_test*",
"libpython*",
"pkgconfig",
"idlelib",
"site-packages",
"test",
"turtledemo",
"LICENSE.txt",
]

if args.ignore_patterns:
custom_patterns = [x.strip() for x in args.ignore_patterns.split(";")]
base_patterns += custom_patterns

ignored_files = shutil.ignore_patterns(*base_patterns)

print("cleaning up...")
if final_location.exists():
shutil.rmtree(final_location)

print("copying library...")
shutil.copytree(base_python, final_location, ignore=ignored_files, dirs_exist_ok=True)
os.makedirs(site_packages, exist_ok=True)

print("making archive...")
if os.path.exists(final_archive):
make_archive(temp_archive, final_location)
if file_hash(temp_archive) != file_hash(final_archive):
shutil.copy(temp_archive, final_archive)
else:
make_archive(final_archive, final_location)
77 changes: 60 additions & 17 deletions demo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
cmake_minimum_required (VERSION 3.21)

set (TARGET_NAME popsicle_demo)
set (PROJECT_NAME popsicle_demo)
get_filename_component (ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
file (STRINGS "${ROOT_PATH}/modules/juce_python/juce_python.h" JUCE_PYTHON_MODULE)
string (REGEX REPLACE "(.*)([0-9]+\.[0-9]+\.[0-9]+)(.*)" "\\2" VERSION_NUMBER ${JUCE_PYTHON_MODULE})
project (${TARGET_NAME} VERSION ${VERSION_NUMBER})
project (${PROJECT_NAME} VERSION ${VERSION_NUMBER})

# Set browsable modules in IDE
set_property (GLOBAL PROPERTY USE_FOLDERS YES)
option (JUCE_ENABLE_MODULE_SOURCE_GROUPS "Enable Module Source Groups" ON)

# Fetch juce
add_subdirectory (${ROOT_PATH}/JUCE JUCE)

# Configure fetching content
#include (FetchContent)
#set (FETCHCONTENT_UPDATES_DISCONNECTED TRUE)

# Add the juce modules
add_subdirectory (${ROOT_PATH}/JUCE JUCE)
#FetchContent_Declare (JUCE
# GIT_REPOSITORY https://github.com/juce-framework/JUCE.git
# GIT_TAG origin/master
Expand All @@ -23,39 +24,80 @@ add_subdirectory (${ROOT_PATH}/JUCE JUCE)
# SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/JUCE)
#FetchContent_MakeAvailable (JUCE)

# Add the straw modules
# Add the popsicle modules
get_filename_component (MODULES_PATH "${ROOT_PATH}/modules" ABSOLUTE)
add_subdirectory (${MODULES_PATH} ./modules)
#FetchContent_Declare (popsicle
# GIT_REPOSITORY https://github.com/kunitoki/popsicle.git
# GIT_TAG origin/master
# GIT_SHALLOW TRUE
# GIT_PROGRESS TRUE
# SOURCE_SUBDIR modules
# SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/popsicle)
#FetchContent_MakeAvailable (popsicle)

# Configure python (APPLE only for now)
set (Python_ROOT_DIR "/Library/Frameworks/Python.framework/Versions/Current")
set (Python_USE_STATIC_LIBS TRUE)
find_package (Python REQUIRED Development.Embed)
find_package (Python REQUIRED Interpreter Development.Embed)

juce_add_gui_app (${TARGET_NAME}
PRODUCT_NAME "Popsicle Demo"
# Setup the juce app
juce_add_gui_app (${PROJECT_NAME}
PRODUCT_NAME "PopsicleDemo"
VERSION "${VERSION_NUMBER}"
BUNDLE_ID "org.kunitoki.popsicledemo")
juce_generate_juce_header (${TARGET_NAME})
juce_generate_juce_header (${PROJECT_NAME})

target_sources (${TARGET_NAME} PRIVATE
# Add the binary target for the python standard library
set (ADDITIONAL_IGNORED_PYTHON_PATTERNS "lib2to3" "pydoc_data" "_xxtestfuzz*")
set (PYTHON_STANDARD_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/python${Python_VERSION_MAJOR}${Python_VERSION_MINOR}.zip")

add_custom_target (
${PROJECT_NAME}_stdlib
${Python_EXECUTABLE} ${ROOT_PATH}/cmake/ArchivePythonStdlib.py
-b ${Python_ROOT_DIR} -o ${CMAKE_CURRENT_BINARY_DIR} -M ${Python_VERSION_MAJOR} -m ${Python_VERSION_MINOR}
-i "\"${ADDITIONAL_IGNORED_PYTHON_PATTERNS}\""
BYPRODUCTS ${PYTHON_STANDARD_LIBRARY})
add_dependencies (${PROJECT_NAME} ${PROJECT_NAME}_stdlib)

juce_add_binary_data (BinaryData SOURCES ${PYTHON_STANDARD_LIBRARY})
add_dependencies (BinaryData ${PROJECT_NAME}_stdlib)

# Setup target properties
target_sources (${PROJECT_NAME} PRIVATE
Main.cpp
PopsicleDemo.cpp
PopsicleDemo.h)

set_target_properties (${TARGET_NAME} PROPERTIES JUCE_TARGET_KIND_STRING "App")
set_target_properties (${TARGET_NAME} PROPERTIES CXX_STANDARD 17)
set_target_properties (${PROJECT_NAME} PROPERTIES JUCE_TARGET_KIND_STRING "App")
set_target_properties (${PROJECT_NAME} PROPERTIES CXX_STANDARD 17)
set_target_properties (${PROJECT_NAME} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
set_target_properties (${PROJECT_NAME} PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
set_target_properties (${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE TRUE)

if (APPLE)
set_target_properties(${TARGET_NAME} PROPERTIES OSX_ARCHITECTURES "arm64;x86_64")
target_link_options(${TARGET_NAME} PRIVATE "-Wl,-weak_reference_mismatches,weak")
#set_target_properties (${PROJECT_NAME} PROPERTIES OSX_ARCHITECTURES "arm64;x86_64")
#set_target_properties (BinaryData PROPERTIES OSX_ARCHITECTURES "arm64;x86_64")
target_link_options (${PROJECT_NAME} PRIVATE "-Wl,-weak_reference_mismatches,weak")
#set (LTO_CONFIGURATION "juce::juce_recommended_lto_flags")
set (LTO_CONFIGURATION "")
else()
set (LTO_CONFIGURATION "")
endif()

target_compile_definitions (${TARGET_NAME} PRIVATE
if (APPLE)
add_custom_command(
TARGET "${PROJECT_NAME}" POST_BUILD DEPENDS "${PROJECT_NAME}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS -x $<TARGET_FILE:${PROJECT_NAME}>)
elseif (UNIX)
add_custom_command(
TARGET "${PROJECT_NAME}" POST_BUILD DEPENDS "${PROJECT_NAME}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS --strip-all $<TARGET_FILE:${PROJECT_NAME}>)
endif()

target_compile_definitions (${PROJECT_NAME} PRIVATE
JUCE_STANDALONE_APPLICATION=1
JUCE_DISPLAY_SPLASH_SCREEN=0
JUCE_MODAL_LOOPS_PERMITTED=1
Expand All @@ -68,7 +110,7 @@ target_compile_definitions (${TARGET_NAME} PRIVATE
JUCE_SILENCE_XCODE_15_LINKER_WARNING=1
PYBIND11_DETAILED_ERROR_MESSAGES=1)

target_link_libraries (${TARGET_NAME} PRIVATE
target_link_libraries (${PROJECT_NAME} PRIVATE
#juce::juce_analytics
juce::juce_audio_basics
juce::juce_audio_devices
Expand All @@ -91,4 +133,5 @@ target_link_libraries (${TARGET_NAME} PRIVATE
Python::Python
popsicle::juce_python
popsicle::juce_python_recommended_warning_flags
BinaryData
${LTO_CONFIGURATION})
Loading

0 comments on commit 97d1357

Please sign in to comment.