Building JS library from scratch

News and discussion of the PC port of Oolite.

Moderators: another_commander, winston

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

Re: Building JS library from scratch

Post by mcarans »

Commander_X wrote: Mon Sep 15, 2025 2:30 am
mcarans wrote: Sun Sep 14, 2025 5:39 am
[...]
Here's a task for which your experience especially of Windows programming would be helpful if you're interested: viewtopic.php?t=21958
I'd have to use some of my Linux experience on that one (as I didn't put in the effort to compile oolite.exe outside the current windows tree).
From what I understand, you managed to compile a DLL version of espeak-ng, but it cannot find its "espeak-ng data". I'm not sure how the current espeak dll is compiled, but from what I could read in the README.md of espeak-ng, it should be "compatible" with espeak. Thus you could use this "trick" to inform espeak-ng library where its data should be, like in Linux, in a command prompt session:

Code: Select all

set ESPEAK_DATA=<absolute_path_to|relative_path_to>\oolite.app\Resources
./oolite
If espeak-ng data is still not found, you can rename/copy the espeak-data in Resources to espeak-ng-data (they say they moved it to avoid conflicts).
Hope this helps.
The data directory is the easy part. The task I had in mind is a bit more difficult but does not need Oolite to be compiled as it can be tested without Oolite. It is fixing the Windows XAudio2 code in https://github.com/espeak-ng/pcaudiolib, a dependency of espeak-ng. espeak-ng uses pcaudiolib to produce sound.

pcaudiolib is a simple C wrapper around various sound servers such as Pulseaudio, CoreAudio etc., but the Windows one, XAudio2 is broken. Fixing it would benefit not only Oolite but also anyone using mingw64 who wants to use espeak-ng (or any other package that uses pcaudiolib). espeak-ng itself can be used to test if pcaudiolib is working properly eg. if it is working, you will hear "hello", if you run:

Code: Select all

espeak-ng "hello"
Alternatively, a new OpenAL output could be added to pcaudiolib, the advantage being that the same endpoint could be used in both Linux and Windows. Oolite already has a dependency on OpenAL.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7138
Joined: Wed Feb 28, 2007 7:54 am

Re: Building JS library from scratch

Post by another_commander »

mcarans wrote: Sat Sep 13, 2025 2:57 am
I was able to replicate the issue by not running from within an MSYS2 mingw64 terminal window. You need the gdnc.exe in the same folder as oolite.exe. Here it is: https://www.filemail.com/d/yfwsghfsqhrhfuu
This application puts a lock on the temporary files stderr.txt and stdout.txt for some reason, which remains even after Oolite has exited. The app continues running in the background. As a result the two files are not deleted as expected when the game exits and cannot be recreated the next time it starts up, which ends up in the logfile written inside stderr.txt in subsequent runs of the game. The only way to delete stderr.txt and stdout.txt is to open Task Manager and kill gdnc.exe manually.

On top of that, gdnc.exe uses a notable CPU percentage when running in the background.

For the above reasons, gdnc.exe should be terminated when Oolite exits. This can probably be done by means of a batch file or with the appropriate game code (via a TerminateProcess Windows API call most likely). I am not a fan of requiring a batch file to play Oolite and believe that the game should be capable of functioning fully just by launching its executable.

And that's before we even get to why it was not able to create the ManagedAddOns folder in your case.

Taking the opportunity here to mention that I am not a fan of the size of the binaries either. The new binaries total up to > 80MB, while the standard ones are four times less than that. The libicudt77.dll in particular is HUGE at 31MB stripped, which is already much more than all the binaries of the standard distribution combined. Not a show stopper, but a considerable amount of bloat nevertheless.

Looks like we still have some ways to go before claiming 1:1 parity with the standard Oolite distribution.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building JS library from scratch

Post by mcarans »

another_commander wrote: Mon Sep 15, 2025 7:36 am
This application puts a lock on the temporary files stderr.txt and stdout.txt for some reason, which remains even after Oolite has exited. The app continues running in the background. As a result the two files are not deleted as expected when the game exits and cannot be recreated the next time it starts up, which ends up in the logfile written inside stderr.txt in subsequent runs of the game. The only way to delete stderr.txt and stdout.txt is to open Task Manager and kill gdnc.exe manually.

On top of that, gdnc.exe uses a notable CPU percentage when running in the background.

For the above reasons, gdnc.exe should be terminated when Oolite exits. This can probably be done by means of a batch file or with the appropriate game code (via a TerminateProcess Windows API call most likely). I am not a fan of requiring a batch file to play Oolite and believe that the game should be capable of functioning fully just by launching its executable.

And that's before we even get to why it was not able to create the ManagedAddOns folder in your case.

Taking the opportunity here to mention that I am not a fan of the size of the binaries either. The new binaries total up to > 80MB, while the standard ones are four times less than that. The libicudt77.dll in particular is HUGE at 31MB stripped, which is already much more than all the binaries of the standard distribution combined. Not a show stopper, but a considerable amount of bloat nevertheless.

Looks like we still have some ways to go before claiming 1:1 parity with the standard Oolite distribution.
I managed to get the existing Windows xaudio2 code in pcaudiolib to work with some small changes. espeak-ng "hello" produced the desired hello result. espeak-ng worked in Oolte as well. Here is the Oolite executable with espeak-ng and pcaudiolib: https://www.filemail.com/d/onbafcayglbwpyi

I'll take a look at the other issues you raise. I'm not surprised there are problems. After all, as I understand it, an update hasn't been done for more than a decade - that's a huge amount of technical debt to pay off.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7138
Joined: Wed Feb 28, 2007 7:54 am

Re: Building JS library from scratch

Post by another_commander »

Coming back to the subject of gdnc.exe and its quirks, I do not feel comfortable at all with needing an external executable to be able to use the Expansion Pack Manager in Oolite. I am mainly thinking safety reasons here, as it would be extremely easy and simple for someone to replace that gdnc.exe with any other (potentially malware) executable, call it with the same name and include it in a game package. Then simply selecting the Expansion Manager in the game would execute arbitrary code. Of course the same can be said about any of the dlls coming with the game, but at least making a malware-oriented dll involves some serious work with export function detours etc. and could be considered a pain in the backside enough to deter most people from trying to use this as path of attack.

Is there any chance that this requirement is somehow lifted? Are there any ways that the gdnc.exe functionality could be reproduced without having to have gdnc.exe itself in there? Environment variables could be an example (haven't researched it) or even an older gnustep-base version maybe? We never required gdnc before, so even the latest gnustep-base version that doesn't need it to function would in my opinion be better than a more recent version that can't work without it.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building JS library from scratch

Post by mcarans »

another_commander wrote: Mon Sep 22, 2025 5:56 am
Coming back to the subject of gdnc.exe and its quirks, I do not feel comfortable at all with needing an external executable to be able to use the Expansion Pack Manager in Oolite. I am mainly thinking safety reasons here, as it would be extremely easy and simple for someone to replace that gdnc.exe with any other (potentially malware) executable, call it with the same name and include it in a game package. Then simply selecting the Expansion Manager in the game would execute arbitrary code. Of course the same can be said about any of the dlls coming with the game, but at least making a malware-oriented dll involves some serious work with export function detours etc. and could be considered a pain in the backside enough to deter most people from trying to use this as path of attack.

Is there any chance that this requirement is somehow lifted? Are there any ways that the gdnc.exe functionality could be reproduced without having to have gdnc.exe itself in there? Environment variables could be an example (haven't researched it) or even an older gnustep-base version maybe? We never required gdnc before, so even the latest gnustep-base version that doesn't need it to function would in my opinion be better than a more recent version that can't work without it.
gdnc was around 17 years ago: https://github.com/gnustep/libs-base/tr ... b9b3/Tools

I'm not sure why it was not required before. It will require debugging to see what is causing it to launch. Maybe it will be possible to avoid launching it.

Before I look into that, I want to first set up scripts to be able to repeatably build everything from scratch (and ideally later have them executed in GitHub Actions to create versioned development environments).
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7138
Joined: Wed Feb 28, 2007 7:54 am

Re: Building JS library from scratch

Post by another_commander »

mcarans wrote: Mon Sep 22, 2025 8:26 am
Before I look into that, I want to first set up scripts to be able to repeatably build everything from scratch (and ideally later have them executed in GitHub Actions to create versioned development environments).
Good plan. Please make sure that anyone starting with a virgin PC system can install all necessary environment elements and complete an entire build of Oolite all the way from git tree checkout to installer ready to go. We will have to keep the two dev environment setups, old and new, in parallel for some time while the new one is tested exhaustively before attempting the switch.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building JS library from scratch

Post by mcarans »

another_commander wrote: Mon Sep 22, 2025 8:33 am
Good plan. Please make sure that anyone starting with a virgin PC system can install all necessary environment elements and complete an entire build of Oolite all the way from git tree checkout to installer ready to go. We will have to keep the two dev environment setups, old and new, in parallel for some time while the new one is tested exhaustively before attempting the switch.
There's a difference between the js-config.h from the repo you shared which I checked in vs the one in Windows dependencies:

https://github.com/mcarans/oolite_mozjs ... fig.h#L118

https://github.com/OoliteProject/oolite ... fig.h#L118

Which one is correct?
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7138
Joined: Wed Feb 28, 2007 7:54 am

Re: Building JS library from scratch

Post by another_commander »

mcarans wrote: Thu Oct 09, 2025 10:46 pm
There's a difference between the js-config.h from the repo you shared which I checked in vs the one in Windows dependencies:

https://github.com/mcarans/oolite_mozjs ... fig.h#L118

https://github.com/OoliteProject/oolite ... fig.h#L118

Which one is correct?
Not entirely sure that JS_BYTES_PER_WORD_LOG2 is actually used, but just in case it is and to avoid future confusion, and based on the fact that JS_BYTES_PER_WORD is defined as 8 for both Windows and Linux in their corresponding deps js-config.h header, I would go ahead and say that the correct answer is 3.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building JS library from scratch

Post by mcarans »

another_commander wrote: Fri Oct 10, 2025 6:20 am
mcarans wrote: Thu Oct 09, 2025 10:46 pm
There's a difference between the js-config.h from the repo you shared which I checked in vs the one in Windows dependencies:

https://github.com/mcarans/oolite_mozjs ... fig.h#L118

https://github.com/OoliteProject/oolite ... fig.h#L118

Which one is correct?
Not entirely sure that JS_BYTES_PER_WORD_LOG2 is actually used, but just in case it is and to avoid future confusion, and based on the fact that JS_BYTES_PER_WORD is defined as 8 for both Windows and Linux in their corresponding deps js-config.h header, I would go ahead and say that the correct answer is 3.
Ok I had copied the Oolite one but have reverted that change so it's now 3 again.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building JS library from scratch

Post by mcarans »

For future reference, here is a diff of the differences between the js folders in https://ftp.mozilla.org/pub/firefox/rel ... ce.tar.bz2 and https://github.com/OoliteProject/spidermonkey-ff4. It seems to be mostly replacing false or JS_FALSE with NULL.

Code: Select all

diff -ruN /home/mcarans/Downloads/mozilla-2.0/js/src/jsapi.cpp js/src/jsapi.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jsapi.cpp	2011-03-19 12:33:50.000000000 +1300
+++ js/src/jsapi.cpp	2025-10-25 18:08:35.355376253 +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 /home/mcarans/Downloads/mozilla-2.0/js/src/jsfun.cpp js/src/jsfun.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jsfun.cpp	2011-03-19 12:33:50.000000000 +1300
+++ js/src/jsfun.cpp	2025-10-25 18:08:35.360376204 +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 /home/mcarans/Downloads/mozilla-2.0/js/src/jsiter.cpp js/src/jsiter.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jsiter.cpp	2011-03-19 12:33:50.000000000 +1300
+++ js/src/jsiter.cpp	2025-10-25 18:08:35.363376174 +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 /home/mcarans/Downloads/mozilla-2.0/js/src/jsparse.cpp js/src/jsparse.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jsparse.cpp	2011-03-19 12:33:51.000000000 +1300
+++ js/src/jsparse.cpp	2025-10-25 18:08:35.368376125 +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 /home/mcarans/Downloads/mozilla-2.0/js/src/jsstr.cpp js/src/jsstr.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jsstr.cpp	2011-03-19 12:33:51.000000000 +1300
+++ js/src/jsstr.cpp	2025-10-25 18:08:35.371376095 +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 /home/mcarans/Downloads/mozilla-2.0/js/src/jstypedarray.cpp js/src/jstypedarray.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jstypedarray.cpp	2011-03-19 12:33:51.000000000 +1300
+++ js/src/jstypedarray.cpp	2025-10-25 18:08:35.374376065 +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 /home/mcarans/Downloads/mozilla-2.0/js/src/jsxml.cpp js/src/jsxml.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/jsxml.cpp	2011-03-19 12:33:51.000000000 +1300
+++ js/src/jsxml.cpp	2025-10-25 18:08:35.375376055 +1300
@@ -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 /home/mcarans/Downloads/mozilla-2.0/js/src/methodjit/InvokeHelpers.cpp js/src/methodjit/InvokeHelpers.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/methodjit/InvokeHelpers.cpp	2011-03-19 12:33:51.000000000 +1300
+++ js/src/methodjit/InvokeHelpers.cpp	2025-10-25 18:08:35.381375996 +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);
diff -ruN /home/mcarans/Downloads/mozilla-2.0/js/src/nanojit/NativeX64.cpp js/src/nanojit/NativeX64.cpp
--- /home/mcarans/Downloads/mozilla-2.0/js/src/nanojit/NativeX64.cpp	2011-03-19 12:33:51.000000000 +1300
+++ js/src/nanojit/NativeX64.cpp	2025-10-25 18:08:35.391375897 +1300
@@ -1899,7 +1899,7 @@
          }
     }
 
-    static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0};
+    static const AVMPLUS_ALIGN16(uint64_t) negateMask[] = {0x8000000000000000LL,0};
 
     void Assembler::asm_fneg(LIns *ins) {
         Register rr, ra;
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building static JS library from scratch

Post by mcarans »

I was able to build Oolite with static Spidermonkey (and NSPR), but it failed with a segmentation fault. I will not investigate further for now. For future reference, I changed in GNUmakefile:

Code: Select all

JS_IMPORT_LIBRARY        = libjs32ECMAv5.a
...
ADDITIONAL_OBJC_LIBS         = -lglu32 -lopengl32 -l$(OPENAL_LIBRARY_NAME).dll -l$(LIBPNG_LIBRARY_NAME).dll -lmingw32 -lSDLmain -lSDL -lvorbisfile.dll -lvorbis.dll -lz -lgnustep-base -L$(JS_LIB_DIR) -l:libnspr4_s.a -l:$(JS_IMPORT_LIBRARY) -lshlwapi -ldwmapi -lwinmm -mwindows -lmswsock
I copied libnspr4_s.a from NSPR (also tried system NSPR). To make the static libjs32ECMAv5.a from Spidermonkey, I added -DNSPR_STATIC to js\src\ref-config\WINNT5.1.mk:

Code: Select all

OS_CFLAGS = -DXP_WIN -DEXPORT_JS_API -DJS_C_STRINGS_ARE_UTF8 -D__STDC_LIMIT_MACROS -D_WINDOWS -DWINVER=0x500 -D_WIN32_WINNT=0x500 -DNSPR_STATIC $(WIN_CFLAGS)
I replaced the long line of build_js_release.sh that starts with g++ -shared with:

Code: Select all

ar rcs WINNT5.1_OPT.OBJ/libjs32ECMAv5.a WINNT5.1_OPT.OBJ/jsanalyze.o WINNT5.1_OPT.OBJ/jsapi.o WINNT5.1_OPT.OBJ/jsarena.o WINNT5.1_OPT.OBJ/jsarray.o WINNT5.1_OPT.OBJ/jsatom.o WINNT5.1_OPT.OBJ/jsbool.o WINNT5.1_OPT.OBJ/jsclone.o WINNT5.1_OPT.OBJ/jscntxt.o WINNT5.1_OPT.OBJ/jscompartment.o WINNT5.1_OPT.OBJ/jsdate.o WINNT5.1_OPT.OBJ/jsdbgapi.o WINNT5.1_OPT.OBJ/jsdhash.o WINNT5.1_OPT.OBJ/jsdtoa.o WINNT5.1_OPT.OBJ/jsemit.o WINNT5.1_OPT.OBJ/jsexn.o WINNT5.1_OPT.OBJ/jsfun.o WINNT5.1_OPT.OBJ/jsgc.o WINNT5.1_OPT.OBJ/jsgcchunk.o WINNT5.1_OPT.OBJ/jsgcstats.o WINNT5.1_OPT.OBJ/jshash.o WINNT5.1_OPT.OBJ/jsinterp.o WINNT5.1_OPT.OBJ/jsinvoke.o WINNT5.1_OPT.OBJ/jsiter.o WINNT5.1_OPT.OBJ/jslock.o WINNT5.1_OPT.OBJ/jslog2.o WINNT5.1_OPT.OBJ/jsmath.o WINNT5.1_OPT.OBJ/jsnativestack.o WINNT5.1_OPT.OBJ/jsnum.o WINNT5.1_OPT.OBJ/jsobj.o WINNT5.1_OPT.OBJ/json.o WINNT5.1_OPT.OBJ/jsopcode.o WINNT5.1_OPT.OBJ/jsparse.o WINNT5.1_OPT.OBJ/jsprf.o WINNT5.1_OPT.OBJ/jsprobes.o WINNT5.1_OPT.OBJ/jspropertycache.o WINNT5.1_OPT.OBJ/jspropertytree.o WINNT5.1_OPT.OBJ/jsproxy.o WINNT5.1_OPT.OBJ/jsreflect.o WINNT5.1_OPT.OBJ/jsregexp.o WINNT5.1_OPT.OBJ/jsscan.o WINNT5.1_OPT.OBJ/jsscope.o WINNT5.1_OPT.OBJ/jsscript.o WINNT5.1_OPT.OBJ/jsstr.o WINNT5.1_OPT.OBJ/jstypedarray.o WINNT5.1_OPT.OBJ/jsutil.o WINNT5.1_OPT.OBJ/jswrapper.o WINNT5.1_OPT.OBJ/jsxdrapi.o WINNT5.1_OPT.OBJ/jsxml.o WINNT5.1_OPT.OBJ/prmjtime.o WINNT5.1_OPT.OBJ/jsbuiltins.o WINNT5.1_OPT.OBJ/jstracer.o WINNT5.1_OPT.OBJ/nanojit/Allocator.o WINNT5.1_OPT.OBJ/nanojit/Assembler.o WINNT5.1_OPT.OBJ/nanojit/CodeAlloc.o WINNT5.1_OPT.OBJ/nanojit/Containers.o WINNT5.1_OPT.OBJ/nanojit/Fragmento.o WINNT5.1_OPT.OBJ/nanojit/LIR.o WINNT5.1_OPT.OBJ/nanojit/NativeX64.o WINNT5.1_OPT.OBJ/nanojit/njconfig.o WINNT5.1_OPT.OBJ/nanojit/RegAlloc.o WINNT5.1_OPT.OBJ/nanojit/avmplus.o WINNT5.1_OPT.OBJ/nanojit/VMPI.o WINNT5.1_OPT.OBJ/tracejit/Writer.o WINNT5.1_OPT.OBJ/assembler/jit/ExecutableAllocator.o WINNT5.1_OPT.OBJ/assembler/jit/ExecutableAllocatorWin.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_exec.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_xclass.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_tables.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_compile.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_ucp_searchfuncs.o WINNT5.1_OPT.OBJ/yarr/yarr/RegexCompiler.o WINNT5.1_OPT.OBJ/yarr/yarr/RegexJIT.o WINNT5.1_OPT.OBJ/assembler/assembler/MacroAssemblerX86Common.o WINNT5.1_OPT.OBJ/assembler/wtf/Assertions.o WINNT5.1_OPT.OBJ/v8-dtoa/checks.o WINNT5.1_OPT.OBJ/v8-dtoa/conversions.o WINNT5.1_OPT.OBJ/v8-dtoa/diy-fp.o WINNT5.1_OPT.OBJ/v8-dtoa/fast-dtoa.o WINNT5.1_OPT.OBJ/v8-dtoa/platform.o WINNT5.1_OPT.OBJ/v8-dtoa/utils.o WINNT5.1_OPT.OBJ/v8-dtoa/v8-dtoa.o WINNT5.1_OPT.OBJ/methodjit/Compiler.o WINNT5.1_OPT.OBJ/methodjit/FastArithmetic.o WINNT5.1_OPT.OBJ/methodjit/FastOps.o WINNT5.1_OPT.OBJ/methodjit/FrameState.o WINNT5.1_OPT.OBJ/methodjit/ImmutableSync.o WINNT5.1_OPT.OBJ/methodjit/InvokeHelpers.o WINNT5.1_OPT.OBJ/methodjit/Logging.o WINNT5.1_OPT.OBJ/methodjit/MethodJIT.o WINNT5.1_OPT.OBJ/methodjit/MonoIC.o WINNT5.1_OPT.OBJ/methodjit/PolyIC.o WINNT5.1_OPT.OBJ/methodjit/Retcon.o WINNT5.1_OPT.OBJ/methodjit/StubCalls.o WINNT5.1_OPT.OBJ/methodjit/StubCompiler.o WINNT5.1_OPT.OBJ/methodjit/TrampolineCompiler.o WINNT5.1_OPT.OBJ/methodjit/TrampolinemingwX64.o
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Static JS library working in Windows

Post by mcarans »

I got it working. Had to do only this step:

Code: Select all

ar rcs WINNT5.1_OPT.OBJ/libjs32ECMAv5.a WINNT5.1_OPT.OBJ/jsanalyze.o WINNT5.1_OPT.OBJ/jsapi.o WINNT5.1_OPT.OBJ/jsarena.o WINNT5.1_OPT.OBJ/jsarray.o WINNT5.1_OPT.OBJ/jsatom.o WINNT5.1_OPT.OBJ/jsbool.o WINNT5.1_OPT.OBJ/jsclone.o WINNT5.1_OPT.OBJ/jscntxt.o WINNT5.1_OPT.OBJ/jscompartment.o WINNT5.1_OPT.OBJ/jsdate.o WINNT5.1_OPT.OBJ/jsdbgapi.o WINNT5.1_OPT.OBJ/jsdhash.o WINNT5.1_OPT.OBJ/jsdtoa.o WINNT5.1_OPT.OBJ/jsemit.o WINNT5.1_OPT.OBJ/jsexn.o WINNT5.1_OPT.OBJ/jsfun.o WINNT5.1_OPT.OBJ/jsgc.o WINNT5.1_OPT.OBJ/jsgcchunk.o WINNT5.1_OPT.OBJ/jsgcstats.o WINNT5.1_OPT.OBJ/jshash.o WINNT5.1_OPT.OBJ/jsinterp.o WINNT5.1_OPT.OBJ/jsinvoke.o WINNT5.1_OPT.OBJ/jsiter.o WINNT5.1_OPT.OBJ/jslock.o WINNT5.1_OPT.OBJ/jslog2.o WINNT5.1_OPT.OBJ/jsmath.o WINNT5.1_OPT.OBJ/jsnativestack.o WINNT5.1_OPT.OBJ/jsnum.o WINNT5.1_OPT.OBJ/jsobj.o WINNT5.1_OPT.OBJ/json.o WINNT5.1_OPT.OBJ/jsopcode.o WINNT5.1_OPT.OBJ/jsparse.o WINNT5.1_OPT.OBJ/jsprf.o WINNT5.1_OPT.OBJ/jsprobes.o WINNT5.1_OPT.OBJ/jspropertycache.o WINNT5.1_OPT.OBJ/jspropertytree.o WINNT5.1_OPT.OBJ/jsproxy.o WINNT5.1_OPT.OBJ/jsreflect.o WINNT5.1_OPT.OBJ/jsregexp.o WINNT5.1_OPT.OBJ/jsscan.o WINNT5.1_OPT.OBJ/jsscope.o WINNT5.1_OPT.OBJ/jsscript.o WINNT5.1_OPT.OBJ/jsstr.o WINNT5.1_OPT.OBJ/jstypedarray.o WINNT5.1_OPT.OBJ/jsutil.o WINNT5.1_OPT.OBJ/jswrapper.o WINNT5.1_OPT.OBJ/jsxdrapi.o WINNT5.1_OPT.OBJ/jsxml.o WINNT5.1_OPT.OBJ/prmjtime.o WINNT5.1_OPT.OBJ/jsbuiltins.o WINNT5.1_OPT.OBJ/jstracer.o WINNT5.1_OPT.OBJ/nanojit/Allocator.o WINNT5.1_OPT.OBJ/nanojit/Assembler.o WINNT5.1_OPT.OBJ/nanojit/CodeAlloc.o WINNT5.1_OPT.OBJ/nanojit/Containers.o WINNT5.1_OPT.OBJ/nanojit/Fragmento.o WINNT5.1_OPT.OBJ/nanojit/LIR.o WINNT5.1_OPT.OBJ/nanojit/NativeX64.o WINNT5.1_OPT.OBJ/nanojit/njconfig.o WINNT5.1_OPT.OBJ/nanojit/RegAlloc.o WINNT5.1_OPT.OBJ/nanojit/avmplus.o WINNT5.1_OPT.OBJ/nanojit/VMPI.o WINNT5.1_OPT.OBJ/tracejit/Writer.o WINNT5.1_OPT.OBJ/assembler/jit/ExecutableAllocator.o WINNT5.1_OPT.OBJ/assembler/jit/ExecutableAllocatorWin.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_exec.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_xclass.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_tables.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_compile.o WINNT5.1_OPT.OBJ/yarr/pcre/pcre_ucp_searchfuncs.o WINNT5.1_OPT.OBJ/yarr/yarr/RegexCompiler.o WINNT5.1_OPT.OBJ/yarr/yarr/RegexJIT.o WINNT5.1_OPT.OBJ/assembler/assembler/MacroAssemblerX86Common.o WINNT5.1_OPT.OBJ/assembler/wtf/Assertions.o WINNT5.1_OPT.OBJ/v8-dtoa/checks.o WINNT5.1_OPT.OBJ/v8-dtoa/conversions.o WINNT5.1_OPT.OBJ/v8-dtoa/diy-fp.o WINNT5.1_OPT.OBJ/v8-dtoa/fast-dtoa.o WINNT5.1_OPT.OBJ/v8-dtoa/platform.o WINNT5.1_OPT.OBJ/v8-dtoa/utils.o WINNT5.1_OPT.OBJ/v8-dtoa/v8-dtoa.o WINNT5.1_OPT.OBJ/methodjit/Compiler.o WINNT5.1_OPT.OBJ/methodjit/FastArithmetic.o WINNT5.1_OPT.OBJ/methodjit/FastOps.o WINNT5.1_OPT.OBJ/methodjit/FrameState.o WINNT5.1_OPT.OBJ/methodjit/ImmutableSync.o WINNT5.1_OPT.OBJ/methodjit/InvokeHelpers.o WINNT5.1_OPT.OBJ/methodjit/Logging.o WINNT5.1_OPT.OBJ/methodjit/MethodJIT.o WINNT5.1_OPT.OBJ/methodjit/MonoIC.o WINNT5.1_OPT.OBJ/methodjit/PolyIC.o WINNT5.1_OPT.OBJ/methodjit/Retcon.o WINNT5.1_OPT.OBJ/methodjit/StubCalls.o WINNT5.1_OPT.OBJ/methodjit/StubCompiler.o WINNT5.1_OPT.OBJ/methodjit/TrampolineCompiler.o WINNT5.1_OPT.OBJ/methodjit/TrampolinemingwX64.o


Then link the NSPR dll.a not the static one:

Code: Select all

JS_IMPORT_LIBRARY        = libjs32ECMAv5.a
...
ADDITIONAL_OBJC_LIBS         = -lglu32 -lopengl32 -l$(OPENAL_LIBRARY_NAME).dll -l$(LIBPNG_LIBRARY_NAME).dll -lmingw32 -lSDLmain -lSDL -lvorbisfile.dll -lvorbis.dll -lz -lgnustep-base -L$(JS_LIB_DIR) -l:libnspr4.dll.a -l:$(JS_IMPORT_LIBRARY) -lshlwapi -ldwmapi -lwinmm -mwindows -lmswsock
No need to change js\src\ref-config\WINNT5.1.mk
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7138
Joined: Wed Feb 28, 2007 7:54 am

Re: Building JS library from scratch

Post by another_commander »

Yup, got it working with static js linking on the legacy build too.
User avatar
mcarans
---- E L I T E ----
---- E L I T E ----
Posts: 661
Joined: Sun Jun 20, 2010 6:00 pm

Re: Building JS library from scratch

Post by mcarans »

another_commander wrote: Mon Dec 29, 2025 8:03 am
Yup, got it working with static js linking on the legacy build too.
That's good. BTW, my best guess for why a source build of the JS from clean repo doesn't work (Oolite starts up, but allocation issues in JS) is the lack of methodjit/TrampolinemingwX64.s from your custom repo. Getting that into the clean build could be enough to fix it and I think it could be done relatively cleanly by editing Makefile.in around line 334 to use. It looks like no assembler file is being added for MinGW builds not even TrampolineMasmX64.asm judging by the ifdefs.
Last edited by mcarans on Sun Jan 11, 2026 11:00 pm, edited 1 time in total.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 7138
Joined: Wed Feb 28, 2007 7:54 am

Re: Building JS library from scratch

Post by another_commander »

I noticed something while examining the executable with the statically linked JS: It exports hundreds of JS_* functions and many with C++ mangled names too, all from the JS library. If the reason we are building this exe is to avoid presenting a js32ECMAv5.dll as part of the binary distribution, then I think that exporting practically the entire JS library from the exe is more sus than the dll. If I were Microsoft and saw all those exports in the exe I would be asking for clarifications.

I don't have the exe handy now but tomorrow I will post a screenshot of what gets exported. Normally the Oolite executable (and most games executables for that matter) are expected to export just 2 functions: The NVidia and AMD functions required in dual-GPU laptops for telling the gfx driver that the discreet GPU must be used for the game.

It's certainly good that we now know how to use static JS linking if we want to, but I would recommend not replacing the dll with static linking at this stage. It just seems more straightforward if the js dll is separate and the exe remains "clean".
Post Reply