add dependency on cmake's built-in target - c

Let's suppose we want to build a simple library, with one header file and one source file (my_lib.c and my_lib.h, respectively).
The CMakeLists.txt will be something like:
cmake_minimum_required(VERSION 3.14)
project(example C)
add_library(example my_lib.c my_lib.h)
the available targets are (output from make help):
my_lib.i
...
Now, suppose we have a script (let's say my_script.py) that requires the preprocessed output of my_lib.c (the output of target my_lib.i) as an input parameter.
So, we add the following code to our CMakeLists.txt:
add_custom_target(my_script
DEPENDS
COMMAND python my_scipt.py path/to/my_lib.i)
The question is: is it possible to add a dependency (DEPENDS parameter of add_custom_target above) in order to build target my_lib.i?
I have read similar questions, but all propose to invoke the preprocessor explicitly, which will probably break the build by modifying the compiler.
Thanks

Related

Flags in sub-Makefile.am

I have a C project with the following structure with 1 target (binary final product)
main.c
configure.in
configure
Makefile.am
Makefile.in
folder-1
..Makefile.am
..Makefile.in
..<static library files .c files>
..<static library files .h files>
folder-2
<some .c files>
<some .h files>
...
...
I am aware how to configure and compile my project with Autotools. In regard to my library of folder-1: i am often changing files in that library with different debug levels by defining a flag called DMYDEBUG.
Compilation time for the whole project takes a while and by now, i am able to change the flag by
(1) modifiying the top-level configure.in file:
CCONFIGFLAGS="${CCONFIGFLAGS} -DSF_BIGENDIAN -DMYDEBUG=3"
(2) running make clean
(3) regenerating configure from the edited configure.in where i modify DMYDEBUG
(3) running ./configure on top level
(4) running make
only this way the wished effect is taking places. Is there a better way to modify DMYDEBUG (which is only relevant to the static library in folder-1) without having to recompile the whole project each time?
In the first place, it's terrible that you modify your configure.in to change the flag value. It would be much better to make configure recognize a custom argument that conveys the information, such as --with-debug-level=x. The AC_ARG_WITH() macro serves this purpose.
However, if you have to reconfigure the project (re-run ./configure, with or without rebuilding it first) to change the flag, then changing the flag will always require a full rebuild. For more narrowly-scoped rebuilding, you need to rely on make detecting the flag modification and re-building the affected targets.
make recognizes only file-level dependencies, so that strategy relies on you putting the macro definition in a header file, which the files that use it #include. Since you're using Automake, you can rely on your build system to recognize header dependencies automatically, but you may need to perform one clean build to bootstrap that.

CMake - Getting list of source/header files for various subprojects

Background
I have a large cmake project that makes use of dozens of subprojects: some from in-house code bases, and some third-party projects which also use CMake.
To ensure common compiler options, I setup a macro in CMake called CreateDevFlags which is run in only the in-house sub-projects own CMakeLists file as the first line of code to execute. This makes sure that I don't break the compiler flags, output directory overrides, etc, for third-party projects, and all of the code I wrote myself is built with identical options.
Additionally, each sub project has a simple block of code along the lines of the following to define the source files to be compiled:
file(GLOB subproject_1A_SRC
"src/*.c"
)
file(GLOB subproject_1A_INC
"inc/*.h"
)
file(GLOB subproject_2B_SRC
"src/*.c"
"extra_src/*.c"
)
file(GLOB subproject_2B_INC
"inc/*.h"
"extra_details_inc/*.h"
)
Goal
I would like to add a sanity-check custom rule/function to the "master" CMakeLists file at the project root which runs all of the code for in-house subprojects through a code sanitizer (checks newlines, enforces style rules, etc).
Question
Is there a trivial way to have all "special" (ie: in-house) subprojects append their own source files to a "master" list of source (.c) and header (.h) files (possibly via the macro I created)? I realize I could manually create this list in the master CMakeLists file, but then I'd be duplicating efforts, and code maintainers would have to modify code in two places with this in effect.
Thank you.
One possible implementation would be to have a list called FILE_TRACKER defined at top scope for your project. Then, you could do something like
# Create local list to append to
set(LOCAL_LIST ${FILE_TRACKER})
# Append all of your source files, from your local source
foreach(SRC_FILE ${subproject_1A_SRC})
list(APPEND LOCAL_LIST ${SRC_FILE})
endforeach()
# Append to the upper macro (note: was initially set with FILE_TRACKER)
set(FILE_TRACKER ${LOCAL_LIST} PARENT_SCOPE)
The developers would only have to add their source to the one list, and the macro at the top level will be updated with the files.
In the end. the following approach solved my problem:
set(DIR1_SRCS "file1.cpp" PARENT_SCOPE)
and then in ./CMakeLists.txt
set(SRCS ${DIR1_SRCS} ${DIR2_SRCS})
I suggest you don't examine header files. Instead use include dirs for the paths to the header files. If you do this you will automatically get the depends working without having to track them yourself.
Your sanitizer should be able to parse the actual code to find and read the included headers.

How do I generate included files using cmake?

I've got a tool that generates files that contain definitions and declarations. These files need to be included from other source files or headers - they aren't usable standalone.
The obvious thing to do is have a custom command to generate them. My CMakeLists.txt that does this is as follows. I'm currently using this with the GNU makefile generator.
project(test_didl)
cmake_minimum_required(VERSION 3.0)
add_custom_command(
OUTPUT test_didl_structs.h test_didl_structs.c
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/didl.py ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)
add_executable(test_didl test_didl.c)
target_include_directories(test_didl PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(test_didl shared_lib)
test_didl.c is very simple:
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "test_didl_structs.h"
#include "test_didl_structs.c"
int main(void) {
}
But on the first build, make tries to build test_didl.c, which of course fails, because test_didl_structs.* haven't been generated yet. Naturally, before the first successful build of test_didl.c, the dependency information isn't known, so make doesn't know to run the python command first.
I tried a custom target, but that's no good, because custom targets are assumed to be always dirty. This means the C file is recompiled on every build and the EXE is linked. This approach won't scale.
My eventual solution was to make the output .h file an input to the executable:
add_executable(test_didl test_didl.c test_didl_structs.h)
.h file inputs are treated as dependencies, but don't otherwise do anything interesting for makefile generators. (I am not currently interested in other generators.)
So that works, but it feels a bit ugly. It doesn't actually state explicitly that the custom commands need to be run first, though in practice this seems to happen. I'm not quite sure how, though (but I'm not up to speed on reading the CMake-generated Makefiles just yet).
Is this how it's supposed to work? Or is there something neater I'm supposed to be doing instead?
(What I'm imagining, I suppose, is something like a Visual Studio pre-build step, in that it's considered for running on every build, before the normal dependency checking. But I want this pre-build step to have dependency checking, so that it's skipped if its inputs are older than its outputs.)
My eventual solution was to make the output .h file an input to the executable.
This way is correct.
It actually states, that building executable depends on given file, and, if that file is OUTPUT for some add_custom_command(), this command will be executed before building executable.
Another way is to generate needed headers at configuration stage using execute_process(). In that case there is no need to add header files as sources for add_executable(): CMake has notion of autodetecting dependencies for compiling, so test_didl will be rebuilt after regeneration of test_didl_structs.h.
execute_process(COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)
# ...
add_executable(test_didl test_didl.c)
Drawback of this approach is that you need manually rerun configuration stage after changing your .py files. See also that question and answer to it.
Another problem is that header file will be updated every time configuration is run.
You can try tell cmake that you are using an external source, see docs about set_source_files_properties, see this past post

How to use autotools for deep projects?

I have a C project that has the following structure
Main/
Makefile.am
bin/
src/
Makefile.am
main.c
SomeLibrarySource/
SomeFuncs.c
SomeFuncs.h
The main.c contains the main function that uses functions defined in the SomeFuncs.{h/c} files.
I want to use autotools for this project. I read a couple of resources on autotools. But, I was only able to manage using autotools for a single level project where all source, object and other files reside in the same directory.
Then I got some links that talked about using autotools for deep projects like this one and then I got confused.
Right now I have two Makefile.am as follows
Makefile.am
SUBDIRS=src
src/Makefile.am
mainprgdir=../
mainprg_PROGRAMS=main
main_SOURCES=main.c
I am pretty sure that these files should not be as I have them now :P
How do I use autotools for the above project structure? (At least what should be there in those Makefile.am(s) and where should I place them.
EDIT:
One more thing! At the end I would like to have the object files created in the bin directory.
Thanks
mainprogdir=../ does not make a whole lot of sense (you don't know what it is relative to on installation). Probably intended:
# Main/Makefile.am
# .━━ target for `make install`
# |
# ↓ ↓━━ target for compilation
bin_PROGRAMS = bin/main
# ↓━━ based upon compilation target name
bin_main_SOURCES = src/main.c
There are two main approaches. If the functions in SomeLibrarySource are used only by main, then there's no need to build a separate library and you can simply specify the source files in src/Makefile.am
main_SOURCES = main.c SomeLibrarySource/SomeFuncs.c
However, if you actually want to use the functions in other code in your tree, you do not want to compile SomeFuncs.c multiple times but should use a convenience library.
# Assigning main_SOURCES is redundant
main_SOURCES = main.c
main_LDADD = SomeLibrarySource/libSomeFuncs.a
noinst_LIBRARIES = SomeLibrarySource/libSomeFuncs.a
AM_CPPFLAGS = -I$(srcdir)/SomeLibrarySource
(You'll need AC_PROG_RANLIB in configure.ac to use convenience libraries.)
If the source file is named SomeFuncs.c, automake will not need Makefile.am to specify SomeLibrarySource_libSomeFuncs_a_SOURCES, but if the name of the source code file does not match the name specified in noinst_LIBRARIES, SomeLibrarySource_libSomeFuncs_a_SOURCES should be set to the list of files used to build the library. Note that you do not need to specify main_SOURCES, since main.c is the default value if left unspecified (but it's not a bad idea to be explicit.) (In all of this, I am not comfortable use CamlCase names, but the system I'm using uses a case insensitive file system (biggest mistake apple ever made) and the examples I give here are working for me. YMMV)
You could of course do a recursive make, or build the library as a separate project and install it. (I like the final option. Libraries with useful features should exist on their own.)

Creating one C file when compiling multiple sources

I have a set of C files to compile using gcc and make. The build process works fine.
I want to know if I can obtain - during compilation - one C file containing all the source code without any preprocessor macro.
One simple was would be to make a file that included all the other source files.
$cat *.c > metafile.c
This would construct such a file, depending on how you set you 'pragma once' and ifndef's this file would probably not be able to compile on its own.
On the other hand, if what you want in a file where all the preprocessor macro's have been unfolded and evaluated, then the answer is to add the following to gcc:
-save-temps
then the file .ii will contain the unfolded and evaluated macros
If you include all files to the gcc compiler at once you could use
gcc -E main.c other.c another.c
This will also include the stdlib functions maybe use -nostdinc
You can't - normally you invoke the compiler to compile just a single source file, resulting in an object file. Later you call the linker on all of the object files to create the executable - it doesn't have the original C source code available.
You can, however, create a separate shell script that calls gcc with the -E option just to preprocess the source files, and then use the cat utility to put all the sources in a single file.
You can use the -save-temps option to get the intermediate outputs. However it will be one output file per source file. Each source file gets compiled separately and represents a compilation unit which can't be mixed up.
You can also use the -E option, however that will only run the preprocessor and not continue compilation.

Resources