Ubuntu和Win 10下用CMAKE + SWIG 为C#写动态库
2021-01-06 14:28
标签:extern fatal 统一 items gre 构建项目 tostring epp 多个 本文采用这个项目的教学代码: https://github.com/Mizux/dotnet-native 作者自称是cmake的开发人员,不知道真假,不过这个项目代码组织看起来挺专业的,就它了。这里主要研究如何用cmake + swig + dotnet + gcc/vc 将代码部署到ubuntu和winows下面,代码本身功能不是重点。 可以参考https://github.com/Mizux/dotnet-native/blob/master/ci/docker/ubuntu/Dockerfile,这里略有修改,下载了各个软件的最新版本 安装CMake 去https://cmake.org/download/ 下载并安装cmake-3.16.8-win64-x64.msi 安装完应该能看到 安装visual studio 2019 现在都免费了.去https://visualstudio.microsoft.com/vs/下载prefessional版本 本项目需要c++和c#,所以要安装两个workload 下载github教学代码 可以下载zip,并解压 构建项目 打开CMake,点击右上角Browse Source,选择上面解压后dotnet-native-master目录 browse build里面的路径=Browse Source里面的路径 + /build,完成后点击左下configure 这时会让你选择generator,这里选择Visual Studio 16 2019,然后点击Finish 这个过程需要十几秒,然后会在下框中显示Configuration done 然后点击Generate按钮,下框中显示Generating done。 点击Open Project,这时会弹出Visual Studio 2019,点击Build Solution, 开始编译项目 编译完成后,File->Close Solution关闭项目。 此时build/dotnet/packages下有了nupkg文件,这就是build产生的包文件。接下来用例子说们怎么用这个包文件 测试样例 重新打开一个项目:Ctrl+Shift+O 打开 dotnet-native-master\ci\samples\Mizux.Sample.csproj 设置nupkg,首先卸载Mizux.Sample.csproj中的Mizux.Foo包,因为这个包默认是从nuget.org上下载的, 具体可以打开Mizux.Sample.csproj,看里面的设置。 Tools->NuGet Package Manager-> Manage NuGet Packages for Solution,在installed面板左边选择Mizux.Foo,在右边选择Mizux.Sample,点击Uninstall 接着需要载入本地编译好的Mizux.Foo包。Tools->Options->NuGet Package Manager->Packages Sources,在右边点绿色的+按钮添加一个包,name填写Mizux.Foo,Source里面选择 接下来添加nupkg文件,右键Mizux.Sample,选择Manager NuGet Packages 现在已经把Mizux.Foo.1.0.0.nupkg安装到项目中了。最后点击绿色的运行按钮,执行结果如下: 先看看代码组织: 先看一下代码,知道这个项目做了什么 就是一些set和print,根据输入是int64还是int调用不同的函数 映射了一些类型,这一段代码应该对所有c#项目有效,无需修改,就不深究了。 根据前面的分析,该代码应该输出 现在开始理解cmake的流程了。从根目录的CMakeLists.txt看起。###后面跟的是本文的注释 看来根目录的CMakeLists.txt主要设置了一些公共变量,至于具体执行什么还要看cmake下面的*.cmake文件 看一下cmake/FooConfig.cmake.in文件,也就是一个include1 Make It Work
1.1 Ubuntu
sudo apt-get update
sudo apt install g++
g++ --version #检查一下版本,显示7.5.0, 这里我们想用最新版本g++-9
sudo apt install software-properties-common #参考https://linuxize.com/post/how-to-install-gcc-compiler-on-ubuntu-18-04/#installing-gcc-on-ubuntu
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt install g++-9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g++ g++ /usr/bin/g++-9 --slave /usr/bin/gcov gcov /usr/bin/gcov-9
g++ --version #检查一下版本,本例子中已经更新为9.3.0
wget "https://cmake.org/files/v3.17/cmake-3.17.2-Linux-x86_64.sh" #sudo apt install cmake只能下载到3.10版本,本例子需要在3.14或以上版本
chmod a+x cmake-3.17.2-Linux-x86_64.sh
sudo ./cmake-3.17.2-Linux-x86_64.sh --prefix=/usr/local/ --skip-license
rm cmake-3.17.2-Linux-x86_64.sh
cmake --version #检查一下版本,3.17.2。使用terminal的需要重开一个窗口,否则会显示找不到cmake
wget ftp://ftp.pcre.org/pub/pcre/pcre-8.00.tar.gz #下载pcre,安装swig 4.0版本需要, sudo apt-get install -y swig只能拿到3.0.12版本
tar -xzf pcre-8.00.tar.gz
cd pcre-8.00/
./configure --prefix=/usr/local/pcre #安装到/usr/local/pcre/bin/pcre-config
make
sudo make install #pcre安装完成
PATH=/usr/local/pcre/bin:$PATH #让pcre-config可以直接被call
cd ..
http://prdownloads.sourceforge.net/swig/swig-4.0.2.tar.gz
tar -xzf swig-4.0.2.tar.gz
cd swig-4.0.2 #参考http://www.swig.org/Doc4.0/SWIGDocumentation.html#Preface_unix_installation
./configure
make
sudo make install
export LD_LIBRARY_PATH=/usr/local/pcre/lib:$LD_LIBRARY_PATH #把libpcre.so.0加入系统库目录中
swig -version #检查一下版本,本例子中使用的是4.0.2版本
cd ..
sudo apt-get update -qq #安装.NET
sudo apt-get install -yq wget apt-transport-https
wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq dotnet-sdk-3.1
sudo apt-get clean
dotnet --version #检查版本,本例子中是3.1.301
git clone https://github.com/Mizux/dotnet-native #下载项目代码
cd dotnet-native
cmake -S. -Bbuild
cmake --build build --target all -v
sudo cmake --build build --target install -v
cmake --build build --target test -v #should read 100% tests passed, 0 tests failed out of 3
cd ..
mkdir sample
cd sample
cp ../dotnet-native/build/dotnet/packages/*.nupkg ./
cp ../dotnet-native/ci/samples/* ./ #sample目录下有Mizux.Foo.1.0.0.nupkg Mizux.Foo.runtime.linux-x64.1.0.0.nupkg Mizux.Sample.csproj Sample.cs
dotnet build
dotnet run #[1] Enter FooApp
#[2] Enter Foo::hello(int)
#[3] Enter fooHello(int)
#[3] Exit fooHello(int)
#[2] Exit Foo::hello(int)
#[1] Exit FooApp
#成功!!
1.2 Windows
dotnet-native-master\dotnet-native-master\build\dotnet\packages,即含有nupkg和snupkg的文件夹。然后点击OK,这样就设置好路径了。
在Browse面板冲,在右上角的下拉框中选择Mizux.Foo (默认是nuget.org),然后在左边选择Mizux.Foo,最后点击右边的install。2 代码分析
xian@chaos:~/code/dotnet-native$ tree
.
├── AUTHORS
├── ci
│?? ├── doc
│?? │?? ├── deps.dot
│?? │?? ├── deps.svg
│?? │?? └── generate_image.sh
│?? ├── docker
│?? │?? ├── alpine
│?? │?? │?? └── Dockerfile
│?? │?? ├── archlinux
│?? │?? │?? └── Dockerfile
│?? │?? ├── centos
│?? │?? │?? └── Dockerfile
│?? │?? ├── debian
│?? │?? │?? └── Dockerfile
│?? │?? ├── fedora
│?? │?? │?? └── Dockerfile
│?? │?? ├── opensuse
│?? │?? │?? └── Dockerfile
│?? │?? └── ubuntu
│?? │?? └── Dockerfile
│?? ├── Makefile
│?? ├── README.md
│?? └── samples
│?? ├── Mizux.Sample.csproj
│?? └── Sample.cs
├── cmake
│?? ├── CMakeLists.txt.swig
│?? ├── cpp.cmake
│?? ├── dotnet.cmake
│?? ├── FooConfig.cmake.in
│?? └── swig.cmake
├── CMakeLists.txt
├── doc
│?? ├── full_pipeline.dot
│?? ├── full_pipeline.png
│?? ├── full_pipeline.svg
│?? ├── generate_image.sh
│?? ├── legend.dot
│?? ├── legend.png
│?? ├── legend.svg
│?? ├── local_pipeline.dot
│?? ├── local_pipeline.png
│?? └── local_pipeline.svg
├── dotnet
│?? ├── base.i
│?? ├── Directory.Build.props
│?? ├── FooApp.cs
│?? ├── FooTests.cs
│?? ├── logo.png
│?? ├── logo.svg
│?? ├── Mizux.FooApp.csproj.in
│?? ├── Mizux.Foo.csproj.in
│?? ├── Mizux.Foo.runtime.csproj.in
│?? └── Mizux.FooTests.csproj.in
├── Foo
│?? ├── CMakeLists.txt
│?? ├── dotnet
│?? │?? ├── CMakeLists.txt
│?? │?? └── foo.i
│?? ├── include
│?? │?? └── foo
│?? │?? └── Foo.hpp
│?? ├── src
│?? │?? └── Foo.cpp
│?? └── test
│?? ├── CMakeLists.txt
│?? └── src
│?? ├── Foo_UT.cpp
│?? └── main.cpp
├── LICENSE
└── README.md
21 directories, 51 files
2.1 Foo/src/Foo.cpp
#include "foo/Foo.hpp"
#include
2.2 Foo/include/foo/Foo.hpp
#pragma once
#include
2.3 Foo/dotnet/foo.i
其中/* */是本文追加注释
%module csFoo
/* c#没有普通函数,所有函数必须是类的成员函数,如何调用c++的普通函数呢,可以用csFoo.函数名来调用,比如csFoo.fooHello(12) */
%include "std_string.i"
/* 提供std::string接口 */
%include "base.i"
// Add necessary symbols to generated header
%{
#include
2.4 dotnet/base.i
%include "stdint.i"
%include "typemaps.i"
#if defined(SWIGCSHARP)
#if defined(SWIGWORDSIZE64)
// By default SWIG map C++ long int (i.e. int64_t) to C# int
// But we want to map it to C# long so we reuse the typemap for C++ long long.
// ref: https://github.com/swig/swig/blob/master/Lib/csharp/typemaps.i
// ref: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types
%define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE)
%clear NEW_TYPE;
%clear NEW_TYPE *;
%clear NEW_TYPE &;
%clear const NEW_TYPE &;
%apply TYPE { NEW_TYPE };
%apply TYPE * { NEW_TYPE * };
%apply TYPE & { NEW_TYPE & };
%apply const TYPE & { const NEW_TYPE & };
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, long long);
PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long);
#undef PRIMITIVE_TYPEMAP
#endif // defined(SWIGWORDSIZE64)
#endif // defined(SWIGCSHARP)
2.5 dotnet/FooApp.cs
using System;
using Mizux.Foo;
namespace FooApp {
class Program {
static void Main(string[] args) {
int level = 1;
Console.WriteLine($"[{level}] Enter FooApp");
Foo.Hello(level+1);
Console.WriteLine($"[{level}] Exit FooApp");
}
}
}
[1] Enter FooApp
[2] Enter Foo::hello(int)
[3] Enter fooHello(int)
[3] Exit fooHello(int)
[2] Exit Foo::hello(int)
[1] Exit FooApp
3 项目组织代码*.csproj代码分析
4 CMake构建、安装代码分析
4.1 CMakeLists.txt
# This file is just an orchestration
cmake_minimum_required(VERSION 3.14) ### cmake版本至少3.14
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") ###相当于 g++ -Icmake
###${CMAKE_CURRENT_SOURCE_DIR}指的是含有当前CMakeLists.txt的文件夹,即根目录
option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compile command" TRUE)
###设置了一个cmake build的参数,默认值为TRUE,具体作用应该在后面作为条件build的根据
project(Foo VERSION 1.0 LANGUAGES CXX)
###设置${PROJECT_NAME} = Foo, ${PROJECT_VERSION} = 1.0 语言是C++
message(STATUS "project: ${PROJECT_NAME}") ###打印 project: Foo
message(STATUS "version: ${PROJECT_VERSION}") ### version: 1.0
# Force default build type to Release
if(NOT CMAKE_BUILD_TYPE) ###cmake build时候可以用-DCMAKE_BUILD_TYPE=Release/Debug/...
### 设置build type是release还是debug还是其他,
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
###默认是Release,
###CACHE=global,表明这个type对其他cmake,CMakeLists文件有效
"Choose the type of build, options are: Debug, Release (default), RelWithDebInfo and MinSizeRel."
FORCE) ###如果CMAKE_BUILD_TYPE被其他调用该项目的项目设置过,这里则强制重新设置。
endif(NOT CMAKE_BUILD_TYPE)
# Layout build dir like install dir
include(GNUInstallDirs) ### 定义了一些安装所需要的路径变量,比如CMAKE_INSTALL_BINDIR用于安装执行程序的相对路径。
###(安装实际上就是复制build好的文件到指定的目录,以便系统调用)
if(UNIX)
option(BUILD_SHARED_LIBS "Build shared libraries(.so or .dyld)." ON) ###build 动态连接库,默认是TRUE
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
### 启用RPATH。当CMake build好可执行文件a.exe以及它所依赖的动态库b.so后,安装时会将他们复制到指定的目录中去,
### 根据系统不同,安装的绝对路径也不同,比如python3.6/...和python3.7/... 这样安装好的a.exe不可能通过绝对路径寻找b.so,因此RPATH
### 就用来提供寻找b.so的相对路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
### CMAKE_LIBRARY_OUTPUT_DIRECTORY = build/lib 存放build好的*.so或*.dll等动态库文件
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
### CMAKE_ARCHIVE_OUTPUT_DIRECTORY = build/lib 存放build好的*.a或*.lib等静态库文件
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
### CMAKE_RUNTIME_OUTPUT_DIRECTORY = build/bin 存放build好的可执行文件
# for multi-config build system (e.g. xcode)
foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
endforeach()
else()
# Currently Only support static build for windows
set(BUILD_SHARED_LIBS OFF) ###如果是windows,不产生动态库
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
# for multi-config builds (e.g. msvc)
foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) ###such as Debug, Release, RelWithDebInfo etc.
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) ###Debug => DEBUG
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
###CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG = build/DEBUG/bin
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
endforeach()
endif()
include(CTest) ###先跳过单元测试
if(BUILD_TESTING)
include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG master
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(Catch2)
endif()
include(cpp) ### include "cmake/cpp.cmake"
if(WIN32)
include(swig) ###include "cmake/swig.cmake"
endif()
include(dotnet) ###include "cmake/dotnet.cmake"
4.2 cmake/cpp.cmake
# Check primitive types
include(CMakePushCheckState) ###这几行不知道要干嘛
cmake_push_check_state(RESET)
set(CMAKE_EXTRA_INCLUDE_FILES "cstdint")
include(CheckTypeSize)
check_type_size("long" SIZEOF_LONG LANGUAGE CXX)
message(STATUS "Found long size: ${SIZEOF_LONG}")
check_type_size("long long" SIZEOF_LONG_LONG LANGUAGE CXX)
message(STATUS "Found long long size: ${SIZEOF_LONG_LONG}")
check_type_size("int64_t" SIZEOF_INT64_T LANGUAGE CXX)
message(STATUS "Found int64_t size: ${SIZEOF_INT64_T}")
check_type_size("unsigned long" SIZEOF_ULONG LANGUAGE CXX)
message(STATUS "Found unsigned long size: ${SIZEOF_ULONG}")
check_type_size("unsigned long long" SIZEOF_ULONG_LONG LANGUAGE CXX)
message(STATUS "Found unsigned long long size: ${SIZEOF_ULONG_LONG}")
check_type_size("uint64_t" SIZEOF_UINT64_T LANGUAGE CXX)
message(STATUS "Found uint64_t size: ${SIZEOF_UINT64_T}")
check_type_size("int *" SIZEOF_INT_P LANGUAGE CXX)
message(STATUS "Found int * size: ${SIZEOF_INT_P}")
cmake_pop_check_state()
add_subdirectory(Foo) ### include ../Foo/CMakeList.txt
# Install
include(GNUInstallDirs) ###和之前一样,取出一些预定义的安装路径变量
install(EXPORT ${PROJECT_NAME}Targets
###安装FooTargets中的Devel部分(命令最后COMPONENT=Devel)
###FooTargets在别的地方定义,build完之后,会产生一个FooTargets.cmake文件
###该文件用来让别的项目调用FooTargets
###用install(EXPORT 将FooTargets中的Devel部分安装到指定目录DESTINATION
NAMESPACE ${PROJECT_NAME}::
###在别的项目引用FooTargets的时候加上Foo::前缀
###即target_link_libraries(xxx Foo::FooTargets)
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
###${CMAKE_INSTALL_PREFIX}/lib/cmake/Foo
###linux 上 ${CMAKE_INSTALL_PREFIX}默认为/usr/local
###windows 上默认为 C:\Program Files
###注意默认的路径需要root账号才有写权限,
###可以通过cmake -DCMAKE_INSTALL_PREFIX=$HOME/Software/recipe-01 修改
COMPONENT Devel)
include(CMakePackageConfigHelpers) ###产生配置文件,这个文件用来检查一些文件是否存在
configure_package_config_file(cmake/${PROJECT_NAME}Config.cmake.in
### 配置cmake/FooConfig.cmake.in (将文件中的变量替换)并复制到
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" ###build/FooConfig.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
###再安装到lib/cmake/Foo下面
NO_SET_AND_CHECK_MACRO ###FooConfig.cmake中不含有set_and_check()
NO_CHECK_REQUIRED_COMPONENTS_MACRO) ###不含有 check_required_components()
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPATIBILITY SameMajorVersion) ###设置版本为主版本号
###CMake的版本格式为 Release:
include("${CMAKE_CURRENT_LIST_DIR}/FooTargets.cmake")
### CMAKE_CURRENT_LIST_DIR为当前文件所在的目录
4.3 Foo/CMakeLists.txt
add_library(Foo "") ###添加一个库
target_sources(Foo ###添加代码
PUBLIC
$
4.4 cmake/dotnet.cmake
# Will need swig
set(CMAKE_SWIG_FLAGS) ###设置一些swig的变量,比如set(CMAKE_SWIG_FLAGS -DPL_DOUBLE_INTERFACE -DSWIG_PYTHON)
###这里什么都没有设置,只是引入,后面会设置
find_package(SWIG REQUIRED) ###寻找SWIG
include(UseSWIG) ###include UseSWIG.cmake 参考https://github.com/Kitware/CMake/blob/master/Modules/UseSWIG.cmake
if(UNIX AND NOT APPLE)
list(APPEND CMAKE_SWIG_FLAGS "-DSWIGWORDSIZE64")
endif()
# Find dotnet
find_program(DOTNET_EXECUTABLE dotnet) ###寻找dotnet的执行文件,需要安装dotnet
if(NOT DOTNET_EXECUTABLE)
message(FATAL_ERROR "Check for dotnet Program: not found")
else()
message(STATUS "Found dotnet Program: ${DOTNET_EXECUTABLE}")
endif()
### ${DOTNET_EXECUTABLE} = dotnet
# Create the native library
###native是最初始的包装c++的库,可供c#调用
add_library(mizux-foo-native SHARED "") ###添加动态库mizux-foo-native
set_target_properties(mizux-foo-native PROPERTIES
PREFIX "" ###如果PREFIX = xxx则生成xxxmizux-foo-native.so
POSITION_INDEPENDENT_CODE ON) ###代码位置独立
###多个程序利用相同的动态库时,动态库只加载一遍,从而减小内存
###这个共享的动态库只有一个代码地址,与具体调用程序无关,所以是独立的
###具体参考 How to write shared libraries https://akkadia.org/drepper/dsohowto.pdf
# note: macOS is APPLE and also UNIX !
if(APPLE)
set_target_properties(mizux-foo-native PROPERTIES INSTALL_RPATH "@loader_path")
# Xcode fails to build if library doesn‘t contains at least one source file.
if(XCODE)
file(GENERATE
OUTPUT ${PROJECT_BINARY_DIR}/mizux-foo-native/version.cpp
CONTENT "namespace {char* version = \"${PROJECT_VERSION}\";}")
target_sources(mizux-foo-native PRIVATE ${PROJECT_BINARY_DIR}/mizux-foo-native/version.cpp)
endif()
elseif(UNIX)
set_target_properties(mizux-foo-native PROPERTIES INSTALL_RPATH "$ORIGIN")
###设置INSTALL_RPATH = $ORIGIN, $ORIGIN是指mizux-foo-native安装的目录,这句话说明安装后,
###mizux-foo-native.so 调用同一目录下的 libFoo.so
###xian@chaos:~/code/dotnet-native/build/lib$ ls
###libFoo.so libFoo.so.1.0 mizux-foo-native.so
endif()
set(DOTNET Mizux.Foo) ###${DOTNET} = Mizux.Foo
foreach(SUBPROJECT IN ITEMS Foo) ###foreach(SUBPROJECT IN ITEMS A B C ...)
add_subdirectory(${SUBPROJECT}/dotnet) ###include Foo/dotnet/CMakeLists.txt
target_link_libraries(mizux-foo-native PRIVATE dotnet_${SUBPROJECT})
###mizux-foo-native依赖于dotnet_Foo
###这里的PRIVATE是指调用mizux-foo-native的项目不需要知道dotnet_Foo的实现和接口。
###mizux-foo-native对dotnet_Foo的所有功能进行重新封装。
###具体参考 https://cmake.org/pipermail/cmake/2016-May/063400.html
endforeach()
file(COPY dotnet/logo.png DESTINATION dotnet) ###复制文件
file(COPY dotnet/Directory.Build.props DESTINATION dotnet)
###Directory.Build.props是.net的文件,为一组项目统一配置版本,作者等等
###接下来是一组lib或者可执行程序。这里选取Mizux.Foo.runtime.
文章标题:Ubuntu和Win 10下用CMAKE + SWIG 为C#写动态库
文章链接:http://soscw.com/index.php/essay/40502.html