简体   繁体   中英

How would I go about creating a static library in Vlang?

I'm relatively new to Vlang, and am trying to create a static library to try and test it out. I assume it just involves compiling to C without and then creating the static library from those C files, and calling from there, but any help would be appreciated. Thank you.

TL;DR: The dumb and dirty way. But I encourage reading the explanation further:

v -shared -o mylibrary.c mylibrary.v
gcc -c mylibrary.c -o mylibrary.o
ar rcs mylibrary.a mylibrary.o
gcc -o main main.c mylibrary.a
./main

There's no official way (or at least not in weekly.2021.42.1 ), but there is a way unofficially as mentioned by @AlexanderBielby. Here it is:

Note: For simple stuff the initialization of V internals shouldn't matter that much, however , for anything at least slightly more complex pretty much all the hell can break loose, so for just playing feel free to experiment, but if it's meant for production, I'd rather not touch it with a 2m pole until there's an official way or the creator is okay with this approach.

Note2: As it's using -shared switch and it's generally used for shared objects (dynamic libs), it should be okay. But such a "should" is rather dangerous in the C/C++ world. :)

With that out of the way, I'm assuming a very simple mylibrary.v file. The current way is possible with module main or with module <anything> + -shared switch for V. I'm using the latter.

There will be one private, fn function and one public pub fn function:

module notmain

fn say_hi() {
    println("Hi!")
}

pub fn say_hello() {
    println("Hello!")
}

Now for building let's start with the simple transpilation to C:

v -shared -o mylibrary.c mylibrary.v

This file would be generally used to create a mylibrary.so file and contains references for our functions.

Now let's assemble a header. The C emitted by V has a prefix of the module name, which will serve as a very good pattern for grep . If you use constants, mutable vars, etc you'll need to check more how exactly that affects the final binary. I'll assume you don't want to use global variables from your library to make things simpler (though "should" work nevertheless if the emitted C is okay).

grep notmain mylibrary.c

I got something like this:

VV_LOCAL_SYMBOL void notmain__say_hi();
void notmain__say_hello();
VV_LOCAL_SYMBOL void notmain__say_hi(void) {
void notmain__say_hello(void) {
    // Initializations for module notmain :

which means the emitted C distinguishes between pub fn and fn . I'll assemble a header only from the public functions:

cat <<EOF > mylibrary.h
#pragma once
#ifndef MYLIBRARY_H
#define MYLIBRARY_H
EOF

for func in $(grep "pub fn" $1|cut -f 3 -d " "|sed -e "s/()//")
do
    grep notmain__${func} mylibrary.c|grep ';' >> mylibrary.h
done

echo '#endif' >> mylibrary.h

Then just compile it and create a static library with ar :

gcc -c mylibrary.c -o mylibrary.o
ar rcs mylibrary.a mylibrary.o

And run it via a sample main.c file:

#include "mylibrary.h"
int main(void) {
    notmain__say_hi();
    notmain__say_hello();
    return 0;
}

You can compile it in two (or more) ways:

gcc -o main main.c mylibrary.a
gcc -o main main.c -L. -l:mylibrary.a

If you name the library lib<something>.a , then you can use -l<something> flag instead. The : is specifying a filename.

GCC will obviously tell about the implicit declaration as the declaration isn't present in the header nor anywhere else and you'll still see it working at the runtime ( here's why ).

And let's make it a bit more usable (clean with rm *.a *.c *.h *.o main_* ):

build.sh :

#!/bin/sh -ex
# use CC, AR and V env vars to set custom paths
if [ -z "$1" ]
then
    echo 'V=<path to V binary> ./build.sh <name>.v'
    exit 1
fi

NAME=$(echo $1|sed -e 's/\.v//')
MOD=$(grep 'module ' $1|cut -f 2 -d' ')
FUNCS=$(grep "pub fn" $1|cut -f 3 -d " "|sed -e "s/()//")
GUARD=$(echo ${NAME}_H|tr '[:lower:]' '[:upper:]')
V=${V:-./v}
CC=${CC:-gcc}
AR=${AR:-ar}

transpile() {
    ${V} -shared -o ${NAME}.c ${NAME}.v
}

headerify() {
    cat <<EOF > ${NAME}.h
#pragma once
#ifndef ${GUARD}
#define ${GUARD}
EOF

    for func in ${FUNCS}
    do
        grep ${MOD}__${func} ${NAME}.c|grep ';' >> ${NAME}.h
    done

    echo '#endif' >> ${NAME}.h
}

static_compile() {
    ${CC} -c ${NAME}.c -o ${NAME}.o
}

archive() {
    ${AR} rcs ${NAME}.a ${NAME}.o
}

create_main() {
    cat <<EOF > main.c
#include "${NAME}.h"
int main(void) {${MOD}__say_hi();${MOD}__say_hello();return 0;}
EOF
}

compile_direct() {
    ${CC} -o main_direct main.c ${NAME}.a
}

compile_link() {
    ${CC} -o main_link main.c -L. -l:mylibrary.a
}

run() {
    ./main_direct
    ./main_link
}

transpile
headerify
static_compile
archive
create_main
compile_direct
compile_link
run

and the log:

# ./build.sh mylibrary.v
+ [ -z mylibrary.v ]
+ echo mylibrary.v
+ sed -e s/\.v//
+ NAME=mylibrary
+ grep module  mylibrary.v
+ cut -f 2 -d 
+ MOD=notmain
+ grep pub fn+ cut -f 3 -d  
 mylibrary.v
+ sed -e s/()//
+ FUNCS=say_hello
+ tr+  [:lower:] [:upper:]
echo mylibrary_H
+ GUARD=MYLIBRARY_H
+ V=./v
+ CC=gcc
+ AR=ar
+ transpile
+ ./v -shared -o mylibrary.c mylibrary.v
+ headerify
+ cat
+ + grep notmain__say_hello mylibrary.c
grep ;
+ echo #endif
+ static_compile
+ gcc -c mylibrary.c -o mylibrary.o
+ archive
+ ar rcs mylibrary.a mylibrary.o
+ create_main
+ cat
+ compile_direct
+ gcc -o main_direct main.c mylibrary.a
main.c: In function ‘main’:
main.c:2:17: warning: implicit declaration of function ‘notmain__say_hi’; did you mean ‘notmain__say_hello’? [-Wimplicit-function-declaration]
    2 | int main(void) {notmain__say_hi();notmain__say_hello();return 0;}
      |                 ^~~~~~~~~~~~~~~
      |                 notmain__say_hello
+ compile_link
+ gcc -o main_link main.c -L. -l:mylibrary.a
main.c: In function ‘main’:
main.c:2:17: warning: implicit declaration of function ‘notmain__say_hi’; did you mean ‘notmain__say_hello’? [-Wimplicit-function-declaration]
    2 | int main(void) {notmain__say_hi();notmain__say_hello();return 0;}
      |                 ^~~~~~~~~~~~~~~
      |                 notmain__say_hello
+ run
+ ./main_direct
Hi!
Hello!
+ ./main_link
Hi!
Hello!

Have fun! ^^

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM