Monday, 29 June 2026

Xcode Command Line Tools

Xcode command line tools standalone package removal

To remove the Xcode Command Line Tools standalone package, including the update prompts which occur when Apple releases new versions of the xcode command line tools, do the following:

  1. In a terminal, execute
    sudo rm -rf /Library/Developer/CommandLineTools
  2. Shut down
  3. Restart in Recovery Mode
  4. Disable SIP. In a terminal (⌘T, or from the Utilities menu), execute
    csrutil disable

    Note you will be asked for an admin user and password

  5. Restart normally and login
  6. In a terminal, execute
    sudo rm /Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_*
  7. Shut down
  8. Restart in Recovery Mode
  9. Enable SIP. In a terminal (⌘T, or from the Utilities menu), execute
    csrutil enable

    Note you will be asked for an admin user and password

  10. Restart normally and login

Xcode command line tools information

If you have xcode installed and you need access to the command line tools, you can either use the xcode preferences to set the path to the appropriate version of xcode which contains the command line tools you want to use, or you can use xcode-select to select the appropriate version of xcode which contains the command line tools you want to use.

sudo xcode-select --switch /Applications/Xcode-26_5/Xcode.app

To find out which version / the path of the xcode command line tools are in use, use

sudo xcode-select -p

Monday, 4 March 2024

Adding Samba to a Windows Domain as a server

My notes for adding SAMBA 4.20 on a Raspberry Pi 5 to a Windows 2019 Domain.

  1. Build SAMBA 4.20 from source (see my previous post).
  2. Setup kerberos
    kinit admin@DOMAIN.EX.INTERNAL
    kinit
    Replace DOMAIN.EX.INTERNAL with the uppercase version of the domain
  3. Join to the domain
    sudo samba-tool domain join domain.ex.internal DC -U"DOMAIN\administrator"
    Also remember to change DOMAIN\administrator to the name of an administrator for the DOMAIN domain/workgroup.

The problem is it fails with the error:

Adding CN=PI-AD-SERVER,OU=Domain Controllers,DC=development,DC=4mation,DC=internal
Adding CN=PI-AD-SERVER,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=domain,DC=ex,DC=internal
Adding CN=NTDS Settings,CN=PI-AD-SERVER,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=domain,DC=ex,DC=internal
Join failed - cleaning up
Deleted CN=PI-AD-SERVER,OU=Domain Controllers,DC=domain,DC=ex,DC=internal
Deleted CN=PI-AD-SERVER,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=domain,DC=ex,DC=internal
ERROR(exception): uncaught exception - File [/usr/share/samba/setup/ad-schema/AD_DS_Attributes__Windows_Server_2012_R2.ldf] not found. Please install samba-ad-provision package
  File "/usr/lib/python3/dist-packages/samba/netcmd/__init__.py", line 185, in _run
    return self.run(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/samba/netcmd/domain.py", line 702, in run
    join_DC(logger=logger, server=server, creds=creds, lp=lp, domain=domain,
  File "/usr/lib/python3/dist-packages/samba/join.py", line 1598, in join_DC
    ctx.do_join()
  File "/usr/lib/python3/dist-packages/samba/join.py", line 1486, in do_join
    ctx.join_add_objects()
  File "/usr/lib/python3/dist-packages/samba/join.py", line 668, in join_add_objects
    ctx.join_add_ntdsdsa()
  File "/usr/lib/python3/dist-packages/samba/join.py", line 593, in join_add_ntdsdsa
    ctx.DsAddEntry([rec])
  File "/usr/lib/python3/dist-packages/samba/join.py", line 479, in DsAddEntry
    ctx.create_tmp_samdb()
  File "/usr/lib/python3/dist-packages/samba/join.py", line 461, in create_tmp_samdb
    ctx.tmp_schema = Schema(ctx.domsid,
                     ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/samba/schema.py", line 110, in __init__
    setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][0]),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/samba/provision/common.py", line 44, in setup_path
    raise Exception("File [%s] not found. Please install samba-ad-provision package" % path)

Trying pulling the latest version from git and rebuilding it

This didn't work but I discovered that there were some samba packages installed via apt so I removed them and this fixed the above error message when I tried to install.

Now I have the issue of incompatible schema versions which was the reason I tried using the latest version of SAMBA in the first place.

I guess I need to try and downgrade my Windows functional level.

After downgrading the functional level I still have issues but with different errors. Adding -d 3 gives more details about the errors encountered as shown below.

sudo /usr/local/samba/bin/samba-tool domain join domain.ex.internal DC -U"DOMAIN\administrator" -d 3

Sunday, 18 February 2024

Building SAMBA 4.20 for use on a Raspberry Pi

My notes for building SAMBA 4.20 on a Raspberry Pi 5 (or 4) with 8GB and a 2TB USB HDD.

  1. Use the Raspberry Pi Imager to install Raspberry Pi OS Lite (64-bit) on to the USB HDD with SSH enabled if configuration is going to be done headless.
  2. Configure the Raspberry Pi to boot from USB (Pi 4 only - the Pi 5 seems to be able to do it by default).
  3. Boot the Raspberry Pi from the HDD
  4. Configure Pi OS to include the en_us.utf8 locale using sudo raspi-config
  5. Setup some extra swap space because the SAMBA self tests require it.
    1. Disable swapping and edit the swapfile settings:
      sudo dphys-swapfile swapoff
      sudo nano /etc/dphys-swapfile
    2. Change CONF_SWAPSIZE to be 81920 and CONF_MAXSWAP to be at least 81920. This gives a /etc/dphys-swapfile which looks something like:
      # where we want the swapfile to be, this is the default
      #CONF_SWAPFILE=/var/swap

      # set size to absolute value, leaving empty (default) then uses computed value
      # you most likely don't want this, unless you have an special disk situation
      #CONF_SWAPSIZE=100
      #80GB Swap size
      CONF_SWAPSIZE=81920

      # set size to computed value, this times RAM size, dynamically adapts,
      # guarantees that there is enough swap without wasting disk space on excess
      #CONF_SWAPFACTOR=2

      # restrict size (computed and absolute!) to maximally this limit
      # can be set to empty for no limit, but beware of filled partitions!
      # this is/was a (outdated?) 32bit kernel limit (in MBytes), do not overrun it
      # but is also sensible on 64bit to prevent filling /var or even / partition
      #CONF_MAXSWAP=2048
      #100GB MAX
      CONF_MAXSWAP=102400
    3. Once that is saved enable swapping:
      sudo dphys-swapfile setup; sudo dphys-swapfile swapon
  6. Create some of the SAMBA folder structure because the self tests require it
    sudo mkdir -p /usr/local/samba/var
    sudo chmod o+w,g+w /usr/local/samba/var
    or maybe there are some environment variables we could set to make the self test fully self contained
  7. Install git and the build essentials
    sudo apt-get -y update
    sudo apt-get -y install git
  8. Clone the SAMBA git repo
    git clone https://git.samba.org/samba.git
  9. Check out the required branch
    cd samba
    git checkout samba-4.20.0rc2
  10. Install the prerequisites
    cd bootstrap/generated-dists/debian12
    sudo ./bootstrap.sh
    cd ../../..
  11. Configure the SAMBA build (include self tests) and to get the config from /etc/samba and to store the local state in /var/samba
    ./configure --enable-selftest --sysconfdir=/etc/samba --localstatedir=/var/samba --with-ads
  12. Build SAMBA (using 4 jobs which is OK if swap space has been added otherwise miss off the -j 4)
    make -j 4
  13. Run the self tests to ensure that the build was successful
    make quicktest
    which takes about half an hour to run on my Raspberry Pi 5.
  14. Install SAMBA
    sudo make install
  15. Add the SAMBA binaries directory to the path.
    export PATH=/usr/local/samba/bin/:/usr/local/samba/sbin/:$PATH
    Also remember to alter the system path definition in /etc/profile

See the SAMBA wiki website for more details on how to build SAMBA from source.

Configure Pi OS to use a static IPv4 Address

To configure Pi OS to use a static IPv4 address on the wired interface use the following commands:

sudo nmcli connection modify 'Wired connection 1' ipv4.address 192.168.200.20/24

This sets the (first) wired interface's IPv4 address to 192.168.200.20 with a net mask of 255.255.255.0.

sudo nmcli connection modify 'Wired connection 1' ipv4.method manual

This sets the (first) wired interface's IPv4 address to be manually set.

sudo nmcli connection modify 'Wired connection 1' ipv4.dns 192.168.200.10

This sets the (first) wired interface's IPv4 DNS server address to be 192.168.200.10.

sudo nmcli connection down 'Wired connection 1' ;sudo nmcli connection up 'Wired connection 1'

This resets the (first) wired interface by taking the connection down and the reestablishing it.

Saturday, 9 October 2021

Finding website paths for Drupal modules

As part of my side projects, I have been helping a friend move his Drupal 8 website from a proof of concept towards going live. One of the problems I was facing was how modules map to URLs so I wrote a little Perl script to generate a URL tree from module routing files.

tree_routes.pl
#!/usr/bin/perl

use strict;
use warnings;
use diagnostics;

use YAML::Tiny;
use Data::Dumper;
use Tree::DAG_Node;

# Nice Tree
{
   package NiceTree;
   use Tree::DAG_Node;
   our @ISA = qw(Tree::DAG_Node);

   sub new {
      my $class = shift;
      my $options = shift;
      my $self = bless $class->SUPER::new($options);
      return $self;
   }

   sub hashref2string {
      my ($self, $hashref) = @_;
      $hashref ||= {};
      return join(", ", map {qq|$_ => "$$hashref{$_}"|} sort keys %$hashref);
   }

   sub format_node {
      my ($self, $options, $node) = @_;
      my ($s) = $node->name;

      if (keys %{ $node->attributes } > 0) {
         $s .= "\t" . $self->hashref2string($node->attributes) if (!$$options{no_attributes});
      }

      return $s;
   }

   sub node2string {
      my ($self, $options, $node, $vert_dashes) = @_;
      my ($depth) = scalar($node->ancestors) || 0;
      my ($sibling_count) = defined $node->mother ? scalar $node->self_and_sisters : 1;
      my ($offset) = ' ' x 3;
      my (@indent) = map {$$vert_dashes[$_] || $offset} 0 .. $depth - 1;
      @$vert_dashes =
         (
            @indent,
            ($sibling_count == 1 ? $offset : '  |'),
         );

      if ($sibling_count == ($node->my_daughter_index + 1)) {
         $$vert_dashes[$depth] = $offset;
      }

      my $x = ((scalar($node->daughters) || 0) ? '  |--+ ' : '  |--- ');

      return join('' => @indent[1 .. $#indent]) . ($depth ? $x : '') . $self->format_node($options, $node);

   }
}

# Find files in path
{
   my @paths;
   sub dir_listing {
      my ($root) = @_;
      $root .= '/' unless $root =~ /\/$/;
      for my $f (glob "$root*") {
         push @paths, $f;
         dir_listing($f) if -d $f;
      }
      return @paths;
   }
}

# Generate tree of URLs
{
   my $path_tree = NiceTree->new({ name => '/' });
   # my $path_tree = Tree::DAG_Node->new({ name => '/' });

   sub add_node {
      my ($current_node, $leaf) = @_[0, 1];

      my $new_daughter = $current_node->new_daughter({ name => $leaf });

      # Keep daughters in alphabetical order
      $current_node->set_daughters(sort {$a->name cmp $b->name} $current_node->daughters);

      return $new_daughter;
   }

   sub get_node_for_path {
      my @paths = split '/', $_[0];

      my $current_node = $path_tree; # Start at the root

      foreach my $leaf (@paths) {
         if ($leaf ne '') {
            my $found = 0;
            my @daughters = $current_node->daughters();

            if (@daughters) {
               foreach my $dau (@daughters) {
                  if ($dau->name eq $leaf) {
                     $current_node = $dau;
                     $found = 1;
                     last;
                  }
               }
            }

            if (not $found) {
               $current_node = add_node($current_node, $leaf);
            }
         }
      }

      return $current_node;
   }
}


sub process_requirements {
   my %requirements = @_;
   my $path_node = $requirements{'path_node'};

   if (defined $requirements{'_permission'}) {
      $path_node->attributes->{'Permission'} = $requirements{'_permission'};
   }

   if (defined $requirements{'_entity_access'}) {
      $path_node->attributes->{'Access'} = $requirements{'_entity_access'};
   }
}


sub process_defaults {
   my %defaults = @_;

   my $path_node = $defaults{'path_node'};

   if (defined $defaults{'_title'}) {
      $path_node->attributes->{Title} = $defaults{'_title'};
   }

   if (defined $defaults{'_controller'}) {
      $path_node->attributes->{'Controller'} = $defaults{'_controller'};
   }

   if (defined $defaults{'_entity_form'}) {
      $path_node->attributes->{'Entity_form'} = $defaults{'_entity_form'};
   }

   if (defined $defaults{'_entity_list'}) {
      $path_node->attributes->{'Entity_list'} = $defaults{'_entity_list'};
   }
}


sub process_form {
   my %form = @_;

   my $filename = $form{'filename'};
   my $formname = $form{'formname'};
   my $path = $form{'path'};

   my $node = get_node_for_path($path);

   $node->attributes->{'Form'} .= $formname . ";";
   $node->attributes->{'File'} .= $filename . ";";

   process_defaults(%{$form{'defaults'}}, path_node => $node);
   process_requirements(%{$form{'requirements'}}, path_node => $node);
}


sub process_yml_file {
   my $filename = $_[0];
   my $yaml = YAML::Tiny->read($filename);

   # print "File: @_\n";
   if (defined $yaml->[0]) {

      my %k = %{$yaml->[0]};
      # print Dumper(%k);

      for my $form (keys %k) {
         if ($form ne '') {
            if (ref($k{$form}) eq 'HASH') {
               process_form(%{$k{$form}}, filename => $filename, formname => $form);
            }
            else {
               warn("Form: $form in file $filename is " . ref($k{$form}) . "\n");
            }
         }
      }
   }
   else {
      warn("yaml file $filename is empty\n");
   }
}


my @paths = dir_listing(@ARGV);

foreach my $file (@paths) {
   if ($file =~ /\.routing\.yml$/) {
      eval {
         process_yml_file($file)
      };
      if ($@ ne '') {
         warn("Error caught while processing file $file\n");
         warn(@$);
      }

   }
}

my $tree = get_node_for_path('/');
print "Tree is:\n";
print map("$_\n", @{$tree->tree2string});

Drupal 8 custom module permissions

If like me you have been wondering how the Drupal 8/9 custom module yml files link together, it goes something like this:
xxxx.routing.yml
free_resources_dashboard:
   path: '/free-resources'
   defaults:
      _controller: '\Drupal\free_resources\Controller\FreeResources::dashboard'
      _title: 'My Resources'
   requirements:
      _permission: 'free resources dashboard'
xxxx.permissions.yml
free resources dashboard:
   title: 'Free Resources Dashboard'
   description: 'Allow access to the free resources dashboard page'

The free resources dashboard: line in the xxxx.permissions.yml file links to the _permissions: 'free resources dashboard' line in the xxxx.routing.yml file. If the _permissions: field does not match any of the defined permissions (for the site?) you will get a permissions error when you try and access your page.

Tuesday, 6 April 2021

Sharing printers via AirPrint

I had been struggling to get my old Canon MP560 to work with my new Mac Mini running Bir Sur. I decided to use my Raspberry Pi 4 running Ubuntu Server 20.04 as a printer server and at the same time to see if I could finally get printing to work from my iPhone.

I discovered that it is relatively straight forward to setup printer sharing via AirPrint. I based my inital attempt on the Linux Magazine's atricle on setting up AirPrint but I have different settings for the cups configuration and didn't need to add the mime types. I also needed to adjust the firewall settings and get my printers working from Linux as I had not previously set them up for Linux, only for Windows and MacOS

CUPS installation

For the CUPS installation I used the following packages:

  • cups-bsd
  • avahi
  • printer-driver-gutenprint

I installed CUPS and the Gutenprint printer drivers (which include drivers for both my Canon MP560 and HP Laserjet 6P) using the following steps:

sudo apt-get update sudo apt-get install cups-bsd avahi-daemon printer-driver-gutenprint sudo systemctl start cups sudo systemctl enable cups

I then edited the CUPS configuration and changed only the bits shown below. I left the rest of the file alone.

# Only listen for connections from the local machine. Port 631 Listen /run/cups/cups.sock # Show shared printers on the local network. Browsing On BrowseLocalProtocols dnssd # Default authentication type, when authentication is required... DefaultAuthType Basic # Web interface setting... WebInterface Yes # Restrict access to the server... <Location /> Order allow,deny Allow @LOCAL </Location> # Restrict access to the admin pages... <Location /admin> AuthType Default Require valid-user Order allow,deny Allow @LOCAL </Location> # Restrict access to configuration files... <Location /admin/conf> AuthType Default Require user @SYSTEM Order allow,deny </Location>

I then configured the firewall to allow access to CUPS and Avahi. Note the network this setup is on is 192.168.200.0 as seen in the config below - change as required.

sudo ufw allow in from 192.168.200.0/24 to any port 631 sudo ufw allow 5353/udp

I then added any required users to the lpadmin group. eg sudo adduser XXX lpadmin before restarting CUPS (sudo systemctl restart cups) and starting and enabling avahi-daemon.

sudo systemctl start avahi-daemon sudo systemctl enable avahi-daemon sudo systemctl restart cups

I then connected to my Raspberry Pi on port 631 and used the CUPS admin interface to add my Canon MP560 and HP Laser 6P printers and checked that they worked by printing a test page for each.

AirPrint configuration

Once I had confirmed that the printers were setup and that the Raspberry Pi could successfully print from them, I used the 'airprint-generate.py' script from https://github.com/tjfontaine/airprint-generate/archive/refs/heads/master.zip to generate avahi service files. 'airprint-generate.py' has the following dependencies:

  • python3
  • python3-cups
sudo apt-get install python3 python3-cups unzip wget https://github.com/tjfontaine/airprint-generate/archive/refs/heads/master.zip unzip master.zip cd airprint-generate-master/ ./airprint-generate.py

Both of my printers were now visible to and usable from both my iPhone and Mac Mini.

Thursday, 14 January 2021

File name wildcards

Earlier I was working on a command line utility that needed to take a list of potentially wildcarded files as input. I didn't want a fully blown regular expression as the input, just the normal ? and * options.

I decided that the quickest way to do this was to convert the wildcarded filename to a regular expression and then use the STL std::regex to do the matching.

Here is a quick way to do it.

#pragma once #include <regex> #include <string> inline std::regex convert_file_wildcards_to_regex(std::string file_pattern) { std::string pattern; for (auto c : file_pattern) { switch (c) { default: pattern += c; break; case '.': pattern += "\\."; break; case '\\': pattern += "\\\\"; break; case '?': pattern += "."; break; case '*': pattern += ".*"; break; } } return std::regex(pattern, std::regex_constants::ECMAScript | std::regex_constants::icase); }

Wednesday, 26 August 2020

Using configure scripts to make libraries for iOS

While building a wxWidgets app for iOS, I wanted to build wxWidgets as a library, not include it as part of the application as the minimal iOS example does. The following script (based on ios-autotools) sets up the required environment and then calls the supplied configure script.

    The main changes are:
  1. the configure script is passed as a parameter so that it does not need to be in the same directory as the iconfigure script which keeps the source folder unchanged
  2. if an SDK version is passed in and the SDK for that version of the SDK does not exist then the default SDK is used with the ios-min-version set to the specified version.
#!/bin/sh set -e usage () { echo "Usage: [VARIABLE...] $(basename $0) architecture path" echo "" echo " architecture Target architecture. [armv7|armv7s|arm64|i386|x86_64]" echo " path path to configure script to run" echo "" echo " VARIABLEs are:" echo " SDKVERSION Target a specific SDK version." echo " PREFIX Custom install prefix, useful for local installs." echo " CHOST Configure host, set if not deducable by ARCH." echo " SDK SDK target, set if not deducable by ARCH. [iphoneos|iphonesimulator]" echo "" echo " CFLAGS CPPFLAGS CXXFLAGS LDFLAGS PKG_CONFIG_PATH" echo "" echo " All additional parameters are passed to the configure script." exit 1 } # Sanity checks if [ "$#" -lt 2 ]; then echo "Please supply an architecture name and configure file" usage fi # Build architecture export ARCH=$1 # Configure script CONFIG=$2 # Export supplied CHOST or deduce by ARCH if [ ! -z "$CHOST" ]; then export CHOST else case $ARCH in armv7 | armv7s ) export CHOST=arm-apple-darwin ;; arm64 ) export CHOST=aarch64-apple-darwin ;; i386 | x86_64 ) export CHOST=$ARCH-apple-darwin ;; * ) usage ;; esac fi # Export supplied SDK or deduce by ARCH if [ ! -z "$SDK" ]; then export SDK echo Using supplied SDK of "$SDK" else case $ARCH in armv7 | armv7s | arm64 ) export SDK=iphoneos ;; i386 | x86_64 ) export SDK=iphonesimulator ;; * ) usage ;; esac fi # Export supplied SDKVERSION or use system default if [ ! -z "$SDKVERSION" ]; then SDKNAME=$(basename $(xcrun --sdk $SDK --show-sdk-platform-path) .platform) export SDKVERSION export SDKROOT=$(xcrun --sdk $SDK --show-sdk-platform-path)"/Developer/SDKs/$SDKNAME.$SDKVERSION.sdk" # If the SDK for the supplied version doesn't exist, use the current one if [ ! -d "$SDKROOT" ]; then export SDKROOT=$(xcrun --sdk $SDK --show-sdk-path) # current version fi else export SDKVERSION=$(xcrun --sdk $SDK --show-sdk-version) # current version export SDKROOT=$(xcrun --sdk $SDK --show-sdk-path) # current version fi # Export supplied SDKVERSION or use system default if [ ! -z "$SDKVERSION" ]; then SDKNAME=$(basename $(xcrun --sdk $SDK --show-sdk-platform-path) .platform) export SDKVERSION export SDKROOT=$(xcrun --sdk $SDK --show-sdk-platform-path)"/Developer/SDKs/$SDKNAME.$SDKVERSION.sdk" # If the SDK for the supplied version doesn't exist, use the current one if [ ! -d "$SDKROOT" ]; then export SDKROOT=$(xcrun --sdk $SDK --show-sdk-path) # current version fi else export SDKVERSION=$(xcrun --sdk $SDK --show-sdk-version) # current version export SDKROOT=$(xcrun --sdk $SDK --show-sdk-path) # current version fi # Export supplied PREFIX or use default if [ ! -z "$PREFIX" ]; then export PREFIX else export PREFIX="/opt/$SDK-$SDKVERSION/$ARCH" fi # Binaries export CC=$(xcrun --sdk $SDK --find gcc) export CPP=$(xcrun --sdk $SDK --find gcc)" -E" export CXX=$(xcrun --sdk $SDK --find g++) export LD=$(xcrun --sdk $SDK --find ld) # Flags export CFLAGS="$CFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include -mios-version-min=$SDKVERSION" export CPPFLAGS="$CPPFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include -mios-version-min=$SDKVERSION" export CXXFLAGS="$CXXFLAGS -arch $ARCH -isysroot $SDKROOT -I$PREFIX/include" export LDFLAGS="$LDFLAGS -arch $ARCH -isysroot $SDKROOT -L$PREFIX/lib" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH":"$SDKROOT/usr/lib/pkgconfig":"$PREFIX/lib/pkgconfig" echo CFLAGS="$CFLAGS" # Remove script parameters shift 2 # Run configure $CONFIG \ --prefix="$PREFIX" \ --host="$CHOST" \ $@

Sunday, 9 August 2020

Issues using wxWidgets on iOS

PNG files fail to load (in the Simulator - not tried a real device yet) using the 'builtin' PNG library

Warning: no bitmap handler for type 50 defined. Warning: CgBI: unhandled critical chunk Error: Couldn't load a PNG image - file is corrupted or not enough memory. Warning: Unknown image data format.

To fix set:

  • Compress PNG Files to NO
  • and
  • Remove Text Metadata From PNG Files to NO

Full screen

Currently wxWidgets doesn't support switching between full screen and non-full screen but I'm working on a patch.

To get fullscreen to work in the current version (3.1.5) you need to set your application to have a lanch screen storyboard and hide the status bar in the setting panel of the target application

Saturday, 8 August 2020

EXC_BAD_ACCESS code=50 when launching an iOS Application under the simulator

If you get an EXC_BAD_ACCESS error with code = 50 when running an iOS application under the simulator, disable the hardened runtime for the simulator

Enable Hardened Runtime > Debug > Any iOS Simulator SDK No. The compile options for real devices can be left on Yes.

Monday, 3 August 2020

Issues I have run into when building wxWidgets

Generally

  • If the (full?) directory name contains an apostrophe (') you get an error message along the lines of:
    syntax error near unexpected token '(' *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;'"
  • If the (full?) directory name contains a space the build will fail.

For iOS

  • The C and CPP flages -miphoneos-min-version need changing to -mios-min-version.

Monday, 13 July 2020

Building GCC for RISC-OS

The instructions at https://www.riscos.info/index.php/Using_GCCSDK are OK but you need to change the URL for the PPL library to https://www.bugseng.com/external/ppl/download/ftp/releases/1.2/ppl-1.2.tar.gz

$ mkdir gccsdk $ cd gccsdk $ svn co svn://svn.riscos.info/gccsdk/trunk/autobuilder/ autobuilder $ svn co svn://svn.riscos.info/gccsdk/trunk/gcc4/ gcc4 $ cd gcc4

Before compiling, you need to edit Makefile and change the PPL URL from

ftp://ftp.cs.unipr.it/pub/ppl/releases/$(PPL_VERSION)/ppl-$(PPL_VERSION).tar.gz

to

https://www.bugseng.com/external/ppl/download/ftp/releases/$(PPL_VERSION)/ppl-$(PPL_VERSION).tar.gz

Once the change has been made you can continue building

$ ./build-world

Once gcc has built (it takes a long time and a few GB of disk space), you're ready to build the packages.

To get autobuilder to compile the packages, you either need rman (I don't know where to get it), or apply the following patch to autobuilder/build

--- build (revision 7339) +++ build (working copy) @@ -76,7 +76,7 @@ popd fi fi - for build_prog in cvs svn wget autoconf automake rman realpath pkg-config doxygen xgettext unzip autoconf2.13 flex bison gperf glib-genmarshal xsltproc intltoolize automake-1.11 ; do + for build_prog in cvs svn wget autoconf automake realpath pkg-config doxygen xgettext unzip autoconf2.13 flex bison gperf glib-genmarshal xsltproc intltoolize automake-1.11 ; do if ! type $build_prog > /dev/null 2>&1 ; then echo "Autobuilder: $build_prog not found; is it installed on your path?" exit 1;

Or you can download my latest version from Git hub. Here you can also find the autobuilder files used to port libpopt and libsmb2 to RISC-OS.

And replace the rman commands in build/env/ro-install (lines 141 and 144 and in some of the packages setvars scripts) with groff -mandoc -Thtml.

Setting up samba as a server for RISC-OS clients

Currently the RISC-OS Lan Manager !OmniClient protocol does not support SMB2 or later protocols.

The following smb.conf file will allow RISC-OS clients to connect using the NT1 (CIFS) protocol. It exports users home folders and configured printers.

# Run 'testparm' to verify the config is correct after you modified it. [global] workgroup = WORKGROUP security = user ntlm auth = ntlmv1-permitted client min protocol = NT1 server min protocol = NT1 passdb backend = tdbsam hosts allow = 192.168.200. printing = cups printcap name = cups load printers = yes cups options = raw [homes] comment = Home Directories valid users = %S, %D%w%S browseable = No read only = No inherit acls = Yes [printers] comment = All Printers path = /var/tmp printable = Yes create mask = 0600 browseable = No [print$] comment = Printer Drivers path = /var/lib/samba/drivers write list = @printadmin root force group = @printadmin create mask = 0664 directory mask = 0775

Wednesday, 24 June 2020

Running Mac OS Big Sur under Parallels

When I tried to install the developer preview of Mac OS Big Sur in a Parallels VM on my Mid 2012 MacBook Pro, I got the dreaded BIErrorDomain 3 error when I tried to select a target disk.

I googled a lot of places and got lots of sort of answers. I tried creating a clean VM from the Recovery Partition and even that didn't work.

The solution I discovered was to add the following lines to the VMs boot flags.
 (Configuration > Hardware > Advanced Settings > Boot flags:)
devices.mac_hw_model="MacBookPro14,1"
devices.smbios.board_id="Mac-B4831CEBD52A0C4C"
You can also set these by editing the VMs config.pvs file and adding them into the SystemFlags section.
<SystemFlags>devices.mac_hw_model="MacBookPro14,1" devices.smbios.board_id="Mac-B4831CEBD52A0C4C"
</SystemFlags>
With these settings the install proceeded as expected, rebooting a few times along the way.
Unfortunately, it doesn't run very well.

Thursday, 10 October 2019

Installing clang 9 on ubuntu 18.04 LTS

  1. Add llvm key to apt keys
    wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
  2. Add llvm bionic clang 9 apt repo
    sudo add-apt-repository -u 'http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
  3. Install clang 9
    sudo apt install clang-9

Saturday, 21 October 2017

Setting up ThingsBoard

Recently I have been playing with ThingsBoard and decided to setup a local install of ThingsBoard on a virtual machine.

I decided to create a new Centos 7 VM since that is my preferred Linux distribution and it is supported by ThingsBoard.

Things to remember when setting it up:-

  • Add the EPEL repository to yum
    yum install epel-release
    yum repolist
  • Install Java 8 - OpenJava 8 is OK
    yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel
    alternatives --config java
    and ensure java 1.8 is the default
  • Follow the instructions on https://thingsboard.io/docs/user-guide/install/linux/ up to the point of downloading the RPM file. Once ThingsBoard RPM file is downloaded use yum installlocal <ThingsBoard RPM file>
  • Optionally edit the ThingsBoard conflict file to use port 80
  • Add the ports ThingsBoard is using to the firewall.
    • firewall-cmd --permanent --add-port=8080/tcp (for default)
    • firewall-cmd --permanent --add-port=80/tcp (for port 80)
    • firewall-cmd --permanent --add-port=1883/tcp (for MQTT)
    • firewall-cmd --reload
  • Connect your web browser to the Centos machine on the chosen port. You will be asked to login. The default username is sysadmin@thingsboard.org with a password of sysadmin. Now change the password and add tenants and devices etc.

Sunday, 19 March 2017

Downloading Apple simulators manually

The other day I decided to download the latest tvOS simulator but the download via Xcode kept failing! I decided to try and download it manually. After a quick google I found that the URL of the download was displayed in the system console the you cancelled the download.

After copying the download URL into Safari, and also using curl via the command line, I had no better luck :(

To get the download to work successfully I found that I had to change the URL from https to http and it just worked! :)

The steps I followed are:

  1. Open XCode, open preferences, go to the Downloads section.
  2. Open the Console App, clear the console for your device (not strictly necessary but makes it easier to find the URL later).
  3. Go back to the XCode preferences. Start the simulator download, then cancel it.
  4. Now in the Console, you will see something about the cancellation with the download URL.
  5. Copy the URL from the Console. Then in Terminal in some suitable directory, download it: 

    curl http://[the url you copied] -O -R 
    (the letter O, not a zero)

  6. Finally, copy this file to ~/Library/Caches/com.apple.dt.Xcode/Downloads
  7. In XCode, in the Downloads section, start the Simulator download again, it should find the file you downloaded and install it.

Example:
robs-macbookpro:~ rob$ curl http://devimages-cdn.apple.com/downloads/xcode/simulators/com.apple.pkg.AppleTVSimulatorSDK10_0-10.0.1.1474488730.dmg -O -R
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1073M  100 1073M    0     0   601k      0  0:30:25  0:30:25 --:--:--  565k
robs-macbookpro:~ rob$ cp com.apple.pkg.AppleTVSimulatorSDK10_0-10.0.1.1474488730.dmg ~/Library/Caches/com.apple.dt.Xcode/Downloads/

Monday, 2 March 2015

How to remove Microsoft Advertising SDK and other packages

From an elevated Powershell prompt, enter the following command:

Remove Microsoft Advertising SDK

gwmi Win32_Product -Filter "Name LIKE 'Microsoft Advertising%'" | foreach { $_.Uninstall() }

Remove Visual F#

gwmi Win32_Product -Filter "Name LIKE 'Visual F#%'" | foreach { $_.Uninstall() }

You will also need to update the extension.vsixmanifest and vspackage.pkgdef files

Tuesday, 17 December 2013

Windows 8 32 bit supports 16 bit MS-DOS apps

A lot of people are under the impression that MS-DOS applications are no longer supported under Windows 8. The 32bit version of Windows 8 does support 16 bit DOS apps.

I've recently been looking at updating a very old but useful FoxPro MS DOS App which we had been using on a creaky old Windows XP machine. Being a lot of effort to convert to a more modern framework I decided to investigate the possibility of using it on Windows 8. From past experience, I knew it would not work on the 64 bit version of Windows 7 so I assmumed the same was true of Windows 8.

To my surprise, it just worked on the 32 bit version of Windows 8 Professional! The only problem was that the keyboard layout was US not UK. Why can't Microsoft set the keyboard layout correctly given that it was a UK version of Windows 8 I installed, not an international version I don't know. To fix the keyboard layout problem all I neede to do was to edit the autoexec.nt and config.nt files (found in c:\windows\system32) just like in the old DOS days, by adding the lines detailed below.

CONFIG.NT
COUNTRY=044,850,C:\Windows\System32\COUNTRY.SYS

AUTOEXEC.NT
C:\Windows\System32\KB16 UK,850,C:\Windows\System32\KEYBOARD.SYS


Update 25-June-2020:
16 bit applications still work in Windows 10 32 bit pro.