Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into fixVRFhighCOP
Browse files Browse the repository at this point in the history
  • Loading branch information
Yujie Xu committed Oct 1, 2024
2 parents d5f8c45 + b422061 commit 55c51df
Show file tree
Hide file tree
Showing 16 changed files with 319 additions and 135 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release_mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ jobs:
echo "Installing gcc@13 for gfortran support of -static-libquadmath"
brew list gcc@13 || brew install gcc@13
which gfortran-13 || echo "FC=$(brew --prefix gcc@13)/bin/gfortran-13" >> $GITHUB_ENV
brew install ninja
brew install ninja tcl-tk
- name: Create Build Directory
run: cmake -E make_directory ./build/
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test_pull_requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
if: runner.os == 'macOS'
run: |
brew update
brew install tcl-tk
brew reinstall gcc@13
echo "FC=$(brew --prefix gcc@13)/bin/gfortran-13" >> $GITHUB_ENV
echo MACOSX_DEPLOYMENT_TARGET=${{ matrix.macos_dev_target }} >> $GITHUB_ENV
Expand Down
3 changes: 2 additions & 1 deletion cmake/PythonCopyStandardLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
ctypes_package_dir = os.path.dirname(ctypes_import_file)
standard_lib_dir = os.path.dirname(ctypes_package_dir)

print(f"PYTHON: Analyzing standard library directory at {standard_lib_dir}")

if os.path.exists(target_dir):
# Let's check the library files to see if the ABI matches
# Otherwise if you build with say python 3.8 initially, and then switch to
Expand Down Expand Up @@ -122,7 +124,6 @@ def find_libs(dir_path):
python_root_dir = os.path.dirname(standard_lib_dir)
tcl_dir = os.path.join(python_root_dir, 'tcl')
shutil.copytree(tcl_dir, target_dir, dirs_exist_ok=True)
# TODO: Need to do this on Mac as well, see the bottom of cmake/PythonFixUpOnMac.cmake for more info

# then I'm going to try to clean up any __pycache__ folders in the target dir to reduce installer size
for root, dirs, _ in os.walk(target_dir):
Expand Down
17 changes: 0 additions & 17 deletions cmake/PythonFixUpOnMac.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,3 @@ foreach(PREREQ IN LISTS PREREQUISITES)
execute_process(COMMAND "install_name_tool" -change "${PREREQ}" "@loader_path/${LIB_INT_FILENAME}" "${LOCAL_PYTHON_LIBRARY}")
endif()
endforeach()

##############3
# we need to look into the tkinter binary's runtime dependencies, copy over the tcl and tk dylibs, update them with install_name_tool, and make sure they all get signed, like this:

# libtcl
# cp /opt/homebrew/opt/tcl-tk/lib/libtcl8.6.dylib /path/to/python_lib/lib-dynload/
# install_name_tool -change "/opt/homebrew/opt/tcl-tk/lib/libtcl8.6.dylib" "@loader_path/libtcl8.6.dylib" /path/to/python_lib/lib-dynload/_tkinter.cpython-312-darwin.so

# Do the same for libtk
# cp /opt/homebrew/opt/tcl-tk/lib/libtk8.6.dylib /path/to/python_lib/lib-dynload/
# install_name_tool -change "/opt/homebrew/opt/tcl-tk/lib/libtk8.6.dylib" "@loader_path/libtk8.6.dylib" /path/to/python_lib/lib-dynload/_tkinter.cpython-312-darwin.so

# Resign _tkinter
# codesign -vvvv -s "Developer ID Application: National ..." -f --timestamp -i "org.nrel.EnergyPlus" -o runtime /path/to/python_lib/lib-dynload/_tkinter.cpython-312-darwin.so
# codesign -vvvv -s "Developer ID Application: National ..." -f --timestamp -i "org.nrel.EnergyPlus" -o runtime /path/to/python_lib/lib-dynload/libtcl8.6.dylib
# codesign -vvvv -s "Developer ID Application: National ..." -f --timestamp -i "org.nrel.EnergyPlus" -o runtime /path/to/python_lib/lib-dynload/libtk8.6.dylib
##############3
134 changes: 134 additions & 0 deletions cmake/PythonFixUpTclTk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University
# of Illinois, The Regents of the University of California, through Lawrence
# Berkeley National Laboratory (subject to receipt of any required approvals
# from the U.S. Dept. of Energy), Oak Ridge National Laboratory, managed by UT-
# Battelle, Alliance for Sustainable Energy, LLC, and other contributors. All
# rights reserved.
#
# NOTICE: This Software was developed under funding from the U.S. Department of
# Energy and the U.S. Government consequently retains certain rights. As such,
# the U.S. Government has been granted for itself and others acting on its
# behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
# Software to reproduce, distribute copies to the public, prepare derivative
# works, and perform publicly and display publicly, and to permit others to do
# so.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# (1) Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# (2) Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# (3) Neither the name of the University of California, Lawrence Berkeley
# National Laboratory, the University of Illinois, U.S. Dept. of Energy nor
# the names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in
# stand-alone form without changes from the version obtained under this
# License, or (ii) Licensee makes a reference solely to the software
# portion of its product, Licensee must refer to the software as
# "EnergyPlus version X" software, where "X" is the version number Licensee
# obtained under this License and may not use a different name for the
# software. Except as specifically required in this Section (4), Licensee
# shall not use in a company name, a product name, in advertising,
# publicity, or other promotional activities any name, trade name,
# trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or
# confusingly similar designation, without the U.S. Department of Energy's
# prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import platform
import re
import shutil
import subprocess
import sys
from pathlib import Path
import os
import stat


def locate_tk_so(python_dir: Path) -> Path:
print(f"Searching for _tkinter so in {python_dir}")
sos = list(python_dir.glob("lib-dynload/_tkinter*.so"))
assert len(sos) == 1, "Unable to locate _tkinter so"
return sos[0]


LINKED_RE = re.compile(
r"(?P<libname>.*) \(compatibility version (?P<compat_version>\d+\.\d+\.\d+), "
r"current version (?P<current_version>\d+\.\d+\.\d+)(?:, \w+)?\)"
)

LINKED_RE_ARM64 = re.compile(r"(?P<libname>.*) \(architecture arm64\)")


def get_linked_libraries(p: Path):
linked_libs = []
lines = subprocess.check_output(["otool", "-L", str(p)], encoding="utf-8", universal_newlines=True).splitlines()
if "is not an object file" in lines[0]:
return None
lines = [x.strip() for x in lines[1:]]

for line in lines:
if 'compatibility version' in line and (m := LINKED_RE.match(line)):
linked_libs.append(m.groupdict())
elif 'architecture arm64' in line and (m := LINKED_RE_ARM64.match(line)):
linked_libs.append(m.groupdict()) # it will only have a libname key, I think that's fine
else:
raise ValueError(f"For {p}, cannot parse line: '{line}'")
return linked_libs


if __name__ == "__main__":

if platform.system() != "Darwin":
sys.exit(0)

print("PYTHON: Copying and fixing up Tcl/Tk")

if len(sys.argv) == 2:
python_dir = Path(sys.argv[1])
else:
print("Must call " + sys.argv[0] + "with one command line argument: the path to the python_lib directory")
sys.exit(1)

assert python_dir.is_dir()
lib_dynload_dir = python_dir / "lib-dynload"

tk_so = locate_tk_so(python_dir)
tcl_tk_sos = [Path(t["libname"]) for t in get_linked_libraries(tk_so) if "libt" in t["libname"]]

for tcl_tk_so in tcl_tk_sos:
new_tcl_tk_so = lib_dynload_dir / tcl_tk_so.name
if str(tcl_tk_so).startswith('@loader_path'):
assert new_tcl_tk_so.is_file(), f"{new_tcl_tk_so} missing when the tkinter so is already adjusted. Wipe the dir"
print("Already fixed up the libtcl and libtk, nothing to do here")
continue
shutil.copy(tcl_tk_so, new_tcl_tk_so)
# during testing, the brew installed tcl and tk libraries were installed without write permission
# the workaround was to manually chmod u+w those files in the brew install folder
# instead let's just fix them up once we copy them here
current_perms = os.stat(str(new_tcl_tk_so)).st_mode
os.chmod(str(new_tcl_tk_so), current_perms | stat.S_IWUSR)
# now that it can definitely be written, we can run install_name_tool on it
lines = subprocess.check_output(
["install_name_tool", "-change", str(tcl_tk_so), f"@loader_path/{new_tcl_tk_so.name}", str(tk_so)]
)
# Change the id that's the first line of the otool -L in this case and it's confusing
lines = subprocess.check_output(["install_name_tool", "-id", str(new_tcl_tk_so.name), str(new_tcl_tk_so)])
2 changes: 1 addition & 1 deletion cmake/install_codesign_script.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ foreach(path ${_all_root_dylibs})
endif()
endforeach()

file(GLOB PYTHON_SOS "${CMAKE_INSTALL_PREFIX}/python_lib/lib-dynload/*.so")
file(GLOB PYTHON_SOS "${CMAKE_INSTALL_PREFIX}/python_lib/lib-dynload/*.so" "${CMAKE_INSTALL_PREFIX}/python_lib/lib-dynload/*.dylib")

print_relative_paths(PREFIX "FULL_PATHS=" ABSOLUTE_PATHS ${FULL_PATHS})
print_relative_paths(PREFIX "ROOT_DYLIBS=" ABSOLUTE_PATHS ${ROOT_DYLIBS})
Expand Down
Loading

4 comments on commit 55c51df

@nrel-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixVRFhighCOP (Unknown) - Win64-Windows-10-VisualStudio-16: OK (2892 of 2892 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixVRFhighCOP (Unknown) - x86_64-Linux-Ubuntu-22.04-gcc-11.4: Tests Failed (0 of 0 tests passed, 0 test warnings)

Build Badge Test Badge

@nrel-bot-2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixVRFhighCOP (Unknown) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-UnitTestsCoverage-RelWithDebInfo: OK (2098 of 2098 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

@nrel-bot-2c
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixVRFhighCOP (Unknown) - x86_64-Linux-Ubuntu-22.04-gcc-11.4-IntegrationCoverage-RelWithDebInfo: OK (799 of 799 tests passed, 0 test warnings)

Build Badge Test Badge Coverage Badge

Please sign in to comment.