Skip to content

Commit

Permalink
Add tlbimp (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
SergiusTheBest authored Aug 8, 2019
1 parent c3680aa commit 8f7d34b
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 16 deletions.
49 changes: 43 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
# FindIDL [![Build status](https://ci.appveyor.com/api/projects/status/github/apriorit/FindIDL?svg=true)](https://ci.appveyor.com/project/apriorit/findidl)
CMake module for building IDL files with MIDL
CMake module for building IDL files with MIDL and generating CLR DLL using Tlbimp.

* [Introduction](#introduction)
* [Requirements](#requirements)
* [Usage](#usage)
* [find_package()](#find_package)
* [add_idl()](#add_idl)
* [add_idl() with tlbimp](#add_idl-with-tlbimp)
* [MIDL flags](#midl-flags)
* [Samples](#samples)
* [License](#license)
* [Version History](#version-history)

# Introduction
IDL is used for creating COM servers. Unfortunately CMake has a limited support for IDL, so this module comes to rescue.
IDL is used for creating COM servers. Unfortunately CMake has a limited support for IDL, so this module comes to rescue. The Type Library Importer (Tlbimp) converts the type definitions found within a COM type library (TLB) into equivalent definitions in a common language runtime assembly. The output of Tlbimp.exe is a binary file (an assembly) that contains runtime metadata for the types defined within the original type library.

## Requirements
- [CMake 3.0](https://cmake.org/download/) or higher
- MIDL compiler
- Tlbimp.exe (optional)

# Usage
## find_package()
Expand All @@ -25,10 +27,10 @@ Add [FindIDL](https://github.com/apriorit/FindIDL) to the module search path and
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
find_package(IDL REQUIRED)
```
[FindIDL](https://github.com/apriorit/FindIDL) will search for midl.exe
[FindIDL](https://github.com/apriorit/FindIDL) will search for midl.exe and tlbimp.exe

## add_idl()
Takes two arguments: the name of the target project and idl file, possible with full path specified.
Takes two arguments: the name of the target project and idl file.
```cmake
add_idl(<name> source)
```
Expand All @@ -41,7 +43,7 @@ Example:
add_idl(GreeterIDL Greeter.idl)
```

The function makes the same work as MIDL, specifically generates files:
The function does the same work as MIDL, specifically generates files:
- Greeter_i.h
- Greeter_i.c
- Greeter_p.c
Expand All @@ -52,12 +54,44 @@ To use the generated files the idl project should be linked as following
target_link_libraries(Main GreeterIDL)
```

## add_idl() with tlbimp
Takes four arguments: the name of the target project, idl file, TLBIMP flag and the name of the tlbimp target.
```cmake
add_idl(<name> source TLBIMP <tlbimp name>)
```
Where:
- `<name>` - name of the target project
- `source` - full path to idl file
- `TLBIMP` - flag to indicate to run tlbimp
- `<tlbimp name>` - name of the tlbimp target

Example:
```cmake
add_idl(GreeterIDLWithTLBIMP Greeter.idl TLBIMP GreeterInterop)
```

The function does the same work as MIDL and tlbimp.exe, specifically generates files:
- Greeter_i.h
- Greeter_i.c
- Greeter_p.c
- Greeter.tlb
- GreeterInterop.dll

To use the generated files the idl project should be linked as following
```cmake
target_link_libraries(MainCpp GreeterIDL)
```
Or if you want to use the file generated by tlbimp:
```cmake
target_link_libraries(MainCsharp GreeterInterop)
```

## MIDL flags
It is possible to specify MIDL flags, such as midl command line keys.
```cmake
set(MIDL_FLAGS /target NT60)
```
Current can be useful to avoid MIDL2455 error.
This can be useful to avoid MIDL2455 error.

# Samples
Take a look at the [samples](samples/) folder to see how to use [FindIDL](https://github.com/apriorit/FindIDL).
Expand All @@ -67,5 +101,8 @@ Take a look at the [samples](samples/) folder to see how to use [FindIDL](https:

# Version History

## Version 1.0.1 (08 Aug 2019)
- New: Add tlbimp

## Version 1.0.0 (26 Oct 2018)
- Initial public release
56 changes: 53 additions & 3 deletions cmake/FindIDL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,58 @@ function(add_idl _target _idlfile)
VERBATIM
)

add_custom_target(${_target}_gen DEPENDS ${MIDL_OUTPUT} SOURCES ${_idlfile})
add_library(${_target} INTERFACE )
add_dependencies(${_target} ${_target}_gen)
set(FINDIDL_TARGET ${_target}_gen)

cmake_parse_arguments(FINDIDL "" "TLBIMP" "" ${ARGN})

if(FINDIDL_TLBIMP)
file(GLOB TLBIMPv7_FILES "C:/Program Files*/Microsoft SDKs/Windows/v7*/bin/TlbImp.exe")
file(GLOB TLBIMPv8_FILES "C:/Program Files*/Microsoft SDKs/Windows/v8*/bin/*/TlbImp.exe")
file(GLOB TLBIMPv10_FILES "C:/Program Files*/Microsoft SDKs/Windows/v10*/bin/*/TlbImp.exe")

list(APPEND TLBIMP_FILES ${TLBIMPv7_FILES} ${TLBIMPv8_FILES} ${TLBIMPv10_FILES})

if(TLBIMP_FILES)
list(GET TLBIMP_FILES -1 TLBIMP_FILE)
endif()

if (NOT TLBIMP_FILE)
message(FATAL_ERROR "Cannot found tlbimp.exe. Try to download .NET Framework SDK and .NET Framework targeting pack.")
return()
endif()

message(STATUS "Found tlbimp.exe: " ${TLBIMP_FILE})

set(TLBIMP_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

if("${TLBIMP_OUTPUT_PATH}" STREQUAL "")
set(TLBIMP_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
endif()

set(TLBIMP_OUTPUT ${TLBIMP_OUTPUT_PATH}/${FINDIDL_TLBIMP}.dll)

add_custom_command(
OUTPUT ${TLBIMP_OUTPUT}
COMMAND ${TLBIMP_FILE} "${MIDL_OUTPUT_PATH}/${IDL_FILE_NAME_WE}.tlb" "/out:${TLBIMP_OUTPUT}"
DEPENDS ${MIDL_OUTPUT_PATH}/${IDL_FILE_NAME_WE}.tlb
VERBATIM
)

add_custom_target(${FINDIDL_TARGET} DEPENDS ${MIDL_OUTPUT} ${TLBIMP_OUTPUT} SOURCES ${_idlfile})

add_library(${FINDIDL_TLBIMP} SHARED IMPORTED GLOBAL)
add_dependencies(${FINDIDL_TLBIMP} ${FINDIDL_TARGET})

set_target_properties(${FINDIDL_TLBIMP}
PROPERTIES
IMPORTED_LOCATION "${TLBIMP_OUTPUT}"
IMPORTED_COMMON_LANGUAGE_RUNTIME "CSharp"
)
else()
add_custom_target(${FINDIDL_TARGET} DEPENDS ${MIDL_OUTPUT} SOURCES ${_idlfile})
endif()

add_library(${_target} INTERFACE)
add_dependencies(${_target} ${FINDIDL_TARGET})
target_include_directories(${_target} INTERFACE ${MIDL_OUTPUT_PATH})
endfunction()
5 changes: 2 additions & 3 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.0)

project(FindIDL)
cmake_minimum_required(VERSION 3.8)

project(FindIDL LANGUAGES C CXX CSharp)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
Expand Down
6 changes: 4 additions & 2 deletions samples/Demo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
add_subdirectory(GreeterLib)
add_subdirectory(GreeterIDL)
add_subdirectory(Main)
add_subdirectory(GreeterIDLWithTLBIMP)
add_subdirectory(GreeterLib)
add_subdirectory(MainCpp)
add_subdirectory(MainCsharp)
Binary file modified samples/Demo/GreeterIDL/Greeter.idl
Binary file not shown.
1 change: 1 addition & 0 deletions samples/Demo/GreeterIDLWithTLBIMP/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_idl(GreeterIDLWithTLBIMP Greeter.idl TLBIMP GreeterInterop)
Binary file added samples/Demo/GreeterIDLWithTLBIMP/Greeter.idl
Binary file not shown.
2 changes: 0 additions & 2 deletions samples/Demo/Main/CMakeLists.txt

This file was deleted.

2 changes: 2 additions & 0 deletions samples/Demo/MainCpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_executable(MainCpp Main.cpp)
target_link_libraries(MainCpp GreeterIDL)
File renamed without changes.
2 changes: 2 additions & 0 deletions samples/Demo/MainCsharp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_executable(MainCsharp Main.cs)
target_link_libraries(MainCsharp GreeterInterop)
15 changes: 15 additions & 0 deletions samples/Demo/MainCsharp/Main.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using GreeterInterop;

namespace Samples
{
class Program
{
public static void Main(string[] args)
{
GreeterClass obj = new GreeterClass();
obj.greet();
Console.WriteLine("");
}
}
}

0 comments on commit 8f7d34b

Please sign in to comment.