@@ -504,32 +504,45 @@ bool PythonWorker::install_torch(std::function<void(std::string)> output_callbac
504504
505505// ---------------------------------------------------------------------------
506506std::string PythonWorker::find_bundled_python_home () {
507- // On macOS .app: applicationDirPath() = .../Contents/MacOS
508- // So ../Resources/Python reaches the bundled Python
507+ // Application directory varies by platform and context:
508+ // - macOS .app: .../Contents/MacOS
509+ // - Linux installed: .../bin
510+ // - Build tree (macOS .app): .../bin/ShapeWorksStudio.app/Contents/MacOS
511+ // - Build tree (CLI/Linux): .../bin
509512 QString app_dir = QCoreApplication::applicationDirPath ();
510513 QDir dir (app_dir);
511514
512- // Try macOS .app bundle layout
513- QString candidate = dir.absoluteFilePath (" ../Resources/Python" );
514- QDir candidate_dir (candidate);
515- QString canonical = candidate_dir.canonicalPath ();
515+ // Candidates for installed bundles (in priority order)
516+ QStringList installed_candidates = {
517+ #ifdef __APPLE__
518+ // macOS .app bundle: ../Resources/Python relative to Contents/MacOS
519+ dir.absoluteFilePath (" ../Resources/Python" ),
520+ #else
521+ // Linux installed: ../lib/python relative to bin/
522+ dir.absoluteFilePath (" ../lib/python" ),
523+ #endif
524+ };
516525
517- if (!canonical.isEmpty () && QFile::exists (canonical + " /lib/python3.12/os.py" )) {
518- return canonical.toStdString ();
526+ for (const auto & c : installed_candidates) {
527+ QDir candidate_dir (c);
528+ QString canonical = candidate_dir.canonicalPath ();
529+ if (!canonical.isEmpty () && QFile::exists (canonical + " /lib/python3.12/os.py" )) {
530+ return canonical.toStdString ();
531+ }
519532 }
520533
521534 // Try build-tree layouts.
522535 // Studio .app: executable is in bin/ShapeWorksStudio.app/Contents/MacOS/
523- // CLI: executable is in bin/
536+ // CLI/Linux: executable is in bin/
524537 // Bundled Python is in _bundled_python/python/ (sibling to bin/)
525538 QStringList build_tree_candidates = {
526- dir.absoluteFilePath (" ../../../../_bundled_python/python" ), // .app bundle
527- dir.absoluteFilePath (" ../_bundled_python/python" ), // CLI executable
539+ dir.absoluteFilePath (" ../../../../_bundled_python/python" ), // macOS .app bundle
540+ dir.absoluteFilePath (" ../_bundled_python/python" ), // CLI executable or Linux
528541 };
529542
530543 for (const auto & c : build_tree_candidates) {
531- candidate_dir = QDir (c);
532- canonical = candidate_dir.canonicalPath ();
544+ QDir candidate_dir (c);
545+ QString canonical = candidate_dir.canonicalPath ();
533546 if (!canonical.isEmpty () && QFile::exists (canonical + " /lib/python3.12/os.py" )) {
534547 return canonical.toStdString ();
535548 }
0 commit comments