Debugging Makefile for target that is not being built - debugging

I need some help debugging a Makefile system. I have a rather huge Makefile dependency tree, actually the Android source makefile system.
At some point the build fails because a file is missing:
/bin/bash: out/host/linux-x86/bin/mkfs.ubifs: No such file or directory
The file mkfs.ubifs is supposed to be "build" during the make process, and indeed it works if I do:
make out/host/linux-x86/bin/mkfs.ubifs
The mkfs.ubifs is build, and everything is working, until I again clean everything and build from the beginning.
This indicates to me, that there is a missing dependency somewhere. So my question is, how do I go about debugging this? How do I discover exactly which target is missing a dependency? What options can I provide for make which will give me clues as to where the error is?
Any other suggestions will also be appreciated. Thanks. :)
Update
Using make -d provides quite a lot of output. How exactly do I determine from which make target (sourcefile and line) and error occurred?

Problem solved. It seems make -p was the most useful way to debug this problem:
-p, --print-data-base
Print the data base (rules and variable values) that results from
reading the makefiles; then execute as usual or as otherwise spec-
ified. This also prints the version information given by the -v
switch (see below). To print the data base without trying to
remake any files, use make -p -f/dev/null.
From that output it is relatively easy to determine which target was failing, and what dependency that should be included.

There is a discrepancy between target's prerequisites and its commands, that is, a dependency is not specified for a target. I don't think you can debug that using make means because make can't tell you that a dependency is missing.
However, you can try invoking make with -d switch. That is going to tell you which target it tries to build when it hits the missing file. The next step would be to find the rule for that target in the makefile and add the missing dependency.

Related

Is there a way to get the info from which makefile target is being running

I have huge code base that includes huge number of makefiles. I am trying to understand the flow. For that i am running make command with debug flags (--debug=basic) to get the information like what is the order of targets being executed.
build command:- make --debug=basic release
Here is the debug info:-
File 'release' does not exist.
Must remake target 'release'.
File 'all' does not exist.
File 'copy_exports_files' does not exist.
File '/test/sw/modules/bin/ctk' does not exist.
Must remake target '/test/sw/modules/bin/ctk'
...
I can see flow of the targets being triggered. But I want to understand from which makefile the target is being triggered. Is there a way to log that info? Because its been hard to find where one makefile include other and soo on.
Thanks!
Try make --debug=verbose release

how to make `mvn package` aware that it has already built the target

In a makefile, I can easily do something like
${target}: ${sources}
mvn package
Where I have ${target} the generated jar file, and ${sources} all the java files and the pom.xml. With this makefile, the target will not be be rebuilt unless one of the sources is changed since the last build of the target. The result is
$> make target/demo-0.8.0-SNAPSHOT-jar-with-dependencies.jar
make: 'target/demo-0.8.0-SNAPSHOT-jar-with-dependencies.jar' is up to date.
But just mvn package will always run the maven-assembly-plugin even though none of the source files has changed.
Question:
Is there a way to make mvn package be aware of the source files, similar to how make knows this so it'll just say "no need, it's already built."
Whether or not something makes sense is maybe up to the use case and the developer.
In a system where integration is far more complicated than passing unit tests the only way to gain confidence is by deploying into a test Kubernetes environment.
Anyway thanks for answering my question that the maven packaging plugin is unable to handle this dependency tracking.

CMake: Is it possible to run CONFIGURE_FILE after each make?

I've got the following piece of script in my CMake file:
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/version.hpp.cmake
${CMAKE_CURRENT_SOURCE_DIR}/version.hpp
)
But it's only run after executing cmake, not make. Is it possible to create the version.hpp file after each make?
Here is the content of version.hpp.cmake:
#ifndef _VERSION_HPP_
#define _VERSION_HPP_
#define MAJOR_VERSION "${MAJOR}"
#define MINOR_VERSION "${MINOR}"
#define PATCH_VERSION "${PATCH}"
#define RELEASE_VERSION "${RELEASE}"
#endif //_VERSION_HPP_
The MAJOR, MINOR, PATCH and RELEASE variables have been defined in the CMakeLists.txt file.
P.S. This post is apparently related to my question, but I can't get a grasp of it.
The problem is that configure_file is supposed to run at configure time, that is when you run cmake, instead of compile time, which is when you run make. There is no easy way around this.
The problem is that the information written by configure_file is dependent on variables from the CMake build environment. Changes to those variables cannot be detected without running CMake again. If you have that information mirrored somewhere else, you can use a custom command to extract it and perform the code generation for you, as Peter's answer suggested.
The approach suggested in the post from the CMake mailing list that you linked in your answer is based on a two-phase CMake run: The outer CMake project (which is run only once) adds a custom build step for building the inner CMake project (which is then run with every make) where the configure_file is performed. The underlying idea is the same as with Peter's answer, only instead of a Python script you use a CMake script for generating the file.
My personal recommendation: For a simple problem as a version header, I would not bother with such a complicated approach. Simply generate the file to your BINARY_DIR (not to your project dir, as you currently do! you want to retain the ability to do several out-of-source builds from the same source) and assume that it will be there for compilation. If a user is brave enough to mess with the generated files there, they can be expected to re-run CMake on their own.
So I accidentally stumbled across this, I know it is probably too late, but calling configure is possible an exactly how I do this with mercurial versions.
The trick requires a lot of different tools, and I don't have time to formulate into a good answer atm, but ask questions and I'll fill it in when I have time.
tool 1: calling exec_program to extract the revision information (this is really easy with mercurial)
exec_program(hg ${PROJECT_SOURCE_DIR} ARGS "id" "-i" OUTPUT_VARIABLE OUTPUT_VARIABLE ${PROJECT_NAME}_HG_HASH_CODE)
I'm probably doing something more complicated than you care about here, but the essential bit is hg which you'll replace with whatever version control you are using, ${PROJECT_SOURCE_DIR} which you'll set to whatever executing directory you want, and fill in the custom args.
I put all of the version extraction into a single macro (ReadProjectRevisionStatus()).
The next step is to make a an entirely different CMake file that calls ReadProjectRevisionStatus() and then CONFIGURE_FILE. This file will assume that all the correct values are set when you come into it. In my case, I store the location of this file into ${CONFIG_FILE_LOC}.
The final step is to add a custom target that will call this script. For example:
ADD_CUSTOM_TARGET(${PROJECT_NAME}_HG_VERSION_CONFIG
COMMAND ${CMAKE_COMMAND}
ARGS -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}
-DPROJECT_NAME=${PROJECT_NAME}
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}
"-D${PROJECT_NAME}_HG_CONFIG_FILE_IN=\"${${PROJECT_NAME}_HG_CONFIG_FILE_IN}\""
"-D${PROJECT_NAME}_HG_CONFIG_FILE_OUT=\"${${PROJECT_NAME}_HG_CONFIG_FILE_OUT}\""
${ARGN}
-P ${CONFIG_FILE_LOC})
One of the beauties of doing it this way is that custom target call can still be called outside of a cmake build system, which I've done on a couple of projects, which a bash call similar to:
cmake -D PROJECT_SOURCE_DIR=$sourcedir -DPROJECT_BINARY_DIR=$sourcedir -DPROJECT_NAME=uControl -DCMAKE_MODULE_PATH=$sourcedir -DuControl_HG_CONFIG_FILE_IN=$sourcedir/tsi_software_version.h.in -DuControl_HG_CONFIG_FILE_OUT=$sourcedir/tsi_software_version.h -P $sourcedir/ConfigureHGVersion.cmake
One possibity is to generate version.hpp from Python and use ADD_CUSTOM_TARGET
... find python ...
ADD_CUSTOM_TARGET(gen_version ALL ${PYTHON_EXECUTABLE} gen_version.py)
SET_SOURCE_FILES_PROPERTIES(version.hpp PROPERTIES GENERATED 1)
... link gen_version to your library/executable ...

LLVM compile error for a custom back-end

I am getting familiar myself to LLVM, and my goal is to implement a back-end for my custom processor.
Before I jump into my back-end implementation, I first try to learn how a build procedure works, so I first copy lib/Target/MSP430 to lib/Target/myproc, and build llvm targeting "myproc" (even though it actually is a back-end for MSP430, I did this just to learn how I can add a new target to LLVM).
When I configure/make llvm, I got the following error message.
...
/bin/cp: cannot stat `/mydir/build/lib/Target/myproc/Debug+Asserts/MSP430GenRegisterInfo.inc.tmp': No such file or directory
...
I checked /lib/Target/myproc, and saw there was only one file, Makefile, copied from /lib/Target/myproc.
Here is what I have done before I configure and make.
In my LLVM source directory, copy lib/Target/MSP430 to lib/Target/myproc.
Modify configure and projects/sample/configure to add "myproc".
Go to lib/Target/myproc and change "MSP430" to "myproc" in MSP430.td, LLVMBuild.txt, and Makefile (I also modify the files in subdirectories).
As the LLVM compile works for other targets on my machine, I believe it's not the problem of machine of tools that I am using, but the problem of my modification.
Am I missing something? Are there any further modifications that I am supposed to make?
There's a decent tutorial for writing backends here:
http://llvm.org/docs/WritingAnLLVMBackend.html
There's also this tutorial from a dev meeting:
http://llvm.org/devmtg/2012-04-12/Slides/Workshops/Anton_Korobeynikov.pdf
*GenRegisterInfo.inc comes from running tblgen on the target .td file. The .inc output file name depends on what the .td files are named in the myproc/ target directory.
It would be helpful to see more of your make log but my guess is that you're getting a tblgen error when processing .td files in myproc/. That tblgen error is the real problem you need to diagnose and address.

Need to build the whole kernel after changing the .config file?

The following script is used to build a specific kernel module.
make modules M=net/sctp
After a second thinking, I've figured out that some of the options were not opened, which is
CONFIG_SCTP_DBG_OBJCNT=y
However, the file that the option control was still not compiled after a "make module" command. Do I need to make the whole kernel to let the option take effects?
All configuration options will be converted into macros and will be written to the file include/generated/autoconf.h once you did make command to build the kernel.
After this when you change any of the configuration option you again need to run the make command which generates required files to include this new configuration options. But if you just use the command "make M=/net/sctp modules" after you change your configuration it will not affect in the make. Instead of building whole kernel what you can do is, just run the "make modules" command which generates the required files and builds your module with the options that you selected. This is the best way which also resolves if there are any dependencies on your newly configured option.
But in your case, if you know that objcnt.c doesn't depend on any other things you can change the make file of the sctp to include your file.
vim net/sctp/Makefile
sctp-y += objcnt.o
Then you can run the "make M=net/sctp modules"
According to https://www.kernel.org/doc/Documentation/kbuild/modules.txt:
To build external modules, you must have a prebuilt kernel available
that contains the configuration and header files used in the build.
[..] use the make target modules_prepare. This will
make sure the kernel contains the information required. The target
exists solely as a simple way to prepare a kernel source tree for
building external modules.
vim .config
make modules_prepare
Answer any kconfig prompts as changes to .config may enable new options that were not manually configured previously.
make M=net/sctp

Resources