Using C/CPP, you can’t avoid dealing with all kinds of header files. The system library is ok, basically do not need to worry about, has been automatically preset into the header file list. The tricky part is using third-party libraries, where you need to manually specify the location of the header and library files. This article documents the setup for compiling manually in a terminal versus in some tools.

Compile manually in terminal using GCC /clang/makefile

GCC -i /include -c test.c -o test.o GCC test.o -l /libs -o test The number of header files and library files is relatively large. It would be rather cumbersome if we wrote them one by one manually. So, pkG-config was born

In short, PKG-config provides the library with the ability to compile and link flags.

PKG – config installation

brew install pkg-config
Copy the code

Pkg-config Common command

  • pkg-config --help: View help
  • pkg-config --list-all: Lists all the libraries currently on the system that support PKG-config
  • PKG - config -- cflags glib - 2.0: Specifies a header file
  • PKG - config - libs glib - 2.0: Specifies the library file

Pkg-config also has other functions. You can see all available commands through pkg-config –help

Compile at the terminal using PKg-config

The most basic usage is simply to write pkG-config –cflags –libs glib-2.0 as one of the arguments to GCC.

# Note 'grave/tilde key, not single quotes
$gccC 'pkg-config --cflags --libs glib-2.0' -o mainCopy the code

Principle of PKG-config and custom location

Pkg-config uses a.pc file defined by a third-party library to locate header files and library files. For example, glib’s PC file looks like this:

The prefix = / usr/local/Cellar/glib / 2.66.7 libdir = ${prefix} / lib includedir = ${prefix} / include bindir = ${prefix} / bin glib_genmarshal=${bindir}/glib-genmarshal gobject_query=${bindir}/gobject-query glib_mkenums=${bindir}/glib-mkenums Name: GLib Description: C Utility Library Version: 2.66.7 Requires. Private: libpcre >= 8.31 - L ${libdir} - lglib - 2.0 - L/usr/local/opt/gettext/lib - lintl Libs. Private: -Wl,-framework,CoreFoundation -Wl,-framework,Carbon -Wl,-framework,Foundation -Wl,-framework,AppKit -liconv -lm Cflags: -i ${includedir} / glib - 2.0 - I ${libdir} / glib - 2.0 / include - I/usr/local/opt/gettext/includeCopy the code

Can see very clearly that glib in the/usr/local/Cellar/glib / 2.66.7 / lib/pkgconfig/glib – 2.0 PC has been defined in the relevant key information, such as Libs and Cflags. By default glib makes a soft link to its PC file in /usr/local/lib/pkgconfig

Some software may not automatically create soft links, or we may need to customize a.pc file. In this case, we need to add the following configuration to.zshrc:

/usr/local/lib/pkgconfig = /usr/local/lib/pkgconfig
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opt/zlib/lib/pkgconfig
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opt/ruby/lib/pkgconfig
export PKG_CONFIG_PATH
Copy the code

GCC main.c ‘pkg-config –cflags –libs zlib’ -o main pkg-config will automatically find the corresponding.pc file

Configure header files in VIm

Youcompleteme dependency header file path

The header file paths that yCM relies on for completion are:

  • C_INCLUDE_PATH/CPP_INCLUDE_PATH of the system

  • ~/. Vimrc set path=***

  • The.ycm_extra_conf file defined in yCM

    Ycm’s.ycm_extra_conf.py I usually define in.vimrc as a fixed configuration

    # ~/.vimrc
    let g:ycm_global_ycm_extra_conf = '~/.ycm_extra_conf.py' "Default configuration file path
    Copy the code

    In the ~/.ycm_extra_conf.py file, flags represents the configuration options we use, where /usr/local/include represents a hint to complete the Homebrew installed header file, or add a custom path if not enough

    # ~/.ycm_extra_conf.py
    flags = [
    '-Wall'.'-Wextra'.'-Werror'.'-fexceptions'.'-DNDEBUG'.'-std=c11'.'-x'.'c'.'-isystem'.'/usr/include'.'-isystem'.'/usr/local/include'.# Important, most of the headers installed via Homebrew are here
    '-isystem'.'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/.. /lib/c++/v1'.'-isystem'.'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include',]Copy the code

    Of course, if each third-party library path needs to be added manually, it would be too cumbersome. We can simply import the system pkg-config output into flags as a path

    # ~/.ycm_extra_conf.py
    Add header file path to YCM completion easily via pkg-config
    def pkg_config(pkg) :
      def not_whitespace(string) :
        return not (string == ' ' or string == '\n')
      output = subprocess.check_output(['pkg-config'.'--cflags', pkg]).decode().strip()
      return list(filter(not_whitespace, output.split(' ')))
    
    flags += pkg_config('glib-2.0')
    Copy the code

All of the above paths can play an auxiliary role in yCM completion.

The header file path on which ALE depends

Ale is a Lint tool that supports many languages. Ale is actually a collection of linters for different languages, so we can just choose one of them. For example, I chose Clangd as a LINter for C/CPP. Ale provides setup options for each linter, and Clangd is no exception:

# ~/.vimrc
/usr/local/lib/pkgconfig = /usr/local/lib/pkgconfig
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opt/zlib/lib/pkgconfig
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opt/ruby/lib/pkgconfig
export PKG_CONFIG_PATH

CPPFLAGS+=$(pkg-config --cflags glib-2.0 zlib ruby-3.0)
exportCPPFLAGS CFLAGS+=$(pkg-config -- CFLAGS glib-2.0 zlib ruby-3.0)export CFLAGS

LDFLAGS+="-I/usr/local/opt/openjdk/include"
LDFLAGS+=$(pkg-config --libs glib-2.0 zlib ruby-3.0)
export LDFLAGS
Copy the code
let g:ale_linters= {\'c': ['clangd'], and \'cpp': ['clangd'], and \'markdown': ['markdownlint'], and \}let g:ale_c_clangd_options = $CFLAGS
let g:ale_cpp_clangd_options = $CFLAGS
let g:ale_markdown_markdownlint_options='-c $HOME/.markdownlint.json'
Copy the code

Here I use CFLAGS in ~/.zshrc to export the custom header configuration, which can be defined in one place and used in multiple places

The path to the header file on which the compile run depends

Skywind3000 /asyncrun: skywind3000/asyncrun: skywind3000/asyncrun: skywind3000/asyncrun: skywind3000/asyncrun: skywind3000/asyncrun: skywind3000/asyncrun: skywind3000/asyncrun

map <F2> : call Run()<CR>

func Run()
    exec 'w'
    if &filetype= ='c'
        exec 'AsyncRun! GCC 'pkg-config --cflags --libs glib-2.0' -wall -o2 "$(VIM_FILEPATH)" -o "$HOME/. Cache /build/C/$(VIM_FILENOEXT)" && "$HOME/.cache/build/C/$(VIM_FILENOEXT)"'
    elseif &filetype= ='java'
        exec 'AsyncRun! javac %; time java %<'
    elseif &filetype= ='sh'
        exec "AsyncRun! time bash %"
    elseif &filetype= ='python'
        exec 'AsyncRun! time python3 "%"'
    endif
endfunc
Copy the code

So in the C file, just press

to execute immediately

Xcode configures header files and library files

TARGETS -> Build Settings -> Search Path -> Header Search Paths/Library Search Paths set the corresponding Header and Library file Paths

conclusion

There are different ways to configure header and library files, but all revolve around how to easily list the paths to header and library files for compiling links. Mastering this point, we can try to solve the problem according to this idea even when using other tools.

reference

  • Principle and usage of PKg-config