Porting Dependent Library
Porting Dependent Library
The following example demonstrates how to port two C# library projects from which one depends on another. We’ll use pre-existing projects from DependentLibrary example located here.
This example consists of two C# projets – CommonLib and DependentLibrary.
Porting CommonLib
CommonLib is a library project consisting of a single .cs source file SomeClass.cs and a project file CommonLib.csproj. This project does not have any special dependenies on other projects or 3-rd party assemblies. Also CommonLib project directory contains precreated configuration file CommonLib.porter.config
. Let us have a closer look at the configuration file.
CommonLib.porter.config is quite simple. It begins with an XML declaration, which specifies that the file contains an XML document.
Then goes the XML root element <porter> which is mandatory for Porter configuration XML document
<porter>
Next, the default Porter configuration file is imported using <import> element. The default configuration assigns default values to all configuration options.
<import config="porter.config"/>
And the XML document is finished with closing tag of the root element <porter>:
</porter>
This example assumes that C# CommonLib library project should be ported into a C++ static library project, which is a default setting.
With C# project and configuration file ready, we can convert the project.
In order to covert BaseLibrary project we run CMD and navigate to the directory with porter binary:
>cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
And run Porter:
>CsToCppPorter.exe -c C:\DependentNUnitTest\CommonLib\CommonLib.porter.config C:\DependentNUnitTest\CommonLib\CommonLib.csproj C:\output
Porter will print some logs of the porting process to the console window and when it finishes porting, directory C:\output
will contain a directory named CommonLib.Cpp
containing the generated C++ source files and Cmake configuration files.
Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the C:\output\CommonLib.Cpp
directory
>cd C:\output\BaseLibrary.Cpp
And run Cmake in configuration mode:
>Cmake --G "Visual Studio 15 2017"
And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:
>Cmake --build . --config Release
The library is built.
Porting DependentLibrary
DependentLibrary is a library C# project that consist of a single .cs source file SomeOtherClass.cs and a project file DependentLibrary.csproj
. This project has a dependency on previously ported project CommonLib. This dependency has to be reflected in the DepedentLibrary project’s configuration file. In our example this configuration file is pre-created, its name is DepedentLibrary.porter.config
and it is located in the project’s directory DependentLibrary
. Let us have a closer look at the configuration file.
DependentLibrary.porter.config begins with an XML declaration, which specifies that the file contains an XML document
Then goes the XML root element <porter> which is mandatory for Porter configuration XML document
<porter>
Next, the default Porter configuration file is imported using <import> element. The default configuration will assign default values to all configuration options
<import config="porter.config"/>
Also we need to import a configuration file include_map.config from ported CommonLib project that maps public types exported by CommonLib library to generated C++ header files in which these types are declared. include_map.config is generated by Porter for each project it ports. Thus, before porting DependentLibrary project, CommonLib project has to be ported first so that Porter generates include_map.config. This is how include_map.config is included in DependentLibrary.porter.config
<import config="../../output/CommonLib.Cpp/include_map.config" />
Here ../../output is a directory that was passed as an output directory to Porter when CommonLib project was ported.
This example assumes that C# project DependentLibrary should be ported into C++ shared/dynamic library project, therefore we assign value ‘true’ to make_shared_lib option:
<opt name="make_shared_lib" value="true" export_per_member="true"/>
Next, we want Porter to add some commands to the output CMakeLists.txt file. We do that by adding <cmake_commands> element to the configuration file containing raw Cmake commands
<cmake_commands>
<![CDATA[
The following commands set the output directory for the library’s binary by setting the corresponding properties on the target ${PROJECT_NAME}:
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
Here ${PROJECT_NAME} is the name of the Cmake project which is equal to the name of the main Cmake executable target.
Because on “DLL-platforms” (i.e. Windows) a DLL shared library is considered by Cmake an executable entity and on “non-DLL-platforms” (i.e. Linux) a shared object is considered by Cmake a library, we set both RUNTIME_OUTPUT_DIRECTORY and LIBRARY_OUTPUT_DIRECTORY properties.
Then the <cmake_commands> element is closed
]]>
</cmake_commands>
Then, we need to tell Porter that DependentLibrary project depends on CommonLib library. We do it using <lib> element:
<lib name="CommonLib.Cpp" csname="CommonLib">
<cmake_link_template>
<![CDATA[
find_package(CommonLib.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../CommonLib.Cpp" NO_DEFAULT_PATH)
target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE CommonLib.Cpp) ]]>
</cmake_link_template>
</lib>
Here ${PROJECT_NAME}dependencies is the name of the Cmake Interface Library target that is defined in the output _CMakeLists.txt file and is linked to main executable target ${PROJECT_NAME}. Thus libraries linked to ${PROJECT_NAME}_dependencies get automatically linked to ${PROJECT_NAME} target.
Finally the XML document is finished with closing tag of the root element <porter>
</porter>
With the C# project at hand and configuration file ready, we can convert the project.
In order to covert DependentLibrary project we run CMD and navigate to the directory with porter binary:
>cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
And run Porter:
>CsToCppPorter.exe -c C:\DependentLibrary\DependentLibrary\DependentLibrary.porter.config C:\DependentLibrary\DependentLibrary\DependentLibrary.csproj C:\output
Porter will print some logs of the porting process to the console window and when it finishes porting, directory C:\output
will contain a directory named DependentLibrary_.Cpp_ containing the generated C++ source files and Cmake configuration files.
Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the C:\output\DependentLibrary.Cpp
directory
>cd C:\output\DependentLibrary.Cpp
And run Cmake in configuration mode:
>Cmake --G "Visual Studio 15 2017"
And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:
>Cmake --build . --config Release
When build finishes, directory D:\output\bin\Release should contain two files: DependentLibrary.dll
, which has just been built from C++ sources, and aspose_cpp_vc140.dll
, which was copied from Porter installation directory during a post-build step.