How to ensure a generated config.h file is in the include path? - c

I use CMake to build a C project. Specifically, I use the following line:
configure_file(config.h.in config.h #ONLY)
this works fine as long as I build in the source directory. However, if I build elsewhere, the config.h file is created in /path/to/build/dir/config.h rather than in the source directory - and that's not part of the include path. How can I have CMake...
Ensure this specific file is included, or
Have the C compiler look both under the original source dir and under the build dir for include files?

There is an automatism for include directories with CMAKE_INCLUDE_CURRENT_DIR in CMake:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
If this variable is enabled, CMake automatically adds CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR to the include path for each directory.
So I prefer to individually have the following call on a need-by basis in my CMakeLists.txt:
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
Edit: Thanks for the hint of #zaufi, if your generated header file has a target scope then you should prefer (CMake >= Version 2.8.12) to make it only visible to that target (not globally to all targets) with:
target_include_directories(MyLibrary PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
Note: For source files with relative paths CMake looks in both directories CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR.

Related

What is the directory the header file is included from?

I have a C project with multiple include directories that hold header files with same names but different content. So how can I know which one is included to my main program.
IDE - Eclipse
Compiler - IAR for MSP430
Build - Makefiles
If your includes use the <[file.h]> form, it depends on the include search path of your preprocessor. For gcc, any -I option will append a path to the include search path. The first matching file is used, so the order of -I options matters.

Adding custom path to gcc command

i know there a a few posts already about this but I do not seem to be able to get it right.
I am working on a shared project using geany and gcc. The file structure looks something like this:
`/Documents/.../project/ main directory of project with makefile`
`/Documents/.../project/src here are some sourcefiles and headers`
`/Documents/.../project/src/extended here are some other source and header files`
`/Documents/.../project/src/tools other header and source files`
now lets say I am working on a sourcefile in /tools that includes from extened with
#include"/extended/some_header.h"
because my makefile is configured to search for files from /src. However when I am trying to compile the file I am working on right now (by using geany compile option which just calls gcc) I cannot compile it obviously because it cannot find /extended/some_header.h in the /src folder. I have tried adding
-iquotes/Documents/.../project/src
to the gcc call by geany but it doesn't work either.
The -I flag tells the gcc compiler where it should look for the header files. Passing the -Idir to the compiler is appending the dir path to the head of the search list, effectively making this path higher priority than the previously (or system) defined paths. As for the source path - there is no such an option for gcc itself. Each source file passed to the compiler has to have it's path (absolute or relative). In order to work it around, a Makefile can be provided, defining a list of files to be compiled.

CMAKE - How to properly copy static library's header file into /usr/include?

I'm getting into CMAKE usage with C and actually I'm creating two very small static libraries.
My goal is:
The libraries are compiled and linked into *.a files. [THIS
WORKS]
Then I wish to copy that *.a files into /usr/local/lib [THIS ALSO WORKS]
As far as I know about libraries (very little), they are linked using -lnameoflib, which is a compiler flag. OK. I have prepared my CMakeLists.txt and it actually copies *.a files into /usr/local/lib. However, to be able to use them in a program, I also need to copy their header files into /usr/local/include, then I can include them the easy way #include <mylibheader.h>. That's how I understand it now.
And my question is - how is the proper way of copying header files into /usr/include folder with CMAKE? I would like it to copy them automatically when make install is executed, like *.a files are.
For both of the libraries I have a smiliar CMakeLists.txt:
project(programming-network)
add_library(programming-network STATIC
send_string.c
recv_line.c
)
INSTALL(TARGETS programming-network
DESTINATION "lib"
)
A better way for newest cmake version is to use target's PUBLIC_HEADER properties.
project(myproject)
add_library(mylib some.c another.c)
set_target_properties(mylib PROPERTIES PUBLIC_HEADER "some.h;another.h")
INSTALL(TARGETS mylib
LIBRARY DESTINATION some/libpath
PUBLIC_HEADER DESTINATION some/includepath
)
Some ref:
PUBLIC_HEADER
CMake install command
In a much better way, will copy all files that match the pattern and will preserve the directory structure.
INSTALL (
DIRECTORY ${CMAKE_SOURCE_DIR}/include/
DESTINATION include
FILES_MATCHING PATTERN "*.h*")
Years later, with CMake 3.23, we can use FILE_SET for public headers:
project(programming-network)
add_library(programming-network STATIC)
target_include_directories(programming-network PRIVATE "${PROJECT_SOURCE_DIR}")
target_sources(programming-network
PRIVATE send_string.c recv_line.c
PUBLIC FILE_SET HEADERS
BASE_DIRS ${PROJECT_SOURCE_DIR}
FILES publicheader1.h publicheader2.h)
install(TARGETS programming-network FILE_SET HEADERS)
Now let's see what these commands do:
add_library(): defines the name of the target, STATIC for a static library, SHARED for a shared library, OBJECT for objects.
target_include_directories(): this line here is only for when you have subdirectories and private headers referencing each other relative to the project directory. But generally, this command is used for including external headers in a project.
target_sources(): This command is used to add definition files and private headers with PRIVATE keyword. Also, it is used to add public headers via FILE_SET keyword. BASE_DIRS is to turn the absolute path of public headers into a relative path by deducting the base directory from their path. So the this public header
/home/someuser/programming-network/sub1/publicheader1.h
with base dir of
/home/someuser/programming-network/
will be installed in
/cmake/install/prefix/include/sub1/publicheader.h
Note target_sources() can be used in CMakeLists.txt of subdirectories as well.
install(): is to install binaries, static/shared libraries and public headers. The default installation subdirectories are bin, lib and include. You can also change that like this
install(TARGETS myTarget
# for executables and dll on Win
RUNTIME DESTINATION bin
# shared libraries
LIBRARY DESTINATION lib
# for static libraries
ARCHIVE DESTINATION lib
# public headers
INCLUDES DESTINATION include)
And finally, the project is built and installed with (for multi-configuration generators: MS Visual C++, Xcode)
# in project directory
mkdir build
cd build
cmake ..
cmake --build . --config Release
cmake --install . --prefix "/usr/local/" --config Release
For single-configuration generators (make, Ninja), drop the above --config Release terms and change cmake .. to cmake -DCMAKE_BUILD_TYPE=Release ...
I don't think your solution is the correct one. /usr/include should be reserved for your vendor to put files in.
The proper thing to do IMO is to install the header in /usr/local/include and then instruct the user to export CPATH="/usr/local/include:${CPATH}".
It seems /usr/local/lib was search automatically but if you wish to use another dir export LIBRARY_PATH="/usr/local/lib:${LIBRARY_PATH}" works similar for the .a binary (but may or may not work good for shared libraries depending on your os).
Optionally, but more cumbersome is to add -I /usr/local/include and -L /usr/local/lib while compiling.
This is a somewhat subjective answer, but it's been working well for me.
In addition to the accepted answer, if you are creating a lot of libraries and the set_property syntax throws you off. You could wrap it in a very simple macro, such as:
# File: target_public_headers.cmake
macro(target_public_headers TARGET)
set_target_properties(${TARGET} PROPERTIES PUBLIC_HEADER "${ARGN}")
endmacro()
Then you can use it like:
project(myproject)
include(target_public_headers)
add_library(mylib some.c another.c)
target_public_headers(mylib some.h another.h) # <<<<<
# If you're exporting this library then you need to tell
# CMake how to include the "installed" version of the headers.
target_include_directories(mylib
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
PUBLIC $<INSTALL_INTERFACE:some/includepath>
)
INSTALL(TARGETS mylib
LIBRARY DESTINATION some/libpath
PUBLIC_HEADER DESTINATION some/includepath
)

C/C++ How to access header files?

I have added some source (header files) in a common folder (..\shared\abc) and my code file from another folder (..\src\xyz) has #include <abc/../foo.hpp>. I get this error:
Cannot open Source file error
I can fix that by giving absolute path but that change needs to be done at many place. What should I see to fix this?
Using VC9 nmake to compile code. This is a Makefile based project.
If the included files are from some library your code is using, you'll want to specify the include path with a compiler option. For the Visual C++ compiler the command-line option to specify additional include directories is /I, e.g.:
cl /I ..\shared foo.cpp
You'll need to modify the compiler options in your Makefile accordingly.

Copy C files to include

I have a set of C files that I would like to use. Can I just copy them to my include directory, or do I have to compile them. I would think they would be compiled in the final binary.
You need to compile those C files if you want to use them.
To make use of what's in those C files, you'll nead a header file that declares what's inside them.
Those header files is what you'd put in your include folder, and you'll compile the C files together with your other C files. (Or you could make a library out of those C files)
Yes, they need to be compiled so that they are available at the linking step. C is not an interpreted language, so having the sources present in an include directory would do nothing for execution.
You can keep the source files at the same location. The include files will be in the include directory. You can use the compilation option -I./<include-file-directory> to specify from where to fetch the include files.
The final binary will be compiled version of all your source files which you give to the compiler. You have to explicitly specify every file to be compiled along the with final executable name.
In case you dont do so a default executable is created with the name a.out(i am assuming the platform to be linux and compiler to be gcc) in the directory where you compile.
Check the link for more details on compilation using Makefile.

Resources