# OpenSpace 0.22.0 -- interactive astrovisualization (openspaceproject.com). # # Packaging notes, because this one is unusual in three ways: # # 1. SUBMODULES. Upstream vendors its entire dependency stack as git submodules # -- 46 of them once nested ones are counted. A GitHub release tarball # contains none of that content (only the empty mount-point directories), # and the top-level CMakeLists.txt hard-fails with "Git submodules are # missing" if ext/ghoul/CMakeLists.txt is absent. Rather than ship a # prefetched mega-tarball (which ci/audit-sources.sh gate 1 and the # "tarballs do not go in git" rule both forbid), every submodule is its own # Source with a real, resolvable GitHub archive URL pinned to the exact # commit the release references. Duplicates are deduplicated: several # submodules appear at more than one path at the same commit (catch2, # freetype2+dlg, glm, json, scnlib, tracy, common-compile-settings), so 31 # tarballs cover 41 placements. %%prep unpacks them parent-directory-first. # # To refresh these for a new release: check out the tag with # --recurse-submodules and run `git submodule status --recursive`. # # 2. NO .git IN A TARBALL. CMakeLists.txt shells out to `git rev-parse` and # `git log`, both marked COMMAND_ERROR_IS_FATAL ANY, to stamp the build with # a branch@commit string. From an unpacked tarball that aborts the configure # outright. Patch0 guards both calls and falls back to values passed in via # -DOPENSPACE_DIST_BRANCH / -DOPENSPACE_DIST_COMMIT, set below to the real # release tag and its commit so the UI still reports accurate provenance. # # 3. NOT AN FHS APPLICATION. OpenSpace expects to live in one self-contained # directory: openspace.cfg defines ${BASE} as its own parent directory and # derives data, shaders, modules, cache, logs, temp, sync and user paths # from it. We install that tree to %%{_libdir}/openspace and put a wrapper in # %%{_bindir} that redirects the *writable* paths into the user's XDG # directories -- otherwise the first cache or log write fails against # read-only /usr. See openspace.sh and the openspace.cfg rewrite in %%install. # # 4. CONFIGURE-TIME DOWNLOADS. Three separate places in this tree reach out to # the network while cmake is *configuring*, which no isolated build can # satisfy. Each needed a different answer: # # * scnlib FetchContent's fast_float v6.1.6. Fedora does package fast_float # with a CMake config, and scnlib has a SCN_USE_EXTERNAL_FAST_FLOAT # switch, but unbundling does NOT work here: Fedora is on 8.2, where # chars_format became a scoped enum, while this scnlib still writes # fast_float::fixed / fast_float::scientific (valid only while the enum # was unscoped, i.e. <= 6.x). It fails to compile with "'fixed' is not a # member of 'fast_float'". So fast_float is bundled at exactly the commit # scnlib asks for, shipped as its own Source, and FetchContent is pointed # at the unpacked copy with FETCHCONTENT_SOURCE_DIR_FAST_FLOAT -- which # satisfies the dependency without any network access. # * modules/webbrowser downloads CEF, a ~1 GB prebuilt Chromium binary # distribution, from cef-builds.spotifycdn.com. # * modules/webgui unconditionally downloads a Node.js toolchain tarball # from nodejs.org (DownloadNodeJs() with a hardcoded URL -- there is no # option to point it at the system nodejs). # # The last two have no unbundling switch, so the four modules that pull them # in are disabled: webbrowser, cefwebgui, webgui and skybrowser. # # skybrowser is in that list for a non-obvious reason worth recording: # disabling a module is not enough on its own. modules/CMakeLists.txt step 4 # walks the dependency graph of every *enabled* module and re-enables each # dependency with `set(... ON CACHE BOOL ... FORCE)`. skybrowser declares # webbrowser and webgui as OPENSPACE_DEPENDENCIES, so leaving skybrowser on # silently overrode -DOPENSPACE_MODULE_WEBBROWSER=OFF and the CEF download # came back. Any module switched off here must have its dependents switched # off too. %global upstream_name OpenSpace %global srcdir %{upstream_name}-releases-v%{version} # Recorded in the binary in place of the git lookup Patch0 disables. %global dist_branch releases/v%{version} %global dist_commit 8615e60f3f3cdf414f8547d5a90565d616271934 # Self-contained application root (${BASE} as far as openspace.cfg is concerned). %global osdir %{_libdir}/openspace # modules/molecule vendors mdlib ("mold"), whose src/core/md_intrinsics.h does an # unconditional `#include ` -- the library is SSE/AVX-only and has no # portable fallback. On aarch64 that is a fatal error before anything else in the # module compiles. There is no upstream switch for it, and nothing else in the # tree depends on the molecule module, so it is simply dropped on non-x86_64. %ifarch x86_64 %global molecule_module ON %else %global molecule_module OFF %endif # The build links one very large executable out of ~40 static archives plus the # whole vendored dependency stack. Full debuginfo runs to several GB and is of # no use to COPR consumers; skip it (same call as 3dslicer and paraview here). %define debug_package %{nil} # Fedora's default -flto=auto -ffat-lto-objects roughly doubles C++ compile # time on a tree this size and makes the final link memory-hungry. Off. %global _lto_cflags %{nil} Name: openspace Version: 0.22.0 Release: 2%{?dist} Summary: Interactive visualization of the known universe # OpenSpace itself is MIT. The remaining identifiers cover the vendored # dependencies that are compiled into the binary and therefore contribute to # the binary's effective license -- see THIRD_PARTY_LICENSES.md and the # Provides: bundled() list below: # MIT OpenSpace, Ghoul, date, glm, nlohmann/json, Lua, # glbinding, tiny-process-library, mold, oscpack, sgct # BSD-3-Clause assimp, tracy, websocketpp, openvr, CCfits, Kameleon # BSD-2-Clause openjpeg, cfitsio # Apache-2.0 scnlib # BSL-1.0 catch2 # Zlib glfw, tinyxml2, soloud # LGPL-2.1-or-later geos, libTUIO11 # FTL OR GPL-2.0-or-later freetype2 License: MIT AND BSD-3-Clause AND BSD-2-Clause AND Apache-2.0 AND BSL-1.0 AND Zlib AND LGPL-2.1-or-later AND (FTL OR GPL-2.0-or-later) URL: https://www.openspaceproject.com/ Source0: https://github.com/OpenSpace/OpenSpace/archive/refs/tags/%{dist_branch}.tar.gz#/%{srcdir}.tar.gz # Launcher wrapper: redirects the ${BASE}-relative writable paths into # $XDG_DATA_HOME / $XDG_CACHE_HOME / $XDG_STATE_HOME before exec'ing the binary. Source1: openspace.sh Source2: openspace.desktop # --------------------------------------------------------------------------- # Vendored submodules, pinned to the commits releases/v%%{version} references. # --------------------------------------------------------------------------- # apps/OpenSpace/ext/sgct Source10: https://github.com/sgct/sgct/archive/f6169d141f75bcf23cd3093832df454923baa466.tar.gz#/sgct-f6169d141f75.tar.gz # apps/OpenSpace/ext/sgct/ext/catch2, ext/ghoul/ext/catch2 Source11: https://github.com/catchorg/Catch2/archive/b670de4fe12ac7c5e858b7de3a14fb4bd18c760e.tar.gz#/Catch2-b670de4fe12a.tar.gz # apps/OpenSpace/ext/sgct/ext/freetype2, ext/ghoul/ext/freetype2 Source12: https://github.com/freetype/freetype/archive/0a0221a1347e2f1e07c395263540026e9a0aa7c7.tar.gz#/freetype-0a0221a1347e.tar.gz # apps/OpenSpace/ext/sgct/ext/freetype2/subprojects/dlg, ext/ghoul/ext/freetype2/subprojects/dlg Source13: https://github.com/nyorain/dlg/archive/395ccad2c1e0daae535c4d20bb0a3f2424648e17.tar.gz#/dlg-395ccad2c1e0.tar.gz # apps/OpenSpace/ext/sgct/ext/glfw Source14: https://github.com/glfw/glfw/archive/7b6aead9fb88b3623e3b3725ebb42670cbe4c579.tar.gz#/glfw-7b6aead9fb88.tar.gz # apps/OpenSpace/ext/sgct/ext/glm, ext/ghoul/ext/glm Source15: https://github.com/g-truc/glm/archive/8d1fd52e5ab5590e2c81768ace50c72bae28f2ed.tar.gz#/glm-8d1fd52e5ab5.tar.gz # apps/OpenSpace/ext/sgct/ext/json, ext/json Source16: https://github.com/nlohmann/json/archive/96c1b52f1cc4742a00ee02b34e043f61bbffa6ae.tar.gz#/json-96c1b52f1cc4.tar.gz # apps/OpenSpace/ext/sgct/ext/json-schema-validator Source17: https://github.com/pboettch/json-schema-validator/archive/c780404a84dd9ba978ba26bc58d17cb43fa7bc80.tar.gz#/json-schema-validator-c780404a84dd.tar.gz # apps/OpenSpace/ext/sgct/ext/openvr is deliberately NOT fetched. sgct only does # add_subdirectory() on it when SGCT_OPENVR_SUPPORT is set, and both that and # OpenSpace's own OPENSPACE_OPENVR_SUPPORT default to OFF (and are pinned OFF in # %%build). The checkout is a 497 MB tree of prebuilt Valve SDK binaries, so # skipping it removes roughly half the source download for every build. # apps/OpenSpace/ext/sgct/ext/scnlib, ext/ghoul/ext/scnlib Source19: https://github.com/eliaskosunen/scnlib/archive/e937be1a52588621b406d58ce8614f96bb5de747.tar.gz#/scnlib-e937be1a5258.tar.gz # apps/OpenSpace/ext/sgct/ext/tinyxml Source20: https://github.com/leethomason/tinyxml2/archive/9148bdf719e997d1f474be6bcc7943881046dba1.tar.gz#/tinyxml2-9148bdf719e9.tar.gz # apps/OpenSpace/ext/sgct/ext/tracy, ext/ghoul/ext/tracy Source21: https://github.com/wolfpld/tracy/archive/05cceee0df3b8d7c6fa87e9638af311dbabc63cb.tar.gz#/tracy-05cceee0df3b.tar.gz # apps/OpenSpace/ext/sgct/support/cmake/common-compile-settings, ext/ghoul/support/cmake/common-compile-settings, support/cmake/common-compile-settings, support/coding/codegen/cmake/common-compile-settings Source22: https://github.com/OpenSpace/common-compile-settings/archive/e141047afdbafebb88852d7ada2423387ca227f4.tar.gz#/common-compile-settings-e141047afdba.tar.gz # ext/date Source23: https://github.com/HowardHinnant/date/archive/f94b8f36c6180be0021876c4a397a054fe50c6f2.tar.gz#/date-f94b8f36c618.tar.gz # ext/ghoul Source24: https://github.com/OpenSpace/Ghoul/archive/668586014d24c2aa79b4ebe77f166bd959007155.tar.gz#/Ghoul-668586014d24.tar.gz # ext/ghoul/ext/assimp Source25: https://github.com/assimp/assimp/archive/e0b52347c6e52de2827ec957a9ebf00ce3c54f79.tar.gz#/assimp-e0b52347c6e5.tar.gz # ext/ghoul/ext/glbinding Source26: https://github.com/cginternals/glbinding/archive/c8a66c92e8a81d82e384a4c80207913519c1f17e.tar.gz#/glbinding-c8a66c92e8a8.tar.gz # ext/ghoul/ext/lua/src Source27: https://github.com/Lua/Lua/archive/1ab3208a1fceb12fca8f24ba57d6e13c5bff15e3.tar.gz#/Lua-1ab3208a1fce.tar.gz # ext/ghoul/ext/tiny-process-library Source28: https://github.com/OpenSpace/tiny-process-library/archive/71ccde743d38d91034cf4555d05f02d4f3679984.tar.gz#/tiny-process-library-71ccde743d38.tar.gz # ext/ghoul/ext/websocketpp Source29: https://github.com/OpenSpace/websocketpp/archive/29ec2d4bc42c02d8a852972692f60d931b00cf7b.tar.gz#/websocketpp-29ec2d4bc42c.tar.gz # ext/spice Source30: https://github.com/OpenSpace/Spice/archive/711ffdb91865c48018ba2efef963ed645ed2557b.tar.gz#/Spice-711ffdb91865.tar.gz # modules/audio/ext/soloud Source31: https://github.com/jarikomppa/soloud/archive/e82fd32c1f62183922f08c14c814a02b58db1873.tar.gz#/soloud-e82fd32c1f62.tar.gz # modules/fitsfilereader/ext/CCfits Source32: https://github.com/OpenSpace/CCfits/archive/3e3ca65a670818f0e2acd63da125a389e913291b.tar.gz#/CCfits-3e3ca65a6708.tar.gz # modules/fitsfilereader/ext/cfitsio Source33: https://github.com/OpenSpace/cfitsio/archive/a7c52b395c7774cd79d3a03e559a6fe803f6208c.tar.gz#/cfitsio-a7c52b395c77.tar.gz # modules/globebrowsing/ext/geos Source34: https://github.com/OpenSpace/geos/archive/e9ca7617f6249a9bbb86721dfc2ebd6283168e53.tar.gz#/geos-e9ca7617f624.tar.gz # modules/kameleon/ext/kameleon Source35: https://github.com/OpenSpace/Kameleon/archive/ec1d850bf596e92341b00013dc68f4fe2be8fe2a.tar.gz#/Kameleon-ec1d850bf596.tar.gz # modules/molecule/ext/mold Source36: https://github.com/scanberg/mdlib/archive/70a27a285029f1606cd540a99edd8ec14af23a38.tar.gz#/mdlib-70a27a285029.tar.gz # modules/opensoundcontrol/ext/oscpack Source37: https://github.com/OpenSpace/oscpack/archive/f66ea70670981386688768a3aa73525be095835e.tar.gz#/oscpack-f66ea7067098.tar.gz # modules/solarbrowsing/ext/openjpeg Source38: https://github.com/uclouvain/openjpeg/archive/1ad9bec2c12ee445ce23e660f5e4fe870b9d5e09.tar.gz#/openjpeg-1ad9bec2c12e.tar.gz # modules/touch/ext/libTUIO11 Source39: https://github.com/OpenSpace/TUIO11_CPP/archive/9c543bc229cc99dcf9628f6e401287af54bc533d.tar.gz#/TUIO11_CPP-9c543bc229cc.tar.gz # scnlib's FetchContent dependency (see note 4 at the top). Pinned to the tag # scnlib itself declares; do not bump independently of scnlib. Source41: https://github.com/fastfloat/fast_float/archive/refs/tags/v6.1.6.tar.gz#/fast_float-6.1.6.tar.gz # support/coding/codegen Source40: https://github.com/OpenSpace/codegen/archive/14426764a08bf14d68a28e01448e228835217bbd.tar.gz#/codegen-14426764a08b.tar.gz # CMakeLists.txt calls `git rev-parse` / `git log` with COMMAND_ERROR_IS_FATAL, # which aborts the configure when building from a tarball (no .git present). Patch0: openspace-cmake-tarball-without-git.patch # packaging.cmake installs binaries from bin/${CMAKE_BUILD_TYPE}/, but the # top-level CMakeLists.txt sets CMAKE_RUNTIME_OUTPUT_DIRECTORY to a plain bin/ # with no per-config suffix. On Ninja/Makefiles that directory never exists, so # the install step shipped a package containing no executables at all. Patch1: openspace-install-binaries-from-bindir.patch # GDAL's metadata accessors became const-correct (GDALGetMetadata() returns # CSLConstList, not char**), which broke globebrowsing on Fedora 45 and rawhide # while Fedora 44 still compiled. Patch2: openspace-gdal-const-metadata.patch # CMakeLists.txt: "OpenSpace can only be generated for 64 bit architectures". ExclusiveArch: x86_64 aarch64 BuildRequires: cmake >= 4.0 BuildRequires: ninja-build BuildRequires: gcc-c++ BuildRequires: python3 BuildRequires: pkgconfig BuildRequires: desktop-file-utils BuildRequires: libappstream-glib # Core application BuildRequires: cmake(Qt6Core) BuildRequires: cmake(Qt6Gui) BuildRequires: cmake(Qt6Widgets) BuildRequires: cmake(Qt6Network) BuildRequires: cmake(Qt6Svg) # OpenGL / windowing. glfw and sgct are vendored but link against the system # X11, GL and Wayland stacks. BuildRequires: mesa-libGL-devel BuildRequires: mesa-libGLU-devel BuildRequires: mesa-libEGL-devel BuildRequires: freeglut-devel BuildRequires: libX11-devel BuildRequires: libXrandr-devel BuildRequires: libXinerama-devel BuildRequires: libXcursor-devel BuildRequires: libXi-devel BuildRequires: libXxf86vm-devel BuildRequires: libxkbcommon-devel BuildRequires: wayland-devel BuildRequires: wayland-protocols-devel BuildRequires: vulkan-loader-devel BuildRequires: vulkan-headers # modules/globebrowsing BuildRequires: gdal-devel # modules/video (find_package(Libmpv) -> pkgconfig(mpv)) BuildRequires: pkgconfig(mpv) # modules/audio (soloud ALSA backend) BuildRequires: alsa-lib-devel # modules/kameleon (ccmc + bundled CDF) BuildRequires: boost-devel # Networking / compression used across ghoul, cfitsio, openjpeg, freetype BuildRequires: libcurl-devel BuildRequires: zlib-devel BuildRequires: libpng-devel BuildRequires: bzip2-devel BuildRequires: brotli-devel Requires: hicolor-icon-theme # The vendored dependency stack, compiled into the binary. None of these are # unbundlable without substantial upstream work: they are pulled in with # add_subdirectory() and several are OpenSpace forks (Spice, CCfits, cfitsio, # geos, Kameleon, oscpack, websocketpp, tiny-process-library, TUIO11_CPP). Provides: bundled(assimp) Provides: bundled(catch2) Provides: bundled(cfitsio) Provides: bundled(ccfits) Provides: bundled(dlg) Provides: bundled(fast_float) Provides: bundled(freetype) Provides: bundled(geos) Provides: bundled(ghoul) Provides: bundled(glbinding) Provides: bundled(glfw) Provides: bundled(glm) Provides: bundled(hinnant-date) Provides: bundled(json-schema-validator) Provides: bundled(kameleon) Provides: bundled(lua) Provides: bundled(mold) Provides: bundled(nlohmann-json) Provides: bundled(openjpeg) Provides: bundled(oscpack) Provides: bundled(scnlib) Provides: bundled(sgct) Provides: bundled(soloud) Provides: bundled(spice) Provides: bundled(tinyxml2) Provides: bundled(tiny-process-library) Provides: bundled(tracy) Provides: bundled(tuio11) Provides: bundled(websocketpp) %description OpenSpace is open source interactive data visualization software designed to visualize the entire known universe and portray humanity's ongoing efforts to investigate the cosmos. It brings the latest techniques from data visualization research to the general public, and supports interactive presentation of dynamic data from observations, simulations and space mission planning and operations. OpenSpace originated at Sweden's Linkoping University and is developed in collaboration with the American Museum of Natural History, NASA Goddard's Community Coordinated Modeling Center, New York University's Tandon School of Engineering, the University of Utah's Scientific Computing and Imaging Institute and others. This build omits the four modules that can only be built by downloading pre-built binaries at compile time: webbrowser and cefwebgui (which need CEF, a pre-built Chromium distribution) and webgui and skybrowser (which need a downloaded Node.js tool chain). The embedded browser panels and the sky browser are therefore not available; everything else, including the full rendering engine, the scene assets and the Lua scripting and network interfaces, is. %prep %autosetup -p1 -n %{srcdir} # --------------------------------------------------------------------------- # Unpack the vendored submodules. The release tarball carries each submodule # mount point as an empty directory; assert that is exactly what we find before # writing into it, so a moved or renamed submodule fails the build loudly here # instead of silently producing a half-populated tree that fails much later. # The placements are ordered parent-directory-first (a submodule's own archive # supplies the empty mount points for its nested submodules). # --------------------------------------------------------------------------- unpack_sub() { _tar="$1" _dest="$2" if [ ! -d "$_dest" ]; then echo "ERROR: submodule mount point '$_dest' does not exist in the source tree" >&2 exit 1 fi if [ -n "$(ls -A "$_dest")" ]; then echo "ERROR: submodule mount point '$_dest' is not empty" >&2 exit 1 fi tar -xf "$_tar" --strip-components=1 -C "$_dest" if [ -z "$(ls -A "$_dest")" ]; then echo "ERROR: '$_dest' is still empty after unpacking '$_tar'" >&2 exit 1 fi } unpack_sub %{SOURCE23} ext/date unpack_sub %{SOURCE24} ext/ghoul unpack_sub %{SOURCE16} ext/json unpack_sub %{SOURCE30} ext/spice unpack_sub %{SOURCE22} support/cmake/common-compile-settings unpack_sub %{SOURCE40} support/coding/codegen unpack_sub %{SOURCE10} apps/OpenSpace/ext/sgct unpack_sub %{SOURCE25} ext/ghoul/ext/assimp unpack_sub %{SOURCE11} ext/ghoul/ext/catch2 unpack_sub %{SOURCE12} ext/ghoul/ext/freetype2 unpack_sub %{SOURCE26} ext/ghoul/ext/glbinding unpack_sub %{SOURCE15} ext/ghoul/ext/glm unpack_sub %{SOURCE19} ext/ghoul/ext/scnlib unpack_sub %{SOURCE28} ext/ghoul/ext/tiny-process-library unpack_sub %{SOURCE21} ext/ghoul/ext/tracy unpack_sub %{SOURCE29} ext/ghoul/ext/websocketpp unpack_sub %{SOURCE31} modules/audio/ext/soloud unpack_sub %{SOURCE32} modules/fitsfilereader/ext/CCfits unpack_sub %{SOURCE33} modules/fitsfilereader/ext/cfitsio unpack_sub %{SOURCE34} modules/globebrowsing/ext/geos unpack_sub %{SOURCE35} modules/kameleon/ext/kameleon unpack_sub %{SOURCE36} modules/molecule/ext/mold unpack_sub %{SOURCE37} modules/opensoundcontrol/ext/oscpack unpack_sub %{SOURCE38} modules/solarbrowsing/ext/openjpeg unpack_sub %{SOURCE39} modules/touch/ext/libTUIO11 unpack_sub %{SOURCE27} ext/ghoul/ext/lua/src unpack_sub %{SOURCE22} ext/ghoul/support/cmake/common-compile-settings unpack_sub %{SOURCE22} support/coding/codegen/cmake/common-compile-settings unpack_sub %{SOURCE11} apps/OpenSpace/ext/sgct/ext/catch2 unpack_sub %{SOURCE12} apps/OpenSpace/ext/sgct/ext/freetype2 unpack_sub %{SOURCE14} apps/OpenSpace/ext/sgct/ext/glfw unpack_sub %{SOURCE15} apps/OpenSpace/ext/sgct/ext/glm unpack_sub %{SOURCE16} apps/OpenSpace/ext/sgct/ext/json unpack_sub %{SOURCE17} apps/OpenSpace/ext/sgct/ext/json-schema-validator unpack_sub %{SOURCE19} apps/OpenSpace/ext/sgct/ext/scnlib unpack_sub %{SOURCE20} apps/OpenSpace/ext/sgct/ext/tinyxml unpack_sub %{SOURCE21} apps/OpenSpace/ext/sgct/ext/tracy unpack_sub %{SOURCE13} ext/ghoul/ext/freetype2/subprojects/dlg unpack_sub %{SOURCE22} apps/OpenSpace/ext/sgct/support/cmake/common-compile-settings unpack_sub %{SOURCE13} apps/OpenSpace/ext/sgct/ext/freetype2/subprojects/dlg # scnlib (vendored under both ghoul and sgct) resolves fast_float through # FetchContent. Unpack the pinned copy into a directory of our own and point # FETCHCONTENT_SOURCE_DIR_FAST_FLOAT at it in %%build, so the configure never # reaches the network. Both copies of scnlib share it: the second one sees # fast_float_POPULATED already set and skips its own add_subdirectory(). mkdir -p ext/fast_float unpack_sub %{SOURCE41} ext/fast_float # The vendored cfitsio copies testprog.tpt from ${CMAKE_SOURCE_DIR}, which is # only its own directory when cfitsio is configured as the top-level project. # Here it is add_subdirectory()'d, so CMAKE_SOURCE_DIR is the OpenSpace root and # the copy fails the whole configure with "FILE COPY cannot find .../testprog.tpt". # CMAKE_CURRENT_SOURCE_DIR is what was meant. This is a sed rather than a Patch: # %%autosetup applies patches before the submodule tarballs are unpacked above, so # a patch against this file would have nothing to apply to. _cfitsio=modules/fitsfilereader/ext/cfitsio/CMakeLists.txt if ! grep -q 'FILE(COPY ${CMAKE_SOURCE_DIR}/testprog.tpt' "$_cfitsio"; then echo "ERROR: cfitsio testprog.tpt anchor not found in $_cfitsio" >&2 exit 1 fi sed -i 's|FILE(COPY ${CMAKE_SOURCE_DIR}/testprog.tpt|FILE(COPY ${CMAKE_CURRENT_SOURCE_DIR}/testprog.tpt|' "$_cfitsio" # The `documentation` and `support/doxygen/css` submodules are the generated # documentation website and its stylesheet -- not referenced by any CMake file # and not needed at runtime, so they are deliberately not fetched. openspace.cfg # still names a DOCUMENTATION path, which the wrapper points at the user's data # directory. # # apps/OpenSpace-MinVR is DEFAULT_APPLICATION OFF, so its glfw and minvr # submodules are not fetched either. %build # CMAKE_INSTALL_PREFIX is the application root: every install() rule in # support/cmake/packaging.cmake uses a DESTINATION relative to it (bin, config, # data, modules, scripts, shaders) and openspace.cfg resolves ${BASE} to it. # # BUILD_SHARED_LIBS=OFF is load-bearing, not a size preference. Nothing in # OpenSpace sets it, but modules/kameleon/ext/kameleon does # `option(BUILD_SHARED_LIBS "Build Shared Libraries" ON)`, and because option() # writes a cache entry that leaks to every other add_subdirectory()'d project, # the whole vendored stack silently switched to shared libraries. That broke two # links at once: # # * openjpeg built libopenjp2.so, but modules/solarbrowsing compiles against # it with target_compile_definitions(... "OPJ_STATIC"), which makes OPJ_API # hidden-visibility. Result: "hidden symbol `opj_stream_create_default_file # _stream' isn't defined" when linking DocsWriter. # * sgct became a shared library and could no longer absorb the vendored glad # static archive: "relocation R_X86_64_PC32 against symbol # `GLAD_GL_VERSION_1_0' can not be used when making a shared object". # # Forcing it off links the vendored stack statically into the OpenSpace # executables, which is how upstream builds it anyway, and matches the # self-contained application directory this package installs. It also stops # cfitsio building its test programs (TestProg, cookbook, FPack, ...). # POSITION_INDEPENDENT_CODE stays ON so anything still built shared is valid. # # MD_LINK_STDLIB_STATIC=OFF is separate and unrelated to the above. # modules/molecule/ext/mold defaults it ON and then appends -static-libgcc and # -static-libstdc++ to its link interface, which propagates to every executable # that links mold -- so DocsWriter died with "cannot find -lstdc++ ... have you # installed the static version of the stdc++ library?". Fedora keeps libstdc++.a # in a separate libstdc++-static package, but pulling that in would be the wrong # fix: a distribution package wants to link the *shared* libstdc++ so it picks up # security updates. Turning mold's option off is the targeted answer; the only # other thing it gates is an MSVC runtime-library property. # # SKIP_INSTALL_ALL=ON is the variable libpng and zlib both use to suppress their # own install rules. sgct's vendored libpng installs # ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} -- a # libpng.a compatibility symlink that only exists in some configurations and is # NOT created in this one, so cmake --install aborted the whole %%install with # "file INSTALL cannot find .../lpng/libpng.a". OpenSpace's own install rules do # not consult this variable, so nothing we actually want to ship is affected. %cmake -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=%{osdir} \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ -DMD_LINK_STDLIB_STATIC=OFF \ -DSKIP_INSTALL_ALL=ON \ -DOPENSPACE_MODULE_MOLECULE=%{molecule_module} \ -DOPENSPACE_DIST_BRANCH=%{dist_branch} \ -DOPENSPACE_DIST_COMMIT=%{dist_commit} \ -DOPENSPACE_HAVE_TESTS=OFF \ -DGHOUL_HAVE_TESTS=OFF \ -DSGCT_BUILD_TESTS=OFF \ -DOPENSPACE_MODULE_WEBBROWSER=OFF \ -DOPENSPACE_MODULE_CEFWEBGUI=OFF \ -DOPENSPACE_MODULE_WEBGUI=OFF \ -DOPENSPACE_MODULE_SKYBROWSER=OFF \ -DFETCHCONTENT_SOURCE_DIR_FAST_FLOAT="$PWD/ext/fast_float" \ -DFETCHCONTENT_FULLY_DISCONNECTED=ON \ -DOPENSPACE_OPENVR_SUPPORT=OFF \ -DSGCT_OPENVR_SUPPORT=OFF \ -DSGCT_DEP_INCLUDE_OPENVR=OFF %cmake_build %install %cmake_install # Every vendored dependency is add_subdirectory()'d, so `cmake --install` runs # their install rules too and the application root fills up with things nobody # can use here: geos and zlib headers, static archives, CMake package configs, # pkg-config files, zlib man pages, and -- most confusingly -- glbinding's own # AUTHORS, LICENSE and VERSION files sitting next to OpenSpace's. # # support/cmake/packaging.cmake writes an exactly known set: bin/, config/, # data/, modules/, scripts/, shaders/ and four files at the top of the prefix. # So this is an allowlist, not a denylist -- a denylist silently lets the next # vendored dependency's leftovers through, and a stray LICENSE that is not # OpenSpace's is worse than clutter. _keep_root=" bin config data modules scripts shaders openspace.cfg CREDITS.md LICENSE.md README.md " for _p in %{buildroot}%{osdir}/*; do [ -e "$_p" ] || continue _n=$(basename "$_p") case "$_keep_root" in *" $_n "*) ;; *) echo "pruning vendored install leftover from the app root: $_n" rm -rf "$_p" ;; esac done # Upstream installs modules/ with FILES_MATCHING for shader and Lua files only, # but CMake still recreates the full directory tree along the way -- so the # package picks up every vendored .github/.vscode directory and a large number # of directories with nothing in them. Drop both (rpmlint flags the hidden ones). find %{buildroot}%{osdir}/modules \( -name '.github' -o -name '.vscode' \) \ -type d -prune -exec rm -rf {} + 2>/dev/null || : while find %{buildroot}%{osdir}/modules -type d -empty -delete 2>/dev/null; do find %{buildroot}%{osdir}/modules -type d -empty | grep -q . || break done # --------------------------------------------------------------------------- # Make the read-only /usr install usable. openspace.cfg derives its writable # paths from ${BASE}, which is now %%{osdir}. Upstream already routes USER, SYNC # and GLOBEBROWSING through environment variables; do the same for the four # remaining writable paths so the wrapper can point all of them at the user's # XDG directories. Each rewrite is asserted, so an upstream change to # openspace.cfg breaks the build instead of shipping an unrunnable package. # --------------------------------------------------------------------------- _cfg=%{buildroot}%{osdir}/openspace.cfg for _tok in CACHE:cache TEMPORARY:temp LOGS:logs DOCUMENTATION:documentation; do _key=${_tok%%%%:*} _sub=${_tok##*:} _before=$(grep -c "os.getenv(\"OPENSPACE_${_key}\")" "$_cfg" || :) sed -i "s|^\(\s*\)${_key} = \"\${BASE}/${_sub}\",|\1${_key} = os.getenv(\"OPENSPACE_${_key}\") or \"\${BASE}/${_sub}\",|" "$_cfg" _after=$(grep -c "os.getenv(\"OPENSPACE_${_key}\")" "$_cfg" || :) if [ "$_before" = "$_after" ]; then echo "ERROR: openspace.cfg rewrite for ${_key} matched nothing" >&2 exit 1 fi done # The webbrowser and cefwebgui modules are compiled out, so stop openspace.cfg # from advertising them as enabled. This is deliberately scoped to those two # ModuleConfigurations tables: a blanket "Enabled = true -> false" also hits the # DefaultTcpSocketInterface and DefaultWebSocketInterface server entries further # down the same file, which would silently disable remote control and the web # GUI socket. python3 - "$_cfg" <<'PYCFG' import re, sys path = sys.argv[1] text = open(path).read() for table in ("WebBrowser", "CefWebGui"): # Match " = {" and flip the first "Enabled = true" inside that block. pattern = re.compile( r"(\b" + table + r"\s*=\s*\{[^}]*?\bEnabled\s*=\s*)true", re.DOTALL, ) text, n = pattern.subn(r"\1false", text, count=1) if n != 1: sys.exit("ERROR: could not disable " + table + " in openspace.cfg") open(path, "w").write(text) print("openspace.cfg: WebBrowser and CefWebGui disabled") PYCFG # --------------------------------------------------------------------------- # Wrappers in %%{_bindir}. The main application gets openspace(1); every other # executable the build installed gets openspace-, sharing the same # environment setup via OPENSPACE_BINARY. # --------------------------------------------------------------------------- install -Dpm0755 %{SOURCE1} %{buildroot}%{_bindir}/openspace sed -i "s|@OS_ROOT@|%{osdir}|g" %{buildroot}%{_bindir}/openspace grep -q '@OS_ROOT@' %{buildroot}%{_bindir}/openspace && { echo "ERROR: @OS_ROOT@ placeholder not substituted in the wrapper" >&2 exit 1 } || : # The top-level CMakeLists.txt points CMAKE_RUNTIME_OUTPUT_DIRECTORY at a single # global bin/, and packaging.cmake then installs that directory wholesale. Every # vendored dependency that builds an executable therefore lands in it too -- # cfitsio alone contributes TestProg, cookbook, FPack, Funpack, Fitscopy and # friends, and the codegen build tool ends up there as well. Ship only the # OpenSpace applications; anything else would become a stray /usr/bin/openspace-* # wrapper for someone else's test program. _keep=" OpenSpace Sync TaskRunner AssetBuilder DocsWriter " for _exe in %{buildroot}%{osdir}/bin/*; do [ -e "$_exe" ] || continue _name=$(basename "$_exe") case "$_keep" in *" $_name "*) ;; *) echo "pruning non-application binary from bin/: $_name" rm -rf "$_exe" ;; esac done for _exe in %{buildroot}%{osdir}/bin/*; do [ -f "$_exe" ] && [ -x "$_exe" ] || continue _name=$(basename "$_exe") [ "$_name" = "OpenSpace" ] && continue _lower=$(echo "$_name" | tr '[:upper:]' '[:lower:]') cat > %{buildroot}%{_bindir}/openspace-"$_lower" </dev/null || : # Desktop entry and icon install -Dpm0644 apps/OpenSpace/openspace.png \ %{buildroot}%{_datadir}/icons/hicolor/256x256/apps/openspace.png desktop-file-install \ --dir=%{buildroot}%{_datadir}/applications \ %{SOURCE2} %check desktop-file-validate %{buildroot}%{_datadir}/applications/openspace.desktop # The wrapper is the package's entry point; a syntax error in it would only # surface at first launch. bash -n %{buildroot}%{_bindir}/openspace # Guard against packaging.cmake regressing to an install with no executables # (see Patch1) -- %%files globs would still succeed on an empty bin/. test -x %{buildroot}%{osdir}/bin/OpenSpace %files %license LICENSE.md %doc README.md CREDITS.md ACKNOWLEDGMENTS.md THIRD_PARTY_LICENSES.md %{_bindir}/openspace %{_bindir}/openspace-* %{_datadir}/applications/openspace.desktop %{_datadir}/icons/hicolor/256x256/apps/openspace.png # The application root is owned as one tree rather than enumerated directory by # directory. Two reasons: # # * support/cmake/packaging.cmake also drops openspace.cfg, CREDITS.md, # LICENSE.md and README.md at the top of the prefix (DESTINATION "."), and # * every vendored dependency is pulled in with add_subdirectory(), so each # one's own install() rules also run during cmake --install (glbinding, # geos, openjpeg, cfitsio, assimp, scnlib, glfw, libpng, zlib, tracy, ...). # # An enumerated list goes stale the moment any of that shifts, and the failure # mode is "Installed (but unpackaged) files found" at the very end of a # multi-hour build. Owning %%{osdir} wholesale is also the honest description of # this package: one self-contained application directory. # # This deliberately includes the ${BASE}-relative data/, modules/, scripts/ and # shaders/ content. That content is architecture-independent, but it cannot move # to a noarch subpackage without leaving %%{_libdir}, and openspace.cfg resolves # all of it relative to ${BASE}. %{osdir}/ %changelog * Fri Aug 28 2026 Morgan Hough - 0.22.0-2 - Fix the three chroots that failed in COPR build 10917037 (f44 x86_64 passed): - Patch2: GDAL's metadata accessors are const-correct in the GDAL that f45 and rawhide ship, so GDALGetMetadata() returns CSLConstList and globebrowsing no longer compiled. const_cast, deliberately unguarded: it is a no-op against the older char** signature, so one source builds on every chroot. - Drop the molecule module on non-x86_64. It vendors mdlib, whose md_intrinsics.h includes unconditionally, so aarch64 died with a fatal error. Nothing else depends on the module. - Fedora 43 is denylisted for this package rather than fixed: it ships cmake 3.31 and OpenSpace's CMakeLists.txt sets cmake_minimum_required(VERSION 4.0), so `BuildRequires: cmake >= 4.0` is unsatisfiable there. Not a packaging bug. * Fri Aug 21 2026 Morgan Hough - 0.22.0-1 - Initial package of OpenSpace 0.22.0 (releases/v0.22.0) - Vendored submodules fetched as 31 individual pinned Source archives - Patch0: tolerate a tarball build with no .git (upstream aborts the configure) - Patch1: install executables from bin/, which is where Ninja actually puts them - Install as a self-contained tree under %%{_libdir}/openspace with a wrapper that redirects cache/log/temp/sync/user paths into the user's XDG directories - Web browser (CEF) modules disabled: CEF is a ~1 GB prebuilt Chromium download