CMake - always build specific file - c

I have a specific file that should be rebuilt on each compilation regardless if it has been modified or not. The reason is that it is depending on system macros whose values change. How could I force rebuild with CMake? I'd like to not bind it to specific target: the file should be "touched" before any of the targets specified in CMakeLists.txt begins the actual build process.

CMake has a add_custom_target command:
Adds a target with the given name that executes the given commands. The target has no output file and is always considered out of date even if the commands try to create a file with the name of the target. [...] By default nothing depends on the custom target. Use the add_dependencies() command to add dependencies to or from other targets.

Related

Why does make just take one rule? [duplicate]

Most Linux apps are compiled with:
make
make install clean
As I understand it, the make command takes names of build targets as arguments. So for example install is usually a target that copies some files to standard locations, and clean is a target that removes temporary files.
But what target will make build if no arguments are specified (e.g. the first command in my example)?
By default, it begins by processing the first target that does not begin with a . aka the default goal; to do that, it may have to process other targets - specifically, ones the first target depends on.
The GNU Make Manual covers all this stuff, and is a surprisingly easy and informative read.
To save others a few seconds, and to save them from having to read the manual, here's the short answer. Add this to the top of your make file:
.DEFAULT_GOAL := mytarget
mytarget will now be the target that is run if "make" is executed and no target is specified.
If you have an older version of make (<= 3.80), this won't work. If this is the case, then you can do what anon mentions, simply add this to the top of your make file:
.PHONY: default
default: mytarget ;
References:
https://www.gnu.org/software/make/manual/html_node/How-Make-Works.html
GNU Make also allows you to specify the default make target using a special variable called .DEFAULT_GOAL. You can even unset this variable in the middle of the Makefile, causing the next target in the file to become the default target.
Ref: The Gnu Make manual - Special Variables
bmake's equivalent of GNU Make's .DEFAULT_GOAL is .MAIN:
$ cat Makefile
.MAIN: foo
all:
#echo all
foo:
#echo foo
$ bmake
foo
See the bmake(1) manual page.

(CLion/CMake) Why does my c file not belong to any target project when it is saved within the project directory?

Preface: I am very new to c and CLion, so apologies in advance if my phrasing is very wrong.
Essentially, I have an assignment that involves two c files (a "main", and one performing a conversion between imperial and metric units). The main c file simply #include-s the conversion file, performs a function within the conversion file, and prints the resulting value to the user. Simple enough, but I keep getting a message every time I try to run it:
"undefined reference to 'conversion'"
I have tried to suss out the problem, and my only idea relates to the banner at the top of conversion.c which says "This file does not belong to any project target, code insight features may not work properly.". I do not understand why I receive this message, because conversion.c and main.c are both within the main project directory, and this setup worked perfectly fine in my previous assignment.
I have searched for solutions online, and the only one that seemed to make sense was to update my CMakeLists.txt file to include add_executable(project conversion.c). This is what my CMakeLists.txt file looks like before I add this line:
cmake_minimum_required(VERSION 3.12)
project(project C)
set(CMAKE_C_STANDARD 11)
add_executable(project main.c)
However, when I add it, I get the error:
CMake Error at CMakeLists.txt:7 (add_executable):
add_executable cannot create target "directory" because another
target with the same name already exists. The existing target is an
executable created in source directory
"/home/john_s/CLionProjects/project". See documentation for
policy CMP0002 for more details.
Presumably this is because the previous line I have (add_executable(project main.c)) is linking to the same directory, but I have no idea how to resolve this. Any suggestions?
From cmake manual:
add_executable(< name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
Adds an executable target called to be built from the source files listed in the command invocation. (The source files can be omitted here if they are added later using target_sources().)
So to combile a single executable using two source files, you just use:
add_executable(target_name source1.c source2.c)

CMake: how to break a PRE_LINK infinite loop?

I'm trying to automatically label my application sign-on line with a build number. This application is a plain vanilla C one without graphic UI; it is intended for command line, therefore it is a "simple" one.
The sign-on id is located in a "template" source file which is customized by CMake with a configure_file() command. Recently, I fancied to include a build number in this sign-on id. Consequently, the customization can no longer be statically done at CMake time, but everytime make is invoked.
To achieve that, there are two possibilities in CMake:
add_custom_target(), but it is triggered even when nothing else changes in the source tree which does not reflect the state of the tree;
add_custom_command(), which can be triggered only when the application (target) needs to be linked again.
I opted for the second solution and did not succeed.
Here is an extract of my CMakeLists.txt, the sign-on id being in file ErrAux.c (template in PROJECT_SOURCE_DIR, configured in PROJECT_BINARY_DIR):
add_executable(anathem ... ${PROJECT_BINARY_DIR}/ErrAux.c ...)
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
This launches script BuildNumber.cmake just before the link step. It computes the next build number and customizes ErrAux.c with configure_file().
It works fine, except ...
It happens late in the make sequence and the update to ErrAux.c goes unnoticed. The sign-on id in the executable contains the previous build number.
Next time I run make, make notices the generated ErrAux.c is younger than its object module and causes it to be compiled again, which in turn causes a link which triggers a build number update. This happens even if no other file has changed and this loop can't be broken. This is clearly shown in the compiling log:
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-45
[ 36%] Built target anathem
The crux seems to be that add_custom_command(TARGET ...) can't specify an output file like add_custom_command(OUTPUT ...) does. But this latter form can't be triggered in PRE_LINK mode.
As a workaround, I forced a compilation to "refresh" the object module with:
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
COMMAND echo "Numbering"
COMMAND echo "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
COMMAND "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
An explicit compilation is forced after sign-on id customization. It mimics what is found in the various Makefile's and my not be safe for production. It's a cheat trick on both CMake and make.
UPDATE: Option -c is required to postpone link step until the final application liniking process.
This addition creates havoc in the link, as shown by the log, where you see a double compilation (the standard make one and the add_custom_command() one):
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-47
Numbering
/usr/bin/cc -DANA_DEBUG=1 -I/home/prog/projects/AnaLLysis/build/AnaThem -I/home/prog/projects/AnaLLysis/AnaThem -g /home/prog/projects/AnaLLysis/build/AnaThem/ErrAux.c
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
AnaThem/CMakeFiles/anathem.dir/build.make:798: recipe for target 'AnaThem/anathem' failed
make[2]: *** [AnaThem/anathem] Error 1
If I force a full recompilation, to make sure all sources are compiled, *main.c* included, I get the same error on `main`.
The only logical explanation is my manual C invocation is faulty and somehow destroys vital information. I checked with *readelf* that `main` is still in the symbol table for *main.c.o* and that it is still taken into account by the link step (from file *link.txt*).
UPDATE: Even with the correct link, I'm still experiencing the infinite loop syndrom. The generated application still has its sign-on id lagging behind the actual build counter.
Can someone give me a clue for the right direction?
FYI I'm quite new to CMake, so I may do things really wrong. Don't hesitate to criticize my mistakes.
The key to the solution is to put the generated module where make expects to find it. CMake organizes the build tree in a non-trivial way.
The shortcomming in my added compilation in add_custom_command() was to believe that by default the binary will be stored in the "usual" CMake locations. Since I forge manually my compiler command, this is not the case.
I found the module in the source directory, which is a consequence of the WORKING_DIRECTORY option, with name ErrAux.o and not ErrAux.c.o.
To obtain the correct behavior, I force an output location with:
-o "${PROJECT_BINARY_DIR}/CMakeFiles/anathem.dir/ErrAux.c.o"
Now, when I run make again, nothing happens since nothing changed.
Side question
To make the solution portable (if needed), are there CMake variables for CMakeFiles and anathem.dir directories? Or in the latter case, for the current target as "anathem" as the target name in add_custom_command()?

How does MAKE remember the file timestamps

I've found this question which is basically asking the same, but got no real answer.
Where is the make's config file / database file where it remembers the file timestamps, so it can tell what changed? I checked and there's no .make or similar in my project, nor in the home directory.
Or does it somehow store the information inside the files themselves, perhaps by modifying the timestamps? (That sounds fishy though)
There is no such "database". The program simply compare the filesystems modification and creation timestamps of source and target files.
Lets say you have the following rule:
some_target: some_source_1 some_source_2
Then if the modified timestamp of either some_source_1 or some_source_2 is later than the modification/creation time of some_target then the rule will activate and the target will be rebuilt.
Makefiles describe targets and dependencies. Make executes commands to create/recreate the target(s) if necessary.
If the target doesn't exist, then make will try to create it.
If the target does exist, make compares the modification times of the target and its dependencies. If any of the dependencies was modified after the target was modified, then make will execute the command(s) to regenerate the target.
For example, for C files the target is the corresponding .o file and the dependency is on the file containing the C source code (and possibly some include files). If the .c file is newer than the .o file, then make runs the C compiler. This will generate a .o file with a newer modification time than the .c file.

How to compile additional source files in cmake after the build process

I have a project in cmake for windows which contains a Pro*C source file called database.proc, my goal is to generate a C source file from the .proc file and add it to the project to be linked along the other source files, I've tried to add a custom command to achieve this without success
add_custom_command(TARGET myproj OUTPUT PRE_LINK
COMMAND ${PROC} iname=${PROJECT_SOURCE_DIR}/connection.proc SQLCHECK=SYNTAX
MODE=ANSI IRECLEN=255 ORECLEN=255
ONAME=${PROJECT_SOURCE_DIR}/connection.c
COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS}
${PROJECT_SOURCE_DIR}/connection.c )
Is there some way to do this?
I'm not familiar with Pro*C, but it looks like you're mixing together the two different versions of add_custom_command.
The first version add_custom_command(OUTPUT ...) is used to generate a file which is then added as a dependency of another CMake target. When that target is built, the custom command is executed first in order to generate the output file.
The second version add_custom_command(TARGET ...) is used to define a pre-build, pre-link or post-build command; one which does not necessarily create a file, but which executes in conjunction with building the associated target.
If you only have one target which depends on the output of Pro*C, then the first version is probably your best bet:
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/connection.c
COMMAND ${PROC} iname=${PROJECT_SOURCE_DIR}/connection.proc SQLCHECK=SYNTAX
MODE=ANSI IRECLEN=255 ORECLEN=255
ONAME=${PROJECT_SOURCE_DIR}/connection.c)
add_executable(myproj ${PROJECT_SOURCE_DIR}/connection.c <other sources>)

Resources