The goal of this project is to port the pkgsrc infrastructure to FreeMiNT.
The project will be considered complete when the bootstrap process successfully creates the binary kit, which is the only way to get pkgsrc working on a clean system..
Status: 🔧️
Requirements
- ARAnyM setup
- FreeMiNT setup
- Command sets
Download pkgsrc
- From the official webiste: www.pkgsrc.org
Changes to be made to the default configuration
- The list of tools: mk/tools/tools.FreeMiNT.mk
The bootstrap script
Script to call bootstrap
#!/bin/bash
# Custom launcher for bootstrap
if [ ! -f /bin/sh ]; then
ln -s /bin/bash /bin/sh
fi
umask 0022
cd /usr/pkgsrc/bootstrap
env CONFIGURE_ENV='ac_cv_func_lchmod=no ac_cv_func_lchflags=no ac_cv_func_getopt=yes' ./bootstrap --prefix /c/usr/pkg --workdir /c/usr/pkgsrc/bootstrap/work --compiler gcc --unprivileged --cwrappers no --prefer-native yes
Source: go.sh on Forgejo
Details
- Environment: disable lchmod and lchflags
- prefix
- workdir
- compiler
- unprivileged mode because the emulator does not have root privileges
- no wrappers
- prefer native tools
Results
Partial bootstrap
- bmake is usable
- The pkgtools are usable in minimal versions (except for delete, which is missing)
- pkg_info displays the packages installed from source (bmake, libnbcompat, ...)
bootstrap successful
- Most calls to libfetch had to be disabled
- Available for download

Building pax
- cd /usr/pkgsrc/archivers/pax; bmake install

- Failure with duplicate symbols: to fix this bug, remove
char *chdname;fromextern.hand add it tooptions.c(extern.his included by bothoptions.candar_io.chence the duplicate). - Next bug: default value of umask :

- Run
umask 0022 ; bmake clean install(diff crashes again)

- Note the binary is
nbpax

The problems encountered
- ./bootstrap does not start
- ./bootstrap indicates that the default paths are not suitable
- ./bootstrap cannot be restarted without deleting everything
- chflags() does not exist
- Incompatibility between off_t and la_int64_t
- getopt is defined multiple times
- awk not found
- Error: dlopen() is required
- Error accessing folder libnbcompat/work/.destdir/pkg
- Files not found
- umask error
- diff crash
- sed crash
- wc crash
- Failure with mman.h (netpgpverify)
- The /usr/pkg directory already exists
- The hostname command returns (null)
- Stuck while searching for files newer than the configure file
- Command not found --modversion
- tsort input contains an odd number of tokens
- Command not found ac_fn_c_try_link
- Failure linking pkg_install with libfetch
- Undefined reference to optreset
- The bmake and pkg_xxx commands are not found
- License denied
- fetch fails when calling bmake
- Error on strerror_r: int and char * types do not match
- Unable to write the archive due to access rights
Problem solving
./bootstrap does not start
- Cause: the binary
shdoes not exist
- Resolution: create a symlink :
cd bin; ln -s bash sh - Explanation: the script is looking for sh, which is not present by default
./bootstrap indicates that the default paths are not suitable
- Cause: bootstrap prohibits the use of links in file paths

- Resolution: use
/c/usr/pkginstead of/usr/pkg. - Explanation:
/usris a link toc:/usr(slndirective inmint.cnf)
./bootstrap cannot be restarted without deleting everything
- Cause: bootstrap wants to start from a clean base each time

- Resolution: skip the test in the script bootstrap
- Explanation: no need to delete anything since we're restarting under the same conditions to find the bugs
--- bootstrap.orig 2025-11-15 15:47:59.722597455 +0100
+++ bootstrap 2025-11-15 15:49:55.875815746 +0100
@@ -962,15 +962,18 @@
check_prog whoamiprog whoami
if [ -d "${wrkdir}" ] || [ -f "${wrkdir}" ]; then
- die "\"${wrkdir}\" already exists, please remove it or use --workdir"
+# die "\"${wrkdir}\" already exists, please remove it or use --workdir"
+ echo "\"${wrkdir}\" already exists, continue..."
fi
if [ -f "${prefix}/share/mk/sys.mk" ]; then
- die "\"${prefix}\" already in use, remove it or use a different --prefix"
+# die "\"${prefix}\" already in use, remove it or use a different --prefix"
+ echo "\"${prefix}\" already in use, continue..."
fi
if [ -d "${pkgdbdir}/bootstrap-mk-files-"* ]; then
- die "\"${pkgdbdir}\" already in use, remove it or use a different --pkgdbdir"
+# die "\"${pkgdbdir}\" already in use, remove it or use a different --pkgdbdir"
+ echo "\"${pkgdbdir}\" already in use, continue..."
fi
mkdir_p_early ${wrkdir}
chflags() does not exist
- Cause: despite the options, the code still uses
chflags
- Resolution: add an exception, as you would for Linux
- Explanation: The code does not depend on the options passed
- Details: file
pkgtools/libnbcompat/files/lchflags.c--- lchflags.c.orig 2025-10-28 19:57:28.979683563 +0100 +++ lchflags.c 2025-10-28 19:45:30.725554587 +0100 @@ -48,7 +48,7 @@ if (S_ISLNK(psb.st_mode)) { return 0; } -#if defined(__illumos__) || defined(__linux__) +#if defined(__illumos__) || defined(__linux__) || defined(__MINT__) errno = (path == NULL ? EINVAL : ENOSYS); return -1; #else
Incompatibility between off_t and la_int64_t
- Cause: a function declares an offset of type off_t (32-bit), but the libarchive function expects a 64-bit value

- Resolution: specify the correct type in the code
- Explanation: on 64-bit architectures, off_t is promoted to 64 bits, but remains 32 bits on 32-bit architectures.
- Details: file
pkg_install/add/perform.c
--- perform.c.orig 2025-04-17 23:29:34.000000000 +0200
+++ perform.c 2025-11-15 17:15:00.116495241 +0100
@@ -654,7 +654,7 @@
int r;
const void *buff;
size_t size;
- off_t offset;
+ la_int64_t offset;
for (;;) {
r = archive_read_data_block(reader, &buff, &size, &offset);
getopt is defined multiple times
- Cause: the use of the function does not seem to depend on the options

- Resolution: skip the test in the configure script (see below) and put "CONFIGURE_ARGS+= --enable-db" in /usr/pkgsrc/pkgtools/libnbcompat/Makefile. Delete in /usr/pkgsrc/bootstrap/work/libnbcompat all files libnbcompat.a, .o, config.status, config.log, then, in nbcompat, files config.h and nbconfig.h
- Explanation: by entering 'no', the following test becomes false and the BSD version is no longer used
- Details: in usr/pkgsrc/pkgtools/libnbcompat/files/configure, add l.5913: "enable_bsd_getopt=no" and delete the line 720
--- configure.orig 2025-03-05 12:54:23.000000000 +0100
+++ configure 2025-11-15 18:13:26.849578264 +0100
@@ -717,7 +717,6 @@
ac_user_opts='
enable_option_checking
enable_db
-enable_bsd_getopt
'
ac_precious_vars='build_alias
host_alias
@@ -5910,7 +5909,7 @@
fi
done
-
+enable_bsd_getopt=no
if test "$enable_bsd_getopt" = yes; then
if test "$ac_cv_have_decl_optreset" = no; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using included getopt and getopt_long" >&5
awk not found
- Cause: /bin/awk is not installed on the base system

- Resolution: add awk from the available archive, but is in /usr/bin. Update tools.FreeMiNT.mk
- Explanation: awk, like other tools, is necessary. The NetBSD base system already includes many commands, including awk
--- tools.FreeMiNT.mk.orig 2023-03-05 00:29:24.000000000 +0100
+++ tools.FreeMiNT.mk 2025-11-15 19:54:09.123705473 +0100
@@ -3,7 +3,7 @@
# System-supplied tools for the FreeMiNT operating system.
TOOLS_PLATFORM.[?= [ # shell builtin
-TOOLS_PLATFORM.awk?= /bin/awk
+TOOLS_PLATFORM.awk?= /usr/bin/awk
TOOLS_PLATFORM.basename?= /bin/basename
TOOLS_PLATFORM.byacc?= /usr/bin/yacc
TOOLS_PLATFORM.bzcat?= /usr/bin/bzcat
Error: dlopen() is required
- Cause: TODO

- Resolution: TODO
- Explanation: TODO
Error accessing folder libnbcompat/work/.destdir/pkg
- Cause: a
pkgfolder is created with the permissions ̀d---------`
- Resolution: not yet found. A workaround is to modify WRKOBJDIR directly in the bootstrap script. Use WRKOBJDIR= /ram
- Explanation: not yet found
--- bootstrap.old 2025-11-15 15:49:55.875815746 +0100
+++ bootstrap 2025-11-15 22:05:25.508120615 +0100
@@ -1414,7 +1414,7 @@
# opsys specific fiddling
opsys_finish
-echo "WRKOBJDIR= ${wrkdir}/wrk" >> ${BOOTSTRAP_MKCONF}
+echo "WRKOBJDIR= /ram" >> ${BOOTSTRAP_MKCONF}
echo "" >> ${TARGET_MKCONF}
echo "" >> ${BOOTSTRAP_MKCONF}
Files not found
- Cause: the cp -r function fails
- Resolution: needs further investigation. Works correctly with
mintelftools but not withminttype tools - Explanation: memory exhausted error. Probably a recursion problem
umask error
- Cause: default value is 0000

- Resolution: run 'umask 0022' before launching the bootstrap script
- Explanation: 0022 is the minimum expected value. In theory, it should be set by the script, but the correct value seems necessary before calling umask
diff crash
- Cause: unknown

- Resolution: unknown
- Explanation: none
- Details :
- diff f1 f2 works
- diff -u f1 f2 works if the files are identical
- diff -u f1 f2 crashes if the files are different
sed crash
- Cause: unknown

- Resolution: unknown
- Explanation: none
wc crash
- Cause: mbrtowc() and iswspace() dont work
- Resolution: replace these two functions with functions that do not use wchar_t
- Explanation: likely a bug in the MiNTLib
- Get the source code here
- Replace
iswspace(*WC)withisspace(*WC) - Replace
r = mbrtowc(wc, p, len, st);withr = fake_mbrtowc(wc, p, len, st); - Add:
size_t fake_mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { if (s == NULL) return 0; if (n == 0) return (size_t)-2; if (pwc) *pwc = (unsigned char)*s; return (*s != '\0') ? 1 : 0; } - Recompile
gcc wc.c -o wc
Failure with mman.h (netpgpverify)
- Cause: the files libverify.c and pgpsum.c include mman.h

- Resolution: replace the mmap()/munmap() calls with malloc()/free()
- Explanation: mmap() is not available on FreeMiNT
- pkgsrc/security/netpgpverify/files/libverify.c
--- libverify.c.orig 2020-11-01 12:28:35.000000000 +0100
+++ libverify.c 2025-11-16 06:56:37.670741897 +0100
@@ -27,7 +27,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
+#if 0
#include <sys/mman.h>
+#endif
#include <arpa/inet.h>
@@ -473,9 +475,27 @@
}
fstat(fileno(mem->fp), &st);
mem->size = (size_t)st.st_size;
+#if 0
mem->mem = mmap(NULL, mem->size, PROT_READ, MAP_SHARED, fileno(mem->fp), 0);
mem->dealloc = UNMAP_MEM;
return 1;
+#endif
+#if 1
+ mem->mem = malloc(mem->size);
+ if (mem->mem == NULL) {
+ fprintf(stderr, "malloc failed for '%s'\n", f);
+ fclose(mem->fp);
+ return 0;
+ }
+ if (fread(mem->mem, 1, mem->size, mem->fp) != mem->size) {
+ fprintf(stderr, "short read on '%s'\n", f);
+ free(mem->mem);
+ fclose(mem->fp);
+ return 0;
+ }
+ mem->dealloc = FREE_MEM;
+ return 1;
+#endif
}
/* DTRT and free resources */
@@ -488,7 +508,9 @@
mem->size = 0;
break;
case UNMAP_MEM:
+#if 0
munmap(mem->mem, mem->size);
+#endif
fclose(mem->fp);
break;
}
- pkgsrc/security/netpgpverify/files/pgpsum.c
--- pgpsum.c.orig 2020-05-04 03:37:28.000000000 +0200
+++ pgpsum.c 2025-11-16 07:01:19.621761352 +0100
@@ -26,7 +26,9 @@
#include <sys/types.h>
#include <sys/stat.h>
+#if 0
#include <sys/mman.h>
+#endif
#include <inttypes.h>
#include <stdio.h>
@@ -225,14 +227,35 @@
goto done;
}
cc = (size_t)(st.st_size);
+#if 0
if ((mem = mmap(NULL, cc, PROT_READ, MAP_SHARED, fileno(fp), 0)) == MAP_FAILED) {
fprintf(stderr, "%s - can't mmap", name);
goto done;
}
+#endif
+#if 1
+ mem = malloc(cc);
+ if (mem == NULL) {
+ fprintf(stderr, "%s - can't allocate %zu bytes\n", name, cc);
+ goto done;
+ }
+ if (fread(mem, 1, cc, fp) != cc) {
+ fprintf(stderr, "%s - short read or read error\n", name);
+ free(mem);
+ mem = NULL;
+ goto done;
+ }
+#endif
ret = calcsum(data, size, mem, cc, hashed, hashsize, doarmor);
done:
if (data) {
+#if 0
munmap(mem, cc);
+#endif
+#if 1
+ if (mem)
+ free(mem);
+#endif
}
fclose(fp);
return ret;
The /usr/pkg directory already exists
- Cause: the bootstrap script checks for the existence of the folder
- Resolution: remove the check from the bootstrap script
- Explanation: same reason as for workdir
The hostname command returns (null)
- Cause: hostname is not defined

- Resolution: create a file /etc/hostname and put the computer name in it
- Explanation: the command returns the content of this file
Stuck while searching for files newer than the configure file
- Cause: configure checks if there are any files newer than itself, in which case it needs to be restarted, but this test fails
- Resolution: run 'find . -name configure -exec touch {} \;' in the directory.
- Explanation: due to modifications made to the .c files during attempts to apply patches to get bootstrap working, these files have updated dates and are therefore newer than the configure script that uses them. By giving all the configure files the current date, no other file can be newer, and the test passes. The cause of the blockage is unknown (slowness of the file date checks?)
Command not found --modversion
- Cause: the pkg-config command was not found or returned an empty string

- Resolution: install pkg-config if it is missing, or copy it to .tools/bin/ if there is a script with the same name but which returns nothing
- Explanation: either pkg-config is missing, or it is a script that returns nothing (in which case the test for a version greater than 0.9.0 fails, even though the existing version returns 0.15.0)
cp /usr/bin/pkg-config /ram/pkgtools/libnbcompat/work/.tools/bin/
cp /usr/bin/pkg-config /ram/pkgtools/boostrap-mk-files/work/.tools/bin/
cp /usr/bin/pkg-config /ram/pkgtools/pkg_install/work/.tools/bin/
tsort input contains an odd number of tokens
- Cause: unknown

- Resolution: unknown
- Explanation: unknown
Command not found ac_fn_c_try_link
- Cause: unknown

- Resolution: unknown
- Explanation: unknown
Failure linking pkg_install with libfetch
-
Cause: the libfetch.a file is created correctly, but it contains no symbols!

-
Resolution: remove the function calls to this library from all programs that use libfetch. Note, all affected files (parse-config.c, pkg_io.c, audit.c and main.c) must be copied from their location in /usr/pkgsrc/pkgtools/pkg_install/files to the same location in /ram/pkgtools/pkg_install/work/pkg_install-20250417/.
-
Explanation: tsort fails
-
File /usr/pkgsrc/pkgtools/pkg_install/files/lib/parse-config.c
--- parse-config.c.orig 2020-12-11 11:06:53.000000000 +0100
+++ parse-config.c 2025-11-16 09:36:36.580951685 +0100
@@ -46,9 +46,11 @@
#include <string.h>
#endif
+#if 0
#ifndef BOOTSTRAP
#include <fetch.h>
#endif
+#endif
#include "lib.h"
@@ -240,9 +242,11 @@
}
config_cache_connections_host = xasprintf("%d", cache_connections_host);
+#if 0
#ifndef BOOTSTRAP
fetchConnectionCacheInit(cache_connections, cache_connections_host);
#endif
+#endif
snprintf(fetch_flags, sizeof(fetch_flags), "%s%s%s%s",
(do_cache_index) ? "c" : "",
- File /usr/pkgsrc/pkgtools/pkg_install/files/lib/pkg_io.c
--- pkg_io.c.orig 2023-11-08 02:24:29.000000000 +0100
+++ pkg_io.c 2025-11-16 09:43:49.598979501 +0100
@@ -79,7 +79,10 @@
{
struct fetch_archive *f = client_data;
struct url_stat us;
-
+#if 1
+ return ENOENT;
+#endif
+#if 0
f->fetch = fetchXGet(f->url, &us, fetch_flags);
if (f->fetch == NULL)
return ENOENT;
@@ -87,8 +90,10 @@
f->restart = 1;
f->url->offset = 0;
return 0;
+#endif
}
+#if 0
static ssize_t
fetch_archive_read(struct archive *a, void *client_data,
const void **buffer)
@@ -140,13 +145,14 @@
free(f);
return 0;
}
+#endif
static struct archive *
open_archive_by_url(struct url *url, char **archive_name)
{
struct fetch_archive *f;
struct archive *a;
-
+#if 0
f = xmalloc(sizeof(*f));
f->url = fetchCopyURL(url);
@@ -162,6 +168,11 @@
}
return a;
+#endif
+#if 1
+ *archive_name = NULL;
+ return NULL;
+#endif
}
#endif /* !BOOTSTRAP */
@@ -201,6 +212,7 @@
#ifdef BOOTSTRAP
return NULL;
#else
+#if 0
if ((u = fetchParseURL(url)) == NULL)
return NULL;
@@ -209,9 +221,14 @@
fetchFreeURL(u);
return a;
#endif
+#if 1
+ return NULL;
+#endif
+#endif
}
#ifndef BOOTSTRAP
+#if 0
static int
strip_suffix(char *filename)
{
@@ -227,6 +244,7 @@
} else
return 0;
}
+#endif
static int
find_best_package_int(struct url *url, const char *pattern,
@@ -235,7 +253,10 @@
char *cur_match, *url_pattern, *best_match = NULL;
struct url_list ue;
size_t i;
-
+#if 1
+ return -1;
+#endif
+#if 0
if (*best_url) {
if ((best_match = fetchUnquoteFilename(*best_url)) == NULL)
return -1;
@@ -296,6 +317,7 @@
free(best_match);
fetchFreeURLList(&ue);
return 0;
+#endif
}
void
@@ -334,7 +356,7 @@
{
struct url *url, *best_match = NULL;
struct pkg_path *pl;
-
+#if 0
if (toplevel) {
url = fetchParseURL(last_toplevel);
if (url != NULL) {
@@ -354,7 +376,7 @@
fetchFreeURL(url);
}
}
-
+#endif
return best_match;
}
#endif /* !BOOTSTRAP */
@@ -392,7 +414,7 @@
#ifndef BOOTSTRAP
fname = last_slash + 1;
*last_slash = '\0';
-
+#if 0
best_match = find_best_package(full_fname, fname, 0);
if (search_path && best_match == NULL)
@@ -404,6 +426,10 @@
return NULL;
a = open_archive_by_url(best_match, archive_name);
fetchFreeURL(best_match);
+#endif
+#if 1
+ return NULL;
+#endif
#endif /* !BOOTSTRAP */
return a;
}
- File /usr/pkgsrc/pkgtools/pkg_install/files/admin/audit.c
--- audit.c.orig 2018-02-27 00:45:02.000000000 +0100
+++ audit.c 2025-11-16 09:54:00.974240159 +0100
@@ -86,8 +86,9 @@
parse_options(int argc, char **argv, const char *options)
{
int ch;
-
+#if 0
optreset = 1;
+#endif
/*
* optind == 0 is interpreted as partial reset request
* by GNU getopt, so compensate against this and cleanup
@@ -298,7 +299,9 @@
ssize_t cur_fetched;
struct url *url;
struct url_stat st;
+#if 0
fetchIO *f;
+#endif
int fd;
struct stat sb;
char my_flags[20];
@@ -310,7 +313,11 @@
if (verbose >= 2)
fprintf(stderr, "Fetching %s\n", pkg_vulnerabilities_url);
-
+#if 1
+ errx(EXIT_FAILURE,
+ "Could not parse location of pkg_vulnerabilities: no support for MiNT");
+#endif
+#if 0
url = fetchParseURL(pkg_vulnerabilities_url);
if (url == NULL)
errx(EXIT_FAILURE,
@@ -382,6 +389,7 @@
free(buf);
exit(EXIT_SUCCESS);
+#endif
}
static int
- File /usr/pkgsrc/pkgtools/pkg_install/files/admin/main.c
--- main.c.orig 2025-02-18 13:04:31.000000000 +0100
+++ main.c 2025-11-16 09:55:26.829210996 +0100
@@ -734,6 +734,7 @@
errx(EXIT_FAILURE, "invalid license");
}
}
+#if 0
#ifndef BOOTSTRAP
else if (strcasecmp(argv[0], "findbest") == 0) {
struct url *url;
@@ -806,6 +807,7 @@
pkg_sign_gpg(argv[0], argv[1]);
}
#endif
+#endif
else {
usage();
}
Undefined reference to optreset
- Cause: extern optreset is not found

- Resolution: unknown
- Explanation: optreset is not available in the MiNTLib
The bmake and pkg_xxx commands are not found
- Cause: the PATH variable needs to be modified manually

- Resolution: edit the mint.cnf file and change the PATH to
setenv PATH /usr/pkg/sbin;/usr/pkg/bin;/sbin;/bin;/usr/sbin;/usr/bin - Explanation: normal behavior, RTFM
License denied
- Cause: non-free licenses are rejected by default

- Resolution: add the relevant license to the /usr/pkg/etc/mk.conf file
- Explanation: normal behavior, RTFM
fetch fails when calling bmake
- Cause: the package source files are missing and there is no network connection

- Resolution: download the required archive and copy it to the /usr/pkgsrc/distfiles folder
- Explanation: normal behavior, RTFM
Error on strerror_r: int and char * types do not match
- Cause: the return value of type char * is being compared to an int

- Resolution: to be determined
- Explanation: POSIX expects a return value of type int, while GNU returns char *
Unable to write the archive due to access rights
- Cause: destdir includes links from /ram to /c

- Resolution: delete links and copy regular file, then run bmake package again
- Explanation: TODO