How to build nodejs as a shared library from source code - c++

I need to include node.h in my c++ project, I tried to build node from source code using:
./configure
sudo make
I got a node executable and some object files and .a files, I need to build as .so file to use it in my c++ code.
I tried to build libnode, but I got cmakelists error and this is not official nodejs project.
if anybody know how to build nodejs from source code as .so file will be great, a similar question in a google group but the answer is not working.

Support for building as a shared library has been added in to node mainline. Please see PR 6994 and specifically this comment.
I just ran
git clone https://github.com/nodejs/node.git
cd node
git checkout v6.9.4
./configure --shared
make -j4
which produced:
ubuntu#server:~/node$ find . -name libnode.so\* -exec ls -la {} \;
-rwxrwxr-x 2 ubuntu ubuntu 31576776 Jan 6 18:57 ./out/Release/lib.target/libnode.so.48
-rw-rw-r-- 1 ubuntu ubuntu 387 Jan 6 18:57 ./out/Release/.deps/home/ubuntu/node/out/Release/lib.target/libnode.so.48.d
-rw-rw-r-- 1 ubuntu ubuntu 4202 Jan 6 18:57 ./out/Release/.deps/home/ubuntu/node/out/Release/obj.target/libnode.so.48.d
-rwxrwxr-x 2 ubuntu ubuntu 31576776 Jan 6 18:57 ./out/Release/obj.target/libnode.so.48
ubuntu#server:~/node$

I think it is easier to build in a static library as shared requires the addition of '-fpic'.
For my projects (under Linux) I use this script to built a static node.js library:
#!/bin/sh
# This script is LGPL feel free to use it!
if test ! "$#" = "1"; then
echo "Run with the archive in parameter:"
echo "\t${0} ./node-v0.XX.XX.tar.gz"
echo "\nIt will build a ./libnode_static.a in current dir"
return
fi
HERE=$PWD
#Extract Tarball
tar xf $1 | exit 1
DIRNAME=`echo $1 | sed s/.tar.gz//g`
cd $DIRNAME
#Patch node.gyp to build in static
sed -i "s/'type': 'executable',/'type': 'static_library',/g" ./node.gyp
#Patch node_main.cc to rename the main in node_main
sed -i "s/int main(/int node_main(/g" ./src/node_main.cc
#Build Node.js
./configure
make -j8
#Move to build directory
cd ./out/Release
#Extract .a
#Cleanup if previous build
rm -fr *.tmpd
echo "== Extracting *.a =="
#Make sure we create a directory
#for each.a as some .o might
#have the same name
for a in `ls *.a`
do
echo "\t${a}..."
mkdir "$a.tmpd"
cd "$a.tmpd"
ar x ../$a
cd ..
done
#Repack in a single .a
find . -iname "*.o" | xargs ar rcs libnode_static.a
#Cleanup
rm -fr *.tmpd
echo "== DONE =="
#Move in start directory
mv ./libnode_static.a ${HERE}/
cd ${HERE}
#Sanity CHECK
echo "== Performing Sanity Check =="
TMP_FILE=`mktemp /tmp/XXXXXX.cxx`
TMP_EXE=`mktemp /tmp/XXXXXX`
cat << . > ${TMP_FILE}
int node_main( int argc, char **argv);
int main(int argc, char ** argv )
{
node_main( argc, argv );
return 0;
}
.
#Try compiling
g++ ${TMP_FILE} -o ${TMP_EXE} -lnode_static -ldl -pthread -L.
#Try running
RET=`${TMP_EXE} -e "console.log('okfromnode')"`
if test "x${RET}" = "xokfromnode"; then
echo "== Sanity check OK =="
else
echo "== Sanity check FAILED =="
exit 1
fi
rm ${TMP_FILE} ${TMP_EXE}
echo "== Node.js is now built statically in ./libnode_static.a =="
exit 0
Run it as follows :
sh script.sh node-v0.10.XX.tar.gz
If everything goes well you should get a libnode_static.a in current directory.
Use it with a code like this:
int node_main( int argc, char **argv);
int main(int argc, char ** argv )
{
/* Here we spawn a node.js instance */
return node_main( argc, argv );
}
And compile like this:
g++ ./test.cxx -o ./my_node -lnode_static -ldl -pthread -L.
And you have embedded node :
./my_node -e "console.log('Hello World')"
#Outputs
Hello World
Hope this helps.

This is how i did it in windows. Except for the build procedures, everything should be same.
Nodejs uses node-gyp for building. You can read this for building and installation. Or just git clone the repository.
Open node.gyp in the node-vX.XX.XX and find
'targets': [
{
'target_name': 'node',
'type': 'executable',
change the executable to shared_library.
Run vcbuild.bat in windows or for other platforms follow instructions.

Update:
https://gist.github.com/aklen/849f3460b7a028c9aed8a84e1d4cecb7
Windows
.\vcbuild release vs2017 dll x64
.\vcbuild release vs2017 dll x86
.\vcbuild debug vs2017 dll x64
.\vcbuild debug vs2017 dll x86
Linux / MacOS
./configure --shared --release
make -j4
./configure --shared --debug
make -j4
Other build options
https://github.com/nodejs/node/blob/master/BUILDING.md

Related

Removing OpenSSL 3.0 devel so C++ compiles on Linux

I'm on Ubuntu 22.04 and compiling this C++ Github pull request:
https://github.com/ftexchange/ftx/pull/13
However, the PR contains a compile error.
Somebody posted to fix the error OpenSSL 3.0 devel version must be "removed":
It seems like the compiler was using OpenSSL 3.0 devel version, I had
to remove that
How do I achieve this?
This is what I did on Ubuntu 22.04 LTS.
$ sudo apt install libboost-dev libssl-dev
$ git clone --recursive --branch openssl-1.1 https://github.com/arf-labs-ou/ftx.git
$ cmake -G Ninja -S ftx/cpp -B build -DCMAKE_BUILD_TYPE=Release
$ cmake --build build
Trying to build at this point will trip deprecation warnings when compiling against the system OpenSSL 3. But because ftx has done the extremely inadvisable thing of hard-coding -Werror in their build, this is promoted to a spurious error. Deprecated doesn't mean "won't work today"; it means "upstream must fix". You are not upstream, so this ought not affect you, but, alas, low-quality build code is not a great surprise.
We will hack around this by wrapping the compiler with a shell script that deletes warning flags from the command line. Create a file called no-warnings.sh:
#!/bin/bash
ARGS=()
for arg in "$#"; do
if [[ ! "$arg" =~ ^-W ]]; then
ARGS+=("$arg")
fi
done
"${ARGS[#]}"
Now let's inject it into the build via the CMAKE_CXX_COMPILER_LAUNCHER hook:
$ chmod +x no-warnings.sh
$ rm -rf build
$ cmake -G Ninja -S ftx/cpp/ -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=$PWD/no-warnings.sh
$ cmake --build build/
This should work but, unfortunately, even this wasn't enough to build successfully. The code itself has a type error! I wonder if something changed between Boost 1.71 and 1.74. Anyway, I applied the following patch:
diff --git a/cpp/src/util/HTTP.cc b/cpp/src/util/HTTP.cc
index 30e0277..2d043f2 100644
--- a/cpp/src/util/HTTP.cc
+++ b/cpp/src/util/HTTP.cc
## -100,8 +100,8 ## void HTTPSession::authenticate(http::request<http::string_body>& req)
std::string path(req.target());
std::string body(req.body());
- long ts = get_ms_timestamp(current_time()).count();
- std::string data = std::to_string(ts) + method + path;
+ auto ts = std::to_string(get_ms_timestamp(current_time()).count());
+ std::string data = ts + method + path;
if (!body.empty()) {
data += body;
}
And now the above commands produce a successful build. The example programs run and produce reasonable output, as well.

Strip/Remove debug symbols and archive names from a static library

I have a static library (C++) (say, libmylib_DARWIN.a and libmylib_LINUX.a for 2 architectures) compiled on my Mac using clang (Apple LLVM version 9.0.0 (clang-900.0.39.2) if is of any relevance).
Right now, there are two problems:
The static library (using a current build configuration) contains debug symbols
It also shows names of the object files that were used for the archive
otool -Iv libmylib_DARWIN.a
Archive : libmylib_DARWIN.a
libmylib_DARWIN.a(firstobjectfile.cpp.o)
libmylib_DARWIN.a(secondobjectfile.cpp.o)
....
I would like to remove both the debug symbols and archived filenames from this library. I wonder if there is a convenient way to do it without changing my build configuration.
will strip on Mac do it for both DARWIN- and LINUX-built libraries? Anything I should pay attention too?
strip doesn't seem to remove the archive filenames
There are some similar questions on SO; however, the ones I found deal with either iOS, Objective C, do not talk about multiplatform, and do not mention archive names.
This script implements Sigismondo's suggestion (unpacks the archive, strips each object file individually, renames them 1000.o, 1001.o, etc., and repacks). The parameters for ar crus may vary depending on your version of ar.
#!/bin/bash
# usage: repack.sh file.a
if [ -z "$1" ]; then
echo "usage: repack file.a"
exit 1
fi
if [ -d tmprepack ]; then
/bin/rm -rf tmprepack
fi
mkdir tmprepack
cp $1 tmprepack
pushd tmprepack
basename=${1##*/}
ar xv $basename
/bin/rm -f $basename
i=1000
for p in *.o ; do
strip -d $p
mv $p ${i}.o
((i++))
done
ar crus $basename *.o
mv $basename ..
popd
/bin/rm -rf tmprepack
exit 0

go unit test runs from %APPDATA%

I am trying to run some of my Go unit tests using "go test" but the test executable is built and run from my machine's %APPDATA%/local/temp directory. My PC has IT enforcement which blocks any unrecognized executable from being run other than from a pre-sanctioned directory (i.e C:/dev/projects"). All my Go source code are in that directory, including my *_test.go files. Is there a way to tell the Go test module to build and run from the current directory?
Yes you can.
Setting temp directory before executing the go test. By default temp directory environment variable gets evaluated in the order of TMP, TEMP, USERPROFILE, Windows directory; refer to msdn doc.
Basically it complies the go test under given temp directory and execute it.
C:\> cd dev\projects\src\mygotest
C:\dev\projects\src\mygotest>echo %CD%
C:\dev\projects\src\mygotest
C:\dev\projects\src\mygotest>set TMP=%CD%
C:\dev\projects\src\mygotest>go test -x
WORK=C:\dev\projects\src\mygotest\go-build306298926
mkdir -p $WORK\mygotest\_test\
mkdir -p $WORK\mygotest\_test\_obj_test\
cd C:\dev\projects\src\mygotest
"C:\\Go\\pkg\\tool\\windows_amd64\\compile.exe" -o "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test\\mygotest.a" -trimpath "C:\\dev\\projects\\src\\mygotest\\go-build306298926" -p main -complete -buildid 86cb7a423d355c7468ad98c4f8bffe77b68d2265 -D _/C_/dev/projects/src/mygotest -I "C:\\dev\\projects\\src\\mygotest\\go-build306298926" -pack "C:\\dev\\projects\\src\\mygotest\\sample.go" "C:\\dev\\projects\\src\\mygotest\\sample_test.go"
cd $WORK\mygotest\_test
"C:\\Go\\pkg\\tool\\windows_amd64\\compile.exe" -o "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test\\main.a" -trimpath "C:\\dev\\projects\\src\\mygotest\\go-build306298926" -p main -complete -D "" -I "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test" -I "C:\\dev\\projects\\src\\mygotest\\go-build306298926" -pack "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test\\_testmain.go"
cd .
"C:\\Go\\pkg\\tool\\windows_amd64\\link.exe" -o "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test\\mygotest.test.exe" -L "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test" -L "C:\\dev\\projects\\src\\mygotest\\go-build306298926" -w -extld=gcc -buildmode=exe "C:\\dev\\projects\\src\\mygotest\\go-build306298926\\mygotest\\_test\\main.a"
$WORK\mygotest\_test\mygotest.test.exe
Hello, playground
PASS
ok mygotest 0.526s
C:\dev\projects\src\mygotest>
Note: TMP set to current terminal session only, it doesn't affect system environment variable.
Important thing to note from above test output is WORK=C:\dev\projects\src\mygotest\go-build306298926.
Happy testing!

replace a part of a string with REGEXP in sqlite3

I installed REGEX support with
apt-get install sqlite3 sqlite3-pcre
now I can use REGEX in my queries on the bash console like
DB="somedb.db"
REGEX_EXTENSION="SELECT load_extension('/usr/lib/sqlite3/pcre.so');"
sqlite3 $DB "$REGEX_EXTENSION select * from sometable where name REGEXP '^[a-z]+$'"
But how can I update a string with an sqlite query using regex?
Sqlite by default does not provide regex_replace function. You need to load it as an extension. Here is how i managed to do it.
Download this C code for the extension (icu_replace)
Compile it using
gcc --shared -fPIC -I sqlite-autoconf-3071100 icu_replace.c -o icu_replace.so
And in sqlite3 runn following command post above mentioned command has run and create a file icu_replace.so
SELECT load_extension(' path to icu_replace.so', 'sqlite3_extension_init') from dual;
After this you will be able to use such a function as :-
select regex_replace('\bThe\b',x,'M') from dual;
The following builds latest sqlite with dynamic library support, and compiles ICU extension and regex_replace extension. It also assumes debian-based linux distributive:
sudo apt build-dep sqlite3 # fetches dependencies to compile sqlite3
mkdir sqlite-compilation
cd sqlite-compilation
wget -O sqlite.tar.gz https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release
tar xzf sqlite.tar.gz
mkdir build
cd build
../sqlite/configure
make OPTS='-DSQLITE_ENABLE_LOAD_EXTENSION'
./sqlite3 -cmd 'pragma compile_options;' <<< .exit
cd -
# https://sqlite.org/src/dir?name=ext/icu
cd sqlite/ext/icu
sed -i 's/int sqlite3_icu_init(/int sqlite3_extension_init(/' icu.c
sed -i 's/int sqlite3IcuInit(/int sqlite3_extension_init(/' sqliteicu.h
gcc -g -O2 -shared icu.c -fPIC -I ../../../build `pkg-config --libs icu-i18n` -o libSqlite3Icu.so
cp libSqlite3Icu.so ../../../build/
cd -
# https://github.com/gwenn/sqlite-regex-replace-ext
cd sqlite/ext
wget -O sqlite-regex-replace-ext-master.zip https://github.com/gwenn/sqlite-regex-replace-ext/archive/master.zip
unzip sqlite-regex-replace-ext-master.zip
cd sqlite-regex-replace-ext-master
gcc -g -O2 -shared icu_replace.c -fPIC -I ../../../build -o libSqlite3IcuReplace.so
cp libSqlite3IcuReplace.so ../../../build/
cd -
cd ../../
In result you will have:
build/sqlite3 # sqlite3 binary
build/libSqlite3Icu.so # unicode support
build/libSqlite3IcuReplace # regex_replace function
Test:
cd build
sqlite3 <<< "
.load ./libSqlite3Icu
.load ./libSqlite3IcuReplace
select regex_replace('^a', 'aab', 'b');
.exit
" # should output: bab
cd -
For me the above answers didn't work because of some missing parameters in the gcc command.
This works for me:
git clone https://github.com/gwenn/sqlite-regex-replace-ext.git
cd sqlite-regex-replace-ext-master/
./icu_replace.sh
Now you should be able to load the extension using: SELECT LOAD_EXTENSION('path-to-icu_replace.so');

devil not loading images with linux build

I was having issues getting an image to load in to Devil so I have provided exactly how I built the libs and how I am trying to use it.
Downloaded Devel source from their website.
$ unzip DevIL-1.7.8.zip
$ mkdir devil
$ cd Devil-1.7.8
+-------------------------------------------+
| Just type: |
| autoreconf -i |
| ./configure <your options here> |
| make |
| sudo make install |
+-------------------------------------------+
If I use autoreconf -i then ./configure with prefix and ilu and ilut. I get an error ..forgot.. to record it. How important is this? I have just not used it.
$ chmod +x configure
$ ./configure --prefix=/home/path/to/TestingDevil/devil --enable-ILU --enable-ILUT
$ make
$ make install
So at this point my library should be built.
I downloaded the devil simple example (simple.c) to TestingDevil/simple/simple.c
built it.
$ gcc -I ../devil/include -L ../devil/lib/ simple.c -o simple -lIL -lILU -lILUT
$ cp ../devil/lib/*.so* .
I have added an image (jpg) to test.
$ LD_LIBRARY_PATH=. ./simple image.jpg
"Could not open file...exiting"
I ran the executable from the simple directory.
simple$ ls
image.jpg libIL.so.1.1.0 libILU.so.1.1.0 libILUT.so.1.1.0 libIL.so
libILU.so libILUT.so simple libIL.so.1 libILU.so.1
libILUT.so.1 simple.c
Whats going wrong? I am using the example from devIL, it compiles and runs fine. Just can't load any files.
My System is Ubuntu 12.10 64 with build-essential installed and other dev packages for opengl dev.
Uni System is Fedora 15(?) 32. This also has exactly the same problem after building devIL in the same way.
On my home machine I installed the package libdevel-dev and that works fine.
This question does not ask about opengl, purely the devIL lib and example.
It looks like you build it withjout jpg support or you do not have jpeg libs available ?