qgis, qgis-ltr: fix dependencies on darwin (#157862)

This commit is contained in:
Ivan Mincik
2026-03-31 09:23:25 +00:00
committed by GitHub
4 changed files with 238 additions and 34 deletions
+4 -1
View File
@@ -1,4 +1,6 @@
{
lib,
stdenv,
makeWrapper,
nixosTests,
symlinkJoin,
@@ -40,7 +42,8 @@ symlinkJoin {
--prefix PATH : $program_PATH \
--set PYTHONPATH $program_PYTHONPATH
done
''
+ lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
ln -s ${qgis-unwrapped.man} $man
'';
+8 -5
View File
@@ -1,4 +1,6 @@
{
lib,
stdenv,
makeWrapper,
nixosTests,
symlinkJoin,
@@ -14,15 +16,13 @@
}:
let
qgis-ltr-unwrapped = libsForQt5.callPackage ./unwrapped-ltr.nix {
withGrass = withGrass;
withServer = withServer;
withWebKit = withWebKit;
inherit withGrass withServer withWebKit;
};
in
symlinkJoin {
inherit (qgis-ltr-unwrapped) version src;
pname = "qgis";
inherit (qgis-ltr-unwrapped) version outputs src;
pname = "qgis-ltr";
paths = [ qgis-ltr-unwrapped ];
@@ -43,6 +43,9 @@ symlinkJoin {
--prefix PATH : $program_PATH \
--set PYTHONPATH $program_PYTHONPATH
done
''
+ lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
ln -s ${qgis-ltr-unwrapped.man} $man
'';
passthru = {
+113 -12
View File
@@ -1,6 +1,8 @@
{
lib,
stdenv,
fetchFromGitHub,
lndir,
makeWrapper,
mkDerivation,
replaceVars,
@@ -11,6 +13,8 @@
withServer,
withWebKit,
darwin,
libtasn1,
bison,
cmake,
draco,
@@ -40,6 +44,7 @@
qtmultimedia,
qtsensors,
qtserialport,
qtsvg,
qtwebkit,
qtxmlpatterns,
qwt,
@@ -68,6 +73,7 @@ let
psycopg2
pygments
pyqt5
pyqt5-sip
pyqt-builder
python-dateutil
pytz
@@ -83,6 +89,7 @@ in
mkDerivation rec {
version = "3.40.15";
pname = "qgis-ltr-unwrapped";
outputs = [ "out" ] ++ lib.optional (!stdenv.hostPlatform.isDarwin) "man";
src = fetchFromGitHub {
owner = "qgis";
@@ -105,6 +112,10 @@ mkDerivation rec {
cmake
flex
ninja
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
darwin.autoSignDarwinBinariesHook
lndir
];
buildInputs = [
@@ -131,6 +142,7 @@ mkDerivation rec {
qtmultimedia
qtsensors
qtserialport
qtsvg
qtxmlpatterns
qwt
sqlite
@@ -139,6 +151,7 @@ mkDerivation rec {
]
++ lib.optional withGrass grass
++ lib.optional withWebKit qtwebkit
++ lib.optional stdenv.hostPlatform.isDarwin libtasn1
++ pythonBuildInputs;
patches = [
@@ -168,6 +181,10 @@ mkDerivation rec {
# See https://github.com/libspatialindex/libspatialindex/issues/276
"-DWITH_INTERNAL_SPATIALINDEX=True"
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
"-DQGIS_MACAPP_BUNDLE=0" # Don't copy Qt into bundle; we fix paths in postFixup
"-DSQLITE3_INCLUDE_DIR=${sqlite.dev}/include" # FindSqlite3.cmake incorrectly assumes framework
]
++ lib.optional (!withWebKit) "-DWITH_QTWEBKIT=OFF"
++ lib.optional withServer [
"-DWITH_SERVER=True"
@@ -186,18 +203,102 @@ mkDerivation rec {
];
dontWrapGApps = true; # wrapper params passed below
dontWrapQtApps = stdenv.hostPlatform.isDarwin;
postFixup = lib.optionalString withGrass ''
# GRASS has to be availble on the command line even though we baked in
# the path at build time using GRASS_PREFIX.
# Using wrapGAppsHook also prevents file dialogs from crashing the program
# on non-NixOS.
for program in $out/bin/*; do
wrapProgram $program \
"''${gappsWrapperArgs[@]}" \
--prefix PATH : ${lib.makeBinPath [ grass ]}
done
'';
postFixup =
lib.optionalString (withGrass && stdenv.hostPlatform.isLinux) ''
# GRASS has to be available on the command line even though we baked in
# the path at build time using GRASS_PREFIX.
# Using wrapGAppsHook also prevents file dialogs from crashing the program
# on non-NixOS.
for program in $out/bin/*; do
wrapProgram $program \
"''${gappsWrapperArgs[@]}" \
--prefix PATH : ${lib.makeBinPath [ grass ]}
done
''
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
mkdir -p $out/Applications $out/bin
mv $out/QGIS.app $out/Applications/
ln -s $out/Applications/QGIS.app/Contents/MacOS/QGIS $out/bin/qgis
SHORT_VERSION=$(echo "${version}" | cut -d. -f1,2)
BUNDLE="$out/Applications/QGIS.app"
FRAMEWORKS="$BUNDLE/Contents/Frameworks"
fix_binary() {
local f="$1"
[[ -f "$f" ]] || return 0
file "$f" | grep -q "Mach-O" || return 0
install_name_tool \
-change "@loader_path/../lib/libqscintilla2_qt5.dylib" "${qscintilla}/lib/libqscintilla2_qt5.dylib" \
-change "@loader_path/../lib/libqt5keychain.dylib" "${qtkeychain}/lib/libqt5keychain.dylib" \
-change "@loader_path/../lib/libqwt.dylib" "${qwt}/lib/libqwt.dylib" \
-change "@loader_path/../../Frameworks/qca-qt5.framework/qca-qt5" "${qca-qt5}/lib/qca-qt5.framework/qca-qt5" \
-change "@loader_path/../../../qca-qt5.framework/qca-qt5" "${qca-qt5}/lib/qca-qt5.framework/qca-qt5" \
-change "@loader_path/../../../../MacOS/lib/libqscintilla2_qt5.dylib" "${qscintilla}/lib/libqscintilla2_qt5.dylib" \
-change "@loader_path/../../../../MacOS/lib/libqt5keychain.dylib" "${qtkeychain}/lib/libqt5keychain.dylib" \
-change "@loader_path/../../../../MacOS/lib/libqwt.dylib" "${qwt}/lib/libqwt.dylib" \
-change "@executable_path/lib/libqwt.dylib" "${qwt}/lib/libqwt.dylib" \
-change "@executable_path/lib/libqscintilla2_qt5.dylib" "${qscintilla}/lib/libqscintilla2_qt5.dylib" \
-change "@executable_path/lib/libqt5keychain.dylib" "${qtkeychain}/lib/libqt5keychain.dylib" \
-change "@executable_path/../Frameworks/qca-qt5.framework/qca-qt5" "${qca-qt5}/lib/qca-qt5.framework/qca-qt5" \
-change "@loader_path/../../../qgis_core.framework/qgis_core" "$FRAMEWORKS/qgis_core.framework/Versions/$SHORT_VERSION/qgis_core" \
-change "@loader_path/../../../qgis_gui.framework/qgis_gui" "$FRAMEWORKS/qgis_gui.framework/Versions/$SHORT_VERSION/qgis_gui" \
-change "@loader_path/../../../qgis_analysis.framework/qgis_analysis" "$FRAMEWORKS/qgis_analysis.framework/Versions/$SHORT_VERSION/qgis_analysis" \
-change "@loader_path/../../../qgis_3d.framework/qgis_3d" "$FRAMEWORKS/qgis_3d.framework/Versions/$SHORT_VERSION/qgis_3d" \
-change "@loader_path/../../../qgis_native.framework/qgis_native" "$FRAMEWORKS/qgis_native.framework/Versions/$SHORT_VERSION/qgis_native" \
"$f" 2>/dev/null || true
}
fix_binary "$BUNDLE/Contents/MacOS/QGIS"
for lib in "$BUNDLE/Contents/MacOS/lib"/*.dylib; do fix_binary "$lib"; done
for fw in qgis_core qgis_gui qgis_analysis qgis_3d qgis_native; do
fix_binary "$FRAMEWORKS/$fw.framework/Versions/$SHORT_VERSION/$fw"
[[ -f "$FRAMEWORKS/$fw.framework/$fw" && ! -L "$FRAMEWORKS/$fw.framework/$fw" ]] && \
fix_binary "$FRAMEWORKS/$fw.framework/$fw"
done
for plugin in "$BUNDLE/Contents/PlugIns/qgis"/*.so; do fix_binary "$plugin"; done
${lib.optionalString withGrass ''
fix_binary "$FRAMEWORKS/qgisgrass8.framework/Versions/$SHORT_VERSION/qgisgrass8"
install_name_tool \
-change "@loader_path/../../../qgisgrass8.framework/qgisgrass8" "$FRAMEWORKS/qgisgrass8.framework/Versions/$SHORT_VERSION/qgisgrass8" \
"$BUNDLE/Contents/MacOS/QGIS" 2>/dev/null || true
for lib in "$BUNDLE/Contents/MacOS/lib"/*.dylib; do
install_name_tool \
-change "@loader_path/../../../qgisgrass8.framework/qgisgrass8" "$FRAMEWORKS/qgisgrass8.framework/Versions/$SHORT_VERSION/qgisgrass8" \
"$lib" 2>/dev/null || true
done
''}
${lib.optionalString withServer ''
fix_binary "$BUNDLE/Contents/MacOS/lib/libqgis_server.${version}.dylib"
''}
# Merge Python packages (lndir handles namespace packages correctly)
QGIS_PYTHON="$BUNDLE/Contents/Resources/python"
for pkg in ${
lib.concatMapStringsSep " " (p: "${p}/${py.pkgs.python.sitePackages}") (
py.pkgs.requiredPythonModules pythonBuildInputs
)
}; do
[[ -d "$pkg" ]] && lndir -silent "$pkg" "$QGIS_PYTHON"
done
# Remove broken symlinks
find "$QGIS_PYTHON" -type l ! -exec test -e {} \; -delete
# Create merged Qt plugins directory in the bundle (LSEnvironment is unreliable)
mkdir -p "$BUNDLE/Contents/PlugIns"
lndir -silent "${qtbase}/${qtbase.qtPluginPrefix}" "$BUNDLE/Contents/PlugIns"
lndir -silent "${qtsvg.bin}/${qtbase.qtPluginPrefix}" "$BUNDLE/Contents/PlugIns"
cat > "$BUNDLE/Contents/Resources/qt.conf" << 'EOF'
[Paths]
Plugins = PlugIns
EOF
'';
# >9k objects, >3h build time on a normal build slot
requiredSystemFeatures = [ "big-parallel" ];
@@ -207,6 +308,6 @@ mkDerivation rec {
homepage = "https://www.qgis.org";
license = lib.licenses.gpl2Plus;
teams = [ lib.teams.geospatial ];
platforms = with lib.platforms; linux;
platforms = lib.platforms.unix;
};
}
+113 -16
View File
@@ -1,6 +1,8 @@
{
lib,
stdenv,
fetchFromGitHub,
lndir,
makeWrapper,
mkDerivation,
replaceVars,
@@ -11,6 +13,8 @@
withServer,
withWebKit,
darwin,
libtasn1,
bison,
cmake,
draco,
@@ -40,6 +44,7 @@
qtmultimedia,
qtsensors,
qtserialport,
qtsvg,
qtwebkit,
qtxmlpatterns,
qwt,
@@ -68,6 +73,7 @@ let
psycopg2
pygments
pyqt5
pyqt5-sip
pyqt-builder
python-dateutil
pytz
@@ -83,10 +89,7 @@ in
mkDerivation rec {
version = "3.44.7";
pname = "qgis-unwrapped";
outputs = [
"out"
"man"
];
outputs = [ "out" ] ++ lib.optional (!stdenv.hostPlatform.isDarwin) "man";
src = fetchFromGitHub {
owner = "qgis";
@@ -109,6 +112,10 @@ mkDerivation rec {
cmake
flex
ninja
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
darwin.autoSignDarwinBinariesHook
lndir
];
buildInputs = [
@@ -135,6 +142,7 @@ mkDerivation rec {
qtmultimedia
qtsensors
qtserialport
qtsvg
qtxmlpatterns
qwt
sqlite
@@ -143,6 +151,7 @@ mkDerivation rec {
]
++ lib.optional withGrass grass
++ lib.optional withWebKit qtwebkit
++ lib.optional stdenv.hostPlatform.isDarwin libtasn1
++ pythonBuildInputs;
patches = [
@@ -168,6 +177,10 @@ mkDerivation rec {
# See https://github.com/libspatialindex/libspatialindex/issues/276
"-DWITH_INTERNAL_SPATIALINDEX=True"
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
"-DQGIS_MACAPP_BUNDLE=0" # Don't copy Qt into bundle; we fix paths in postFixup
"-DSQLITE3_INCLUDE_DIR=${sqlite.dev}/include" # FindSqlite3.cmake incorrectly assumes framework
]
++ lib.optional (!withWebKit) "-DWITH_QTWEBKIT=OFF"
++ lib.optional withServer [
"-DWITH_SERVER=True"
@@ -186,18 +199,102 @@ mkDerivation rec {
];
dontWrapGApps = true; # wrapper params passed below
dontWrapQtApps = stdenv.hostPlatform.isDarwin;
postFixup = lib.optionalString withGrass ''
# GRASS has to be available on the command line even though we baked in
# the path at build time using GRASS_PREFIX.
# Using wrapGAppsHook also prevents file dialogs from crashing the program
# on non-NixOS.
for program in $out/bin/*; do
wrapProgram $program \
"''${gappsWrapperArgs[@]}" \
--prefix PATH : ${lib.makeBinPath [ grass ]}
done
'';
postFixup =
lib.optionalString (withGrass && stdenv.hostPlatform.isLinux) ''
# GRASS has to be available on the command line even though we baked in
# the path at build time using GRASS_PREFIX.
# Using wrapGAppsHook also prevents file dialogs from crashing the program
# on non-NixOS.
for program in $out/bin/*; do
wrapProgram $program \
"''${gappsWrapperArgs[@]}" \
--prefix PATH : ${lib.makeBinPath [ grass ]}
done
''
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
mkdir -p $out/Applications $out/bin
mv $out/QGIS.app $out/Applications/
ln -s $out/Applications/QGIS.app/Contents/MacOS/QGIS $out/bin/qgis
SHORT_VERSION=$(echo "${version}" | cut -d. -f1,2)
BUNDLE="$out/Applications/QGIS.app"
FRAMEWORKS="$BUNDLE/Contents/Frameworks"
fix_binary() {
local f="$1"
[[ -f "$f" ]] || return 0
file "$f" | grep -q "Mach-O" || return 0
install_name_tool \
-change "@loader_path/../lib/libqscintilla2_qt5.dylib" "${qscintilla}/lib/libqscintilla2_qt5.dylib" \
-change "@loader_path/../lib/libqt5keychain.dylib" "${qtkeychain}/lib/libqt5keychain.dylib" \
-change "@loader_path/../lib/libqwt.dylib" "${qwt}/lib/libqwt.dylib" \
-change "@loader_path/../../Frameworks/qca-qt5.framework/qca-qt5" "${qca-qt5}/lib/qca-qt5.framework/qca-qt5" \
-change "@loader_path/../../../qca-qt5.framework/qca-qt5" "${qca-qt5}/lib/qca-qt5.framework/qca-qt5" \
-change "@loader_path/../../../../MacOS/lib/libqscintilla2_qt5.dylib" "${qscintilla}/lib/libqscintilla2_qt5.dylib" \
-change "@loader_path/../../../../MacOS/lib/libqt5keychain.dylib" "${qtkeychain}/lib/libqt5keychain.dylib" \
-change "@loader_path/../../../../MacOS/lib/libqwt.dylib" "${qwt}/lib/libqwt.dylib" \
-change "@executable_path/lib/libqwt.dylib" "${qwt}/lib/libqwt.dylib" \
-change "@executable_path/lib/libqscintilla2_qt5.dylib" "${qscintilla}/lib/libqscintilla2_qt5.dylib" \
-change "@executable_path/lib/libqt5keychain.dylib" "${qtkeychain}/lib/libqt5keychain.dylib" \
-change "@executable_path/../Frameworks/qca-qt5.framework/qca-qt5" "${qca-qt5}/lib/qca-qt5.framework/qca-qt5" \
-change "@loader_path/../../../qgis_core.framework/qgis_core" "$FRAMEWORKS/qgis_core.framework/Versions/$SHORT_VERSION/qgis_core" \
-change "@loader_path/../../../qgis_gui.framework/qgis_gui" "$FRAMEWORKS/qgis_gui.framework/Versions/$SHORT_VERSION/qgis_gui" \
-change "@loader_path/../../../qgis_analysis.framework/qgis_analysis" "$FRAMEWORKS/qgis_analysis.framework/Versions/$SHORT_VERSION/qgis_analysis" \
-change "@loader_path/../../../qgis_3d.framework/qgis_3d" "$FRAMEWORKS/qgis_3d.framework/Versions/$SHORT_VERSION/qgis_3d" \
-change "@loader_path/../../../qgis_native.framework/qgis_native" "$FRAMEWORKS/qgis_native.framework/Versions/$SHORT_VERSION/qgis_native" \
"$f" 2>/dev/null || true
}
fix_binary "$BUNDLE/Contents/MacOS/QGIS"
for lib in "$BUNDLE/Contents/MacOS/lib"/*.dylib; do fix_binary "$lib"; done
for fw in qgis_core qgis_gui qgis_analysis qgis_3d qgis_native; do
fix_binary "$FRAMEWORKS/$fw.framework/Versions/$SHORT_VERSION/$fw"
[[ -f "$FRAMEWORKS/$fw.framework/$fw" && ! -L "$FRAMEWORKS/$fw.framework/$fw" ]] && \
fix_binary "$FRAMEWORKS/$fw.framework/$fw"
done
for plugin in "$BUNDLE/Contents/PlugIns/qgis"/*.so; do fix_binary "$plugin"; done
${lib.optionalString withGrass ''
fix_binary "$FRAMEWORKS/qgisgrass8.framework/Versions/$SHORT_VERSION/qgisgrass8"
install_name_tool \
-change "@loader_path/../../../qgisgrass8.framework/qgisgrass8" "$FRAMEWORKS/qgisgrass8.framework/Versions/$SHORT_VERSION/qgisgrass8" \
"$BUNDLE/Contents/MacOS/QGIS" 2>/dev/null || true
for lib in "$BUNDLE/Contents/MacOS/lib"/*.dylib; do
install_name_tool \
-change "@loader_path/../../../qgisgrass8.framework/qgisgrass8" "$FRAMEWORKS/qgisgrass8.framework/Versions/$SHORT_VERSION/qgisgrass8" \
"$lib" 2>/dev/null || true
done
''}
${lib.optionalString withServer ''
fix_binary "$BUNDLE/Contents/MacOS/lib/libqgis_server.${version}.dylib"
''}
# Merge Python packages (lndir handles namespace packages correctly)
QGIS_PYTHON="$BUNDLE/Contents/Resources/python"
for pkg in ${
lib.concatMapStringsSep " " (p: "${p}/${py.pkgs.python.sitePackages}") (
py.pkgs.requiredPythonModules pythonBuildInputs
)
}; do
[[ -d "$pkg" ]] && lndir -silent "$pkg" "$QGIS_PYTHON"
done
# Remove broken symlinks
find "$QGIS_PYTHON" -type l ! -exec test -e {} \; -delete
# Create merged Qt plugins directory in the bundle (LSEnvironment is unreliable)
mkdir -p "$BUNDLE/Contents/PlugIns"
lndir -silent "${qtbase}/${qtbase.qtPluginPrefix}" "$BUNDLE/Contents/PlugIns"
lndir -silent "${qtsvg.bin}/${qtbase.qtPluginPrefix}" "$BUNDLE/Contents/PlugIns"
cat > "$BUNDLE/Contents/Resources/qt.conf" << 'EOF'
[Paths]
Plugins = PlugIns
EOF
'';
# >9k objects, >3h build time on a normal build slot
requiredSystemFeatures = [ "big-parallel" ];
@@ -207,6 +304,6 @@ mkDerivation rec {
homepage = "https://www.qgis.org";
license = lib.licenses.gpl2Plus;
teams = [ lib.teams.geospatial ];
platforms = with lib.platforms; linux;
platforms = lib.platforms.unix;
};
}