sciter-sdk / go-sciter

Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development
https://sciter.com
2.58k stars 268 forks source link

Linking Sciter statically #112

Open inkeliz opened 6 years ago

inkeliz commented 6 years ago

If I have an "INDIE" (or greater) license I'm allowed to "Linking Sciter statically". It's suported by go-sciter?

pravic commented 6 years ago

I think, you can specify CGO_CFLAGS=-DSTATIC_LIB , CGO_LDFLAGS=-lsciter-win-64 and recompile go-sciter package.

gcstang commented 6 years ago

Does this mean without a license of some sort you have to have the person you give your application to install sciter? Also the "INDIE" one only supports Windows?

pravic commented 6 years ago

It is better to ask such questions on forum: https://sciter.com/forums

gcstang commented 6 years ago

@pravic how do you or others package the library normally?

pravic commented 6 years ago

Just put a sciter dll/so/dylib near the executable. HTML/CSS/Tis files either in their own folder or linked into executable. Or just in zip archive.

gcstang commented 6 years ago

@pravic do you then have the user add it to the environment or load it somehow in a relative way from the program?

pravic commented 6 years ago

Yes, correct. Or just like this where dlls in the same directory as executables: https://github.com/c-smile/sciter-sdk/tree/master/bin.gtk

gcstang commented 6 years ago

@pravic I'm really new to the go language, would you have an example of how you're loading it from a relative path that you could share?

pravic commented 6 years ago

If you are talking about how to load libsciter using relative path, right now it is not possible, because it is hardcoded to be loaded either from current directory or from the system PATH:

https://github.com/sciter-sdk/go-sciter/blob/8b236559b9ac242721e96957c71469fd9d21c1a8/sciter-x-api.c#L22-L27

What are you trying to achieve? It would be easier to give a more suitable answer.

gcstang commented 6 years ago

@pravic ah I see the issue now, I'm on a Mac and that snippet isn't loading for MacOS only Windows and Linux. The lib for Mac is sciter-osx-64.dylib

pravic commented 6 years ago

For OSX it loads from the following paths:

https://github.com/sciter-sdk/go-sciter/blob/8b236559b9ac242721e96957c71469fd9d21c1a8/sciter-x-api.c#L75-L80

where "/" is relative to your executable.

gcstang commented 6 years ago

@pravic thank you, have it working now. I must have tried it before in a different location, my apologies and thank you for this project.

pravic commented 6 years ago

thank you for this project

It was not me. Andrew @c-smile is the only author of the Sciter engine. @oskca has created Go bindings.

I am just a maintainer of binding libraries :)

inkeliz commented 6 years ago

It doesn't work, not using the -DSTATIC_LIB, it returns:

sciter-x-api.c: In function 'SAPI':
sciter-x-api.c:15:20: error: expected expression before ':' token
           tiscript::ni( _api->TIScriptAPI() );

https://github.com/sciter-sdk/go-sciter/blob/master/sciter-x-api.c#L15

pravic commented 6 years ago

@Inkeliz True, it was C++ portion. I've pushed a fix.

inkeliz commented 6 years ago

Well, it fix the problem, but I think have another error. :'(

In my case it returns some warnings:

sciter-x-api.c: In function 'SAPI':
sciter-x-api.c:14:34: error: 'nullptr' undeclared (first use in this function)
        static ISciterAPI* _api = nullptr;
                                  ^~~~~~~
sciter-x-api.c:14:34: note: each undeclared identifier is reported only once for each function it appears in
sciter-x-api.c: At top level:
sciter-x-api.c:14:27: warning: '_api' is static but declared in inline function 'SAPI' which is not static
        static ISciterAPI* _api = nullptr;
                           ^~~~

The compilation didn't work at all.

pravic commented 6 years ago

@Inkeliz Yeah, sorry, I have missed it :)

inkeliz commented 6 years ago

Well, one error was remove, but seems one continue, with more explanation:

# github.com/sciter-sdk/go-sciter
C:\Users\Inkeliz\AppData\Local\Temp\go-build523114306\b126\_x007.o: In function `SAPI':
..\..\sciter-sdk\go-sciter/sciter-x-api.c:18: undefined reference to `SciterAPI'
..\..\sciter-sdk\go-sciter/sciter-x-api.c:18: undefined reference to `SciterAPI'
..\..\sciter-sdk\go-sciter/sciter-x-api.c:18: undefined reference to `SciterAPI'
..\..\sciter-sdk\go-sciter/sciter-x-api.c:18: undefined reference to `SciterAPI'
..\..\sciter-sdk\go-sciter/sciter-x-api.c:18: undefined reference to `SciterAPI'
C:\Users\Inkeliz\AppData\Local\Temp\go-build523114306\b126\_x007.o:E:\Documentos\GoProjects\src\github.com\sciter-sdk\go-sciter/sciter-x-api.c:18: more undefined references to `SciterAPI' follow
collect2.exe: error: ld returned 1 exit status
# github.com/sciter-sdk/go-sciter
sciter-x-api.c:14:27: warning: '_api' is static but declared in inline function 'SAPI' which is not static
        static ISciterAPI* _api = 0;
                           ^~~~

I don't know if I'm doing something wrong, I'm changing this line, also I change this, for testing. I test to append the -DSTATIC_LIB, or only with -DSTATIC_LIB and so on. But always gets some error. :'(

c-smile commented 6 years ago

STATIC_LIB define means that SciterAPI function is defined in sciter's static library that needs to be linked with your executable. You need a) access to sciter sources, b) build that static lib ({sciter-src-root}/lib/Release/sciter-win-64.lib) and c) include that lib into linkage list of your application.

pravic commented 6 years ago

include that lib into linkage list of your application

@Inkeliz That said, you need to set something like:

set CGO_CFLAGS=-DSTATIC_LIB
set CGO_LDFLAGS="-lsciter-win-64 -LC:/path/to/static/build"
go build -a

including requirements mentioned by Andrew, of course.

pravic commented 6 years ago

don't know if I'm doing something wrong, I'm changing this line, also I change this, for testing.

@Inkeliz if you want to test it, compile the following code into a static library and try to link it with go-sciter:

// test.c
void* __stdcall SciterAPI(void) { return 0; }
$ cl.exe /c test.c
$ lib.exe test.obj /out:sciter-win-64.lib

Then set the CGO flags above and try to recompile go-sciter/examples/simple. It should be compiled without errors and after run you should see something like:

File: sciter-x-api.c, Line 23 Expression: _api

as a result of the assert from the sciter-x-api.c: https://github.com/sciter-sdk/go-sciter/blob/57abd660ac262f4cda570bd6c7d390395946ae03/sciter-x-api.c#L23-L24

And if you remove CGO flags and recompile it again, you'll see a normal example window, as usual.

inkeliz commented 6 years ago

Finally, I could compile the Sciter and gets the lib.

But using the same command mentioned by @pravic it returns:

# runtime/cgo
gcc: error: "-lsciter-win-64: Invalid argument
c-smile commented 6 years ago

You are compiling static lib using Microsoft Visual C++. And trying to use in with gcc, right?

If "yes" then this may not work - at least I haven't heard about successfull attempts of doing so.

inkeliz commented 6 years ago

Yes. So, that is impossible? :\ Can I compile the lib with GCC, or something compatible?

c-smile commented 6 years ago

http://www.mingw.org/wiki/Interoperability_of_Libraries_Created_by_Different_Compiler_Brands

c-smile commented 6 years ago

Theoretically possible but practically - not.

c-smile commented 6 years ago

I am compiling sciter on Linux using GCC so source code is GCC compatible. But I haven't done this on Windows. Had no reason of doing so.

inkeliz commented 6 years ago

My knowledge about GCC, and Microsoft Visual C++, is close to zero. Do you think that is possible to compile using GCC on Windows? If I compile using linux, can I create the executable on Windows, with the same "lib"?

I really don't know anything about it, I just literaly wanted to "hide" de .dll. :\

c-smile commented 6 years ago

Do you think that is possible to compile using GCC on Windows?

I think so. It will take some time but feasible. To create make/CMakeFile using VS project as a prototype, it will be quite time consuming though. In principle there are tools that can convert VS projects to CMake files: https://cmake.org/Wiki/CMake#Visual_Studio With CMake files you may generate make files for GCC.

But even that....

There are two GCC toolchains on Windows: GCC/MinGW and GCC/Cygwin. They use incompatible runtimes... What version of GCC your host application is using?

inkeliz commented 6 years ago

I'm using the MinGW, which is mentioned on README. To be precise, I'm using "x86_64-w64-mingw32 6.3.0".

I'll take a look on that. But, I'm closer to give up about this idea, at least for now. I think have another alternative to, even if not the best solution, it will achieve the same goal. My goal is a way to "hide" the .dll only having the .exe.

inkeliz commented 6 years ago

There a possibility to load the .dll from other location than the System32 and the same folder as the executable?

This "solution" is far-far-far from optimal, but I will use it for now, until I have some time to understand the GCC and build it staticly.

The following code will create one sciter.go that inside have the sciter.dll, so when you open the software the sciter.dll can be created,, because exist inside the go. It's possible to apply some gzip to minify.

func main() {
    f, _ := os.Create("Path/To/sciter.go")

    dll, err := ioutil.ReadFile("sciter.dll")
    hex := Util.UnsafeHexEncode(dll)

    f.WriteString("// Code generated by go generate; DO NOT EDIT. \npackage Front \n\n var Sciter = []byte{")

    var sciter []byte
    for i := 0; i < len(hex); i += 2 {
        // 0xHH,
        sciter = append(sciter, 0x30, 0x78, byte(hex[i]), byte(hex[i+1]), 0x2C)
    }

    f.Write(sciter[:len(sciter)-1])
    f.WriteString("}")
}

So only do one go generate using it and you have the sciter.go with:

package Front 

 var Sciter = []byte{0x4D,0x5A,0x90,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,0x21,0xB8, //...

So, in the main.go simply have:

f, _ := os.Create("sciter.dll")
_, err := f.Write(Front.Sciter)
f.Close()

    w, err := window.New(...)

It will create the dll.


It works, but I think will be a little better if the sciter.dll is on /tmp/ or similar folder. Put it directly under System32 needs privileges.

c-smile commented 6 years ago

In C/C++ you can do it by loading sciter.dll from any place you like, calling SciterAPI() function from it and calling SAPI(ISciterAPI*). After that all API functions will use that interface.

pravic commented 6 years ago

gcc: error: "-lsciter-win-64: Invalid argument

Could you change sciter-win-64.lib to, say, sciter.lib and set it as -lsciter? Because it works for me with Mingw64 7.2.0 x64.

inkeliz commented 6 years ago

I need to sleep now, but I tried it right now, the problem is the same. I think I'm doing something wrong. The sciter-win-64.lib should be place in another location? The -LC need to point here the lib is?

I'm totally lost now. But, if I remove the " " in the command I get: cannot find -lsciter-win-64

If I send the command under " ... " I get: gcc: error: "-lsciter: Invalid argument

I don't know what is the correct one. I have updated my MinGW now, the error is the same. :(

inkeliz commented 6 years ago

Now I think it is "working", but not as expected,results in other error:

# github.com/sciter-sdk/go-sciter
C:\Users\Inkeliz\OneDrive\Documentos\Sciter2\lib\Release/sciter-win-64.lib: error adding symbols: File format not recognized
collect2.exe: error: ld returned 1 exit status
pravic commented 6 years ago

Then yes, you have to compile Sciter via GCC. So either stick with your workaround via saving DLL to some location or.. we need to figure out a way to compile via mingw.

It's not that hard I guess, just need to convert the VS project to CMake or CodeBlocks one.

inkeliz commented 6 years ago

Yes, I would like to compile it, but I don't know how to do, sincerely. :(

pravic commented 6 years ago

No, I doubt that GCC will be able to compile DirectX headers under Windows. So it looks like dll is only the option then.

But I'll check that to be sure.

inkeliz commented 6 years ago

For now I would keep the DLL, the "workaround way", at least for now.

However, I'm looking to modify the API to be capable to set one custom directory. Far I see, we have the SetDllDirectory, so if exist something like sciter.SetDLL("path/to/dll") that sets this function.... But, I don't think it's need, we can use the LoadLibrary alone, however need one way to set the value too.

But now, I'm worry about the security of the LoadLibrary, since it can load the dll from many places.

Anyway, I do some tests, manually change the value of sciter.dll, in LoadLibrary, this function can be also one path (c:/path/to/sciter.dll), the absolute path.

I don't know how dificult it should be, but if exist something like:

sciter.SetDLL(path string)

The value of this function should be used in:

HMODULE hm = LoadLibrary( TEXT( {here} ) );

So, if use sciter.SetDLL("c:/something/sciter.dll") it will be the same of LoadLibrary("c:/something/sciter.dll").

I don't know how the magic behind how the Golang talks with C. My idea is to create one global variable to hold the information about the path, them one function can set it from Go. If this variable is empty them use the defaults.


Also, in the documentation says:

If the string specifies a full path, the function searches only that path for the module.

In result set the absolute path seems to be more secure. 👍

inkeliz commented 6 years ago

I do the changes needed, I think. I'm testing it right now. I would send one PR, if you consider it usefull. It makes possible to set one custom location, the default still the sciter.dll, so it is totally compatible. The version for Linux/Mac remains unchanged.

pravic commented 6 years ago

Well, currently there is no way to mix an MSVC static lib with Go (which uses GCC as its toolchain). But there is a chance that it will be changed anytime soon: https://github.com/golang/go/issues/20982

l0hn commented 4 years ago

@pravic / @c-smile I've been following this for a while and It seems the work is complete over at golang/go#20982 for linking MSVC object files. However they're in need of help testing, I wonder if this might be something you'd be interested in as it would surely be a big plus point for sciter to have static compilation using Go.

pravic commented 4 years ago

Interesting. Is there any walk through about how to try the MSVC backend?

c-smile commented 4 years ago

By the way, there is a Sciter Quark as an option for creating self contained GUI applications.

Go code, if needed, can be contained in a dll placed in the same folder as GUI executable. That dll can provide functions to be called from UI/script of the application.

phuonghuynh commented 3 years ago

By the way, there is a Sciter Quark as an option for creating self contained GUI applications.

@c-smile Is there a way to use Quark as a CLI tool beside GUI mode? I would like to use it in CI runner.