Building libcurl on Windows and using it from Kotlin/Native
Once upon a time, I decided to answer a question on
StackOverflow
to explain how to use libcurl
with Kotlin/Native. Now it turned out I will cover a
more detailed instruction here. How @shanselman once told in his talk - if
a reply is big enough it should go to a documentation of a blog post.
Building Curl and Libcurl on Windows
The first step is to open the https://curl.haxx.se/libcurl/ page and read it. Let’s download sources from https://curl.haxx.se/download.html. In my case, I downloaded the curl-7.61.1.zip. There is also a sources mirror on GitHub: https://github.com/curl/curl.
Of course, we need a Windows machine or a VM to build it and use it from Windows.
Let’s extract the downloaded sources. There will be the curl-7.61.1
folder.
Let’s assume the extracted curl
sources directory
is the current working directory.
I open the VS2015 x64 Native Command Prompt
shell on my machine. That one comes from
Microsoft Visual Studio 2015. There might be another shortcut to run the shell
from a newer or older version of Visual Studio.
It is a useful file under winbuild/BUILD.WINDOWS.txt
Execute the command
cd winbuild
nmake /f Makefile.vc mode=dll
The command above build curl
and libcurl
for us. The build generates static library
that uses some default dependencies from the system to run. For example, it uses
Windows SSPI
as the implementation of the SSL and TLS. Check out more options on curl
building in the
winbuild/BUILD.WINDOWS.txt.
The compiled binaries are found under the builds
folder. The contest should be as follows:
dir builds
...
10/29/2018 09:48 PM <DIR> .
10/29/2018 09:48 PM <DIR> ..
10/29/2018 09:48 PM <DIR> libcurl-vc-x64-release-dll-ipv6-sspi-winssl
10/29/2018 09:48 PM <DIR> libcurl-vc-x64-release-dll-ipv6-sspi-winssl-obj-curl
10/29/2018 09:48 PM <DIR> libcurl-vc-x64-release-dll-ipv6-sspi-winssl-obj-lib
...
We have our dynamic curl
library and include files directory under
the builds/libcurl-vc-x64-release-dll-ipv6-sspi-winssl
folder.
Importing libcurl into Kotlin/Native
Let’s use the curl sample and the libcurl sample from the Kotlin/Native repository and adapt them to work on Windows too.
The first step is to create the .def
file to import the native libcurl
library into Kotlin.
More details on that are explained in the
Interop with C Libraries
tutorial.
Let’s add the following libcurl.def
file:
headers = curl/curl.h
headerFilter = curl/*
Now we may call the cinteop
tool from Kotlin/Native from a parent folder, where we extracted curl
sources:
cinterop -def libcurl.def -compilerOpts -Icurl-7.61.1\builds\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\include -o libcurl
We assume here that we have Kotlin/Native compiler installed and registered in the system PATH. For more information,
please refer to the
A Basic Kotlin Application.
Let’s assume, we have a console, where the kotlinc-native
, cinterop
, and klib
commands are available.
The call to cinterop
generates the libcurl.klib
file for us. Let’s use it from the Kotlin/Native sources!
Using libcurl from Kotlin/Native
It is time to follow the example from the curl sample
and create our first curl
application in Windows.
Let’s create the file curl.kt
with the following contents:
Now we call the command to build the executable with Kotlin/Native:
kotlinc-native curl.kt -l libcurl -linker-options "curl-7.61.1\builds\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\lib\libcurl.lib" -o kurl
The application kurl.exe
is ready to go. The only thing it requires is the libcurl.dll
. The file you may find under the
curl-7.61.1\builds\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\bin\libcurl.dll
path. You may try running it.
Static Linking
It is not too nice to have a requirement to have the libcurl.dll
included and located near the executable we
create. Static linking, in theory, allows having only one solid binary, that contains everything.
One may easily change the curl
build to mode=static
. The result will be the static library libcurl_a.lib
.
Linking it with Kotlin/Native binary turned out to be tricky. To start, Kotlin/Native uses MinGW environment and
the libcurl_a.lib
is compiled to use dynamic MSVCRT. Theoretically, it should be possible to make it work, if you
know the answer - just let me know!
It is also a good comment for the original StackOverflow thread to use MinGW specific build of curl.
comments powered by Disqus