Success building JavaScript library from scratch on Linux

For discussion of ports to POSIX based systems, especially using GNUStep.

Moderators: another_commander, winston, Getafix

Post Reply
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 779
Joined: Sun Jun 20, 2010 6:00 pm

Success building JavaScript library from scratch on Linux

Post by mcarans »

I managed to build the JavaScript library on Linux and use it with Oolite successfully. The greatest challenge is that Python 2 is obsolete. Python 2 must be built from source on Kubuntu 25.10. To build Python 2.7:

Code: Select all

wget https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz
tar -xvf Python-2.7.18.tgz
cd Python-2.7.18
export CFLAGS="-std=c17"
./configure --prefix=/usr/local --enable-optimizations
make -j16
I wanted to see the minimal set of changes to the original package to get it to work with Oolite. That package is here: https://ftp.mozilla.org/pub/firefox/rel ... ce.tar.bz2. I unzipped only the js/src folder into a folder mozilla-2.0. mozilla-2.0 is in the same folder as my oolite directory.

I edited Oolite's libjs.make to:

Code: Select all

#
# This makefile is used to build the Javascript dependency for Oolite
#
# This Makefile is used to download and build the Javascript library
# for use by Oolite.
# Depending on invocation, a debug or release (default) version of the
# library will be built.
#
# To use:
# $ make -f libjs.make debug=(yes|no)

include config.make

LIBJS_SRC_DIR                    = ../mozilla-2.0/js/src
LIBJS_CONFIG_FLAGS               = --disable-shared-js
LIBJS_CONFIG_FLAGS               += --enable-threadsafe
LIBJS_CONFIG_FLAGS               += --with-system-nspr
LIBJS_CONFIG_FLAGS               += --disable-tests
ifeq ($(OO_JAVASCRIPT_TRACE),yes)
    LIBJS_CONFIG_FLAGS           += --enable-trace-jscalls
endif
LIBJS_CFLAGS                = -std=gnu89
LIBJS_CXXFLAGS              = -Wno-error=narrowing
ifeq ($(debug),yes)
    LIBJS_BUILD_DIR              = $(LIBJS_SRC_DIR)/build-debug
    LIBJS_CONFIG_FLAGS           += --enable-debug
    LIBJS_CONFIG_FLAGS           += --disable-optimize
else
    LIBJS_BUILD_DIR              = $(LIBJS_SRC_DIR)/build-release
endif
LIBJS                            = $(LIBJS_BUILD_DIR)/libjs_static.a
LIBJS_BUILD_STAMP                = $(LIBJS_BUILD_DIR)/build_stamp
LIBJS_CONFIG_STAMP               = $(LIBJS_BUILD_DIR)/config_stamp


.PHONY: all
all: $(LIBJS)

$(LIBJS): $(LIBJS_BUILD_STAMP)

$(LIBJS_BUILD_STAMP): $(LIBJS_CONFIG_STAMP)
	@echo
	@echo "Building Javascript library..."
	@echo
	$(MAKE) -C $(LIBJS_BUILD_DIR)
	touch $@

$(LIBJS_CONFIG_STAMP):
	@echo
	@echo "Configuring Javascript library..."
	@echo
	mkdir -p $(LIBJS_BUILD_DIR)
	cd $(LIBJS_BUILD_DIR) && CC="gcc $(LIBJS_CFLAGS)" CFLAGS="$(LIBJS_CFLAGS)" CXXFLAGS="$(LIBJS_CXXFLAGS)" ../configure $(LIBJS_CONFIG_FLAGS)
	touch $@

.PHONY: clean
clean:
	-$(MAKE) -C $(LIBJS_BUILD_DIR) clean
	-$(RM) $(LIBJS_BUILD_STAMP)

# This target also removes the configuration status, forcing
# a reconfiguration. Use this after changing LIBJS_CONFIG_FLAGS
.PHONY: distclean
distclean:
	-$(RM) -r $(LIBJS_BUILD_DIR)
The only changes needed to the mozilla code was to change some false and JS_FALSE values to NULL. This is a slightly smaller set of changes than is currently in https://github.com/OoliteProject/spidermonkey-ff4

Code: Select all

diff -ruN src_old/jsapi.cpp src/jsapi.cpp
--- src_old/jsapi.cpp	2011-03-19 12:33:50.000000000 +1300
+++ src/jsapi.cpp	2025-11-28 17:51:34.029783960 +1300
@@ -3977,7 +3977,7 @@
     AutoIdVector props(cx);
     JSIdArray *ida;
     if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
-        return false;
+        return NULL;
     for (size_t n = 0; n < size_t(ida->length); ++n)
         JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
     return ida;
diff -ruN src_old/jsfun.cpp src/jsfun.cpp
--- src_old/jsfun.cpp	2011-03-19 12:33:50.000000000 +1300
+++ src/jsfun.cpp	2025-11-28 19:54:22.686549344 +1300
@@ -2052,7 +2052,7 @@
 
     JSString *str = JS_DecompileFunction(cx, fun, indent);
     if (!str)
-        return false;
+        return NULL;
 
     if (!indent)
         cx->compartment->toSourceCache.put(fun, str);
@@ -2658,7 +2658,7 @@
     const Shape *shape = funobj->nativeLookup(id);
     if (!shape) {
         if (!ResolveInterpretedFunctionPrototype(cx, funobj))
-            return false;
+            return NULL;
         shape = funobj->nativeLookup(id);
     }
     JS_ASSERT(!shape->configurable());
diff -ruN src_old/jsiter.cpp src/jsiter.cpp
--- src_old/jsiter.cpp	2011-03-19 12:33:50.000000000 +1300
+++ src/jsiter.cpp	2025-11-28 19:55:49.322088177 +1300
@@ -425,7 +425,7 @@
          */
         JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT0);
         if (!obj)
-            return false;
+            return NULL;
         obj->init(cx, &js_IteratorClass, NULL, NULL, NULL, false);
         obj->setMap(cx->compartment->emptyEnumeratorShape);
         return obj;
diff -ruN src_old/jsparse.cpp src/jsparse.cpp
--- src_old/jsparse.cpp	2011-03-19 12:33:51.000000000 +1300
+++ src/jsparse.cpp	2025-11-28 18:08:47.242185339 +1300
@@ -3352,7 +3352,7 @@
     if (!outertc->inFunction() && bodyLevel && funAtom && !lambda && outertc->compiling()) {
         JS_ASSERT(pn->pn_cookie.isFree());
         if (!DefineGlobal(pn, outertc->asCodeGenerator(), funAtom))
-            return false;
+            return NULL;
     }
 
     pn->pn_blockid = outertc->blockid();
diff -ruN src_old/jsstr.cpp src/jsstr.cpp
--- src_old/jsstr.cpp	2011-03-19 12:33:51.000000000 +1300
+++ src/jsstr.cpp	2025-11-28 18:01:16.809181447 +1300
@@ -1734,7 +1734,7 @@
         if (flat) {
             patstr = flattenPattern(cx, fm.patstr);
             if (!patstr)
-                return false;
+                return NULL;
         } else {
             patstr = fm.patstr;
         }
@@ -3400,7 +3400,7 @@
                                  UndefinedValue(), NULL, NULL,
                                  JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0,
                                  NULL)) {
-        return JS_FALSE;
+        return NULL;
     }
 
     return proto;
diff -ruN src_old/jstypedarray.cpp src/jstypedarray.cpp
--- src_old/jstypedarray.cpp	2011-03-19 12:33:51.000000000 +1300
+++ src/jstypedarray.cpp	2025-11-28 20:00:22.614582793 +1300
@@ -1334,7 +1334,7 @@
         if (size != 0 && count >= INT32_MAX / size) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_NEED_DIET, "size and count");
-            return false;
+            return NULL;
         }
 
         int32 bytelen = size * count;
@@ -1668,7 +1668,7 @@
 
       default:
         JS_NOT_REACHED("shouldn't have gotten here");
-        return false;
+        return NULL;
     }
 }
 
diff -ruN src_old/jsxml.cpp src/jsxml.cpp
--- src_old/jsxml.cpp	2011-03-19 12:33:51.000000000 +1300
+++ src/jsxml.cpp	2025-11-28 20:01:02.884222691 +1300
@@ -1,4 +1,4 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=4 sw=4 et tw=78:
  *
  * ***** BEGIN LICENSE BLOCK *****
@@ -282,7 +282,7 @@
 
     obj = NewBuiltinClassInstanceXML(cx, &js_NamespaceClass);
     if (!obj)
-        return JS_FALSE;
+        return NULL;
     JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal()));
     JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal()));
     JS_ASSERT(JSVAL_IS_VOID(obj->getNamespaceDeclared()));
@@ -431,7 +431,7 @@
         size_t length = str->length();
         jschar *chars = (jschar *) cx->malloc((length + 2) * sizeof(jschar));
         if (!chars)
-            return JS_FALSE;
+            return NULL;
         *chars = '@';
         const jschar *strChars = str->getChars(cx);
         if (!strChars) {
diff -ruN src_old/methodjit/InvokeHelpers.cpp src/methodjit/InvokeHelpers.cpp
--- src_old/methodjit/InvokeHelpers.cpp	2011-03-19 12:33:51.000000000 +1300
+++ src/methodjit/InvokeHelpers.cpp	2025-11-29 07:42:40.832218462 +1300
@@ -728,7 +728,7 @@
 {
     JSStackFrame *fp = cx->fp();
     if (fp->hasImacropc())
-        return false;
+        return NULL;
 
     JSScript *script = fp->script();
     return script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc);
I ran:

Code: Select all

make -f libjs.make distclean
make -f libjs.make -j16
The static library was created in mozilla-2.0/js/src/build-release/libjs_static.a. I copied it to oolite/deps/Linux-deps/x86_64/mozilla/. I built the Oolite game and ran it installing a few expansions. It worked fine.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 779
Joined: Sun Jun 20, 2010 6:00 pm

Re: Success building JavaScript library from scratch on Linux

Post by mcarans »

I have made a repo for this: https://github.com/mcarans/spidermonkey-linux

You can use distrobox to build for old gcc:

Code: Select all

distrobox create --name ubuntu22 --image ubuntu:22.04
distrobox enter ubuntu22
Then:

Code: Select all

sudo apt update
sudo apt install -y software-properties-common

sudo add-apt-repository universe
sudo apt update

sudo apt install -y python2.7
sudo apt install -y build-essential

sudo apt install -y libnspr4
sudo apt install -y libnspr4-dev
Then make:

Code: Select all

make -f libjs.make -j$(nproc)

Last edited by mcarans on Wed Mar 25, 2026 1:11 am, edited 2 times in total.
User avatar
Lone_Wolf
---- E L I T E ----
---- E L I T E ----
Posts: 832
Joined: Wed Aug 08, 2007 10:59 pm
Location: Netherlands

Re: Success building JavaScript library from scratch on Linux

Post by Lone_Wolf »

-j16 will slow compiling and cause OOM to abort the compilation (or other programs like a browser, DE etc) if the host system lacks cores/threads or memory .

Use make -j$(nproc) instead .
OS : Arch Linux 64-bit - rolling release

From: The Netherlands, Europe

OXPs : My user page (needs updating)

Retired, occasionally active
User avatar
hiran
Theorethicist
Posts: 2639
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Success building JavaScript library from scratch on Linux

Post by hiran »

We need to start managing a backlog. One item is to get rid of the python 2 dependencies.

Another one could be the javascript version. As far as I understand we have some Oolite custom JavaScript engine that noone outside the project would know.
Sunshine - Moonlight - Good Times - Oolite
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 779
Joined: Sun Jun 20, 2010 6:00 pm

Re: Success building JavaScript library from scratch on Linux

Post by mcarans »

Lone_Wolf wrote: Tue Mar 24, 2026 10:59 am
-j16 will slow compiling and cause OOM to abort the compilation (or other programs like a browser, DE etc) if the host system lacks cores/threads or memory .

Use make -j$(nproc) instead .
README fixed.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 779
Joined: Sun Jun 20, 2010 6:00 pm

Re: Success building JavaScript library from scratch on Linux

Post by mcarans »

hiran wrote: Tue Mar 24, 2026 12:34 pm
We need to start managing a backlog. One item is to get rid of the python 2 dependencies.

Another one could be the javascript version. As far as I understand we have some Oolite custom JavaScript engine that noone outside the project would know.
The problem with the engine is more its age. It is well known - people know Mozilla - but very very old. My preference would be to try to change the engine for a new one that is still C based for ease of using with Obj-C - I wrote about this here: viewtopic.php?p=303297#p303297
User avatar
hiran
Theorethicist
Posts: 2639
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Success building JavaScript library from scratch on Linux

Post by hiran »

mcarans wrote: Wed Mar 25, 2026 1:17 am
hiran wrote: Tue Mar 24, 2026 12:34 pm
We need to start managing a backlog. One item is to get rid of the python 2 dependencies.

Another one could be the javascript version. As far as I understand we have some Oolite custom JavaScript engine that noone outside the project would know.
The problem with the engine is more its age. It is well known - people know Mozilla - but very very old. My preference would be to try to change the engine for a new one that is still C based for ease of using with Obj-C - I wrote about this here: viewtopic.php?p=303297#p303297
I am with you but would like to track such activity on a backlog. It would allow others to add ideas and more people to work in the same direction.
Sunshine - Moonlight - Good Times - Oolite
User avatar
Lone_Wolf
---- E L I T E ----
---- E L I T E ----
Posts: 832
Joined: Wed Aug 08, 2007 10:59 pm
Location: Netherlands

Re: Success building JavaScript library from scratch on Linux

Post by Lone_Wolf »

hiran wrote: Wed Mar 25, 2026 6:43 am
I am with you but would like to track such activity on a backlog. It would allow others to add ideas and more people to work in the same direction.
Tracking/documenting this would also make it easier to adjust/update the baseline (assuming it's defined before this change happens) .
OS : Arch Linux 64-bit - rolling release

From: The Netherlands, Europe

OXPs : My user page (needs updating)

Retired, occasionally active
User avatar
hiran
Theorethicist
Posts: 2639
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Success building JavaScript library from scratch on Linux

Post by hiran »

Here's my stab at the backlog:
viewtopic.php?t=22072
Sunshine - Moonlight - Good Times - Oolite
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7204
Joined: Wed Feb 28, 2007 7:54 am

Re: Success building JavaScript library from scratch on Linux

Post by another_commander »

mcarans wrote: Mon Mar 23, 2026 11:22 pm
I have made a repo for this: https://github.com/mcarans/spidermonkey-linux

You can use distrobox to build for old gcc:

Code: Select all

distrobox create --name ubuntu22 --image ubuntu:22.04
distrobox enter ubuntu22
Then:

Code: Select all

sudo apt update
sudo apt install -y software-properties-common

sudo add-apt-repository universe
sudo apt update

sudo apt install -y python2.7
sudo apt install -y build-essential

sudo apt install -y libnspr4
sudo apt install -y libnspr4-dev
Then make:

Code: Select all

make -f libjs.make -j$(nproc)

Just to confirm: We now have Linux-deps at revision e46d304 containing the latest libjs_static.a built on Ubuntu 22.04 but the master branch still has Linux deps set at revision 0dacb28 (the previous one). We should bump Linux-deps to the latest libjs-static.a revision on master, correct?
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 779
Joined: Sun Jun 20, 2010 6:00 pm

Re: Success building JavaScript library from scratch on Linux

Post by mcarans »

another_commander wrote: Tue Mar 31, 2026 3:40 pm
mcarans wrote: Mon Mar 23, 2026 11:22 pm
I have made a repo for this: https://github.com/mcarans/spidermonkey-linux

You can use distrobox to build for old gcc:

Code: Select all

distrobox create --name ubuntu22 --image ubuntu:22.04
distrobox enter ubuntu22
Then:

Code: Select all

sudo apt update
sudo apt install -y software-properties-common

sudo add-apt-repository universe
sudo apt update

sudo apt install -y python2.7
sudo apt install -y build-essential

sudo apt install -y libnspr4
sudo apt install -y libnspr4-dev
Then make:

Code: Select all

make -f libjs.make -j$(nproc)

Just to confirm: We now have Linux-deps at revision e46d304 containing the latest libjs_static.a built on Ubuntu 22.04 but the master branch still has Linux deps set at revision 0dacb28 (the previous one). We should bump Linux-deps to the latest libjs-static.a revision on master, correct?
Yes, that's right. I've made a PR with that change and to remove some unused git submodules.

The oolite-binary-resources has only had 80 commits since 2012 so it doesn't look like these binaries change much and 216Mb is not a lot to put in a repo these days. What are your thoughts on making Resources/Binary into a real folder in the Oolite repo rather than a submodule?

Once the other submodules have been cleaned up, the same could be done for them. Then there will just be one Oolite repo to check out and build. It will be simpler to manage without the troublesome submodule update and detached head business that could be off-putting to potential contributors (and confusing to current ones from comments on this forum). From what I can see, a monorepo is how they have done it with Pioneer: https://github.com/pioneerspacesim/pion ... aster/data
Post Reply