I am looking for a way to get CMake to re-run a shell command every time it detects that the dependencies for a specific target/executable has changed. I tried adding a custom command the has a dependency on a target, but this does not seem to be doing the trick.
Example of what I thought might work:
ADD_CUSTOM_COMMAND(
OUTPUT temp
DEPENDS my_Target
COMMAND ./some_command.sh)
Any suggestions of a command that may be able to run a command when a dependency change has been detected for a target. Or even better if we can check for a change in specific files.
From your description, it sounds like you might want this:
cmake_minimum_required(VERSION 2.8)
project(cmaketest)
add_custom_command(OUTPUT some_file.cpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bar.cpp
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/bar.cpp
${CMAKE_CURRENT_BINARY_DIR}/some_file.cpp
VERBATIM
)
add_executable(mn main.cpp some_file.cpp)
Put the output file in the source list of the target which depends on it.
add_custom_command() uses simple check for OUTPUT file existence to determine if the command should be run. If it doesn't exist, then CMake do make my_Target and only then run your command. At the same time, if OUTPUT exist, CMake doesn't run anything at all.
To achieve what you want you need to add_custom_target() (probably with ALL keyword to run it with make) and implement checking for changes inside your some_command.sh.
Related
Is there a way to tell make to show me a list of inputs to a target and which ones are triggering a rebuild because they have been modified?
Yes, you can use the -d option in make to show detailed information about the dependencies and the commands being executed. For example, if you run make -d , make will show a list of the dependencies of the target, as well as the commands being executed and their output.
Additionally, you can use the -n option to show what make would do, without actually executing any commands. This is useful to see which targets would be rebuilt because their dependencies have been modified. For example, if you run make -n , make will show the dependencies of the target and the commands that would be executed, without actually executing them.
I tried to use a make file in code::blocks but I am doing it wrong. I have the version installed with the compilers included. http://sourceforge.net/projects/codeblocks/files/Binaries/10.05/Windows/codeblocks-10.05mingw-setup.exe/download. What do I do with the make file? It starts with:
CC=gcc
best, US
You don't tend to execute the make file itself, rather you execute make, giving it the make file as an argument:
make -f pax.mk
If your make file is actually one of the standard names (like makefile or Makefile), you don't even need to specify it. It'll be picked up by default (if you have more than one of these standard names in your build directory, you better look up the make man page to see which takes precedence).
As paxdiablo said make -f pax.mk would execute the pax.mk makefile, if you directly execute it by typing ./pax.mk, then you would get syntax error.
Also you can just type make if your file name is makefile/Makefile.
Suppose you have two files named makefile and Makefile in the same directory then makefile is executed if make alone is given. You can even pass arguments to makefile.
Check out more about makefile at this Tutorial : Basic understanding of Makefile
I'm using PVS-Studio in docker image based on ubuntu:18.04 for cross-compiling a couple of files with arm-none-eabi-gcc. After doing pvs-studio-analyzer trace -- .test/compile_with_gcc.sh strace_out file is successfully created, it's not empty and contains calls to arm-none-eabi-gcc.
However pvs-studio-analyzer analyze complains that "No compilation units were found". I tried using --compiler arm-none-eabi-gcc key with no success.
Any ideas?
The problem was in my approach to compilation. Instead of using a proper build system, I used a wacky shell script (surely, I thought, using a build system for 3 files is an overkill, shell script won't hurt anybody). And in that script I used grep to redefine one constant in the source - kinda like that: grep -v -i "#define[[:blank:]]\+${define_name}[[:blank:]]" ${project}/src/main/main.c | ~/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gcc -o main.o -xc
So compiler didn't actually compiled a proper file, it compiled output of grep. So naturally, PVS-Studio wasn't able to analyze it.
TL;DR: Don't use shell scripts as build system.
We have reviewed the stace_out file. It can be handled correctly by the analyzer, if the source files and compilers are located by the absolute path in the stace_out file. We have a suggestion what might help you. You can "wrap" the build command in a call to pvs-studio-analyzer -- trace and pvs-studio-analyzer analyze and place them inside your script (compile_with_gcc.sh). Thus, the script should start with the command:
pvs-studio-analyzer trace --
and end with the command:
pvs-studio-analyzer analyze
This way we will make sure that the build and analysis were started at the same container run. If the proposed method does not help, please describe in more detail, by commands, the process of building the project and running the analyzer. Also tell us whether the container reruns between the build and the formation of strace_out, and the analysis itself.
It would also help us a lot if you ran the pvs-studio-analyzer command with the optional --dump-log flag and provided it to us. An example of a command that can be used to do this:
pvs-studio-analyzer analyze --dump-log ex.log
Also, it seems that it is not possible to quickly solve the problem and it is probably more convenient to continue the conversation via the feedback form on the product website.
I want to force a recipe for "output.file", even though it is up-to-date.
I have already tried make --assume-old=output.file output.file, but it does not run the recipe again.
In case you are curious: use case:
I want to use this together with --dry-run to find out the command that produce a target.
I ended up hiding the file to run make --dry-run output.file, but I was hoping for something more elegant + FMI: for future debugging makefile.
I think you're misunderstanding what that option does: it does exactly the opposite of what you hoped; from the man page:
-o file, --old-file=file, --assume-old=file
Do not remake the file file even if it is older than its dependenā
cies, and do not remake anything on account of changes in file.
Essentially the file is treated as very old and its rules are
ignored.
You want output.file to be remade, so using -o is clearly not what you want.
There is no option in GNU make to say "always rebuild this target". What you can do is tell make to pretend that some prerequisite of the target you want to be rebuilt has been updated. See this option:
-W file, --what-if=file, --new-file=file, --assume-new=file
Pretend that the target file has just been modified. When used
with the -n flag, this shows you what would happen if you were to
modify that file. Without -n, it is almost the same as running a
touch command on the given file before running make, except that
the modification time is changed only in the imagination of make.
Say for example your output.file had a prerequisite input.file. Then if you run:
make -W input.file
it will show you what rules it would run, which would include rebuilding output.file.
If I type just
$ make
it will invoke the make command with the default target (typically the first target specified in the Makefile, but the rules are a bit more complicated than that).
Is there a way to specify the default target on the command line without knowing what it is, other than by simply omitting the target name?
What I'd like to be able to do is combine these two commands:
$ make clean
$ make
into a single invocation of make. If I happen to know that the default target is all, I can type:
$ make clean all
but that doesn't work if I don't know what the default target is.
Ideally, I'd like some syntax that refers to the default target (the GNU make manual calls it the "default goal"). This:
$ make clean .DEFAULT_GOAL
shows the general idea, but it doesn't work.
Second best would be a simple and reliable way to determine, from the command line, what the default target is:
$ make clean $(get-default-target)
A GNU-specific solution would be ok.
I suspect, from a quick look into the manual, that there's no good way to do this.
For a shot at the second-best solution, you can parse the default goal from the output of make -pq:
make -pq | sed -ne 's/^.DEFAULT_GOAL := //p'