cmake: Update internal docs
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
# CI: Makefile/Docker/Vagrant testing
|
||||
To test the build on various distro, I'm using docker containers and a Makefile for orchestration.
|
||||
|
||||
To test the build on various distro, I'm using docker containers and a Makefile
|
||||
for orchestration.
|
||||
|
||||
pros:
|
||||
* You are independent of third party CI runner config (e.g. github actions runners or Travis-CI VM images).
|
||||
* You can run it locally on your linux system.
|
||||
* Most CI provide runner with docker and Makefile already installed (e.g. tarvis-ci [minimal images](https://docs.travis-ci.com/user/languages/minimal-and-generic/).
|
||||
|
||||
* You are independent of third party CI runner config (e.g. github actions
|
||||
runners or Travis-CI VM images).
|
||||
* You can run it locally on your linux system.
|
||||
* Most CI provide runner with docker and Makefile already installed (e.g.
|
||||
tarvis-ci
|
||||
[minimal images](https://docs.travis-ci.com/user/languages/minimal-and-generic/).
|
||||
|
||||
cons:
|
||||
|
||||
* Only GNU/Linux distro supported.
|
||||
* Could take few GiB (~30 GiB for all distro and all languages)
|
||||
* ~500MiB OS + C++/CMake tools,
|
||||
@@ -14,72 +21,86 @@ cons:
|
||||
* ~400 MiB dotnet-sdk,
|
||||
* ~400 MiB java-jdk.
|
||||
|
||||
# Usage
|
||||
## Usage
|
||||
|
||||
To get the help simply type:
|
||||
|
||||
```sh
|
||||
make
|
||||
```
|
||||
|
||||
note: you can also use from top directory
|
||||
|
||||
```sh
|
||||
make --directory=cmake
|
||||
```
|
||||
|
||||
## Example
|
||||
### Example
|
||||
|
||||
For example to test `Python` inside an `Alpine` container:
|
||||
|
||||
```sh
|
||||
make alpine_python_test
|
||||
```
|
||||
|
||||
# Docker
|
||||
## Docker
|
||||
|
||||
[Docker](https://www.docker.com/resources/what-container) is a set of platform
|
||||
as a service products that use OS-level virtualization to deliver software in
|
||||
packages called containers.
|
||||
|
||||
You can find official base image on the Docker registry [Docker Hub](https://hub.docker.com/search?type=image)
|
||||
|
||||
## Layers
|
||||
Dockerfile is splitted in several stages.
|
||||
### Layers
|
||||
|
||||
Dockerfile is split in several stages.
|
||||

|
||||
|
||||
# Vagrant
|
||||
[Vagrant](https://www.vagrantup.com/intro) is a tool for building and managing virtual machine environments in a single workflow.
|
||||
It is currently used to test FreeBSD inside a VirtualBox since we don't have any
|
||||
FreeBSD machine.
|
||||
Vagrant call a base image a *box*.
|
||||
## Vagrant
|
||||
|
||||
[Vagrant](https://www.vagrantup.com/intro) is a tool for building and managing
|
||||
virtual machine environments in a single workflow. It is currently used to test
|
||||
FreeBSD inside a VirtualBox since we don't have any FreeBSD machine. \
|
||||
Vagrant call a base image a *box*. \
|
||||
Vagrant call a container a *vagrant machine*.
|
||||
|
||||
You can find official box on the Vagrant registry [Vagrant Cloud](https://app.vagrantup.com/boxes/search)
|
||||
|
||||
note: Currently only github MacOS runner provide virtualization support (i.e. [VirtualBox](https://www.virtualbox.org/)).
|
||||
|
||||
## Basic usage
|
||||
Once `vagrant` and `VirtualBox` are installed, all commands must be run where the `Vagrantfile` is
|
||||
located.
|
||||
### Basic usage
|
||||
|
||||
Once `vagrant` and `VirtualBox` are installed, all commands must be run where
|
||||
the `Vagrantfile` is located.
|
||||
|
||||
Generate a `Vagrantfile` skeleton, e.g. using the box `generic/freebsd12`:
|
||||
|
||||
```sh
|
||||
vagrant init generic/freebsd12
|
||||
```
|
||||
|
||||
Build and run a new *vagrant machine*:
|
||||
|
||||
```sh
|
||||
vagrant up
|
||||
```
|
||||
note: If you run `virtualbox` you should see it.
|
||||
|
||||
Connect to a *vagrant machine*:
|
||||
|
||||
```sh
|
||||
vagrant ssh
|
||||
[vagrant@freebsd12 ~]$ ...
|
||||
```
|
||||
|
||||
Execute few commands:
|
||||
|
||||
```sh
|
||||
vagrant ssh -c "pwd; ls project ..."
|
||||
```
|
||||
|
||||
Stop and delete a *vagrant machine*:
|
||||
|
||||
```sh
|
||||
vagrant destroy -f
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| Linux | macOS | Windows |
|
||||
|-------|-------|---------|
|
||||
| [![Status][linux_cpp_svg]][linux_cpp_link] | [![Status][macos_cpp_svg]][macos_cpp_link] | [![Status][windows_cpp_svg]][windows_cpp_link] |
|
||||
Linux | macOS | Windows
|
||||
------------------------------------------ | ------------------------------------------ | -------
|
||||
[![Status][linux_cpp_svg]][linux_cpp_link] | [![Status][macos_cpp_svg]][macos_cpp_link] | [![Status][windows_cpp_svg]][windows_cpp_link]
|
||||
|
||||
[linux_cpp_svg]: https://github.com/google/or-tools/actions/workflows/cmake_linux_cpp.yml/badge.svg?branch=master
|
||||
[linux_cpp_link]: https://github.com/google/or-tools/actions/workflows/cmake_linux_cpp.yml
|
||||
@@ -10,55 +10,72 @@
|
||||
[windows_cpp_link]: https://github.com/google/or-tools/actions/workflows/cmake_windows_cpp.yml
|
||||
|
||||
# Introduction
|
||||
For building OR-Tools as a CMake standalone project, you can read the following instructions.
|
||||
|
||||
For building OR-Tools as a CMake standalone project, you can read the following
|
||||
instructions.
|
||||
|
||||
This project should run on GNU/Linux, MacOS and Windows.
|
||||
|
||||
# C++ Project Build
|
||||
## C++ Project Build
|
||||
|
||||
1. Get the source code and change to it.
|
||||
```sh
|
||||
git clone https://github.com/google/or-tools.git
|
||||
cd or-tools
|
||||
```
|
||||
|
||||
```sh
|
||||
git clone https://github.com/google/or-tools.git
|
||||
cd or-tools
|
||||
```
|
||||
|
||||
2. Run CMake to configure the build tree.
|
||||
```sh
|
||||
cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DBUILD_DEPS=ON
|
||||
```
|
||||
note: To get the list of available generators (e.g. Visual Studio), use `-G ""`
|
||||
|
||||
```sh
|
||||
cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DBUILD_DEPS=ON
|
||||
```
|
||||
note: To get the list of available generators (e.g. Visual Studio), use `-G`
|
||||
|
||||
3. Afterwards, generated files can be used to compile the project.
|
||||
```sh
|
||||
cmake --build build --config Release -v
|
||||
```
|
||||
|
||||
```sh
|
||||
cmake --build build --config Release -v
|
||||
```
|
||||
|
||||
4. Test the build software (optional).
|
||||
```sh
|
||||
cmake --build build --target test
|
||||
```
|
||||
|
||||
```sh
|
||||
cmake --build build --target test
|
||||
```
|
||||
|
||||
5. Install the built files (optional).
|
||||
```sh
|
||||
cmake --build build --target install
|
||||
```
|
||||
|
||||
# Testing
|
||||
```sh
|
||||
cmake --build build --target install
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
To list tests:
|
||||
|
||||
```sh
|
||||
cd build
|
||||
ctest -N
|
||||
```
|
||||
|
||||
To only run C++ tests
|
||||
To only run C++ tests:
|
||||
|
||||
```sh
|
||||
cd build
|
||||
ctest -R "cxx_.*"
|
||||
```
|
||||
|
||||
# Technical Notes
|
||||
## Managing RPATH
|
||||
Since we want to use the [CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html) to generate the wrapper package (e.g. python wheel package) as well as be able to test from the build directory.
|
||||
## Technical Notes
|
||||
|
||||
### Managing RPATH
|
||||
|
||||
Since we want to use the
|
||||
[CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html)
|
||||
to generate the wrapper package (e.g. python wheel package) as well as be able
|
||||
to test from the build directory. \
|
||||
We need to enable:
|
||||
|
||||
```cmake
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| Linux | macOS | Windows |
|
||||
|-------|-------|---------|
|
||||
| [![Status][linux_dotnet_svg]][linux_dotnet_link] | [![Status][macos_dotnet_svg]][macos_dotnet_link] | [![Status][windows_dotnet_svg]][windows_dotnet_link] |
|
||||
Linux | macOS | Windows
|
||||
------------------------------------------------ | ------------------------------------------------ | -------
|
||||
[![Status][linux_dotnet_svg]][linux_dotnet_link] | [![Status][macos_dotnet_svg]][macos_dotnet_link] | [![Status][windows_dotnet_svg]][windows_dotnet_link]
|
||||
|
||||
[linux_dotnet_svg]: https://github.com/google/or-tools/actions/workflows/cmake_linux_dotnet.yml/badge.svg?branch=master
|
||||
[linux_dotnet_link]: https://github.com/google/or-tools/actions/workflows/cmake_linux_dotnet.yml
|
||||
@@ -10,35 +10,47 @@
|
||||
[windows_dotnet_link]: https://github.com/google/or-tools/actions/workflows/cmake_windows_dotnet.yml
|
||||
|
||||
# Introduction
|
||||
Try to build a .NetStandard2.0 native (for win-x64, linux-x64 and osx-x64) nuget multi package using [`dotnet/cli`](https://github.com/dotnet/cli) and the *new* .csproj format.
|
||||
|
||||
# Build the Binary Packages
|
||||
Try to build a .NetStandard2.0 native (for win-x64, linux-x64 and osx-x64) nuget
|
||||
multi package using [`dotnet/cli`](https://github.com/dotnet/cli) and the *new*
|
||||
.csproj format.
|
||||
|
||||
## Build the Binary Packages
|
||||
|
||||
To build the .Net nuget packages, simply run:
|
||||
|
||||
```sh
|
||||
cmake -S. -Bbuild -DBUILD_DOTNET=ON
|
||||
cmake --build build --target dotnet_package -v
|
||||
```
|
||||
note: Since `dotnet_package` is in target `all`, you can also ommit the
|
||||
note: Since `dotnet_package` is in target `all`, you can also omit the
|
||||
`--target` option.
|
||||
|
||||
# Testing
|
||||
## Testing
|
||||
|
||||
To list tests:
|
||||
|
||||
```sh
|
||||
cd build
|
||||
ctest -N
|
||||
```
|
||||
|
||||
To only run .NET tests:
|
||||
|
||||
```sh
|
||||
cd build
|
||||
ctest -R "dotnet_.*"
|
||||
```
|
||||
|
||||
# Technical Notes
|
||||
First you should take a look at the [ortools/dotnet/README.md](../../ortools/dotnet/README.md) to understand the layout.
|
||||
## Technical Notes
|
||||
|
||||
First you should take a look at the
|
||||
[ortools/dotnet/README.md](../../ortools/dotnet/README.md) to understand the
|
||||
layout. \
|
||||
Here I will only focus on the CMake/SWIG tips and tricks.
|
||||
|
||||
## Build directory layout
|
||||
### Build directory layout
|
||||
|
||||
Since .Net use a `.csproj` project file to orchestrate everything we need to
|
||||
generate them and have the following layout:
|
||||
|
||||
@@ -89,4 +101,5 @@ generate them and have the following layout:
|
||||
├── replace.cmake
|
||||
└── replace_runtime.cmake
|
||||
```
|
||||
|
||||
src: `tree build/dotnet --prune -I "obj|bin"`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| Linux | macOS | Windows |
|
||||
|-------|-------|---------|
|
||||
| [![Status][linux_java_svg]][linux_java_link] | [![Status][macos_java_svg]][macos_java_link] | [![Status][windows_java_svg]][windows_java_link] |
|
||||
Linux | macOS | Windows
|
||||
-------------------------------------------- | -------------------------------------------- | -------
|
||||
[![Status][linux_java_svg]][linux_java_link] | [![Status][macos_java_svg]][macos_java_link] | [![Status][windows_java_svg]][windows_java_link]
|
||||
|
||||
[linux_java_svg]: https://github.com/google/or-tools/actions/workflows/cmake_linux_java.yml/badge.svg?branch=master
|
||||
[linux_java_link]: https://github.com/google/or-tools/actions/workflows/cmake_linux_java.yml
|
||||
@@ -11,16 +11,18 @@
|
||||
|
||||
# Introduction
|
||||
|
||||
First, verify you have the `JAVA_HOME` environment variable set otherwise CMake and Maven won't be able to find your Java SDK.
|
||||
First, verify you have the `JAVA_HOME` environment variable set otherwise CMake
|
||||
and Maven won't be able to find your Java SDK.
|
||||
|
||||
## Build the Binary Package
|
||||
|
||||
To build the java maven packages, simply run:
|
||||
|
||||
```sh
|
||||
cmake -S. -Bbuild -DBUILD_JAVA=ON
|
||||
cmake --build build --target java_package -v
|
||||
```
|
||||
note: Since `java_package` is in target `all`, you can also ommit the
|
||||
note: Since `java_package` is in target `all`, you can also omit the
|
||||
`--target` option.
|
||||
|
||||
## Testing
|
||||
@@ -41,13 +43,16 @@ ctest -R "java_.*"
|
||||
|
||||
## Technical Notes
|
||||
|
||||
First you should take a look at the [ortools/java/README.md](../../ortools/java/README.md) to understand the layout.
|
||||
First you should take a look at the
|
||||
[ortools/java/README.md](../../ortools/java/README.md) to understand the layout.
|
||||
\
|
||||
Here I will only focus on the CMake/SWIG tips and tricks.
|
||||
|
||||
### Build directory layout
|
||||
|
||||
Since Java use the directory layout and we want to use the [CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html)
|
||||
to generate the Java binary package.
|
||||
Since Java use the directory layout and we want to use the
|
||||
[CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html)
|
||||
to generate the Java binary package.
|
||||
|
||||
We want this layout:
|
||||
|
||||
@@ -70,7 +75,7 @@ We want this layout:
|
||||
│ ├── constraintsolver
|
||||
│ │ ├── ConstraintSolver.java
|
||||
│ │ └── ...
|
||||
│ ├── ...
|
||||
│ ├── ...
|
||||
│ └── sat
|
||||
│ ├── CpModel.java
|
||||
│ └── ...
|
||||
@@ -81,24 +86,31 @@ We want this layout:
|
||||
│ └── com/google/ortools
|
||||
│ └── Tsp.java
|
||||
```
|
||||
|
||||
src: `tree build/java --prune -U -P "*.java|*.xml|*.so*" -I "target"`
|
||||
|
||||
### Managing SWIG generated files
|
||||
|
||||
You can use `CMAKE_SWIG_DIR` to change the output directory for the `.java` file e.g.:
|
||||
You can use `CMAKE_SWIG_DIR` to change the output directory for the `.java` file
|
||||
e.g.:
|
||||
|
||||
```cmake
|
||||
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||
```
|
||||
And you can use `CMAKE_LIBRARY_OUTPUT_DIRECTORY` to change the output directory for the `.so` file e.g.:
|
||||
|
||||
And you can use `CMAKE_LIBRARY_OUTPUT_DIRECTORY` to change the output directory
|
||||
for the `.so` file e.g.:
|
||||
|
||||
```cmake
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||
```
|
||||
[optional]You can use `SWIG_OUTFILE_DIR` to change the output directory for the `.cxx` file e.g.:
|
||||
|
||||
[optional]You can use `SWIG_OUTFILE_DIR` to change the output directory for the
|
||||
`.cxx` file e.g.:
|
||||
|
||||
```cmake
|
||||
set(SWIG_OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||
```
|
||||
|
||||
Then you only need to create a `pom.xml` file in `build/java` to be able to use
|
||||
the build directory to generate the Java package.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| Linux | macOS | Windows |
|
||||
|-------|-------|---------|
|
||||
| [![Status][linux_python_svg]][linux_python_link] | [![Status][macos_python_svg]][macos_python_link] | [![Status][windows_python_svg]][windows_python_link] |
|
||||
Linux | macOS | Windows
|
||||
------------------------------------------------ | ------------------------------------------------ | -------
|
||||
[![Status][linux_python_svg]][linux_python_link] | [![Status][macos_python_svg]][macos_python_link] | [![Status][windows_python_svg]][windows_python_link]
|
||||
|
||||
[linux_python_svg]: https://github.com/google/or-tools/actions/workflows/cmake_linux_python.yml/badge.svg?branch=master
|
||||
[linux_python_link]: https://github.com/google/or-tools/actions/workflows/cmake_linux_python.yml
|
||||
@@ -9,69 +9,92 @@
|
||||
[windows_python_svg]: https://github.com/google/or-tools/actions/workflows/cmake_windows_python.yml/badge.svg?branch=master
|
||||
[windows_python_link]: https://github.com/google/or-tools/actions/workflows/cmake_windows_python.yml
|
||||
|
||||
# Introduction
|
||||
To be compliant with [PEP513](https://www.python.org/dev/peps/pep-0513/#the-manylinux1-policy) a python package should embbed all its C++ shared libraries.
|
||||
# Introduction
|
||||
|
||||
Creating a Python native package containing all `.py` and `.so` (with good rpath/loaderpath) is not so easy...
|
||||
To be compliant with
|
||||
[PEP513](https://www.python.org/dev/peps/pep-0513/#the-manylinux1-policy) a
|
||||
python package should embbed all its C++ shared libraries.
|
||||
|
||||
Creating a Python native package containing all `.py` and `.so` (with good
|
||||
rpath/loaderpath) is not so easy...
|
||||
|
||||
## Build the Binary Package
|
||||
|
||||
# Build the Binary Package
|
||||
To build the Python wheel package, simply run:
|
||||
|
||||
```sh
|
||||
cmake -S. -Bbuild -DBUILD_PYTHON=ON
|
||||
cmake --build build --target python_package -v
|
||||
```
|
||||
note: Since `python_package` is in target `all`, you can also ommit the
|
||||
note: Since `python_package` is in target `all`, you can also omit the
|
||||
`--target` option.
|
||||
|
||||
# Testing
|
||||
## Testing
|
||||
|
||||
To list tests:
|
||||
|
||||
```sh
|
||||
cd build
|
||||
ctest -N
|
||||
```
|
||||
|
||||
To only run Python tests:
|
||||
|
||||
```sh
|
||||
cd build
|
||||
ctest -R "python_.*"
|
||||
```
|
||||
|
||||
# Technical Notes
|
||||
First you should take a look at the [ortools/python/README.md](../../ortools/python/README.md) to understand the layout.
|
||||
## Technical Notes
|
||||
|
||||
First you should take a look at the
|
||||
[ortools/python/README.md](../../ortools/python/README.md) to understand the
|
||||
layout. \
|
||||
Here I will only focus on the CMake/SWIG tips and tricks.
|
||||
|
||||
## Build directory layout
|
||||
### Build directory layout
|
||||
|
||||
Since Python use the directory name where `__init__.py` file is located and we
|
||||
want to use the [CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html)
|
||||
to generate the Python binary package.
|
||||
want to use the
|
||||
[CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html)
|
||||
to generate the Python binary package.
|
||||
|
||||
We want this layout:
|
||||
|
||||
```shell
|
||||
<CMAKE_BINARY_DIR>/python
|
||||
├── setup.py
|
||||
└── ortools
|
||||
├── __init__.py
|
||||
├── algorithms
|
||||
│ ├── __init__.py
|
||||
│ ├── _pywrap.so
|
||||
│ └── pywrap.py
|
||||
│ ├── __init__.py
|
||||
│ ├── _pywrap.so
|
||||
│ └── pywrap.py
|
||||
├── graph
|
||||
│ ├── __init__.py
|
||||
│ ├── pywrapgraph.py
|
||||
│ └── _pywrapgraph.so
|
||||
│ ├── __init__.py
|
||||
│ ├── pywrapgraph.py
|
||||
│ └── _pywrapgraph.so
|
||||
├── ...
|
||||
└── .libs
|
||||
├── libXXX.so.1.0
|
||||
└── libXXX.so.1.0
|
||||
```
|
||||
|
||||
src: `tree build --prune -U -P "*.py|*.so*" -I "build"`
|
||||
|
||||
note: On UNIX you always need `$ORIGIN/../../${PROJECT_NAME}/.libs` since `_pywrapXXX.so` will depend on `libortools.so`.
|
||||
note: On APPLE you always need `"@loader_path;@loader_path/../../${PROJECT_NAME}/.libs` since `_pywrapXXX.so` will depend on `libortools.dylib`.
|
||||
note: on Windows since we are using static libraries we won't have the `.libs` directory...
|
||||
note: On UNIX you always need `$ORIGIN/../../${PROJECT_NAME}/.libs` since
|
||||
`_pywrapXXX.so` will depend on `libortools.so`. \
|
||||
note: On APPLE you always need
|
||||
`"@loader_path;@loader_path/../../${PROJECT_NAME}/.libs` since `_pywrapXXX.so`
|
||||
will depend on `libortools.dylib`. \
|
||||
note: on Windows since we are using static libraries we won't have the `.libs`
|
||||
directory...
|
||||
|
||||
So we also need to create few `__init__.py` files to be able to use the build directory to generate the Python package.
|
||||
So we also need to create few `__init__.py` files to be able to use the build
|
||||
directory to generate the Python package.
|
||||
|
||||
### Why on APPLE lib must be .so
|
||||
|
||||
## Why on APPLE lib must be .so
|
||||
Actually, the cpython code responsible for loading native libraries expect `.so`
|
||||
on all UNIX platforms.
|
||||
|
||||
@@ -90,17 +113,26 @@ const char *_PyImport_DynLoadFiletab[] = {
|
||||
NULL,
|
||||
};
|
||||
```
|
||||
ref: https://github.com/python/cpython/blob/master/Python/dynload_shlib.c#L36-L48
|
||||
|
||||
ref:
|
||||
https://github.com/python/cpython/blob/master/Python/dynload_shlib.c#L36-L48
|
||||
|
||||
i.e. `pywrapXXX` -> `_pywrapXXX.so` -> `libortools.dylib`
|
||||
|
||||
## Why setup.py has to be generated
|
||||
To avoid to put hardcoded path to SWIG `.so/.dylib` generated files,
|
||||
we could use `$<TARGET_FILE_NAME:tgt>` to retrieve the file (and also deal with Mac/Windows suffix, and target dependencies).
|
||||
### Why setup.py has to be generated
|
||||
|
||||
To avoid to put hardcoded path to SWIG `.so/.dylib` generated files, we could
|
||||
use `$<TARGET_FILE_NAME:tgt>` to retrieve the file (and also deal with
|
||||
Mac/Windows suffix, and target dependencies). \
|
||||
In order for `setup.py` to use
|
||||
[cmake generator expression](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#informational-expressions)
|
||||
(e.g. $<TARGET_FILE_NAME:_pyFoo>). We need to generate it at build time (e.g. using
|
||||
[add_custom_command()](https://cmake.org/cmake/help/latest/command/add_custom_command.html)).
|
||||
note: This will also add automatically a dependency between the command and the TARGET !
|
||||
(e.g. `$<TARGET_FILE_NAME:_pyFoo>`). We need to generate it at build time (e.g.
|
||||
using
|
||||
[add_custom_command()](https://cmake.org/cmake/help/latest/command/add_custom_command.html)).
|
||||
|
||||
todo(mizux): try to use [`file(GENERATE ...)`](https://cmake.org/cmake/help/latest/command/file.html#generate) instead.
|
||||
note: This will also add automatically a dependency between the command and the
|
||||
TARGET !
|
||||
|
||||
todo(mizux): try to use
|
||||
[`file(GENERATE ...)`](https://cmake.org/cmake/help/latest/command/file.html#generate)
|
||||
instead.
|
||||
|
||||
@@ -1,41 +1,51 @@
|
||||
# SWIG Wrapper Generation
|
||||
Using [swig](https://github.com/swig/swig) to generate wrapper it's easy thanks to the modern
|
||||
[UseSWIG](https://cmake.org/cmake/help/latest/module/UseSWIG.html) module (**CMake >= 3.14**).
|
||||
|
||||
note: SWIG automatically put its target(s) in `all`, thus `cmake --build build` will also call
|
||||
swig and generate `_module.so`.
|
||||
Using [swig](https://github.com/swig/swig) to generate wrapper it's easy thanks
|
||||
to the modern [UseSWIG](https://cmake.org/cmake/help/latest/module/UseSWIG.html)
|
||||
module (**CMake >= 3.14**).
|
||||
|
||||
note: SWIG automatically put its target(s) in `all`, thus `cmake --build build`
|
||||
will also call swig and generate `_module.so`.
|
||||
|
||||
## Policy
|
||||
|
||||
# Policy
|
||||
UseSWIG is impacted by two policies:
|
||||
|
||||
* [CMP0078](https://cmake.org/cmake/help/latest/policy/CMP0078.html):UseSWIG generates standard target names (CMake 3.13+).
|
||||
* [CMP0086](https://cmake.org/cmake/help/latest/policy/CMP0086.html): UseSWIG honors `SWIG_MODULE_NAME` via `-module` flag (CMake 3.14+).
|
||||
|
||||
That's why I recommnend to use CMake >= 3.14 with both policies set to new for
|
||||
SWIG development.
|
||||
|
||||
# int64_t Management
|
||||
When working on a `k8` (aka `x86_64`) architecture, you may face issue with `int64_t`
|
||||
and `uint64_t` management.
|
||||
## int64_t Management
|
||||
|
||||
When working on a `k8` (aka `x86_64`) architecture, you may face issue with
|
||||
`int64_t` and `uint64_t` management.
|
||||
|
||||
First `long long` and `long int` are **different** types and `int64_t` is just a
|
||||
typedef on one of them...
|
||||
|
||||
## Linux
|
||||
### Linux
|
||||
|
||||
On Linux we have:
|
||||
|
||||
```
|
||||
sizeof(long long): 8
|
||||
sizeof(long int): 8
|
||||
sizeof(int64_t): 8
|
||||
```
|
||||
|
||||
### Gcc
|
||||
#### Gcc
|
||||
|
||||
First try to find where and how the compiler define `int64_t` and `uint64_t`.
|
||||
|
||||
```sh
|
||||
grepc -rn "typedef.*int64_t;" /lib/gcc
|
||||
/lib/gcc/x86_64-linux-gnu/9/include/stdint-gcc.h:43:typedef __INT64_TYPE__ int64_t;
|
||||
/lib/gcc/x86_64-linux-gnu/9/include/stdint-gcc.h:55:typedef __UINT64_TYPE__ uint64_t;
|
||||
```
|
||||
So we need to find this compiler macro definition
|
||||
|
||||
```sh
|
||||
gcc -dM -E -x c /dev/null | grep __INT64
|
||||
#define __INT64_C(c) c ## L
|
||||
@@ -48,51 +58,63 @@ gcc -dM -E -x c /dev/null | grep __UINT64
|
||||
#define __UINT64_TYPE__ long unsigned int
|
||||
```
|
||||
|
||||
### Clang
|
||||
#### Clang
|
||||
|
||||
```sh
|
||||
clang -dM -E -x c++ /dev/null | grep INT64_TYPE
|
||||
#define __INT64_TYPE__ long int
|
||||
#define __UINT64_TYPE__ long unsigned int
|
||||
```
|
||||
|
||||
Clang, GNU compilers:
|
||||
`-dM` dumps a list of macros.
|
||||
`-E` prints results to stdout instead of a file.
|
||||
`-x c` and `-x c++` select the programming language when using a file without a filename extension, such as `/dev/null`
|
||||
Clang, GNU compilers: \
|
||||
`-dM` dumps a list of macros. \
|
||||
`-E` prints results to stdout instead of a file. \
|
||||
`-x c` and `-x c++` select the programming language when using a file without a
|
||||
filename extension, such as `/dev/null`
|
||||
|
||||
Ref: https://web.archive.org/web/20190803041507/http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros
|
||||
Ref:
|
||||
https://web.archive.org/web/20190803041507/http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros
|
||||
|
||||
### MacOS
|
||||
|
||||
## MacOS
|
||||
On Catalina 10.15 we have:
|
||||
|
||||
```
|
||||
sizeof(long long): 8
|
||||
sizeof(long int): 8
|
||||
sizeof(int64_t): 8
|
||||
```
|
||||
|
||||
### Clang
|
||||
#### Clang
|
||||
|
||||
```sh
|
||||
clang -dM -E -x c++ /dev/null | grep INT64_TYPE
|
||||
#define __INT64_TYPE__ long long int
|
||||
#define __UINT64_TYPE__ long long unsigned int
|
||||
```
|
||||
with:
|
||||
`-dM` dumps a list of macros.
|
||||
`-E` prints results to stdout instead of a file.
|
||||
`-x c` and `-x c++` select the programming language when using a file without a filename extension, such as `/dev/null`
|
||||
|
||||
Ref: https://web.archive.org/web/20190803041507/http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros
|
||||
with: `-dM` dumps a list of macros. \
|
||||
`-E` prints results to stdout instead of a file. \
|
||||
`-x c` and `-x c++` select the programming language when using a file without a
|
||||
filename extension, such as `/dev/null`
|
||||
|
||||
Ref:
|
||||
https://web.archive.org/web/20190803041507/http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros
|
||||
|
||||
### Windows
|
||||
|
||||
## Windows
|
||||
Contrary to macOS and Linux, Windows 64bits (x86_64) try hard to keep compatibility, so we have:
|
||||
|
||||
```
|
||||
sizeof(long int): 4
|
||||
sizeof(long long): 8
|
||||
sizeof(int64_t): 8
|
||||
```
|
||||
|
||||
### Visual Studio 2019
|
||||
#### Visual Studio 2019
|
||||
|
||||
Thus, in `stdint.h` we have:
|
||||
|
||||
```cpp
|
||||
#if _VCRT_COMPILER_PREPROCESSOR
|
||||
|
||||
@@ -106,16 +128,22 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
```
|
||||
|
||||
## SWIG int64_t management stuff
|
||||
First, take a look at [Swig stdint.i](https://github.com/swig/swig/blob/3a329566f8ae6210a610012ecd60f6455229fe77/Lib/stdint.i#L20-L24).
|
||||
So, when targeting Linux you **must use define SWIGWORDSIZE64** (i.e. `-DSWIGWORDSIZE64`) while
|
||||
on macOS and Windows you **must not define it**.
|
||||
### SWIG int64_t management stuff
|
||||
|
||||
Now the bad news, even if you can control the SWIG typedef using `SWIGWORDSIZE64`,
|
||||
[SWIG Java](https://github.com/swig/swig/blob/3a329566f8ae6210a610012ecd60f6455229fe77/Lib/java/java.swg#L74-L77) and
|
||||
[SWIG CSHARP](https://github.com/swig/swig/blob/1e36f51346d95f8b9848e682c2eb986e9cb9b4f4/Lib/csharp/csharp.swg#L117-L120) do not take it into account for typemaps...
|
||||
First, take a look at
|
||||
[Swig stdint.i](https://github.com/swig/swig/blob/3a329566f8ae6210a610012ecd60f6455229fe77/Lib/stdint.i#L20-L24).
|
||||
So, when targeting Linux you **must use define SWIGWORDSIZE64** (i.e.
|
||||
`-DSWIGWORDSIZE64`) while on macOS and Windows you **must not define it**.
|
||||
|
||||
Now the bad news, even if you can control the SWIG typedef using
|
||||
`SWIGWORDSIZE64`,
|
||||
[SWIG Java](https://github.com/swig/swig/blob/3a329566f8ae6210a610012ecd60f6455229fe77/Lib/java/java.swg#L74-L77)
|
||||
and
|
||||
[SWIG CSHARP](https://github.com/swig/swig/blob/1e36f51346d95f8b9848e682c2eb986e9cb9b4f4/Lib/csharp/csharp.swg#L117-L120)
|
||||
do not take it into account for typemaps...
|
||||
|
||||
So you may want to use this for Java:
|
||||
|
||||
```swig
|
||||
#if defined(SWIGJAVA)
|
||||
#if defined(SWIGWORDSIZE64)
|
||||
@@ -157,10 +185,13 @@ PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long);
|
||||
#endif // defined(SWIGCSHARP)
|
||||
```
|
||||
|
||||
So `int64_t` (i.e. `long int` in this case) will be correctly bind to Java/.Net primitive type `long`.
|
||||
So `int64_t` (i.e. `long int` in this case) will be correctly bind to Java/.Net
|
||||
primitive type `long`.
|
||||
|
||||
## swig_add_library()
|
||||
|
||||
# swig_add_library()
|
||||
You can use `OUTPUT_DIR` to change the output directory for the `.py` file e.g.:
|
||||
|
||||
```cmake
|
||||
swig_add_library(pyFoo
|
||||
TYPE SHARED
|
||||
@@ -169,9 +200,14 @@ swig_add_library(pyFoo
|
||||
SOURCES foo.i)
|
||||
```
|
||||
|
||||
# Doxygen
|
||||
Since swig 4.0, swig can now [extract doxygen comments](http://www.swig.org/Doc4.0/Doxygen.html) from C++ to inject it in
|
||||
Python and Java.
|
||||
## Doxygen
|
||||
|
||||
## Csharp documentation
|
||||
note: Doxygen to csharp was [planned](https://github.com/swig/swig/wiki/SWIG-4.0-Development#doxygen-documentation) but currently is not supported.
|
||||
Since swig 4.0, swig can now
|
||||
[extract doxygen comments](http://www.swig.org/Doc4.0/Doxygen.html) from C++ to
|
||||
inject it in Python and Java.
|
||||
|
||||
### Csharp documentation
|
||||
|
||||
note: Doxygen to csharp was
|
||||
[planned](https://github.com/swig/swig/wiki/SWIG-4.0-Development#doxygen-documentation)
|
||||
but currently is not supported.
|
||||
|
||||
Reference in New Issue
Block a user