I am attempting to use SWIG to generate a C# wrapper for some C++ code, and then use that generated code in another C# project. Right now, I’m just trying to get things working in an example project. Starting with the CMake example on the SWIG website (http://www.swig.org/Doc3.0/Introduction.html#Introduction_build_system), I updated it a bit to try and match the latest CMake documentation (https://cmake.org/cmake/help/latest/module/UseSWIG.html), as well as removed the Python parts in favour of C# equivalents.
Now I’m looking at
cmake_minimum_required(VERSION 3.17)
project(example
LANGUAGES CSharp
)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_SWIG_FLAGS "")
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/example_out)
set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
swig_add_library(example
TYPE SHARED
LANGUAGE csharp
SOURCES example.i example.c
)
If anyone’s trying to get this to work locally, I also needed to change example.i
from the SWIG website to directly #include "example.c"
, rather than use extern
s.
This does generate a C# wrapper, and outputs it to ${CMAKE_CURRENT_BINARY_DIR}/example_out
. The problem then is, that I need to reference these output files from another project. One approach would be
get_property(EXAMPLE_OUT_DIR TARGET ${PROJECT_NAME} PROPERTY SWIG_SUPPORT_FILES_DIRECTORY)
file(GLOB OUT_SRC
CONFIGURE_DEPENDS
"${EXAMPLE_OUT_DIR}/*.cs"
)
add_library(newlib SHARED ${OUT_SRC} tmp.cs)
add_library(mylibs::newlib ALIAS newlib)
set_property(TARGET newlib PROPERTY DOTNET_TARGET_FRAMEWORK_VERSION "v4.6.1")
set_property(TARGET newlib PROPERTY VS_DOTNET_REFERENCES
"Microsoft.CSharp"
)
The properties being there to force this project to be a C# project (which is necessary for setting it as a reference for another C# project), and tmp.cs
being an empty file to get this to run before anything’s been generated (since the generation from SWIG happens at build time).
Even with CONFIGURE_DEPENDS
, though, this still requires compiling twice, and then touch
ing the CMakeLists to get a further C# project to recognise that the wrappers have been added to it.
Example C# project for consuming this:
cmake_minimum_required(VERSION 3.17)
project(thing_using_example
LANGUAGES CSharp)
include(CSharpUtilities)
set(SOURCES
ThingUsingExample.cs
)
add_executable(${PROJECT_NAME} ${SOURCES})
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.6.1")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_ROOTNAMESPACE "ThingUsingExample")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_Prefer32Bit "false")
set(CMAKE_CSharp_FLAGS "${CMAKE_CSharp_FLAGS} /langversion:6")
add_dependencies(${PROJECT_NAME} mylibs::newlib)
My question is: what is the right way to create a library, consisting of files generated at build time, the names of which are not known in advance? Right now I’m leaning towards replacing the swig_add_library
with a custom command, but I’m sure there’s a cleaner/nicer way.