CoolProp / CoolProp

Thermophysical properties for the masses
http://coolprop.org/
MIT License
780 stars 307 forks source link

[Feature Request] golang support #1871

Open mantielero opened 4 years ago

mantielero commented 4 years ago

Golang is becoming an interesting alternative to python due to how easy it is to deploy and because it is generally faster.

It would be brilliant being able to do just:

go get  github.com/CoolProp/CoolProp/wrapper/golang/...

(or something similar) in order to get CoolProp module installed.

I am not familiar with neither C++ nor Swig in order to just do it myself.

It looks like somebody has already tried here.

ibell commented 4 years ago

To bad that person didn't email the making list, as we recommend. I think I tried to help another person with this before as well.

You would need to add a new block to the CMakeLists.txt file, then build. That's how all the other swig-based wrappers work. But I'm sure there is an interop option with Python in go as well

On Wed, Nov 27, 2019, 2:01 AM mantielero notifications@github.com wrote:

Golang is becoming an interesting alternative to python due to how easy it is to deploy and because it is generally faster.

It would be brilliant being able to do just:

go get github.com/CoolProp/CoolProp/wrapper/golang/...

(or something similar) in order to get CoolProp module installed.

I am not familiar with neither C++ nor Swig in order to just do it myself.

It looks like somebody has already tried here https://stackoverflow.com/questions/54831998/swig-coolprop-wrapping-for-golang .

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/CoolProp/CoolProp/issues/1871?email_source=notifications&email_token=AAOGC23W2Q6AXAXHALPRYLDQVYLMZA5CNFSM4JSCLD52YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4H4KJMSA, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOGC2YZNVND4IQFQ4TUISDQVYLMZANCNFSM4JSCLD5Q .

mantielero commented 4 years ago

I have tried something very naive (I am not a pro-developer) without success. I have downloaded the CoolProp repository and then:

$ cd wrappers
$ mkdir Golang
$ cd Golang
$ swig -c++ -go -cgo -intgosize 64 -I../../include/ -I../../src -outdir ./ ../../src/CoolProp.i
../../include/Configuration.h:199: Warning 312: Nested union not currently supported (ignored).
../../include/Configuration.h:91: Warning 503: Can't wrap 'operator bool' unless renamed to a valid identifier.
../../include/Configuration.h:93: Warning 503: Can't wrap 'operator double' unless renamed to a valid identifier.
../../include/Configuration.h:95: Warning 503: Can't wrap 'operator std::string' unless renamed to a valid identifier.
../../include/Configuration.h:97: Warning 503: Can't wrap 'operator int' unless renamed to a valid identifier.

Afterwards I did:

$ go build

getting lots of error messages.

ibell commented 4 years ago

Can you post the lots of errors?

mantielero commented 4 years ago

I did:

$ go build 2> salida.txt

salida.txt

ibell commented 4 years ago

What does go build actually do? I still maintain that you will probably need to add a block to the CMakeLists.txt and use cmake. At the very least, you will need to compile all the sources of CoolProp and the interface into one compilation unit.

On Thu, Nov 28, 2019, 1:27 PM mantielero notifications@github.com wrote:

I did:

$ go build 2> salida.txt

salida.txt https://github.com/CoolProp/CoolProp/files/3902783/salida.txt

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/CoolProp/CoolProp/issues/1871?email_source=notifications&email_token=AAOGC24KRJMH6SZF4RINL23QWAEQPA5CNFSM4JSCLD52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFNICFY#issuecomment-559579415, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOGC24GQZ5VQP6W5IJQ3D3QWAEQPANCNFSM4JSCLD5Q .

mantielero commented 4 years ago

I don't know how to do that. I just tried to create the bindings in accordance with swig documentation. But I used go build instead of go install as a previous step.

ibell commented 4 years ago

The go build seems to be missing all the includes. Is there a spec file somewhere for go where you can specify these things?

GautierR commented 4 years ago

Hello Ian and mantielero !

Indeed I tried that time to generate this wrapper for Golang without success. However, I'm still very interested in it. If I have some time could try to go back to this next week.

I've forked the CoolProp repository at that time and tried to modify the CMakeList as Ian proposed : https://github.com/GautierR/CoolProp/blob/golang_module/CMakeLists.txt

I think you could try to continue this. Here is the mentioned conversation with Ian on the CoolProps mailing list (yes I try to follow the recommendation :) ) However, I know that you are very busy Ian and I understand you did not reply / has any idea of where to go afterward.

https://groups.google.com/forum/#!searchin/coolprop-users/golang%7Csort:date/coolprop-users/KYBAKpw63EA/BERny-gPBAAJ

ibell commented 4 years ago

Could you please post here the output of your efforts with cmake?

GautierR commented 4 years ago

Using my modified CMakeList.txt with the GOLANG_MODULE.

Doing something similar to the Java or C# wrapper, I've first built the makefile using

cmake .. -G "MinGW Makefiles" -DCOOLPROP_GOLANG_MODULE=ON -DCMAKE_SH="CMAKE_SH-NOTFOUND"

Then I've tried to generate CoolPropGO_wrap.cxx and CoolProp.go using

cmake --build .

First at swig compile of CoolProp.i for Go I have 4 warnings :

C:\Workspace\src\CoolProp\include\Configuration.h(195) : Warning 312: Nested union not currently supported (ignored).
C:\Workspace\src\CoolProp\include\Configuration.h(89) : Warning 503: Can't wrap 'operator bool' unless renamed to a valid identifier.
C:\Workspace\src\CoolProp\include\Configuration.h(91) : Warning 503: Can't wrap 'operator double' unless renamed to a valid identifier.
C:\Workspace\src\CoolProp\include\Configuration.h(93) : Warning 503: Can't wrap 'operator std::string' unless renamed to a valid identifier.

Then it built the CoolPropGO_wrap.cxx, all the library objects and the dependencies (Backends) without any problem. (expect some warnings for the Solvers.cpp)

And at the end during the linking process I have 2 errors :

[100%] Linking CXX shared module CoolProp.dll
CMakeFiles\CoolProp.dir/objects.a(CoolPropGO_wrap.cxx.obj):CoolPropGO_wrap.cxx:(.text+0x4f): undefined reference to `crosscall2'
CMakeFiles\CoolProp.dir/objects.a(CoolPropGO_wrap.cxx.obj):CoolPropGO_wrap.cxx:(.rdata$.refptr._cgo_panic[.refptr._cgo_panic]+0x0): undefined reference to `_cgo_panic'
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [CMakeFiles\CoolProp.dir\build.make:758: CoolProp.dll] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:105: CMakeFiles/CoolProp.dir/all] Error 2
mingw32-make: *** [Makefile:83: all] Error 2

If this works my idea was then to use the Go compiler to try to build the CoolProp.go file.

ibell commented 4 years ago

The warnings are just that: warnings. Sounds like you are missing a go include or library that you need to link.

GautierR commented 4 years ago

I just tried to redo all the previous steps on a linux machine (Fedora 31). Now, I don't have any error in the linking process.

The CoolPropGO_wrap.cxx and the corresponding CoolProp.go looks fine. However, when I try to build the go file it seems that the reference to CoolPropGO_wrap.cxx is missing.

For every external function I have the following kind of error :

/usr/bin/ld: $WORK/b001/_x002.o: in function `_cgo_56d5590d45f5_Cfunc__wrap_set_reference_stateS_CoolProp_ef03193b832d75f0':
/tmp/go-build/cgo-gcc-prolog:10766: undefined reference to `_wrap_set_reference_stateS_CoolProp_ef03193b832d75f0'

I think includes are missing inside the CoolProp.go file. But I thought SWIG would have added them automatically (since both files are automatically generated).

ibell commented 4 years ago

Can you please push your changes to your fork and put here all the commands you ran and the output you received? It is otherwise quite hard to imagine what you have done.

On Mon, Feb 3, 2020 at 9:36 AM Gautier Rouaze notifications@github.com wrote:

I just tried to redo all the previous steps on a linux machine (Fedora 31). Now, I don't have any error in the linking process.

The CoolPropGO_wrap.cxx and the corresponding CoolProp.go looks fine. However, when I try to build the go file it seems that the reference to CoolPropGO_wrap.cxx is missing.

For every external function I have the following kind of error :

/usr/bin/ld: $WORK/b001/_x002.o: in function _cgo_56d5590d45f5_Cfunc__wrap_set_reference_stateS_CoolProp_ef03193b832d75f0': /tmp/go-build/cgo-gcc-prolog:10766: undefined reference to_wrap_set_reference_stateS_CoolProp_ef03193b832d75f0'

I think includes are missing inside the CoolProp.go file. But I thought SWIG would have added them automatically (since both files are automatically generated).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/CoolProp/CoolProp/issues/1871?email_source=notifications&email_token=AAOGC27II4NBW7HKSVASPN3RBA2ZLA5CNFSM4JSCLD52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKUJDDI#issuecomment-581472653, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOGC24725A53SIKJ3XOFDLRBA2ZLANCNFSM4JSCLD5Q .

GautierR commented 4 years ago

All the changes are up to date on the branch "golang_module". The only modification is on the CMakeList file: https://github.com/GautierR/CoolProp/tree/golang_module

The commands I have used so far are the following inside a new created build directory.

cmake .. -DCOOLPROP_GOLANG_MODULE=ON

Then,

cmake --build .

On Windows, I've got an error at the linking process, and the library is not built completely (cf. 2 comments before). While on Linux the process reached the end without any error.

I have then on the build directory a CoolProp.go file and a CoolProp.so file. The SWIG generated CoolPropGo_wrap.cxx is placed under /build/CMakeFiles/CoolProp.dir/.

If I try to build the go file, I obtain the following :

[rouaze@jjcooling32 build]$ go build -x
WORK=/tmp/go-build376194332
mkdir -p $WORK/b001/
cd /home/rouaze/go/src/CoolProp/build
CGO_LDFLAGS='"-g" "-O2"' /usr/lib/golang/pkg/tool/linux_amd64/cgo -objdir $WORK/b001/ -importpath CoolProp/build -- -I $WORK/b001/ -g -O2 ./CoolProp.go
cd $WORK
gcc -fno-caret-diagnostics -c -x c - -o /dev/null || true
gcc -Qunused-arguments -c -x c - -o /dev/null || true
gcc -fdebug-prefix-map=a=b -c -x c - -o /dev/null || true
gcc -gno-record-gcc-switches -c -x c - -o /dev/null || true
cd $WORK/b001
TERM='dumb' gcc -I /home/rouaze/go/src/CoolProp/build -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x001.o -c _cgo_export.c
TERM='dumb' gcc -I /home/rouaze/go/src/CoolProp/build -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x002.o -c CoolProp.cgo2.c
TERM='dumb' gcc -I /home/rouaze/go/src/CoolProp/build -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_cgo_main.o -c _cgo_main.c
cd /home/rouaze/go/src/CoolProp/build
TERM='dumb' gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_cgo_.o $WORK/b001/_cgo_main.o $WORK/b001/_x001.o $WORK/b001/_x002.o -g -O2
#CoolProp/build
/usr/bin/ld: $WORK/b001/_x002.o: in function _cgo_56d5590d45f5_Cfunc__wrap_ALTERNATIVE_REFPROP_HMX_BNC_PATH_CoolProp_ef03193b832d75f0':
/tmp/go-build/cgo-gcc-prolog:51: undefined reference to _wrap_ALTERNATIVE_REFPROP_HMX_BNC_PATH_CoolProp_ef03193b832d75f0'

Followed by all the list of CoolProp functions with the same error "undefined reference to _wrap_XXX".

So, my understanding is that the link with the CoolPropGO_wrap.cxx is missing. By placing the file side by side (moving the CoolProp.go into the CoolProp.dir directory). The previous error does not happen anymore. But now, other references seem to be missing during the build of CoolPropGo_wrap.cxx :

[rouaze@jjcooling32 CoolProp.dir]$ go build -x
WORK=/tmp/go-build484969665
mkdir -p $WORK/b001/
cd /home/rouaze/go/src/CoolProp/build/CMakeFiles/CoolProp.dir
CGO_LDFLAGS='"-g" "-O2"' /usr/lib/golang/pkg/tool/linux_amd64/cgo -objdir $WORK/b001/ -importpath CoolProp/build/CMakeFiles/CoolProp.dir -- -I $WORK/b001/ -g -O2 ./CoolProp.go
cd $WORK
gcc -fno-caret-diagnostics -c -x c - -o /dev/null || true
gcc -Qunused-arguments -c -x c - -o /dev/null || true
gcc -fdebug-prefix-map=a=b -c -x c - -o /dev/null || true
gcc -gno-record-gcc-switches -c -x c - -o /dev/null || true
cd $WORK/b001
TERM='dumb' gcc -I /home/rouaze/go/src/CoolProp/build/CMakeFiles/CoolProp.dir -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x001.o -c _cgo_export.c
TERM='dumb' gcc -I /home/rouaze/go/src/CoolProp/build/CMakeFiles/CoolProp.dir -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x002.o -c CoolProp.cgo2.c
cd $WORK
g++ -fno-caret-diagnostics -c -x c - -o /dev/null || true
g++ -Qunused-arguments -c -x c - -o /dev/null || true
g++ -fdebug-prefix-map=a=b -c -x c - -o /dev/null || true
g++ -gno-record-gcc-switches -c -x c - -o /dev/null || true
cd /home/rouaze/go/src/CoolProp/build/CMakeFiles/CoolProp.dir
TERM='dumb' g++ -I . -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I $WORK/b001/ -g -O2 -o $WORK/b001/_x003.o -c CoolPropGO_wrap.cxx
#CoolProp/build/CMakeFiles/CoolProp.dir
CoolPropGO_wrap.cxx:318:10: fatal error: DataStructures.h: No such file or directory
  318 | #include "DataStructures.h"
      |          ^~~~~~~~~~~~~~~~~~
compilation terminated.

The feeling I have is that I am trying to do the job twice. The CoolPropGo_wrap.cxx has been already compiled inside the CMake building and I shouldn't have to compile it again. It should be just something about linking.

Now I'm going into two different directions.

The first one is to try to link the generated shared library inside the golang file. By following what this guy tried https://stackoverflow.com/questions/58049430/how-to-use-c-shared-library-in-go-code-with-the-help-of-swig, I manage to build the go file without errors. (even if I'm not sure this is the correct way to do).

So the change, I've made is to add the following line just before the import "C" line as comments (all the lines commented before are considered as C code).

#cgo LDFLAGS: -L. -l:CoolProp.so -ldl

Now I can run go install, and it's working. However, if I try to use the library inside a small go example.

package main

import "CoolProp/build"
import "fmt"

func main() {
        test := CoolProp.Props1SI("Tcrit", "water")
        fmt.Printf("Test : %v", test)
}

I can build it go build, but if I try to run the executable, I have the following error :

./coolprop-test: error while loading shared libraries: CoolProp.so: cannot open shared object file: No such file or directory

Since apparently it does not find the file, I tried to move the shared library .so to the executable location, but the error remain the same. I also tried to move the library inside the default Linux path, but I'm not used to this at all.

The second direction I’m going is to try to reduce the problem and start to add layers step by step.

I read again the last version of the documentation for SWIG and Go : http://www.swig.org/Doc4.0/Go.html#Go

In a few words, with the last version of Go, it should not be more complicated than :

% swig -go example.i
% go install

However, the SWIG example is only showing an example for C with all the file inside the same location: https://github.com/swig/swig/tree/master/Examples/go/simple

So I went back to Zacg's example: https://github.com/zacg/simplelib which is also quite simple but using C++.

This example need only the two following commands:

swig -go -cgo -c++ -intgosize 64 simplelib.i

go install

Then I can use this package in any other go program. It works and is a very simple example. The main difference with CoolProp is that all the files are not located in the same directory. Also, CoolProp is using external libraries.

So I tried to continue with this simple example and moving simpleclass.cxx and simplelib.i inside an src folder and simpleclass.h inside an include folder (something similar to CoolProp).

simplelib
  |-src
    |-simplelib.cpp
    |-simplelib.i
  |-include
    |-simplelib.h

By adding and include a flag to the swig command I managed to generate the simplelib_wrap.cxx and simplelib.go files :

swig -go -Iinclude -cgo -c++ -intgosize 64 ./src/simplelib.i

However, if I try to compile it:

$ go install ./src/
# simplelib/src
simpleclass.cpp:1:10: fatal error: simpleclass.h: No such file or directory
 #include "simpleclass.h"
          ^~~~~~~~~~~~~~~
compilation terminated.

Nothing inside the go help install is showing a way to include some files, so I'm stuck here now.

GautierR commented 4 years ago

I think I went one step forward. I just understood how to pass directives to the C++ compiler.

For now, I'm not using CMake, only because I don't know how to use the go compiler with it. But I will try to create a custom command afterward.

Using a new cloned CoolProp repository and located at the root :

`swig -go -cgo -c++ -Iinclude -intgosize 64 ./src/CoolProp.i

The CoolProp.go and CoolProp_wrap.cxx are generated in the /src folder.

Then I had to modify the CoolProp.go file and add the following line (just before import "C" to include the folder during the C++ compilation :

#cgo CXXFLAGS: -I${SRCDIR}/.. -I${SRCDIR}/../include -I${SRCDIR}/../externals/Eigen -I${SRCDIR}/../externals/msgpack-c/include -I${SRCDIR}/../externals/fmtlib/include -I${SRCDIR}/../externals/fmtlib -I${SRCDIR} -I${SRCDIR}/Backends/Helmholtz -I${SRCDIR}/Backends/Helmholtz/Fluids

${SRCDIR} corresponds to the location of the go package to be built. Here it's CoolProp/src/.

Now, if I run the compilation go build ./src , all the files start to be compiled one by one. It crashes while compiling and give me tones of errors of the type :

go-build184082078\b001\_x014.o:HumidAirProp.cpp:(.rdata$_ZTVN8CoolProp19HelmholtzEOSBackendE[_ZTVN8CoolProp19HelmholtzEOSBackendE]+0x470): undefined reference to CoolProp::HelmholtzEOSMixtureBackend::set_mass_fractions(std::vector<double, std::allocator<double> > const&)'

I think I'm still missing some files to include inside the CXXFLAGS. On top of this, it does not look like a good maintainable solution to write inside the go file.

EDIT:

By adding the CGO_CXXFLAGS environment variable to the compiler inside the CLI command we can add the desired flags for the CXX compiler without modifying the CoolProp.go file. The main drawback is that it needs an absolute path, the ${SRCDIR} is working only inside the file itself.

CGO_CXXFLAGS="-IC:/Workspace/src/CoolProp ... ..." go build ./src

Using this environment variable might be the solution for a custom CMake command with all the files to be included.

GautierR commented 4 years ago

Looking at all the prints during the compilation, it seems that the command go build -x only builds the files inside the current directory. Meaning that all the backends are not built during the process.

The error I got (the error shown in the last comment) comes from this.

According to this discussion (https://stackoverflow.com/questions/28881072/how-to-add-c-files-in-a-subdirectory-as-part-of-go-build-by-using-pseudo-cgo-dir), the best should be to build separately the backends and link them using the LDFLAGS. Or wrap all the backends and import them into the CoolProp package.

I went back to the first idea of using the generated shared library. I read all the CMakeList but I still not understand why a shared library is built and linked when I'm using the GOLANG_MODULE I've written. The only lines that I've added are about SWIG.

Using the following workflow I finally managed to use CoolProp with Go.

git clone -b golang_module git@github.com:GautierR/CoolProp.git --recursive

cd CoolProp

mkdir build && cd build

cmake .. -DCOOLPROP_GOLANG_MODULE=ON

cmake --build .

Move the CoolProp.go and CoolProp.so files inside a new go package (under /go/src/CoolProp).

mkdir $GOPATH/src/CoolProp scp CoolProp.go $GOPATH/src/CoolProp/CoolProp.go scp CoolProp.so $GOPATH/src/CoolProp/CoolProp.so

Move to this directory and update the cgo part of CoolProp.go file with the LDFLAGS (linking the shared library).

cd $GOPATH/src/CoolProp vim CoolProp.go

Add the following line just before the import "C" statement (inside all the commented part). #cgo LDFLAGS: -L${SRCDIR} -l:CoolProp.so -ldl

Try to build the package:

go install

Export the shared library to the LD_LIBRARY_PATH :

export LD_LIBRARY_PATH=$GOPATH/src/CoolProp

Then you can use the go package inside another program :

package main

import "CoolProp"
import "fmt"

func main() {
        waterTCrit := CoolProp.Props1SI("Tcrit", "water")
        fmt.Printf("Water TCrit : %v degC \n", waterTCrit - 273.16)
}

This is working only on Linux. But if I manage to build the shared library as a .dll I'm pretty sure this will work the same with Windows. But on my windows, even the shared library (without the swig part) failed during the linking. (cf. http://www.coolprop.org/coolprop/wrappers/SharedLibrary/index.html#windows)

ibell commented 4 years ago

Sorry I've not been more helpful on this thread. My guess is that your best bet goes like this:

One bad choice we made a long time ago was to have the swig modules generated be also called CoolProp.so, just like the "normal" shared library of CoolProp. That has caused no end of confusion.

For windows, which compiler suite are you using? The MINGW ecosystem has all kinds of pain points not present in other operating systems.

GautierR commented 4 years ago

There is for sure a way to directly link a shared/static library with Go. But then it becomes a nightmare to program anything since we need to define each variable or function types.

I still believe SWIG is the best way to go for this problem.

One bad choice we made a long time ago was to have the swig modules generated be also called CoolProp.so, just like the "normal" shared library of CoolProp. That has caused no end of confusion.

Could you please explain where inside the CMake part this module is generated and why it is generated ?

When I do : cmake --build .

The compiler starts by the CoolProp_swig_compilation and generates the CoolPropGo_wrap.cxx file. But then it starts to build all the other targets. I would like that the Go compiler does it instead.

ibell commented 4 years ago

Let's see if I can explain my idea a bit better: 1) Generate a "normal" static library of CoolProp with -DCOOLPROP_STATIC_LIBRARY=ON 2) Generate the CoolProp_wrap.cxx file with swig 3) Add the static library and swig-generated files into Go build.

I don't know if this proposal will work without modification, but I have tried similar approaches before when I have had to integrate with pre-existing build tools.

GautierR commented 4 years ago

Ok, I understand better what you are proposing.

I can build a static library without any error. The problem comes after I generate the CoolProp_wrap.cxx and CoolProp.go files using swig. If I try to build this with Go, the builder will detect the CoolProp_wrap.cxx the file inside the same folder and try to build it with g++. But this file has dependencies with all the other include and source files of the project. And I end up with the same problem as if I try to build all with the Go builder.

In the previous solution, I used the CMake build part to generate the CoolProp_wrap.cxx file AND compile all the other source files (including CoolProp_wrap.cxx). Adding the link to the CoolProp.so file inside the CoolProp.go file, and building it make it work. However, this is not so pretty as we have to modify by hand the CoolProp.go file and add the link to the LIBRARY_PATH.

ibell commented 4 years ago

When you build the CoolProp_wrap.cxx file, did you specify the include files that are needed, and the static library of CoolProp to link against? I think you missed either one or both of those dependencies? Can you show your output from the failure?

GautierR commented 4 years ago

Yes this was the problem. I though I had to add all the includes and dependencies again, like the ones in CMake. And this would be quite hard with the go build tool.

But simply using the following flags (including the include folder and the fmtlib) it worked :

#cgo CXXFLAGS: -I${SRCDIR}/../../include -I${SRCDIR}/../../externals/fmtlib
#cgo LDFLAGS: -L. -lCoolProp -ldl

I also managed to build the whole library with the go build tool (without using cmake). By moving all the sources and includes the file in a temporary folder where you have the CoolProp_wrap.cxx and the CoolProp.go. This might be automatized with a Makefile or a CMake module. And it has the advantages that we don't have to modify any files.

I don't know which solution is the most appropriate.

GautierR commented 4 years ago

I'm proposing the following workflow which seems to works quite well.

Golang users using GOPATH should have their working directory as the following:

go
  |-bin
  |-pkg
  |-src

First move to your src directory:

cd /go/src

Go get the CoolProp repository. The empty CoolProp.go file with the package name allow to get it via the go get command. The "GautierR" user will be changed by "CoolProp" after possible PR.

go get github.com/GautierR/CoolProp/wrappers/Go

Move to the Go wrappers directory:

cd github.com/GautierR/CoolProp/wrappers/Go

Build the static library:

cmake ../.. -DCOOLPROP_STATIC_LIBRARY=ON
cmake --build .

Generate the SWIG files:

swig -go -go -c++ -intgosize 64 -I../../include -outcurrentdir ../../src/CoolProp.i

Build the golang package (will be discarded after the build as this is only a package). The includes and link flags for cgo are passed via environment variables.

CGO_CXXFLAGS="-g -O2 -I../../include -I../../externals/fmtlib" CGO_LDFLAGS="-g -O2 -L$GOPATH/src/github.com/GautierR/CoolProp/wrappers/Go -lCoolProp -ldl" go build

Using the package inside another program:

package main

import "github.com/GautierR/CoolProp/wrappers/Go"
import "fmt"

func main() {
        waterTCrit := CoolProp.Props1SI("Tcrit", "water")
        fmt.Printf("Water TCrit : %v degC \n", waterTCrit - 273.16)
}

Before thinking about a PR, I think I need to find a proper way to integrate the static library build and the swig generation into a CMake module. Do you have any proposition for this? I don't think that copy-paste the "STATIC_LIBRARY" module and add the SWIG part will be a good solution. And I still have this problem of CoolProp.so file generated with SWIG and CMake.

Also, the workaround found with the environment variable, allowed us to not have to write the flags inside the CoolProp.go file. But this variable will have to be added for any use of the CoolProp package. Writing them inside the file (ie using sed command) will allow the users to use the package without the CGO environment variables.

ibell commented 4 years ago

I see what you mean about the need to sed. I found a couple of missing (but important) characters in the above commands. This worked for me to get everything working:

Starting in $HOME/go, on ubuntu, after installing go with "sudo apt-get install golang-go":

go get -d github.com/coolprop/coolprop cd github.com/coolprop/coolprop/wrappers git submodule update --init mkdir -s Go/lib cd Go/lib cmake ../.. -DCOOLPROP_STATIC_LIBRARY=ON cmake --build . cd .. swig -go -cgo -c++ -intgosize 64 -I../../include -outcurrentdir ../../src/CoolProp.i CGO_CXXFLAGS="-g -O2 -I../../include -I../../externals/fmtlib" CGO_LDFLAGS="-g -O2 ../lib/libCoolProp.a -ldl" go install

That successfully builds and installs CoolProp package. Where things start to get a bit murky is how to use the installed library.

It does indeed seem that it is necessary to indicate the header include paths at runtime, which is rather problematic in my opinion. A library should fully specify everything needed, like in Python for instance.

On Wed, Feb 26, 2020 at 5:39 AM Gautier Rouaze notifications@github.com wrote:

I'm proposing the following workflow which seems to works quite well.

Golang users using GOPATH should have their working directory as the following:

go |-bin |-pkg |-src

First move to your src directory:

cd /go/src

Go get the CoolProp repository. The empty CoolProp.go file with the package name allow to get it via the go get command. The "GautierR" user will be changed by "CoolProp" after possible PR.

go get github.com/GautierR/CoolProp/wrappers/Go

Move to the Go wrappers directory:

cd github.com/GautierR/CoolProp/wrappers/Go

Build the static library:

cmake ../.. -DCOOLPROP_STATIC_LIBRARY=ON cmake --build .

Generate the SWIG files:

swig -go -go -c++ -intgosize 64 -I../../include -outcurrentdir ../../src/CoolProp.i

Build the golang package (will be discarded after the build as this is only a package). The includes and link flags for cgo are passed via environment variables.

CGO_CXXFLAGS="-g -O2 -I../../include -I../../externals/fmtlib" CGO_LDFLAGS="-g -O2 -L$GOPATH/src/github.com/GautierR/CoolProp/wrappers/Go -lCoolProp -ldl" go build

Using the package inside another program:

package main

import "github.com/GautierR/CoolProp/wrappers/Go" import "fmt"

func main() { waterTCrit := CoolProp.Props1SI("Tcrit", "water") fmt.Printf("Water TCrit : %v degC \n", waterTCrit - 273.16) }

Before thinking about a PR, I think I need to find a proper way to integrate the static library build and the swig generation into a CMake module. Do you have any proposition for this? I don't think that copy-paste the "STATIC_LIBRARY" module and add the SWIG part will be a good solution. And I still have this problem of CoolProp.so file generated with SWIG and CMake.

Also, the workaround found with the environment variable, allowed us to not have to write the flags inside the CoolProp.go file. But this variable will have to be added for any use of the CoolProp package. Writing them inside the file (ie using sed command) will allow the users to use the package without the CGO environment variables.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/CoolProp/CoolProp/issues/1871?email_source=notifications&email_token=AAOGC25JKQU3Y7OF7YWFK3DREZBE7A5CNFSM4JSCLD52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEM7WYWQ#issuecomment-591359066, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOGC26VHNN7NUJRUH4XBGLREZBE7ANCNFSM4JSCLD5Q .

GautierR commented 4 years ago

Could you please detail a bit from which command you obtain any error ? I did again all the step with a new installation and all the commands of my last comment are working well.

Below is the sed command to make it works without any flags even at runtime:

sed -i 's@import "C"@//#cgo CXXFLAGS: -I${SRCDIR}/../../include -I${SRCDIR}/../../externals/fmtlib\n//#cgo LDFLAGS: -L. -lCoolProp -ldl\nimport "C"@g' CoolProp.go

go build
ibell commented 4 years ago

Sorry, I should have been more clear. Updates:

  1. Need the -d for go get to not also build
  2. Need -cgo -go instead of -go -go

Seems that Golang has still quite some way to go on the packaging front if you need to use sed to load the package :/