CI/CD: Implement weekly builds.

Brings over the functionality in https://github.com/FreeCAD/FreeCAD-Bundle
to build Linux AppImage, macOS .dmg, and Windows 7z releases.

This version also creates a tagged release for each build, creating an
archive of the weekly builds as well as the ability to easily tie each
build to a git commit.  This will make running 'git bisect' easy to
identify sources of regressions.
This commit is contained in:
Jacob Oursland
2025-03-19 16:29:04 -07:00
parent 2727550e90
commit 8af8b7d0e9
27 changed files with 20362 additions and 36 deletions

143
.github/workflows/sub_weeklyBuild.yml vendored Normal file
View File

@@ -0,0 +1,143 @@
name: Weekly Build
on:
schedule:
- cron: "42 7 * * 2"
permissions:
contents: write
jobs:
tag_build:
runs-on: ubuntu-latest
outputs:
build_tag: ${{ steps.tag_build.outputs.build_tag }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
submodules: 'recursive'
- name: Tag Build
id: tag_build
shell: bash -l {0}
run: |
export BUILD_TAG=weekly-$(date "+%Y.%m.%d")
git tag ${BUILD_TAG}
git push origin tag ${BUILD_TAG} -f
echo "BUILD_TAG=${BUILD_TAG}" >> "$GITHUB_ENV"
echo "build_tag=${BUILD_TAG}" >> "$GITHUB_OUTPUT"
- name: Upload Source
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 package/rattler-build/scripts/make_version_file.py ../freecad_version.txt
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git config user.name 'github-actions[bot]'
git apply package/rattler-build/scripts/disable_git_info.patch
git commit -a -m "Disable git info write to Version.h"
git archive HEAD -o freecad_source_${BUILD_TAG}.tar
git submodule foreach --recursive \
"git archive HEAD --prefix=\$path/ -o \$sha1.tar && \
tar -A -f \$toplevel/freecad_source_${BUILD_TAG}.tar \$sha1.tar && \
rm \$sha1.tar"
gzip freecad_source_${BUILD_TAG}.tar
sha256sum freecad_source_${BUILD_TAG}.tar.gz > freecad_source_${BUILD_TAG}.tar.gz-SHA256.txt
gh release create ${BUILD_TAG} --title "Weekly Build ${BUILD_TAG}" --notes "Weekly Build ${BUILD_TAG}" --prerelease || true
gh release upload --clobber ${BUILD_TAG} "freecad_source_${BUILD_TAG}.tar.gz" "freecad_source_${BUILD_TAG}.tar.gz-SHA256.txt"
build:
needs: tag_build
strategy:
matrix:
include:
- { target: linux-64, os: ubuntu-22.04 }
- { target: linux-arm64, os: ubuntu-22.04-arm }
- { target: osx-64, os: macos-13 }
- { target: osx-arm64, os: macos-latest }
- { target: win-64, os: windows-latest }
fail-fast: false
runs-on: ${{ matrix.os }}
environment: weekly-build
steps:
- name: Set Platform Environment Variables
shell: bash -l {0}
env:
BUILD_TAG: ${{ needs.tag_build.outputs.build_tag }}
OPERATING_SYSTEM: ${{ runner.os }}
run: |
echo "BUILD_TAG=${BUILD_TAG}" >> "$GITHUB_ENV"
if [[ $OPERATING_SYSTEM == 'Windows' ]]; then
echo 'PIXI_CACHE_DIR=D:\rattler' >> "$GITHUB_ENV"
echo 'RATTLER_CACHE_DIR=D:\rattler' >> "$GITHUB_ENV"
fi
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
submodules: 'recursive'
- uses: prefix-dev/setup-pixi@v0.8.3
with:
pixi-version: v0.42.1
cache: false
- name: Install the Apple certificate and provisioning profile
if: runner.os == 'macOS'
env:
APP_SPECIFIC_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
DEVELOPER_TEAM_ID: ${{ secrets.DEVELOPER_TEAM_ID }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/FreeCAD_Weekly.provisionprofile
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
export KEYCHAIN_PASSWORD=$(openssl rand -base64 8)
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# apply provisioning profile
mkdir -p ~/Library/Provisioning\ Profiles
cp $PP_PATH ~/Library/Provisioning\ Profiles
xcrun notarytool store-credentials "FreeCAD Weekly" --keychain "$KEYCHAIN_PATH" --apple-id "${APPLE_ID}" --password "${APP_SPECIFIC_PASSWORD}" --team-id "${DEVELOPER_TEAM_ID}"
- name: Build and Release Packages
shell: bash
env:
GH_TOKEN: ${{ github.token }}
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
SIGN_RELEASE: "true"
TARGET_PLATFORM: ${{ matrix.target }}
UPLOAD_RELEASE: "true"
run: |
cd package/rattler-build
pixi install
pixi run -e package create_bundle
## Needed if running on a self-hosted runner:
# - name: Clean up keychain and provisioning profile
# if: ${{ always() }}
# run: |
# security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
# rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision

View File

@@ -63,6 +63,10 @@
"type": "BOOL",
"value": "ON"
},
"BUILD_REVERSEENGINEERING": {
"type": "BOOL",
"value": "OFF"
},
"ENABLE_DEVELOPER_TESTS": {
"type": "BOOL",
"value": "ON"
@@ -91,6 +95,10 @@
"type": "BOOL",
"value": "ON"
},
"FREECAD_QT_VERSION": {
"type": "STRING",
"value": "6"
},
"OCCT_CMAKE_FALLBACK": {
"type": "BOOL",
"value": "ON"
@@ -111,22 +119,10 @@
},
"cmakeExecutable": "${sourceDir}/conda/cmake.sh",
"cacheVariables": {
"CMAKE_INCLUDE_PATH": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/include"
},
"CMAKE_INSTALL_LIBDIR": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/lib"
},
"CMAKE_INSTALL_PREFIX": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}"
},
"CMAKE_LIBRARY_PATH":{
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/lib"
},
"CMAKE_PREFIX_PATH": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}"
@@ -151,22 +147,10 @@
"type": "STRING",
"value": "/opt/homebrew;/usr/local/homebrew"
},
"CMAKE_INCLUDE_PATH": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/include"
},
"CMAKE_INSTALL_LIBDIR": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/lib"
},
"CMAKE_INSTALL_PREFIX": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}"
},
"CMAKE_LIBRARY_PATH":{
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/lib"
},
"CMAKE_PREFIX_PATH": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}"
@@ -187,22 +171,10 @@
},
"cmakeExecutable": "${sourceDir}/conda/cmake.cmd",
"cacheVariables": {
"CMAKE_INCLUDE_PATH": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/Library/include"
},
"CMAKE_INSTALL_LIBDIR": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/Library/lib"
},
"CMAKE_INSTALL_PREFIX": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/Library"
},
"CMAKE_LIBRARY_PATH":{
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/Library/lib"
},
"CMAKE_PREFIX_PATH": {
"type": "FILEPATH",
"value": "$env{CONDA_PREFIX}/Library"

View File

@@ -0,0 +1,37 @@
@echo on
@REM :: free up extra disk space, compare
@REM :: https://github.com/conda-forge/conda-smithy/issues/1949
@REM rmdir /s /q C:\hostedtoolcache\windows
@REM set "CFLAGS= "
@REM set "CXXFLAGS= -DBOOST_PROGRAM_OPTIONS_DYN_LINK=1"
@REM set "LDFLAGS_SHARED= ucrt.lib"
set "CMAKE_GENERATOR="
set "CMAKE_GENERATOR_PLATFORM="
cmake ^
--preset conda-windows-release ^
-D CMAKE_INCLUDE_PATH:FILEPATH="%LIBRARY_PREFIX%/include" ^
-D CMAKE_INSTALL_LIBDIR:FILEPATH="%LIBRARY_PREFIX%/lib" ^
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
-D CMAKE_LIBRARY_PATH:FILEPATH="%LIBRARY_PREFIX%/lib" ^
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
-D FREECAD_USE_OCC_VARIANT="Official Version" ^
-D INSTALL_TO_SITEPACKAGES:BOOL=ON ^
-D OCC_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%/include" ^
-D OCCT_CMAKE_FALLBACK:BOOL=OFF ^
-D Python_EXECUTABLE:FILEPATH="%PYTHON%" ^
-D Python3_EXECUTABLE:FILEPATH="%PYTHON%" ^
-B build ^
-S . ^
${CMAKE_PLATFORM_FLAGS[@]}
if %ERRORLEVEL% neq 0 exit 1
ninja -C build install
if %ERRORLEVEL% neq 0 exit 1
rmdir /s /q "%LIBRARY_PREFIX%\doc"
ren %LIBRARY_PREFIX%\bin\FreeCAD.exe freecad.exe
ren %LIBRARY_PREFIX%\bin\FreeCADCmd.exe freecadcmd.exe

View File

@@ -0,0 +1,47 @@
if [[ ${HOST} =~ .*linux.* ]]; then
CMAKE_PRESET=conda-linux-release
fi
if [[ ${HOST} =~ .*darwin.* ]]; then
CMAKE_PRESET=conda-macos-release
# add hacks for osx here!
echo "adding hacks for osx"
# install space-mouse
/usr/bin/curl -o /tmp/3dFW.dmg -L 'https://download.3dconnexion.com/drivers/mac/10-7-0_B564CC6A-6E81-42b0-82EC-418EA823B81A/3DxWareMac_v10-7-0_r3411.dmg'
hdiutil attach -readonly /tmp/3dFW.dmg
sudo installer -package /Volumes/3Dconnexion\ Software/Install\ 3Dconnexion\ software.pkg -target /
diskutil eject /Volumes/3Dconnexion\ Software
CMAKE_PLATFORM_FLAGS+=(-DFREECAD_USE_3DCONNEXION:BOOL=ON)
CMAKE_PLATFORM_FLAGS+=(-D3DCONNEXIONCLIENT_FRAMEWORK:FILEPATH="/Library/Frameworks/3DconnexionClient.framework")
CXXFLAGS="${CXXFLAGS} -D_LIBCPP_DISABLE_AVAILABILITY"
fi
unset CMAKE_GENERATOR
unset CMAKE_GENERATOR_PLATFORM
cmake \
--preset ${CMAKE_PRESET} \
-D CMAKE_IGNORE_PREFIX_PATH="/opt/homebrew;/usr/local/homebrew" \
-D CMAKE_INCLUDE_PATH:FILEPATH="$PREFIX/include" \
-D CMAKE_INSTALL_LIBDIR:FILEPATH="$PREFIX/lib" \
-D CMAKE_INSTALL_PREFIX:FILEPATH="$PREFIX" \
-D CMAKE_LIBRARY_PATH:FILEPATH="$PREFIX/lib" \
-D CMAKE_PREFIX_PATH:FILEPATH="$PREFIX" \
-D FREECAD_USE_OCC_VARIANT="Official Version" \
-D INSTALL_TO_SITEPACKAGES:BOOL=ON \
-D OCC_INCLUDE_DIR:FILEPATH="$PREFIX/include" \
-D OCCT_CMAKE_FALLBACK:BOOL=OFF \
-D Python_EXECUTABLE:FILEPATH="$PYTHON" \
-D Python3_EXECUTABLE:FILEPATH="$PYTHON" \
-B build \
-S . \
${CMAKE_PLATFORM_FLAGS[@]}
cmake --build build
cmake --install build
mv ${PREFIX}/bin/FreeCAD ${PREFIX}/bin/freecad || true
mv ${PREFIX}/bin/FreeCADCmd ${PREFIX}/bin/freecadcmd || true

View File

@@ -0,0 +1,7 @@
c_compiler: # [win]
- vs2022 # [win]
cxx_compiler: # [win]
- vs2022 # [win]
MACOSX_SDK_VERSION: # [osx]
- '11.0' # [osx]

View File

@@ -0,0 +1,31 @@
#!/bin/bash
HERE="$(dirname "$(readlink -f "${0}")")"
export PREFIX=${HERE}/usr
# export LD_LIBRARY_PATH=${HERE}/usr/lib${LD_LIBRARY_PATH:+':'}$LD_LIBRARY_PATH
export PYTHONHOME=${HERE}/usr
export PATH_TO_FREECAD_LIBDIR=${HERE}/usr/lib
# export QT_QPA_PLATFORM_PLUGIN_PATH=${HERE}/usr/plugins
# export QT_XKB_CONFIG_ROOT=${HERE}/usr/lib
export FONTCONFIG_FILE=/etc/fonts/fonts.conf
export FONTCONFIG_PATH=/etc/fonts
# Show packages info if DEBUG env variable is set
if [ "$DEBUG" = 1 ]; then
cat ${HERE}/packages.txt
fi
# SSL
# https://forum.freecad.org/viewtopic.php?f=4&t=34873&start=20#p327416
export SSL_CERT_FILE=$PREFIX/ssl/cacert.pem
# https://github.com/FreeCAD/FreeCAD-AppImage/pull/20
export GIT_SSL_CAINFO=$HERE/usr/ssl/cacert.pem
# Support for launching other applications (from /usr/bin)
# https://github.com/FreeCAD/FreeCAD-AppImage/issues/30
if [ ! -z "$1" ] && [ -e "$HERE/usr/bin/$1" ] ; then
MAIN="$HERE/usr/bin/$1" ; shift
else
MAIN="$HERE/usr/bin/freecad"
fi
"${MAIN}" "$@"

View File

@@ -0,0 +1,85 @@
#!/bin/bash
set -e
set -x
conda_env="AppDir/usr"
mkdir -p ${conda_env}
cp -a ../.pixi/envs/default/* ${conda_env}
export PATH="${PWD}/${conda_env}/bin:${PATH}"
export CONDA_PREFIX="${PWD}/${conda_env}"
echo -e "\nDelete unnecessary stuff"
rm -rf ${conda_env}/include
find ${conda_env} -name \*.a -delete
mv ${conda_env}/bin ${conda_env}/bin_tmp
mkdir ${conda_env}/bin
cp ${conda_env}/bin_tmp/freecad ${conda_env}/bin/
cp ${conda_env}/bin_tmp/freecadcmd ${conda_env}/bin
cp ${conda_env}/bin_tmp/ccx ${conda_env}/bin/
cp ${conda_env}/bin_tmp/python ${conda_env}/bin/
cp ${conda_env}/bin_tmp/pip ${conda_env}/bin/
cp ${conda_env}/bin_tmp/pyside6-rcc ${conda_env}/bin/
cp ${conda_env}/bin_tmp/gmsh ${conda_env}/bin/
cp ${conda_env}/bin_tmp/dot ${conda_env}/bin/
cp ${conda_env}/bin_tmp/unflatten ${conda_env}/bin/
rm -rf ${conda_env}/bin_tmp
sed -i '1s|.*|#!/usr/bin/env python|' ${conda_env}/bin/pip
echo -e "\nCopying Icon and Desktop file"
cp ${conda_env}/share/applications/org.freecad.FreeCAD.desktop AppDir/
sed -i 's/Exec=FreeCAD/Exec=AppRun/g' AppDir/org.freecad.FreeCAD.desktop
cp ${conda_env}/share/icons/hicolor/scalable/apps/org.freecad.FreeCAD.svg AppDir/
# Remove __pycache__ folders and .pyc files
find . -path "*/__pycache__/*" -delete
find . -name "*.pyc" -type f -delete
# reduce size
rm -rf ${conda_env}/conda-meta/
rm -rf ${conda_env}/doc/global/
rm -rf ${conda_env}/share/gtk-doc/
rm -rf ${conda_env}/lib/cmake/
find . -name "*.h" -type f -delete
find . -name "*.cmake" -type f -delete
build_tag=$(git describe --tags)
python_version=$(python -c 'import platform; print("py" + platform.python_version_tuple()[0] + platform.python_version_tuple()[1])')
version_name="FreeCAD_${build_tag}-Linux-$(uname -m)-${python_version}"
echo -e "\################"
echo -e "version_name: ${version_name}"
echo -e "################"
pixi list -e default > AppDir/packages.txt
sed -i "1s/.*/\nLIST OF PACKAGES:/" AppDir/packages.txt
export tag="weekly-builds" # should retreive from git tag
curl -LO https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$(uname -m).AppImage
chmod a+x appimagetool-$(uname -m).AppImage
echo -e "\nCreate the appimage"
# export GPG_TTY=$(tty)
chmod a+x ./AppDir/AppRun
./appimagetool-$(uname -m).AppImage \
--comp zstd \
--mksquashfs-opt -Xcompression-level \
--mksquashfs-opt 22 \
-u "gh-releases-zsync|FreeCAD|FreeCAD-Bundle|$tag|FreeCAD*$(uname -m)*.AppImage.zsync" \
AppDir ${version_name}.AppImage
# -s --sign-key ${GPG_KEY_ID} \
echo -e "\nCreate hash"
sha256sum ${version_name}.AppImage > ${version_name}.AppImage-SHA256.txt
if [ "${UPLOAD_RELEASE}" == "true" ]; then
gh release create ${BUILD_TAG} --title "Weekly Build ${BUILD_TAG}" --notes "Weekly Build ${BUILD_TAG}" --prerelease || true
gh release upload --clobber ${BUILD_TAG} "${version_name}.AppImage" "${version_name}.AppImage-SHA256.txt"
fi

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>FreeCAD</string>
<key>CFBundleGetInfoString</key>
<string></string>
<key>CFBundleIconFile</key>
<string>freecad.icns</string>
<key>CFBundleIdentifier</key>
<string>org.freecad.FreeCAD</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string></string>
<key>CFBundleName</key>
<string>APPLICATION_MENU_NAME</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string></string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>FREECAD_VERSION</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string></string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>NSRequiresAquaSystemAppearance</key>
<string>False</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>FCStd</string>
<string>FCMat</string>
<string>FCParam</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>freecad-doc.icns</string>
<key>LSIsAppleDefaultForType</key>
<true/>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>FCMacro</string>
<string>FCScript</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>freecad-script.icns</string>
<key>LSIsAppleDefaultForType</key>
<true/>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>FreeCAD Document</string>
<key>UTTypeIdentifier</key>
<string>org.freecad.fcstd</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>FCStd</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,85 @@
#!/bin/bash
set -e
set -x
conda_env="FreeCAD.app/Contents/Resources"
mkdir -p ${conda_env}
cp -a ../.pixi/envs/default/* ${conda_env}
export PATH="${PWD}/${conda_env}/bin:${PATH}"
export CONDA_PREFIX="${PWD}/${conda_env}"
# delete unnecessary stuff
rm -rf ${conda_env}/include
find ${conda_env} -name \*.a -delete
mv ${conda_env}/bin ${conda_env}/bin_tmp
mkdir ${conda_env}/bin
cp ${conda_env}/bin_tmp/freecad ${conda_env}/bin/
cp ${conda_env}/bin_tmp/freecadcmd ${conda_env}/bin
cp ${conda_env}/bin_tmp/ccx ${conda_env}/bin/
cp ${conda_env}/bin_tmp/python ${conda_env}/bin/
cp ${conda_env}/bin_tmp/pip ${conda_env}/bin/
cp ${conda_env}/bin_tmp/pyside6-rcc ${conda_env}/bin/
cp ${conda_env}/bin_tmp/gmsh ${conda_env}/bin/
cp ${conda_env}/bin_tmp/dot ${conda_env}/bin/
cp ${conda_env}/bin_tmp/unflatten ${conda_env}/bin/
rm -rf ${conda_env}/bin_tmp
sed -i '1s|.*|#!/usr/bin/env python|' ${conda_env}/bin/pip
# copy resources
cp resources/* ${conda_env}
# Remove __pycache__ folders and .pyc files
find . -path "*/__pycache__/*" -delete
find . -name "*.pyc" -type f -delete
# fix problematic rpaths and reexport_dylibs for signing
# see https://github.com/FreeCAD/FreeCAD/issues/10144#issuecomment-1836686775
# and https://github.com/FreeCAD/FreeCAD-Bundle/pull/203
python ../scripts/fix_macos_lib_paths.py ${conda_env}/lib
# build and install the launcher
cmake -B build launcher
cmake --build build
mkdir -p FreeCAD.app/Contents/MacOS
cp build/FreeCAD FreeCAD.app/Contents/MacOS/FreeCAD
python_version=$(python -c 'import platform; print("py" + platform.python_version_tuple()[0] + platform.python_version_tuple()[1])')
version_name="FreeCAD_${BUILD_TAG}-macOS-$(uname -m)-${python_version}"
application_menu_name="FreeCAD_${BUILD_TAG}"
echo -e "\################"
echo -e "version_name: ${version_name}"
echo -e "################"
cp Info.plist.template ${conda_env}/../Info.plist
sed -i "s/FREECAD_VERSION/${version_name}/" ${conda_env}/../Info.plist
sed -i "s/APPLICATION_MENU_NAME/${application_menu_name}/" ${conda_env}/../Info.plist
pixi list -e default > FreeCAD.app/Contents/packages.txt
sed -i '1s/.*/\nLIST OF PACKAGES:/' FreeCAD.app/Contents/packages.txt
# copy the plugin into its final location
cp -a ${conda_env}/Library ${conda_env}/..
rm -rf ${conda_env}/Library
if [[ "${SIGN_RELEASE}" == "true" ]]; then
# create the signed dmg
./macos_sign_and_notarize.zsh -p "FreeCAD Weekly" -k ${SIGNING_KEY_ID} -o "${version_name}.dmg"
else
# create the dmg
dmgbuild -s dmg_settings.py "FreeCAD" "${version_name}.dmg"
fi
# create hash
sha256sum ${version_name}.dmg > ${version_name}.dmg-SHA256.txt
if [[ "${UPLOAD_RELEASE}" == "true" ]]; then
gh release create ${BUILD_TAG} --title "Weekly Build ${BUILD_TAG}" --notes "Weekly Build ${BUILD_TAG}" --prerelease || true
gh release upload --clobber ${BUILD_TAG} "${version_name}.dmg" "${version_name}.dmg-SHA256.txt"
fi

View File

@@ -0,0 +1,12 @@
# Ensure default values are set in defines if they are not already provided
defines.setdefault('containing_folder', '.')
defines.setdefault('app_name', 'FreeCAD.app')
defines.setdefault('icon_path', 'Contents/Resources/freecad.icns')
files = [f"{defines['containing_folder']}/{defines['app_name']}"]
symlinks = {"Applications": "/Applications"}
badge_icon = f"{defines['containing_folder']}/{defines['app_name']}/{defines['icon_path']}"
window_rect = ((200, 200), (600, 400))
icon_locations = {f"{defines['app_name']}": (180, 150), "Applications": (420, 150)}
size = "4g"

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.20)
project(freecad-launcher LANGUAGES CXX)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version" FORCE)
set(CMAKE_CXX_STANDARD 17)
add_executable(FreeCAD FreeCAD.cpp)
target_link_libraries(FreeCAD)

View File

@@ -0,0 +1,75 @@
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <vector>
#include <libgen.h>
#include <unistd.h>
int main(int argc, char *argv[], char *const *envp) {
char *cwd = dirname(realpath(argv[0], NULL));
std::string FreeCAD = realpath((std::string(cwd) + "/../Resources/bin/freecad").c_str(), NULL);
std::map<std::string, std::string> env;
for(int i = 0; envp[i] != NULL; ++i) {
std::string e(envp[i]);
auto sep = e.find('=');
auto var = e.substr(0, sep);
auto value = e.substr(sep+1, std::string::npos);
env[var] = value;
}
std::string prefix = realpath((std::string(cwd) + "/../Resources").c_str(), NULL);
env["PREFIX"] = prefix;
env["LD_LIBRARY_PATH"] = prefix + "/lib";
env["PYTHONPATH"] = prefix;
env["PYTHONHOME"] = prefix;
env["FONTCONFIG_FILE"] = "/etc/fonts/fonts.conf";
env["FONTCONFIG_PATH"] = "/etc/fonts";
env["LANG"] = "UTF-8"; // https://forum.freecad.org/viewtopic.php?f=22&t=42644
env["SSL_CERT_FILE"] = prefix + "/ssl/cacert.pem"; // https://forum.freecad.org/viewtopic.php?f=3&t=42825
env["GIT_SSL_CAINFO"] = prefix + "/ssl/cacert.pem";
env["QT_MAC_WANTS_LAYER"] = "1";
char **new_env = new char*[env.size() + 1];
int i = 0;
for (const auto& [var, value] : env) {
auto line = var + '=' + value;
size_t len = line.length() + 1;
new_env[i] = new char[len];
memset(new_env[i], 0, len);
strncpy(new_env[i], line.c_str(), len);
i++;
}
new_env[i] = NULL;
i = 0;
while(new_env[i] != NULL) {
std::cout << new_env[i] << std::endl;
i++;
}
std::cout << "Running: " << FreeCAD << std::endl;
i = 0;
while(argv[i] != NULL) {
i++;
}
char **new_argv = new char*[i + 1];
new_argv[0] = new char[FreeCAD.length() + 1];
memset(new_argv[0], 0, FreeCAD.length() + 1);
strncpy(new_argv[0], FreeCAD.c_str(), FreeCAD.length());
i = 1;
while(argv[i] != NULL) {
new_argv[i] = new char[strlen(argv[i])+1];
memset(new_argv[i], 0, strlen(argv[i])+1);
strncpy(new_argv[i], argv[i], strlen(argv[i]));
i++;
}
new_argv[i] = NULL;
return execve(FreeCAD.c_str(), new_argv, new_env);
}

View File

@@ -0,0 +1,126 @@
#!/bin/zsh
# SPDX-License-Identifier: LGPL-2.1-or-later
# Default values
SIGNING_KEY_ID="${FREECAD_SIGNING_KEY_ID}"
KEYCHAIN_PROFILE="FreeCAD"
CONTAINING_FOLDER="."
APP_NAME="FreeCAD.app"
VOLUME_NAME="FreeCAD"
DMG_NAME="FreeCAD-macOS-$(uname -m).dmg"
DMG_SETTINGS="dmg_settings.py"
# Function to display usage information
function usage {
echo "Usage: $0 [-k|--key-id <signing_key_id>] [-p|--keychain-profile <keychain_profile>]"
echo " [-d|--dir <containing_folder>] [-n|--app-name <app_name.app>]"
echo " [-v|--volume-name <volume_name>] [-o|--output <image_name.dmg>]"
echo " [-s|--dmg-settings <dmg_settings.py>]"
echo
echo "This script signs and notarizes a FreeCAD.app bundle. It expects that the bundle is in a folder"
echo "by itself (that folder will be used as the basis for the created disk image file, so anything"
echo "else in it will become part of the image). That folder should be located in the same folder as"
echo "this script."
echo
echo "If <signing_key_id> is not passed it defaults to env variable FREECAD_SIGNING_KEY_ID, it should"
echo "be a Developer ID Application certificate that has been installed into the login keychain."
echo "For a list of available keys see the output of"
echo " security find-identity -p basic -v"
echo "For instructions on how to configure the credentials for the tool for use before running this"
echo "script see the documentation for"
echo " xcrun notarytool store-credentials"
exit 1
}
# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-k|--key-id)
SIGNING_KEY_ID="$2"
shift 2
;;
-p|--keychain-profile)
KEYCHAIN_PROFILE="$2"
shift 2
;;
-d|--dir)
CONTAINING_FOLDER="$2"
shift 2
;;
-n|--app-name)
APP_NAME="$2"
shift 2
;;
-v|--volume-name)
VOLUME_NAME="$2"
shift 2
;;
-o|--output)
DMG_NAME="$2"
shift 2
;;
-s|--dmg-settings)
DMG_SETTINGS="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown parameter passed: $1"
usage
;;
esac
done
# Check if SIGNING_KEY_ID is set
if [ -z "$SIGNING_KEY_ID" ]; then
echo "Error: Signing key ID is required."
usage
fi
# Check for dmgbuild executable
if ! command -v dmgbuild &> /dev/null; then
echo "Error: dmgbuild not installed. Please install it for example using pip:"
echo 'pip3 install "dmgbuild[badge_icons]>=1.6.0,<1.7.0"'
exit 1
fi
function run_codesign {
echo "Signing $1"
/usr/bin/codesign --options runtime -f -s ${SIGNING_KEY_ID} --timestamp --entitlements entitlements.plist "$1"
}
IFS=$'\n'
dylibs=($(/usr/bin/find "${CONTAINING_FOLDER}/${APP_NAME}" -name "*.dylib"))
shared_objects=($(/usr/bin/find "${CONTAINING_FOLDER}/${APP_NAME}" -name "*.so"))
bundles=($(/usr/bin/find "${CONTAINING_FOLDER}/${APP_NAME}" -name "*.bundle"))
executables=($(/usr/bin/find "${CONTAINING_FOLDER}/${APP_NAME}" -type f -perm +111 -exec file {} + | grep "Mach-O 64-bit executable" | sed 's/:.*//g'))
IFS=$' \t\n' # The default
signed_files=("${dylibs[@]}" "${shared_objects[@]}" "${bundles[@]}" "${executables[@]}")
# This list of files is generated from:
# file `find . -type f -perm +111 -print` | grep "Mach-O 64-bit executable" | sed 's/:.*//g'
for exe in ${signed_files}; do
run_codesign "${exe}"
done
# Two additional files that must be signed that aren't caught by the above searches:
run_codesign "${CONTAINING_FOLDER}/${APP_NAME}/Contents/packages.txt"
run_codesign "${CONTAINING_FOLDER}/${APP_NAME}/Contents/Library/QuickLook/QuicklookFCStd.qlgenerator/Contents/MacOS/QuicklookFCStd"
# Finally, sign the app itself (must be done last)
run_codesign "${CONTAINING_FOLDER}/${APP_NAME}"
# Create a disk image from the folder
echo "Creating disk image ${DMG_NAME}"
dmgbuild -s ${DMG_SETTINGS} -Dcontaining_folder="${CONTAINING_FOLDER}" -Dapp_name="${APP_NAME}" "${VOLUME_NAME}" "${DMG_NAME}"
# Submit it for notarization (requires that an App Store API Key has been set up in the notarytool)
time xcrun notarytool submit --wait --keychain-profile "${KEYCHAIN_PROFILE}" "${DMG_NAME}"
# Assuming that notarization succeeded, it's a good practice to staple that notarization to the DMG
xcrun stapler staple "${DMG_NAME}"

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
[workspace]
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
platforms = ["linux-64", "linux-aarch64", "osx-64", "osx-arm64", "win-64"]
preview = ["pixi-build"]
[package]
name = "freecad"
version = "1.1.0dev"
homepage = "https://freecad.org"
repository = "https://github.com/FreeCAD/FreeCAD"
description = "FreeCAD"
[package.build]
backend = { name = "pixi-build-rattler-build", version = "*" }
[feature.freecad.dependencies]
freecad = { path = "." }
[feature.package.dependencies]
python = "==3.12.9"
## Linux (x86-64)
[feature.package.target.linux-64.dependencies]
coreutils = "*"
[feature.package.target.linux-64.tasks]
create_bundle = 'bash -c "cd linux && bash create_bundle.sh"'
## Linux (aarch64)
[feature.package.target.linux-aarch64.dependencies]
coreutils = "*"
[feature.package.target.linux-aarch64.tasks]
create_bundle = 'bash -c "cd linux && bash create_bundle.sh"'
## macOS (Intel)
[feature.package.target.osx-64.dependencies]
coreutils = "*"
dmgbuild = "*"
sed = "*"
[feature.package.target.osx-64.tasks]
create_bundle = 'bash -c "cd osx && bash create_bundle.sh"'
## macOS (Apple Silicon)
[feature.package.target.osx-arm64.dependencies]
coreutils = "*"
dmgbuild = "*"
sed = "*"
[feature.package.target.osx-arm64.tasks]
create_bundle = 'bash -c "cd osx && bash create_bundle.sh"'
## Windows dependencies (x86-64)
[feature.package.target.win-64.dependencies]
git = "*"
[feature.package.target.win-64.tasks]
create_bundle = 'bash -c "cd windows && bash create_bundle.sh"'
[environments]
default = ["freecad"]
package = ["package"]

View File

@@ -0,0 +1,169 @@
context:
version: "1.1.0dev"
package:
name: freecad
version: "${{ version }}"
source:
path: ../..
use_gitignore: true
build:
number: 0
requirements:
build:
- ccache
- cmake>=3.31.6,<4.0.0
- compilers
- doxygen
- ninja
- noqt5
- python==3.12.9
- qt6-main==6.8.2
- swig
- if: linux and x86_64
then:
- kernel-headers_linux-64
- libdrm-cos7-x86_64
- libselinux-cos7-x86_64
- libsepol-cos7-x86_64
- libspnav
- libx11-common-cos7-x86_64
- libx11-cos7-x86_64
- libxau-cos7-x86_64
- libxcb-cos7-x86_64
- libxdamage-cos7-x86_64
- libxext-cos7-x86_64
- libxfixes-cos7-x86_64
- libxi-cos7-x86_64
- libxi-devel-cos7-x86_64
- libxxf86vm-cos7-x86_64
- mesa-dri-drivers-cos7-x86_64
- mesa-libegl-cos7-x86_64
- mesa-libegl-devel-cos7-x86_64
- mesa-libgl-cos7-x86_64
- mesa-libgl-devel-cos7-x86_64
- pixman-cos7-x86_64
- sed
- sysroot_linux-64
- xorg-x11-server-common-cos7-x86_64
- xorg-x11-server-xvfb-cos7-x86_64
- xorg-xproto
- if: linux and aarch64
then:
- kernel-headers_linux-aarch64
- libdrm-cos7-aarch64
- libselinux-cos7-aarch64
- libsepol-cos7-aarch64
- libspnav
- libx11-common-cos7-aarch64
- libx11-cos7-aarch64
- libxau-cos7-aarch64
- libxcb-cos7-aarch64
- libxdamage-cos7-aarch64
- libxext-cos7-aarch64
- libxfixes-cos7-aarch64
- libxi-cos7-aarch64
- libxi-devel-cos7-aarch64
- libxxf86vm-cos7-aarch64
- mesa-dri-drivers-cos7-aarch64
- mesa-libegl-cos7-aarch64
- mesa-libegl-devel-cos7-aarch64
- mesa-libgl-cos7-aarch64
- mesa-libgl-devel-cos7-aarch64
- pixman-cos7-aarch64
- sed
- sysroot_linux-aarch64
- xorg-x11-server-common-cos7-aarch64
- xorg-x11-server-xvfb-cos7-aarch64
- xorg-xproto
- if: build_platform != target_platform
then:
- cross-python_${{ target_platform }}
host:
- coin3d
- eigen
- fmt
- freetype
- hdf5
- libboost-devel
- matplotlib-base
- noqt5
- numpy
- occt
- pcl
- pivy
- ply
- pybind11
- pyside6
- python==3.12.9
- qt6-main==6.8.2
- six
- smesh
- vtk
- xerces-c
- yaml-cpp
- zlib
- if: windows
then:
- tbb-devel
- if: unix
then:
- sed
- if: linux
then:
- libspnav
- xorg-xproto
- if: osx
then:
- blas * accelerate*
run:
- blas
- blinker
- calculix
- debugpy
- docutils
- gmsh
- graphviz
# - ifcopenshell
- jinja2
- lark
- lxml
- matplotlib-base
- nine
- noqt5
- numpy
- occt
- olefile
- opencamlib
- opencv
- pandas
- pip
- pivy
- ply
- pycollada
- pyside6
- python==3.12.9
- pythonocc-core
- pyyaml
- qt6-main==6.8.2
- requests
- scipy
- sympy
- vtk
- xlutils
- if: linux
then:
- libspnav

View File

@@ -0,0 +1,13 @@
diff --git a/src/Tools/SubWCRev.py b/src/Tools/SubWCRev.py
index 1f3f0a436343..c314003736f1 100644
--- a/src/Tools/SubWCRev.py
+++ b/src/Tools/SubWCRev.py
@@ -523,7 +523,7 @@ def main():
inp = open("%s/src/Build/Version.h.in" % (bindir))
lines = inp.readlines()
inp.close()
- lines = i.writeVersion(lines)
+ #lines = i.writeVersion(lines)
out = open("%s/src/Build/Version.h.out" % (bindir), "w")
out.writelines(lines)
out.write("\n")

View File

@@ -0,0 +1,88 @@
import os
import subprocess
import re
import sys
if len(sys.argv) < 1 or "-h" in sys.argv:
print("""Usage: python fix_macos_paths.py <scan_path> [-r] [-s]
Options:
-r scan the directory recursively
-s scan only without fixing absolute paths in LC_RPATH or LC_REEXPORT_DYLIB
""")
sys.exit(1)
scan_path = os.path.abspath(os.path.expanduser(sys.argv[1]))
recursive = "-r" in sys.argv
scanmode = "-s" in sys.argv
def get_lc_paths(output):
if "is not an object file" in output:
return [], []
rpath_result = []
reexport_result = []
matches = re.finditer(r'cmd LC_RPATH', output)
for match in matches:
pos = match.start(0)
path_match = re.search(r'path (.*) \(offset.+?\)', output[pos:])
rpath_result.append(path_match.group(1))
matches = re.finditer(r'cmd LC_REEXPORT_DYLIB', output)
for match in matches:
pos = match.start(0)
path_match = re.search(r'name (.*) \(offset.+?\)', output[pos:])
reexport_result.append(path_match.group(1))
return rpath_result, reexport_result
def remove_rpath(file_path, rpath):
subprocess.run(['install_name_tool', '-delete_rpath', rpath, file_path])
subprocess.run(['codesign', '--force', '--sign', '-', file_path])
print(f'\nRemoved rpath {rpath} from {file_path}')
def change_reexport_dylib(file_path, reexport_dylib):
rel_reexport_dylib = "@rpath/" + os.path.basename(reexport_dylib)
subprocess.run(['install_name_tool', '-change', reexport_dylib, rel_reexport_dylib, file_path])
subprocess.run(['codesign', '--force', '--sign', '-', file_path])
print(f'\nChanged reexport dylib {reexport_dylib} to {rel_reexport_dylib} in {file_path}')
def scan_directory(directory, recursive=False):
if recursive:
print(f"Recursively scanning dir: {scan_path}")
else:
print(f"Scanning dir: {scan_path}")
for filename in os.listdir(directory):
full_path = os.path.join(directory, filename)
if recursive and os.path.isdir(full_path):
scan_directory(full_path, recursive)
continue
elif not os.path.isfile(full_path) or os.path.islink(full_path):
continue
try:
output = subprocess.check_output(['otool', '-l', full_path], text=True)
rpaths, reexport_dylibs = get_lc_paths(output)
except:
continue
file_dir = os.path.dirname(full_path)
for rpath in rpaths:
if os.path.isabs(rpath) and os.path.samefile(file_dir, rpath):
if scanmode:
print(f'\nFound absolute path in LC_RPATH: {rpath}\nIn: {full_path}')
else:
remove_rpath(full_path, rpath)
for reexport_dylib in reexport_dylibs:
if os.path.isabs(reexport_dylib):
if scanmode:
print(f'\nFound absolute path inLC_REEXPORT_DYLIB: {reexport_dylib}\nIn: {full_path}')
else:
change_reexport_dylib(full_path, reexport_dylib)
scan_directory(scan_path, recursive)
print("Done")

View File

@@ -0,0 +1,53 @@
import sys
import os
import subprocess
import platform
from datetime import datetime
import freecad
import FreeCAD
package_manager = "conda"
system = platform.platform().split("-")[0]
arch = platform.machine()
# Windows uses a different syntax
if arch == "AMD64":
arch = "x86_64"
if "ARCH" in os.environ:
if os.environ["ARCH"] != "":
arch = os.environ["ARCH"]
python_version = platform.python_version().split(".")
python_version = "py" + python_version[0] + python_version[1]
date = str(datetime.now()).split(" ")[0]
version_info = FreeCAD.Version()
build_version_suffix = FreeCAD.ConfigGet("BuildVersionSuffix")
dev_version = version_info[0] + "." + version_info[1] + "." + version_info[2] + build_version_suffix
revision = version_info[3].split(" ")[0]
if system == "macOS":
import jinja2
print("create plist from template")
osx_directory = os.path.join(os.path.dirname(__file__), "..", "osx")
with open(os.path.join(osx_directory, "Info.plist.template")) as template_file:
template_str = template_file.read()
template = jinja2.Template(template_str)
rendered_str = template.render( FREECAD_VERSION="{}-{}".format(dev_version, revision),
APPLICATION_MENU_NAME="FreeCAD-{}-{}".format(dev_version, revision) )
with open(os.path.join(osx_directory, "FreeCAD.app", "Contents", "Info.plist"), "w") as rendered_file:
rendered_file.write(rendered_str)
if "DEPLOY_RELEASE" in os.environ and os.environ["DEPLOY_RELEASE"] == "weekly-builds":
dev_version = "weekly-builds"
revision_separator = "-"
else:
revision_separator = ""
revision = ""
bundle_name = f"FreeCAD_{dev_version}{revision_separator}{revision}-{package_manager}-{system}-{arch}-{python_version}"
with open("bundle_name.txt", "w") as bundle_name_file:
bundle_name_file.write(bundle_name)

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env python
# call this file from within the FreeCAD git repo
# this script creates a file with the important version information
import os
import sys
import subprocess
sys.path.append(f"{os.getcwd()}/src/Tools")
import SubWCRev
gitInfo = SubWCRev.GitControl()
gitInfo.extractInfo("","")
i = open("src/Build/Version.h.cmake")
content = []
for line in i.readlines():
line = line.replace("${PACKAGE_WCREF}",gitInfo.rev)
line = line.replace("${PACKAGE_WCDATE}",gitInfo.date)
line = line.replace("${PACKAGE_WCURL}",gitInfo.url)
content.append(line)
with open("src/Build/Version.h.cmake", "w") as o:
content.append('// Git relevant stuff\n')
content.append('#define FCRepositoryHash "%s"\n' % (gitInfo.hash))
content.append('#define FCRepositoryBranch "%s"\n' % (gitInfo.branch))
o.writelines(content)
with open(os.sys.argv[1], "w") as f:
f.write(f"rev_number: {gitInfo.rev}\n")
f.write(f"branch_name: {gitInfo.branch}\n")
f.write(f"commit_date: {gitInfo.date}\n")
f.write(f"commit_hash: {gitInfo.hash}\n")
f.write(f"remote_url: {gitInfo.url}\n")
p = subprocess.Popen(["git", "-c", "user.name='github-actions[bot]'", "-c", "user.email='41898282+github-actions[bot]@users.noreply.github.com'",
"commit", "-a", "-m", "add git information"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
print(out.decode())
print(err.decode())

View File

@@ -0,0 +1,56 @@
set conda_env="fc_env"
robocopy ..\.pixi\envs\default\* %conda_env% /S /MT:%NUMBER_OF_PROCESSORS% > nul
%conda_env%\python ..\scripts\get_freecad_version.py
set /p freecad_version_name= <bundle_name.txt
echo **********************
echo %freecad_version_name%
echo **********************
REM remove arm binaries that fail to extract unless using latest 7zip
for /r %conda_env% %%i in (*arm*.exe) do (@echo "%%i will be removed" & @del "%%i")
set copy_dir="FreeCAD_Conda_Build"
mkdir %copy_dir%
REM Copy Conda's Python and (U)CRT to FreeCAD/bin
robocopy %conda_env%\DLLs %copy_dir%\bin\DLLs /S /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Lib %copy_dir%\bin\Lib /XD __pycache__ /S /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Scripts %copy_dir%\bin\Scripts /S /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\python*.* %copy_dir%\bin\ /XF *.pdb /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\msvc*.* %copy_dir%\bin\ /XF *.pdb /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\ucrt*.* %copy_dir%\bin\ /XF *.pdb /MT:%NUMBER_OF_PROCESSORS% > nul
REM Copy meaningful executables
robocopy %conda_env%\Library\bin %copy_dir%\bin\ ccx.exe /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\bin %copy_dir%\bin\ gmsh.exe /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\bin %copy_dir%\bin\ dot.exe /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\bin %copy_dir%\bin\ unflatten.exe /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\mingw-w64\bin * %copy_dir%\bin\ /MT:%NUMBER_OF_PROCESSORS% > nul
REM Copy Conda's QT5/plugins to FreeCAD/bin
robocopy %conda_env%\Library\plugins %copy_dir%\bin\ /S /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\resources %copy_dir%\resources /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\translations %copy_dir%\translations /MT:%NUMBER_OF_PROCESSORS% > nul
REM get all the dependency .dlls
robocopy %conda_env%\Library\bin *.dll %copy_dir%\bin /XF *.pdb /XF api*.* /MT:%NUMBER_OF_PROCESSORS% > nul
REM Copy FreeCAD build
robocopy %conda_env%\Library\bin FreeCAD* %copy_dir%\bin /XF *.pdb /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\data %copy_dir%\data /XF *.txt /S /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\Ext %copy_dir%\Ext /S /XD __pycache__ /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\lib %copy_dir%\lib /XF *.lib /XF *.prl /XF *.sh /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\Mod %copy_dir%\Mod /S /XD __pycache__ /MT:%NUMBER_OF_PROCESSORS% > nul
robocopy %conda_env%\Library\doc %copy_dir%\doc ThirdPartyLibraries.html LICENSE.html /MT:%NUMBER_OF_PROCESSORS% > nul
REM Apply Patches
rename %copy_dir%\bin\Lib\ssl.py ssl-orig.py
copy ssl-patch.py %copy_dir%\bin\Lib\ssl.py
cd %copy_dir%\..
ren %copy_dir% %freecad_version_name%
dir
REM if errorlevel1 exit 1
"%ProgramFiles%\7-Zip\7z.exe" a -t7z -mx9 -mmt=%NUMBER_OF_PROCESSORS% %freecad_version_name%.7z %freecad_version_name%\ -bb
certutil -hashfile "%freecad_version_name%.7z" SHA256 > "%freecad_version_name%.7z"-SHA256.txt
echo %date%-%time% >>"%freecad_version_name%.7z"-SHA256.txt

View File

@@ -0,0 +1,80 @@
#!/bin/bash
set -e
set -x
conda_env="fc_env"
mkdir -p ${conda_env}
cp -a ../.pixi/envs/default/* ${conda_env}
export PATH="${PWD}/${conda_env}/bin:${PATH}"
export CONDA_PREFIX="${PWD}/${conda_env}"
# remove arm binaries that fail to extract unless using latest 7zip
rm $(find ${conda_env} -name \*arm\*.exe)
# delete unnecessary stuff
rm -rf ${conda_env}/include
find ${conda_env} -name \*.a -delete
copy_dir="FreeCAD_Conda_Build"
mkdir -p ${copy_dir}/bin
# Copy Conda's Python and (U)CRT to FreeCAD/bin
cp -a ${conda_env}/DLLs ${copy_dir}/bin/DLLs
cp -a ${conda_env}/Lib ${copy_dir}/bin/Lib
cp -a ${conda_env}/Scripts ${copy_dir}/bin/Scripts
cp -a ${conda_env}/python*.* ${copy_dir}/bin
cp -a ${conda_env}/msvc*.* ${copy_dir}/bin
cp -a ${conda_env}/ucrt*.* ${copy_dir}/bin
# Copy meaningful executables
cp -a ${conda_env}/Library/bin/ccx.exe ${copy_dir}/bin
cp -a ${conda_env}/Library/bin/gmsh.exe ${copy_dir}/bin
cp -a ${conda_env}/Library/bin/dot.exe ${copy_dir}/bin
cp -a ${conda_env}/Library/bin/unflatten.exe ${copy_dir}/bin
cp -a ${conda_env}/Library/mingw-w64/bin/* ${copy_dir}/bin
# copy resources -- perhaps needs reduction
cp -a ${conda_env}/Library/share ${copy_dir}/share
# get all the dependency .dlls
cp -a ${conda_env}/Library/bin/*.dll ${copy_dir}/bin
# Copy FreeCAD build
cp -a ${conda_env}/Library/bin/freecad* ${copy_dir}/bin
cp -a ${conda_env}/Library/bin/FreeCAD* ${copy_dir}/bin
cp -a ${conda_env}/Library/data ${copy_dir}/data
cp -a ${conda_env}/Library/Ext ${copy_dir}/Ext
cp -a ${conda_env}/Library/lib ${copy_dir}/lib
cp -a ${conda_env}/Library/Mod ${copy_dir}/Mod
rm -rf ${conda_env}/bin_tmp
# Apply Patches
mv ${copy_dir}/bin/Lib/ssl.py ssl-orig.py
cp ssl-patch.py ${copy_dir}/bin/Lib/ssl.py
echo '[Paths]' >> ${copy_dir}/bin/qt6.conf
echo 'Prefix = ../lib/qt6' >> ${copy_dir}/bin/qt6.conf
build_tag=$(git describe --tags)
python_version=$(python -c 'import platform; print("py" + platform.python_version_tuple()[0] + platform.python_version_tuple()[1])')
version_name="FreeCAD_${build_tag}-Windows-$(uname -m)-${python_version}"
application_menu_name="FreeCAD_${build_tag}"
echo -e "################"
echo -e "version_name: ${version_name}"
echo -e "################"
pixi list -e default > ${copy_dir}/packages.txt
sed -i '1s/.*/\nLIST OF PACKAGES:/' ${copy_dir}/packages.txt
mv ${copy_dir} ${version_name}
"${PROGRAMFILES}/7-Zip/7z.exe" a -t7z -mx9 -mmt=${NUMBER_OF_PROCESSORS} ${version_name}.7z ${version_name} -bb
# create hash
sha256sum ${version_name}.7z > ${version_name}.7z-SHA256.txt
if [ "${UPLOAD_RELEASE}" == "true" ]; then
gh release create ${BUILD_TAG} --title "Weekly Build ${BUILD_TAG}" --notes "Weekly Build ${BUILD_TAG}" --prerelease || true
gh release upload --clobber ${BUILD_TAG} "${version_name}.7z" "${version_name}.7z-SHA256.txt"
fi

File diff suppressed because it is too large Load Diff