Giter Site home page Giter Site logo

ifc-reader's Introduction

IFC Reader

This is C++ library for reading ifc-files (ifc-core and its more user friendly interface reflifc) and 2 optional extra tiny libraries, namely ifc-msvc and ifc-blob-reader. The reason for this separation is the following: ifc-core and reflifc don't want to know anything about files, configs and so on. The entry point for IFC-reading -- ifc::File -- is constructed from BlobView and how to get BlobView is responsibility of library users.

Tests and examples do it via single-function library ifc-blob-reader wrapping Boost::iostreams.

One more issue arising during inspecting IFC is how to process cross-module references. For example, the following module interface

export module hello;

import <string_view>;

export namespace hello {
  void say_hello(std::string_view name);
}

depends on type std::string_view defined in outer header unit <string_view> (see struct DeclReference). Conseqeuntly during inspecting some ifc-file it may be necessary to find other ifc-files. How to do it is not specified in IFC specification itself and depends on a compiler/build system. In ifc-core this is done via class Environment receiving Config and library ifc-msvc provides such config, reading it from .json produced by MSVC.

How to use

This project contains a demonstration application dump-decls, which allows you do display the declarations in an IFC file.

To use dump-decls (or to generate information that can be loaded by ifc-reader), you need to compile your module into its IFC file, as well as generating its associated "source dependencies".

For example, consider the following file (based on hello.mxx), but it should be called something like hello.cpp, as .mxx is not an extension recognised by MSVC:

export module hello;

import std.core;

export namespace hello {
  void say_hello(uint32_t count);
}

You need compile this MSVC and generate its "source dependencies":

cl.exe /W4 /WX /experimental:module /interface /sourceDependencies . /std:c++latest /EHsc /MD /c hello.cpp

This will generate two files:

  • hello.ifc -- the binary module interface (that this repository aims to parse); and

  • hello.cpp.json -- the source dependencies for hello.cpp (note: the name of this .json is the name of your source file and not the name of your module; if your module has a different name, then the name of the IFC may not match your source file name)

The source dependencies look something like:

{
    "Version": "1.1",
    "Data": {
        "Source": "C:\\path\\to\\src\\hello.cpp",
        "ProvidedModule": "hello",
        "Includes": [],
        "ImportedModules": [
            {
                "Name": "std.core",
                "BMI": "C:\\path\\to\\visual_studio\\MSVC\\14.30.30705\\ifc\\x64\\release\\std.core.ifc"
            }
        ],
        "ImportedHeaderUnits": []
    }

You can then call dump-decls as follows:

/path/to/ifc-reader/build/examples/dump-decls/dump-decls.exe hello.ifc

which will give you (at the time of writing):

IFC Version: 0.40
File contains 14 partitions
Global Scope Index: 1
Total declarations count: 2
Scopes count: 2
Count of declarations from all scopes: 2
-------------------------------------- Global Scope --------------------------------------
Namespace 'hello' {
  Function 'say_hello', type: void(unsigned int)
}

A note on wine

If you wish to use cl.exe under wine but compile ifc-reader natively under Linux, then this is possible, but you must correct the paths in the source dependencies to point to native file paths before calling dump-decls. For example, if cl.exe (when run under wine) gives you:

  • z:\\home\\avj\\clones\\ifc-reader\\how_to\\hello.cpp

in the source dependencies, then you need to edit the json to have:

  • /home/avj/clones/ifc-reader/how_to/hello.cpp

which is the output from:

  • readlink -f $(wine64 winepath -u "z:\\home\\avj\\clones\\ifc-reader\\how_to\\hello.cpp")

After changing all paths to be their Linux equivalents, you can then load your IFC file with dump-decls

Building from source

Dependencies

ifc-core and reflifc don't have external dependencies, but require C++20 for compilation.

ifc-blob-reader depends on Boost::iostreams for crossplatform implementation of file mapping.

ifc-msvc depends on nlohmann::json for reading .json configs produced by MSVC.

Tests depend on GoogleTest.

Build

  1. If tests or examples are needed, then install required dependencies, mentioned above. It not, then go to step 1.
  2. Just run CMake, something like this should be enough:
mkdir build
cd build
cmake ..

To build tests switch on CMake option BUILD_IFC_READER_TESTS, to build examples -- BUILD_IFC_READER_EXAMPLES (see top-level CMakeLists.txt).

Windows

Vcpkg could be used for fetching dependencies. If it's not installed yet, you could run the following commands for pulling package manager itself:

git clone https://github.com/microsoft/vcpkg
cd vcpkg
bootstrap-vcpkg.bat

And then install dependencies (required for both tests and examples):

vcpkg.exe install boost-iostreams:x64-windows
vcpkg.exe install nlohmann-json:x64-windows

and GoogleTest required only for tests:

vcpkg.exe install gtest:x64-windows

After that you could generate normal Visual Studio solution:

mkdir build
cd build
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake ..

or work with CMake directly in Visual Studio.

Visual Studio

From Visual Studio, open CMakeLists.txt

After cmake wizard pops up, open the CMake Settings Editor

In CMake toolchain file - browse and select vcpkg\scripts\buildsystems\vcpkg.cmake

Delete cache, generate cache.

Build solution normally.

ifc-reader's People

Contributors

andreyg avatar aytey avatar fireflyforlife avatar tapika avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

ifc-reader's Issues

`uint32_t` becomes `Unsupported DeclSort '8'`

Issue

I've just been revisiting my steps from:

which work apart from the MSVC hello.cpp.json needs to renamed to hello.ifc.d.json (but that's fine).

However, when I run dump-decls on this example:

export module hello;

import std.core;

export namespace hello {
  void say_hello(uint32_t count);
}

I get:

IFC Version: 0.43
File contains 18 partitions
Global Scope Index: 1
Total declarations count: 2
Scopes count: 2
Count of declarations from all scopes: 2
-------------------------------------- Global Scope --------------------------------------
Namespace 'hello' {
  Function 'say_hello', type: void(Unsupported DeclSort '8')
}

So I'm surprised I'm seeing Unsupported DeclSort '8' rather than uint32_t (the 8 is also weird, because if this was bytes it should be 4).

Is this expected? Should I be able to see uint32_t here?

Notes

The IFC was generated with:

cl.exe /Bv
Microsoft (R) C/C++ Optimizing Compiler Version 19.40.33521 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

Compiler Passes:
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\cl.exe:        Version 19.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\c1.dll:        Version 19.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\c1xx.dll:      Version 19.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\c2.dll:        Version 19.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\c1xx.dll:      Version 19.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\link.exe:      Version 14.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\mspdb140.dll:  Version 14.40.33521.0
 Z:\home\avj\visual_studio\MSVC\14.40.33521\bin\Hostx64\x64\1033\clui.dll: Version 19.40.33521.0

Allow reflifc types to be assignable.

Currently I see that most types have a reference back to their file as ifc::File const&. This is considered bad practice because it makes the type not copy/move assignable. I suggest keeping the references in the constructor to keep the invariance, but store a pointer in the class.

This is also backed up by the C++ Core Guidelines C.12.

Remove boost dependency

Currently ifc-reader depends on boost-iostreams for memory mapping the ifc file.

I propose letting this be application defined, and which means they can use boost-iostreams themselves, or use something more lightweight like mio, or just reading a file the normal way.

Then the ifc-reader would only need to accept a const char*, similar to raw_pdb for example.

We could still have boost-iostreams as a dependency for our examples & unit tests. Just have it not be required for any applications that want to use this as a library.

Let me know what you think!

Ability to get reflifc::Module from any reflifc object.

All reflifc types combine the ifc::File and some pointer/index, however the file is never exposed.

This might be partly a design decision, but for my current use case I need to check if a certain type/declaration from a certain module (so ifc::File, or reflifc::Module). To determine if a type is visibility or reachable.

Do you have any concerns with adding this to the API?

Make reflifc types hashable and Comparable.

For my use cases I really need to cache declarations etc to avoid circular dependencies. While traversing all types.

Most of the reflifc types are build as: ifc::File* + ifc::SomeIndex or ifc::PartitionData*.
Those two numbers can easily be hashed together with a hash combine. But I cannot do it outside the library as the members are private.

Would you like me to work on a pull request for this? Or would you prefer to put it in yourself.

`d.json` suffix doesn't match MSVC

With cl.exe @ 19.30.30705.0, compiling the following:

cl.exe /W4 /WX /experimental:module /interface /sourceDependencies . /std:c++latest /EHsc /MD /c mod_moo.cpp

where the argument to /sourceDependencies is ., then MSVC gives you:

mod_moo.cpp.json

There are two things here:

  1. ifc-reader looks for the suffix .d.json, but the output from MSVC is just .json
  2. ifc-reader looks for <ifc_name>.<suffix> but MSVC generates <src_file_name>.<suffix> (that is, the name of the output file is the name of the source file and not the name of the IFC file)

Maybe a suggested fix here should be that ifc-reader could take an additional argument for the path to the source dependencies file?

License

Hi @AndreyG,

Thanks for the great work you've done on this project so far, it looks seriously awesome!

I'd be interested in playing around with some of your code, but I'm hesitant to do so without their being a license on the repo -- would you be able to add one? MIT would be awesome, if you'd be happy with that.

Thanks!

Name implementation not complete yet

I ran into an issue where I wanted to access the conversion function name, which wasn't exposed yet.

So I fully implemented the Name kinds and structures, submitted as PR #34.

reflifc default constructibility of types

In principle, reflifc wraps an AbstractReference with the accompanying ifc File. These both have sane defaults. An AbstractReference has AbstractReference::is_null() and the file can be nullptr.

I wanted to start a discussion, if making these types default constructible was something you had already considered. I've found it nice if I can default construct them.

Unit testing

It would be good to have some unit tests to maintain the library, as you mentioned too.

The simple approach would be to upload a bunch of .ifc files for specific tests.

However, I'd argue it's also important to build those .ifc's from source code. So you are verifying a platform instead of just the platform of the developer who uploaded that specific .ifc file. So I prefer this approach.

My issue is I am not aware of a reliable way to get the path to a .ifc file from a .ixx file.
Eg Visual Studo Open Folder (so with Ninja as the build system) will follow relative subfolders to the .ifc file, and a .sln build will plonk everything in the intermediate directory.

Do you think this be abstracted in the MSVCEnvironment? we could have different defines identifying if we are running from CMake, Visual Studio, Ninja or MSBuild for example.

(Incidently this linking of an .ixx to it's .ifc file is something I need to solve for my own side project too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.