DkSDK CMake Tutorial¶
What you need to know¶
To complete this tutorial, you should:
Be able to use
git
to clone a projectBe familiar enough with one of the following C IDEs to open, configure and build a C project:
Visual Studio Code
CLion
Visual Studio
Xcode
Have access to at least one computer from the following list:
Windows 64-bit
macOS
Linux x86_64
Step One - Accessing DkSDK¶
Follow the steps laid out in the DkSDK Subscriber Access Guide
.
Step Two - Creating a Project¶
For your new project, decide on
- NAME
A project name like
AcmeWidgets
, whereAcme
is a short abbreviation for your company, brand or team andWidgets
describes your project.The project naming rules are as follows:
The project name must be at least 3 characters long
must only have alphanumeric characters
must have its first character be an uppercase letter
must have its second character be a lowercase letter
must contain, after the second character, another sequence of an upper case letter followed by a lowercase letter
- DIR
Where you would like to place your new project directory
Then:
Make a
git clone
of DkHelloWorld.Open PowerShell on Windows, Terminal on macOS, or a shell on Linux. Then change directory to where you cloned
DkHelloWorld
:cd .../DkHelloWorld
In the same PowerShell/Terminal/shell, run the following with your chosen NAME and DIR:
./dk dksdk.project.new NAME AcmeWidgets DIR ../acme-widgets
Open your new project in your C IDE.
You can build and run the
main-cli
target in thesrc/MainCLI
directory to start an echo server. You won't get any output unless you add the-v
option tomain-cli
.There is a
README.md
in your new project with other instructions. For now though, just continue with Step Three - Embedding OCaml in C below.
Step Three - Embedding OCaml in C¶
You won't need to read these references now, but the two references below explain in detail how to embed OCaml into your C code:
What follows is the simple example from Real World OCaml - The Compiler Backend:
Create a directory
src/EmbedOut
in your project tree.Create the file
src/EmbedOut/embed_out.c
. The highlighted line is the interesting line: it will call the OCaml code we'll write in the next step. Here is the C code:
/* filename: src/EmbedOut/embed_out.c *//************************************************************************* * * * Copyright 2023 Diskuv, Inc. * * * * Licensed under the DkSDK SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT * * <https://diskuv.com/legal/> or under the * * Open Software License version 3.0 * * <https://opensource.org/license/osl-3-0-php/>, at your option. * * This file may not be copied, modified, or distributed except * * according to those terms. * * * *************************************************************************/ #include <stdio.h> #include <caml/alloc.h> #include <caml/mlvalues.h> #include <caml/memory.h> #include <caml/callback.h>
#ifdef _WIN32 # define portable_main wmain # define portable_char wchar_t #else # define portable_main main # define portable_char char #endif
int (portable_main)(int argc, portable_char **argv) { printf("Before calling OCaml\n"); fflush(stdout); caml_startup (argv); caml_shutdown (); printf("After calling OCaml\n"); return 0; }
Note
Windows
wmain
functionIf you are familiar with Unix C programming, the
wmain
function andwchar_t
typedef may be unusual to you. In Windows thew
prefix means wide-characters, which is a fancy way of saying Unicode support.
Create the files
src/EmbedOut/embed_ml.ml
:(* filename: src/EmbedOut/embed_ml.ml *) let () = print_endline "hello embedded world 1"; Embed_me2.run ()
and
src/EmbedOut/embed_me2.ml
:(* filename: src/EmbedOut/embed_me2.ml *) let run () = print_endline "hello embedded world 2"
Note
Differences from Real World OCaml
With DkSDK you provide one entry point to a library, and from that entry point do all the calls to other modules you need. That entry point (
embed_ml.ml
in our case) must have the same name as the library which we'll define in the next step.Create
src/EmbedOut/CMakeLists.txt
:# src/EmbedOut/CMakeLists.txt
DkSDKProject_AddPackage(AUTO_OPAM_PACKAGE)
add_library(embed_ml STATIC embed_ml.ml embed_me2.ml)
add_executable(embed-out embed_out.c) target_link_libraries(embed-out PRIVATE DkSDK::OCaml::Compile DkSDK::OCaml::ForStaticBinary embed_ml)
Add the highlighted line to bottom of
src/CMakeLists.txt
:# src/CMakeLists.txt
add_subdirectory(HelloLib) add_subdirectory(MainCLI) add_subdirectory(EmbedOut)
Then configure the project. You can now build and run the embed-out
target. You should see:
Before calling OCaml
hello embedded world 1
hello embedded world 2
After calling OCaml
Step Four - What's Next?¶
You have just:
Created a new project
Created a new target that embeds C and OCaml code
There is a README.md
inside your new project that you should skim.
Enjoy!!