1

Given:

  • a C file with several included header files
  • a bunch of include file search folder

Is there a way to generate some kind of include map for the C file?

Though IDEs can sometimes help locate the definition/declaration of a symbol in the header file. But I think an include map can give me a better insight into how these files are related when project gets complicated. And identify issues such as circular includes.

ADD 1

A similar thread but not much helpful.

  • It only generates an include hierarchy in text in the Output window when building.
  • And it only works for native VC++ project. Not work for NMAKE C project.

Displaying the #include hierarchy for a C++ file in Visual Studio

ADD 2

I just tried the Include Manager mentioned in above thread. Though not free, it's not expensive and perfectly fits in my scenario.

Community
  • 1
  • 1
smwikipedia
  • 61,609
  • 92
  • 309
  • 482
  • I think these may help [Detecting superfluous #includes?](http://stackoverflow.com/q/614794/995714), [Tools to find included headers which are unused?](http://stackoverflow.com/q/1301850/995714) – phuclv Mar 08 '17 at 02:15

2 Answers2

2

Not sure if this is quite what you're after, but I was curious what a graph of this would look like, so I threw this together. It's a bit of a mess, but workable for a throw-away script:

#!/bin/bash

INCLUDE_DIRS=()

# Add any include dirs here
# INCLUDE_DIRS+=("/usr/include")

# If you want to add flags for some pkg-config modules (space
# separated)
PKG_CONFIG_PKGS=""

FOLLOW_SYS_INCLUDES=y



while read dir; do
    dir="$(readlink -f "${dir}")"
    for d in "${INCLUDE_DIRS[@]}"; do
    if [ "${dir}" = "${d}" ]; then
        continue
    fi
    done

    INCLUDE_DIRS+=("${dir}")
done < <(echo | cc -Wp,-v -x c - -fsyntax-only 2>&1 | grep '^ ' | cut -b2-)

PROCESSED=()

while read flag; do
    if [ -n "${flag}" ]; then
    INCLUDE_DIRS+=("${flag}")
    fi
done < <(pkg-config --cflags-only-I "${PKG_CONFIG_PKGS}" | sed -E 's/-I([^ ]*)/\1\n/g')

function not_found {
    echo "  \"$1\" [style=filled,color=lightgrey];"
    echo "  \"$2\" -> \"$1\""
}

function handle_file {
    filename="${1}"
    for f in "${PROCESSED[@]}"; do
    if [ "${f}" = "${1}" ]; then
        echo "  \"$2\" -> \"$1\""
        return
    fi
    done

    PROCESSED+=("$1")
    if [ -n "${2}" ]; then
    echo "  \"${2}\" -> \"${1}\";"
    fi

    if [ ! "${FOLLOW_SYS_INCLUDES}" = "y" ]; then
    for d in "${INCLUDE_DIRS[@]}"; do
        case "${1}" in
        "${d}"/*)
            return
            ;;
        esac
    done
    fi

    parse_file "$1"
}

function handle_include {
    case "${1}" in
    /*)
        handle_file "${name}" "$2"
        return
        ;;
    esac

    for dir in "${INCLUDE_DIRS[@]}"; do
    if [ -f "${dir}/${1}" ]; then
        handle_file "${dir}/${1}" "$2"
        return
    fi
    done

    not_found "${1}" "${2}"
}

function handle_include_2 {
    case "${1}" in
    /*)
        handle_file "${1}" "$2"
        return
        ;;
    esac

    FILE="$(readlink -f "$(dirname "${2}")/${1}")"
    if [ -f "${FILE}" ]; then
    handle_file "${FILE}" "$2"
    fi
}

function parse_file {
    while read name; do
        handle_include "$name" "$1";
    done < <(grep '^[ \t]*#[ \t]*include <' "$1" | sed -E 's/[ \t]*#[ \t]*include ?<([^>]+)>.*/\1/')

    while read name; do
        handle_include_2 "$name" "$1" "$PWD";
    done < <(grep '^[ \t]*#[ \t]*include "' "$1" | sed -E 's/[ \t]*#[ \t]*include \"([^"]+)\"/\1/')
}

echo "digraph G {"
echo "graph [rankdir = \"LR\"];"
parse_file "$(readlink -f "${1}")" "" "$PWD"
echo "}"

Pass it a file and it will generate a graphviz file. Pipe it to dot:

$ ./include-map.sh /usr/include/stdint.h | dot -Tx11

And you have something nice to look at.

nemequ
  • 16,623
  • 1
  • 43
  • 62
0

Recently almost any of the featured IDE can help you in that built in.Visual Studio or Jetbrain's Clion are proper for that. You did not wrote neither platform or environment, but maybe it worth to give a try even with efforts to properly set the project that compiles. Back in days I found also useful to generate documentation with doxygen, as I remember that will also create such maps /links/ as well.

Schwarzy
  • 1
  • 1