Trying to make a snap from a source file

I am trying to make a snap of citterding-beta14 from source code. When I patch and compile the program from the command line I can run it fine.

But when I create, install and run the snap, it runs fine as well, except that textures that are loaded from jpeg files are not rendered in the program. Strangely textures that are loaded from png files render fine. I have tried including just about everything I could think of in the LD_LIBRARY_PATH, and I have included everything I thought relevant in the stage-packages. But to no avail. If I convert the textures in the source tree from jpg to png files, and change the names accordingly in the .mtl files, all textures are rendered correctly. But there should be a way to create a working snap without having to script all this converting and patching from within the snapcraft.yaml

What am I missing?

    name: critterding14-hans
    base: core18
    confinement: strict
    grade: devel
    version: beta14.0
    summary: Evolving Artificial Life
    description:   Critterding is a "Petri dish" universe in 3D that demonstrates evolving artificial life. Critters start out with completely random brains and bodies, but will automatically start evolving into something with much better survival skills.

    apps:
      critterding:
        command: usr/bin/critterding
        environment:
          LD_LIBRARY_PATH: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/mesa:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/mesa-gl:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/xorg:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio/:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/caca:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/engines-1.1:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/gio:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/glib-2.0:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/krb5:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pkgconfig:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/qt4:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/qt-default
          LIBGL_DRIVERS_PATH: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri
          DISABLE_WAYLAND: 1
        plugs:
          - home
          - network
          - opengl
          - removable-media
          - unity7
          - x11
          - wayland
          - desktop
          - desktop-legacy
    parts:
      patches:
        source: patches/
        plugin: dump
        prime: [-*]
        stage: [patchfile.patch]
      desktop:
        plugin: cmake
        source: https://sourceforge.net/projects/critterding/files/critterding/sources/critterding-beta14.tar.bz2
        configflags: [-DCMAKE_BUILD_TYPE=Debug, -DCMAKE_INSTALL_PREFIX=/usr]
        build-environment:
          - CFLAGS: "$CFLAGS -march=native -Ofast"
        after: [patches]
        override-build: |
          cd $SNAPCRAFT_PART_SRC
          patch -p1 < $SNAPCRAFT_STAGE/patchfile.patch
          snapcraftctl build
        build-packages:
          - gcc
          - bzip2
          - libsdl1.2-dev
          - libqt4-dev
          - libqt4-opengl-dev
          - libfreetype6-dev
          - libboost-dev
          - libboost-iostreams-dev
          - libboost-filesystem-dev
          - libboost-thread-dev
          - libsdl-image1.2-dev
          - freeglut3-dev
          - libpng-dev
          - libjpeg-dev
          - zlib1g-dev
        stage-packages:
          - qt4-default
          - libfreetype6
          - bzip2
          - libsdl1.2debian
          - libsdl-image1.2
          - libboost-atomic1.65.1
          - libboost-chrono1.65.1
          - libboost-date-time1.65.1
          - libboost-filesystem1.65.1
          - libboost-iostreams1.65.1
          - libboost-locale1.65.1
          - libboost-regex1.65.1
          - libboost-serialization1.65.1
          - libboost-system1.65.1
          - libboost-thread1.65.1
          - libgl1
          - libglu1-mesa
          - libglvnd0
          - libglx0
          - libgomp1
          - libqt4-opengl
          - libslang2
          - freeglut3
          - mesa-utils
          - libgl1-mesa-dri
          - mesa-va-drivers
          - libpng16-16
          - libpng-tools
          - libcupsimage2
          - libsdl2-2.0-0
          - libjpeg8
          - libgl1-mesa-glx
          - libqt5opengl5
          - libglapi-mesa
          - libbullet2.87
          - libbullet-extras2.87
          - libglewmx1.13
          - libglu1
          - libtinyxml2-6

The patch file used in the snapcraft.yaml file (otherwise the program will not compile):

    diff -ruN critterding-beta14/src/common/be_command_system.cpp critterding-beta14_P/src/common/be_command_system.cpp
    --- critterding-beta14/src/common/be_command_system.cpp	2011-09-11 00:01:23.000000000 +0200
    +++ critterding-beta14_P/src/common/be_command_system.cpp	2021-02-01 20:38:01.769455137 +0100
    @@ -10,9 +10,9 @@
     BeCommandSystem::BeCommandSystem()
     {
     	Settings* const	settings = Settings::Instance();
    -	registerStringCommand("settings_saveprofile", boost::bind(&Settings::saveProfile, settings, _1));
    -	registerStringCommand("settings_increase", boost::bind(&Settings::increaseCVar, settings, _1, 1));
    -	registerStringCommand("settings_decrease", boost::bind(&Settings::decreaseCVar, settings, _1, 1));
    +	registerStringCommand("settings_saveprofile", boost::bind(&Settings::saveProfile, settings, boost::placeholders::_1));
    +	registerStringCommand("settings_increase", boost::bind(&Settings::increaseCVar, settings, boost::placeholders::_1, 1));
    +	registerStringCommand("settings_decrease", boost::bind(&Settings::decreaseCVar, settings, boost::placeholders::_1, 1));
     }
     
     void BeCommandSystem::registerVoidCommand(const std::string& name, FunctionVoid function)
    diff -ruN critterding-beta14/src/scenes/critterding/evolution.cpp critterding-beta14_P/src/scenes/critterding/evolution.cpp
    --- critterding-beta14/src/scenes/critterding/evolution.cpp	2013-09-28 00:33:54.000000000 +0200
    +++ critterding-beta14_P/src/scenes/critterding/evolution.cpp	2021-02-01 20:42:22.558181137 +0100
    @@ -148,7 +148,7 @@
     // 	}
     	
      	BeCommandSystem::Instance()->registerVoidCommand("quit", boost::bind(&Evolution::quit, this));
    -	BeCommandSystem::Instance()->registerIntCommand("cs_unregister", boost::bind(&Evolution::unregisterCritterVID, this, _1));
    +	BeCommandSystem::Instance()->registerIntCommand("cs_unregister", boost::bind(&Evolution::unregisterCritterVID, this, boost::placeholders::_1));
     	BeCommandSystem::Instance()->registerVoidCommand("cs_clear", boost::bind(&Evolution::clear, this));
     
     	BeCommandSystem::Instance()->registerVoidCommand("decreaseenergy", boost::bind(&Evolution::decreaseenergy, this));
    @@ -172,8 +172,8 @@
     	BeCommandSystem::Instance()->registerVoidCommand("camera_lookleft", boost::bind(&Evolution::camera_lookleft, this));
     	BeCommandSystem::Instance()->registerVoidCommand("camera_lookright", boost::bind(&Evolution::camera_lookright, this));
     
    -	BeCommandSystem::Instance()->registerFloatCommand("camera_lookleftright_mouse", boost::bind(&Evolution::camera_lookleftright_mouse, this, _1));
    -	BeCommandSystem::Instance()->registerFloatCommand("camera_lookupdown_mouse", boost::bind(&Evolution::camera_lookupdown_mouse, this, _1));
    +	BeCommandSystem::Instance()->registerFloatCommand("camera_lookleftright_mouse", boost::bind(&Evolution::camera_lookleftright_mouse, this, boost::placeholders::_1));
    +	BeCommandSystem::Instance()->registerFloatCommand("camera_lookupdown_mouse", boost::bind(&Evolution::camera_lookupdown_mouse, this, boost::placeholders::_1));
     		
     	
     	BeCommandSystem::Instance()->registerVoidCommand("camera_rollleft", boost::bind(&Evolution::camera_rollleft, this));
    @@ -212,13 +212,13 @@
     	BeCommandSystem::Instance()->registerVoidCommand("cs_resetage", boost::bind(&WorldB::resetageSelectedCritter, world));
     	BeCommandSystem::Instance()->registerVoidCommand("cs_follow", boost::bind(&WorldB::followCritter, world));
     
    -	BeCommandSystem::Instance()->registerIntCommand("cs_select", boost::bind(&Evolution::gui_selectCritter, this, _1));
    -	BeCommandSystem::Instance()->registerIntCommand("cs_select_species", boost::bind(&Evolution::gui_selectSpecies, this, _1));
    -	BeCommandSystem::Instance()->registerStringCommand("gui_togglepanel", boost::bind(&Evolution::canvas_swapchild, this, _1));
    +	BeCommandSystem::Instance()->registerIntCommand("cs_select", boost::bind(&Evolution::gui_selectCritter, this, boost::placeholders::_1));
    +	BeCommandSystem::Instance()->registerIntCommand("cs_select_species", boost::bind(&Evolution::gui_selectSpecies, this, boost::placeholders::_1));
    +	BeCommandSystem::Instance()->registerStringCommand("gui_togglepanel", boost::bind(&Evolution::canvas_swapchild, this, boost::placeholders::_1));
     	BeCommandSystem::Instance()->registerVoidCommand("gui_toggle", boost::bind(&Evolution::gui_swap, this));
     
    -	BeCommandSystem::Instance()->registerFloatCommand("movepickedbodyX", boost::bind(&Evolution::movePickedBodyX, this, _1));
    -	BeCommandSystem::Instance()->registerFloatCommand("movepickedbodyY", boost::bind(&Evolution::movePickedBodyY, this, _1));
    +	BeCommandSystem::Instance()->registerFloatCommand("movepickedbodyX", boost::bind(&Evolution::movePickedBodyX, this, boost::placeholders::_1));
    +	BeCommandSystem::Instance()->registerFloatCommand("movepickedbodyY", boost::bind(&Evolution::movePickedBodyY, this, boost::placeholders::_1));
     /*	BeCommandSystem::Instance()->registerVoidCommand("canvas_press", boost::bind(&Evolution::canvas_press, this));
     	BeCommandSystem::Instance()->registerVoidCommand("canvas_release", boost::bind(&Evolution::canvas_release, this));
     	BeCommandSystem::Instance()->registerVoidCommand("canvas_pressAlt", boost::bind(&Evolution::canvas_pressAlt, this));

Any output on the console? Try running with SDL_DEBUG=1 set.

When I run the compiled source (without any extra environment variables set) I get the following messages in the console:

GL_INVALID_ENUM
RNG: seed: 1170666

Running the snap in the same environment I get an extra warning after some seconds into the game:

GL_INVALID_ENUM
RNG: seed: 334927
warning btCollisionDispatcher::needsCollision: static-static collision!

Setting if I type export SDL_DEBUG=1 before running, no additional messages are reported.
If I also “export MESA_DEBUG=1” and “export LIBGL_DEBUG=1” I get some more messages when running the compiled source code:

libGL: Can’t open configuration file /etc/drirc: No such file or directory.
libGL: Can’t open configuration file /home/hans/.drirc: No such file or directory.
libGL: Can’t open configuration file /etc/drirc: No such file or directory.
libGL: Can’t open configuration file /home/hans/.drirc: No such file or directory.
Mesa: User error: GL_INVALID_ENUM in glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY)
Mesa: 6 similar GL_INVALID_ENUM errors
Mesa: User error: GL_INVALID_OPERATION in glGetUniformLocation(program not linked)
Mesa: User error: GL_INVALID_OPERATION in glUniform(program not linked)
Mesa: User error: GL_INVALID_OPERATION in glGetUniformLocation(program not linked)
Mesa: User error: GL_INVALID_OPERATION in glUniform(program not linked)
Mesa: User error: GL_INVALID_ENUM in glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY)
GL_INVALID_ENUM
RNG: seed: 2447640

Running the snap with those extra variables set gives the extra message again:

libGL: Can’t open configuration file /etc/drirc: No such file or directory.
libGL: Can’t open configuration file /home/hans/snap/critterding14-hans/x1/.drirc: No such file or directory.
libGL: Can’t open configuration file /etc/drirc: No such file or directory.
libGL: Can’t open configuration file /home/hans/snap/critterding14-hans/x1/.drirc: No such file or directory.
Mesa: User error: GL_INVALID_ENUM in glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY)
Mesa: 1 similar GL_INVALID_ENUM errors
Mesa: User error: GL_INVALID_OPERATION in glGetUniformLocation(program not linked)
Mesa: User error: GL_INVALID_OPERATION in glUniform(program not linked)
Mesa: User error: GL_INVALID_OPERATION in glGetUniformLocation(program not linked)
Mesa: User error: GL_INVALID_OPERATION in glUniform(program not linked)
Mesa: User error: GL_INVALID_ENUM in glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY)
GL_INVALID_ENUM
RNG: seed: 623572
warning btCollisionDispatcher::needsCollision: static-static collision!

I FOUND THE PROBLEM :slight_smile:

It turns out I was looking everywhere but the wrong place. For the entertainment of other snapcraft beginners I will outline how I searched for the answer:

Converting all the jpeg textures to png textures actually worked, but the png textures took up a huge amount of disk space, and it feels like cheating. Trying to wildly add as many libraries to the stage-packages lead nowhere, just the snap getting bigger all the time. Next I tried to reduce the size of the texture jpeg images because they were 2048x2048 pixels, a bit large I guess for textures. But that did not help either. Still any texture from a jpeg was not rendered.

Then I compared the output of the following command: lsof -p $(pgrep -nf critterding), one time while running critterding from source and a second time while running from the snap. Here it became clear that when run from source, critterding was using quite a few qt4 libraries that critterding was not using when run from the snap, eg libqtiff, libqsvg, libqjpeg, etc…

These libraries were actually installed in my snap, but for some weird reason qt4 apps only find them when referenced by an environment variable: QT_PLUGIN_PATH. If this variable is not set correctly, the application runs without errors, but does not function as it should.

So, adding the following line in the environment section in the snapcraft.yaml file solved the problem:

QT_PLUGIN_PATH: “$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/qt4/plugins/”

I will add critterding14 to my repository tomorrow if I can find some more time to clean up my snapcraft.yaml

I hope this helps some other beginners.

4 Likes