|
|
|
|
@@ -1,6 +1,9 @@
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
|
# Build a .deb package from the installed build directory
|
|
|
|
|
#
|
|
|
|
|
# This script creates a Debian binary package following Debian Policy Manual guidelines.
|
|
|
|
|
# See: https://www.debian.org/doc/debian-policy/
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
@@ -19,113 +22,293 @@ if [ -z "$INSTALL_DIR" ] || [ -z "$OUTPUT_DIR" ]; then
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Validate install directory exists
|
|
|
|
|
if [ ! -d "$INSTALL_DIR" ]; then
|
|
|
|
|
echo "Error: Install directory does not exist: $INSTALL_DIR"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Get version from git if not provided
|
|
|
|
|
if [ -z "$VERSION" ]; then
|
|
|
|
|
VERSION=$(cd "$PROJECT_ROOT" && git describe --tags --always 2>/dev/null || echo "0.1.0")
|
|
|
|
|
# Clean up version for debian (replace - with .)
|
|
|
|
|
VERSION="${VERSION#v}" # Remove leading 'v' if present
|
|
|
|
|
VERSION="${VERSION//-/.}" # Replace - with .
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Convert version to Debian-compatible format
|
|
|
|
|
# Debian Policy Manual 5.6.12: version must start with a digit
|
|
|
|
|
# Format: [epoch:]upstream_version[-debian_revision]
|
|
|
|
|
convert_to_debian_version() {
|
|
|
|
|
local ver="$1"
|
|
|
|
|
|
|
|
|
|
# Remove leading 'v' if present (common in git tags)
|
|
|
|
|
ver="${ver#v}"
|
|
|
|
|
|
|
|
|
|
# Replace hyphens with dots (hyphens have special meaning in Debian versions)
|
|
|
|
|
ver="${ver//-/.}"
|
|
|
|
|
|
|
|
|
|
# If version starts with a letter (e.g., 'weekly'), prefix with '0~'
|
|
|
|
|
# The ~ character sorts before anything else, ensuring:
|
|
|
|
|
# 0~weekly.2025.01.01 < 0.1.0 < 1.0.0
|
|
|
|
|
if [[ "$ver" =~ ^[a-zA-Z] ]]; then
|
|
|
|
|
ver="0~${ver}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "$ver"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERSION=$(convert_to_debian_version "$VERSION")
|
|
|
|
|
|
|
|
|
|
PACKAGE_NAME="kindred-create"
|
|
|
|
|
ARCH="amd64"
|
|
|
|
|
# Debian package naming: <name>_<version>_<arch>.deb
|
|
|
|
|
DEB_NAME="${PACKAGE_NAME}_${VERSION}_${ARCH}"
|
|
|
|
|
|
|
|
|
|
echo "Building .deb package: ${DEB_NAME}.deb"
|
|
|
|
|
echo " Source: ${INSTALL_DIR}"
|
|
|
|
|
echo " Output: ${OUTPUT_DIR}"
|
|
|
|
|
echo " Version: ${VERSION}"
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo "Building Debian package"
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo " Package: ${PACKAGE_NAME}"
|
|
|
|
|
echo " Version: ${VERSION}"
|
|
|
|
|
echo " Arch: ${ARCH}"
|
|
|
|
|
echo " Source: ${INSTALL_DIR}"
|
|
|
|
|
echo " Output: ${OUTPUT_DIR}/${DEB_NAME}.deb"
|
|
|
|
|
echo "========================================"
|
|
|
|
|
|
|
|
|
|
# Create staging directory
|
|
|
|
|
STAGING_DIR=$(mktemp -d)
|
|
|
|
|
trap "rm -rf ${STAGING_DIR}" EXIT
|
|
|
|
|
|
|
|
|
|
# Create debian package structure
|
|
|
|
|
# Create debian package structure following Filesystem Hierarchy Standard
|
|
|
|
|
mkdir -p "${STAGING_DIR}/DEBIAN"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/opt/${PACKAGE_NAME}"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/bin"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/applications"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/icons/hicolor/scalable/apps"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/icons/hicolor/48x48/apps"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/icons/hicolor/256x256/apps"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/mime/packages"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/metainfo"
|
|
|
|
|
mkdir -p "${STAGING_DIR}/usr/share/doc/${PACKAGE_NAME}"
|
|
|
|
|
|
|
|
|
|
# Copy installed files
|
|
|
|
|
echo "Copying installed files..."
|
|
|
|
|
cp -a "${INSTALL_DIR}"/* "${STAGING_DIR}/opt/${PACKAGE_NAME}/"
|
|
|
|
|
|
|
|
|
|
# Create symlinks in /usr/bin
|
|
|
|
|
# Create symlinks in /usr/bin for system-wide access
|
|
|
|
|
ln -sf "/opt/${PACKAGE_NAME}/bin/FreeCAD" "${STAGING_DIR}/usr/bin/kindred-create"
|
|
|
|
|
ln -sf "/opt/${PACKAGE_NAME}/bin/FreeCADCmd" "${STAGING_DIR}/usr/bin/kindred-create-cmd"
|
|
|
|
|
|
|
|
|
|
# Create desktop entry
|
|
|
|
|
# Create desktop entry following freedesktop.org specification
|
|
|
|
|
cat > "${STAGING_DIR}/usr/share/applications/kindred-create.desktop" << 'EOF'
|
|
|
|
|
[Desktop Entry]
|
|
|
|
|
Version=1.1
|
|
|
|
|
Type=Application
|
|
|
|
|
Name=Kindred Create
|
|
|
|
|
GenericName=CAD Application
|
|
|
|
|
Comment=Engineering-focused parametric 3D CAD platform
|
|
|
|
|
Exec=/opt/kindred-create/bin/FreeCAD %F
|
|
|
|
|
Exec=kindred-create %F
|
|
|
|
|
Icon=kindred-create
|
|
|
|
|
Terminal=false
|
|
|
|
|
Type=Application
|
|
|
|
|
Categories=Graphics;Science;Engineering;
|
|
|
|
|
MimeType=application/x-extension-fcstd;
|
|
|
|
|
MimeType=application/x-extension-fcstd;application/x-freecad;
|
|
|
|
|
Keywords=CAD;3D;modeling;engineering;design;parametric;FreeCAD;
|
|
|
|
|
StartupNotify=true
|
|
|
|
|
StartupWMClass=FreeCAD
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
# Copy icon if available, otherwise create a placeholder reference
|
|
|
|
|
# Copy or create icon files
|
|
|
|
|
if [ -f "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/org.freecad.FreeCAD.svg" ]; then
|
|
|
|
|
cp "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/org.freecad.FreeCAD.svg" \
|
|
|
|
|
"${STAGING_DIR}/usr/share/icons/hicolor/scalable/apps/kindred-create.svg"
|
|
|
|
|
elif [ -f "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/freecad.svg" ]; then
|
|
|
|
|
cp "${INSTALL_DIR}/share/icons/hicolor/scalable/apps/freecad.svg" \
|
|
|
|
|
elif [ -f "${PROJECT_ROOT}/resources/branding/kindred-create.svg" ]; then
|
|
|
|
|
cp "${PROJECT_ROOT}/resources/branding/kindred-create.svg" \
|
|
|
|
|
"${STAGING_DIR}/usr/share/icons/hicolor/scalable/apps/kindred-create.svg"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Copy PNG icons if available
|
|
|
|
|
for size in 48 256; do
|
|
|
|
|
if [ -f "${INSTALL_DIR}/share/icons/hicolor/${size}x${size}/apps/org.freecad.FreeCAD.png" ]; then
|
|
|
|
|
cp "${INSTALL_DIR}/share/icons/hicolor/${size}x${size}/apps/org.freecad.FreeCAD.png" \
|
|
|
|
|
"${STAGING_DIR}/usr/share/icons/hicolor/${size}x${size}/apps/kindred-create.png"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Create MIME type definition for .fcstd files
|
|
|
|
|
cat > "${STAGING_DIR}/usr/share/mime/packages/kindred-create.xml" << 'EOF'
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
|
|
|
|
<mime-type type="application/x-freecad">
|
|
|
|
|
<comment>FreeCAD Document</comment>
|
|
|
|
|
<glob pattern="*.fcstd"/>
|
|
|
|
|
<glob pattern="*.FCStd"/>
|
|
|
|
|
<icon name="kindred-create"/>
|
|
|
|
|
</mime-type>
|
|
|
|
|
</mime-info>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
# Create AppStream metainfo for software centers
|
|
|
|
|
cat > "${STAGING_DIR}/usr/share/metainfo/kindred-create.metainfo.xml" << EOF
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<component type="desktop-application">
|
|
|
|
|
<id>kindred-create</id>
|
|
|
|
|
<name>Kindred Create</name>
|
|
|
|
|
<summary>Engineering-focused parametric 3D CAD platform</summary>
|
|
|
|
|
<metadata_license>CC0-1.0</metadata_license>
|
|
|
|
|
<project_license>LGPL-2.1-or-later</project_license>
|
|
|
|
|
<description>
|
|
|
|
|
<p>
|
|
|
|
|
Kindred Create is an engineering-focused parametric 3D CAD platform
|
|
|
|
|
built on FreeCAD 1.0+. It provides a streamlined interface for
|
|
|
|
|
mechanical engineering and product design.
|
|
|
|
|
</p>
|
|
|
|
|
<p>Features include:</p>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Parametric modeling with constraint-based sketcher</li>
|
|
|
|
|
<li>Part Design workbench for solid modeling</li>
|
|
|
|
|
<li>Assembly workbench for multi-part designs</li>
|
|
|
|
|
<li>TechDraw workbench for 2D technical drawings</li>
|
|
|
|
|
<li>FEM workbench for finite element analysis</li>
|
|
|
|
|
<li>CAM workbench for CNC machining</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</description>
|
|
|
|
|
<launchable type="desktop-id">kindred-create.desktop</launchable>
|
|
|
|
|
<url type="homepage">https://gitea.kindred.internal/kindred/create</url>
|
|
|
|
|
<url type="bugtracker">https://gitea.kindred.internal/kindred/create/issues</url>
|
|
|
|
|
<provides>
|
|
|
|
|
<binary>kindred-create</binary>
|
|
|
|
|
<binary>kindred-create-cmd</binary>
|
|
|
|
|
</provides>
|
|
|
|
|
<content_rating type="oars-1.1"/>
|
|
|
|
|
<releases>
|
|
|
|
|
<release version="${VERSION}" date="$(date +%Y-%m-%d)"/>
|
|
|
|
|
</releases>
|
|
|
|
|
</component>
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
# Create basic copyright file (required by Debian policy)
|
|
|
|
|
cat > "${STAGING_DIR}/usr/share/doc/${PACKAGE_NAME}/copyright" << 'EOF'
|
|
|
|
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
|
|
|
Upstream-Name: Kindred Create
|
|
|
|
|
Upstream-Contact: Kindred Team <team@kindred.internal>
|
|
|
|
|
Source: https://gitea.kindred.internal/kindred/create
|
|
|
|
|
|
|
|
|
|
Files: *
|
|
|
|
|
Copyright: 2024-2026 Kindred
|
|
|
|
|
2001-2024 FreeCAD Contributors
|
|
|
|
|
License: LGPL-2.1-or-later
|
|
|
|
|
|
|
|
|
|
License: LGPL-2.1-or-later
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
.
|
|
|
|
|
On Debian systems, the complete text of the GNU Lesser General Public
|
|
|
|
|
License can be found in `/usr/share/common-licenses/LGPL-2.1'.
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
# Generate control file with actual version
|
|
|
|
|
sed "s/\${VERSION}/${VERSION}/" "${SCRIPT_DIR}/control" > "${STAGING_DIR}/DEBIAN/control"
|
|
|
|
|
|
|
|
|
|
# Calculate installed size (in KB)
|
|
|
|
|
# Calculate and append installed size (in KiB, as required by Debian policy)
|
|
|
|
|
INSTALLED_SIZE=$(du -sk "${STAGING_DIR}" | cut -f1)
|
|
|
|
|
echo "Installed-Size: ${INSTALLED_SIZE}" >> "${STAGING_DIR}/DEBIAN/control"
|
|
|
|
|
|
|
|
|
|
# Create postinst script for updating desktop database
|
|
|
|
|
# Create postinst script for post-installation setup
|
|
|
|
|
cat > "${STAGING_DIR}/DEBIAN/postinst" << 'EOF'
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
set -e
|
|
|
|
|
if [ -x /usr/bin/update-desktop-database ]; then
|
|
|
|
|
/usr/bin/update-desktop-database -q /usr/share/applications || true
|
|
|
|
|
fi
|
|
|
|
|
if [ -x /usr/bin/gtk-update-icon-cache ]; then
|
|
|
|
|
/usr/bin/gtk-update-icon-cache -q /usr/share/icons/hicolor || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
case "$1" in
|
|
|
|
|
configure)
|
|
|
|
|
# Update desktop database
|
|
|
|
|
if command -v update-desktop-database > /dev/null 2>&1; then
|
|
|
|
|
update-desktop-database -q /usr/share/applications 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Update icon cache
|
|
|
|
|
if command -v gtk-update-icon-cache > /dev/null 2>&1; then
|
|
|
|
|
gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Update MIME database
|
|
|
|
|
if command -v update-mime-database > /dev/null 2>&1; then
|
|
|
|
|
update-mime-database /usr/share/mime 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
exit 0
|
|
|
|
|
EOF
|
|
|
|
|
chmod 755 "${STAGING_DIR}/DEBIAN/postinst"
|
|
|
|
|
|
|
|
|
|
# Create postrm script
|
|
|
|
|
# Create postrm script for post-removal cleanup
|
|
|
|
|
cat > "${STAGING_DIR}/DEBIAN/postrm" << 'EOF'
|
|
|
|
|
#!/bin/bash
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
set -e
|
|
|
|
|
if [ -x /usr/bin/update-desktop-database ]; then
|
|
|
|
|
/usr/bin/update-desktop-database -q /usr/share/applications || true
|
|
|
|
|
fi
|
|
|
|
|
if [ -x /usr/bin/gtk-update-icon-cache ]; then
|
|
|
|
|
/usr/bin/gtk-update-icon-cache -q /usr/share/icons/hicolor || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
case "$1" in
|
|
|
|
|
remove|purge)
|
|
|
|
|
# Update desktop database
|
|
|
|
|
if command -v update-desktop-database > /dev/null 2>&1; then
|
|
|
|
|
update-desktop-database -q /usr/share/applications 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Update icon cache
|
|
|
|
|
if command -v gtk-update-icon-cache > /dev/null 2>&1; then
|
|
|
|
|
gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Update MIME database
|
|
|
|
|
if command -v update-mime-database > /dev/null 2>&1; then
|
|
|
|
|
update-mime-database /usr/share/mime 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
exit 0
|
|
|
|
|
EOF
|
|
|
|
|
chmod 755 "${STAGING_DIR}/DEBIAN/postrm"
|
|
|
|
|
|
|
|
|
|
# Set proper permissions
|
|
|
|
|
# Set proper permissions following Debian policy
|
|
|
|
|
# Directories: 755, Files: 644, Executables: 755
|
|
|
|
|
echo "Setting file permissions..."
|
|
|
|
|
find "${STAGING_DIR}" -type d -exec chmod 755 {} \;
|
|
|
|
|
find "${STAGING_DIR}/opt" -type f -exec chmod 644 {} \;
|
|
|
|
|
find "${STAGING_DIR}/opt/${PACKAGE_NAME}/bin" -type f -exec chmod 755 {} \;
|
|
|
|
|
|
|
|
|
|
# Make binaries executable
|
|
|
|
|
if [ -d "${STAGING_DIR}/opt/${PACKAGE_NAME}/bin" ]; then
|
|
|
|
|
find "${STAGING_DIR}/opt/${PACKAGE_NAME}/bin" -type f -exec chmod 755 {} \;
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Make shared libraries executable (required for proper loading)
|
|
|
|
|
find "${STAGING_DIR}/opt/${PACKAGE_NAME}" -name "*.so" -type f -exec chmod 755 {} \;
|
|
|
|
|
find "${STAGING_DIR}/opt/${PACKAGE_NAME}" -name "*.so.*" -type f -exec chmod 755 {} \;
|
|
|
|
|
|
|
|
|
|
# Ensure DEBIAN scripts have correct permissions (must be 0555 to 0775)
|
|
|
|
|
chmod 755 "${STAGING_DIR}/DEBIAN/postinst"
|
|
|
|
|
chmod 755 "${STAGING_DIR}/DEBIAN/postrm"
|
|
|
|
|
|
|
|
|
|
# Build the .deb package
|
|
|
|
|
# --root-owner-group ensures all files are owned by root:root (standard practice)
|
|
|
|
|
mkdir -p "${OUTPUT_DIR}"
|
|
|
|
|
echo "Building package..."
|
|
|
|
|
dpkg-deb --build --root-owner-group "${STAGING_DIR}" "${OUTPUT_DIR}/${DEB_NAME}.deb"
|
|
|
|
|
|
|
|
|
|
# Generate checksum
|
|
|
|
|
# Verify the package
|
|
|
|
|
echo "Verifying package..."
|
|
|
|
|
dpkg-deb --info "${OUTPUT_DIR}/${DEB_NAME}.deb"
|
|
|
|
|
|
|
|
|
|
# Generate checksums
|
|
|
|
|
cd "${OUTPUT_DIR}"
|
|
|
|
|
sha256sum "${DEB_NAME}.deb" > "${DEB_NAME}.deb.sha256"
|
|
|
|
|
|
|
|
|
|
echo "Package created: ${OUTPUT_DIR}/${DEB_NAME}.deb"
|
|
|
|
|
ls -lh "${OUTPUT_DIR}/${DEB_NAME}.deb"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo "Package built successfully!"
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo " File: ${OUTPUT_DIR}/${DEB_NAME}.deb"
|
|
|
|
|
echo " Size: $(ls -lh "${DEB_NAME}.deb" | awk '{print $5}')"
|
|
|
|
|
echo " SHA256: $(cat "${DEB_NAME}.deb.sha256" | cut -d' ' -f1)"
|
|
|
|
|
echo "========================================"
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Install with: sudo dpkg -i ${DEB_NAME}.deb"
|
|
|
|
|
echo " sudo apt-get install -f # to resolve dependencies"
|
|
|
|
|
|