Passing extra compilation flags to debug build in bitbake recipe - debugging

As Bitbake builds -dev and -debug for recipes is it possible for defining compilation definitions specific to debug build for a particular recipe. Lets say I have some source code under DEBUG_INFO for some recipe i.e.,
#ifdef DEBUG_INFO
........... do something
#endif /* DEBUG_INFO */
and uses cmake in bitbake environment.
I want this flag be enabled for the debug binaries generated in the .debug folder. Is this possible?
If I use EXTRA_OECMAKE = "-DDEBUG_INFO" it gets enabled to both dev and debug builds.

No, it is not possible. All packages of a recipe are built in one go, they're just the same files but split somehow.
The only difference is with "special flavors" of a recipe (native, nativesdk, target, multilib, toolchain-specific recipes, etc...), in that case, you can have different flags but still, all the packages resulting from the build of this "flavor" will be built with the same flag.

If you want to build another variant of a package where a certain CMake flag is set in the compilation, you can create a variant of the recipe. If the main recipe is named my-app_git.bb you can create another recipe file named my-app-tweak_git.bb and a common base, my-app.inc. In the bb files, include the inc file:
require my-app.inc
Move most of what's now in my-app_git.bb to my_app.inc, e.g. SRC_URI, but define different contents for EXTRA_OECMAKE in the .bb files.
Now you will have to decide which one of my-app and my-app-tweak goes into the image by specifying either my-app or my-app-tweak in an IMAGE_INSTALL definition.
This is not exactly what you asked for, but as has been stated by qschulz, you cannot change the contents of the -dev and -dbg sub-packages.
Also note that dbg and dev can be considered reserved words for variants of the package name, so if you want to use something other than tweak, as in my example, you cannot use any of them.

Related

CMake: Use variables from existing Makefile of 3rdparty library

I'm facing the following scenario:
Existing project which uses cmake
External 3rdparty library which only comes with Makefiles
The difference of my situation compared to existing questions is that I don't need to have cmake to build the 3rdparty library via the Makefile. Instead, the 3rdparty library provides a library.mk Makefile which has variables like LIB_SRCS and LIB_INCS containing all source and header files required to compile the library.
My idea is to include the library.mk into the project's CMakeLists.txt and then adding those $(LIB_SRCS) and $(LIB_INCS) to target_sources().
My question: How can I include library.mk into the existing CMakeLists.txt to get access to the $(LIB_SRCS) and $(LIB_INCS) for adding them to target_sources()? I'm looking for something like this:
include("/path/to/library.mk") # Somehow include the library's `library.mk` to expose variables to cmake.
add_executable(my_app)
target_sources(
my_app
PRIVATE
main.c
$(LIB_SRCS) # Add 3rd-party library source files
$(LIB_INCS) # Add 3rd-party library header files
)
Using include() does not work as the library.mk is not a CMake list/file.
Since you can't be sure that your target system will even have Make on it, the only option is to parse the strings out of the .mk file, which might be easy if the variables are set directly as a list of filenames, or really hard if they are set with expansions of other variables, conditionals, etc. Do this with FILE(STRINGS) cmake doc.
Your plan will only work if the Makefiles are trivial, and do not set important compiler flags, define preprocessor variables, modify the include directory, etc. And if they really are trivial, skip the parsing, and just do something like aux_source_directory(<dir> <variable>) to collect all the sources from the library directory.
You might also consider building and maintaining a CMakeLists.txt for this third-party library. Do the conversion once, and store it as a branch off of the "vendor" main branch in your version control system. Whenever you update, update the vendor branch from upstream, and merge or rebase your modifications. Or just store it in your existing project, referring to the source directory of the 3rd-party stuff.

Scons: how to specify file dependency for 3rd party compile result?

It seem to me that scons targets are being generated not in declaration sequence. My problem is, I need to generate some code first, I'm using protoc to process a my.proto file into .h and .cc file, I need some pseudo code like this(what should the working code look like?)
import os
env=Environment(ENV=os.environ,LIBPATH='/usr/local/lib')
env.ShellExecute('protoc', '--outdir=. --out-lang=cpp', 'my.proto')//produces my.cc
myObj=Object('my.cc')//should wait until 'my.cc' is generated by protoc
Dependency(myObj, 'my.cc')
mainObj=Object('main.cpp')
My question is:
How to specify this ShellExecution of protoc in SConstruct/SConscript?
How to make sure that the compilation of 'main.cpp' depends on the existence of 'my.cc', in another word, wait until 'my.cc' is generated and then execute?
Your observations and assumptions are correct, SCons will not execute the single build commands in the order that you list them in the SConstruct files. It will run them based on the dependencies of the targets and source files in your build, either defined implicitly (header includes in C++, for example) or explicitly (via the Depends() method).
So you have to define and setup your dependencies correctly, such that SCons delivers the output that you want. For the special protoc case in your example, a special Builder exists that will help you to get the dependency graph right. It is available in our ToolsIndex, where also support for a variety of other languages and dialects can be found.
These special builders will emit the correct target nodes, e.g. when given a *.proto input file, and SCons is then able to automatically detect the dependency between the protoc input file and your main program if you say something like:
env=Environment(tools=['default','protoc'])
env.Protoc([], "test.proto")
env.Program('main', ['main.cpp'] + Glob('*.cc'))
The Glob('*.cc') will detect your *.cc files, coming out of the protoc Tool, and include them as dependencies for your final target main.
You can always write your own Builders and Emitters in SCons, which is the canonical way of making new tools/toolchains known to SCons dependency analysis. In the UserGuide, sect. "18 Writing Your Own Builders", and especially our ToolsForFools Guide you can find more infos about this.

GNU Make does not include all auto-generated includes before executing dependent rule

My makefile makes use of auto-generated dependencies. To do this, I have in my top-level makefile something similar to:
# Makefile
include target1.deps
include target2.deps
all: target2.deps
cat $^
target2.deps: target1.deps
target1.deps:
echo "target2.deps:" > $#
echo " touch target2.deps" >> $#
Initially, target1.deps and target2.deps do not exist. When make is first instantiated, it parses the entire Makefile and searches for a way to generate these include files. After building them, it reinvokes itself, causing the Makefile to be reparsed and the include files to be included this time. At least, that's my understanding.
The issue is that when I run the above Makefile, Make first builds target1.deps, then executes the body of the all rule, never having built or included target2.deps. This causes cat to error: cat: target2.deps: No such file or directory
This seems like a contradiction to me. I explicitly tell Make that all depends on target2.deps, but it attempts to execute the rule before satisfying its prerequisites!
The intended behavior is that target1.deps should be built and included, then target2.deps should be built and included using the rule contained within target1.deps, and then all should be run. How do I achieve this?
Context: Since this is weirdly abstract, here's my goal: I have a target index.html, which gets generated from a template index.html.in, but I don't know anything about its dependencies. I need to find out (a) which files I need to create before building index.html and (b) which files index.html will depend on at runtime.
For example index.html includes some inline css that's pulled out of global.css - I need to therefore build global.css before building index.html. On the other hand, index.html links to about.html, so after I build index.html I want to also build about.html. I call the former "build dependencies" and the latter "runtime dependencies". So my makefile looks something like this:
include index.html.build_deps
include index.html.runtime_deps
all: index.html $(runtime_deps_index.html)
%.build_deps: %.in
./extract_build_deps %< -o %#
%.runtime_deps: %
./extract_runtime_deps %< -o %#
%: %.in
./compile_template %< -o $#
What I want to happen is for Make to follow these steps:
Build index.html.build_deps
Include index.html.build_deps
Build global.css (now a known prerequisite of index.html)
Build index.html
Build index.html.runtime_deps
Include index.html.runtime_deps
Build about.html (contained inside $(runtime_deps_index.html) included from index.html.runtime_deps)
Target all is reached
What actually happens:
Make sees that index.html.build_deps can be directly build from index.html.in; does so.
Make sees that index.html.runtime_deps can be built from index.html, can be built from index.html.in.
Make builds index.html. It errors because global.css hasn't yet been built.
If Make had included index.html.build_deps after building that, then it would be aware of the global.css dependency. But because it tries to build all include files before expanding any of them, it's unaware of the dependency. I want to add a dependency "index.html.runtime_deps depends on index.html.build_deps having been included, but I'm not sure how to specify such a dependency.
#Dario is correct. To be a bit more specific, these are the steps make will follow here:
Read the makefile.
Try to build target1.deps.
Find a target target1.deps and execute the recipe.
The recipe succeeds, but make observes that the file target1.deps still does not exist, so make doesn't mark the target as updated.
Try to build target2.deps.
There's a target for it that depends on target1.deps, which make already built, but there's no recipe for it so make doesn't mark target2.deps as updated (since it was never updated, as far as make can tell--it didn't run any recipe to update it).
So, make decides none of the included makefiles were actually updated and it won't re-exec.
Then make wants to build all; it sees that all depends on target2.deps but make already considered that target and decided it didn't need to be rebuilt, so now make is done with all its work.
You can run make -d and follow along with the decisions make takes.

force object files in current directory even when subdir-objects is on

I have 2 libraries that share same source files:
# src/lib_mt/Makefile.am:
libppb_la_SOURCES = rphs_mt.c timer_mt.c
# src/sipplib/Makefile.am:
libsipp_a_SOURCES = ../lib_mt/rphs_mt.c ../lib_mt/timer_mt.c
Each source file compiled twice. First for lib_mt with -fPIC, second for sipplib without -fPIC.
Object files for each library created in corresponding directory.
Eventually subdir-objects becomes default. How to keep current behavior for these 2 source files? Some explicit rule maybe?
There is no way to disable that the moment it becomes the default. What you can do instead is migrate this to a non-recursive Automake buildsystem. At that point, it will know that there are different targets compiling the same source files with different flags (it requires AC_PROG_CC_C_O to be called in configure.ac.)
Alternatively, the hacky version is to create a src/sipplib/rphs_mt.c file that only contains
#include "../libmt/rphs_mt.c"
so that it is actually a separate build target.

cmake: add_custom_command only invoked first time

I'm running into a problem with add_custom_command for a custom target (created using add_custom_target).
My general idea is to incorporate a static code analysis tool into the cmake tool-chain. My solution is based on the one described here: https://github.com/rpavlik/cmake-modules/blob/master/CppcheckTargets.cmake
In a nutshell, each project that I want to run static code analysis for has the following two lines of code:
include(cppcheck)
add_cppcheck(${le_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
The module has this at the top of the file:
if (NOT TARGET ANALYZE_CODE)
add_custom_target(ANALYZE_CODE WORKING_DIRECTORY ${LE_LITEN_ROOT})
set_target_properties(ANALYZE_CODE PROPERTIES EXCLUDE_FROM_ALL TRUE)
endif ()
and later on in the function the custom command is added:
add_custom_command(TARGET
ANALYZE_CODE
PRE_BUILD
COMMAND
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT
"${_name}_cppcheck: Running cppcheck on target ${_name}..."
VERBATIM)
The problem I'm seeing is that the command is only added for the project that included the file first. I'm not sure why and what is going on. I verified the following using message() commands:
The target is only created once
The add_custom_command is run for every project that calls the function, with proper arguments
But when I actually look at the target in visual studio, only the first include / function call command is added.
If the file is only included without calling the function, no custom commands are added at all.
Desired behavior:
I would like ONE target named "ANALYZE_CODE" to run all commands added by calls to the function.
I.e. if 3 projects include the two lines from above, the target ANALYZE_CODE is created once but 3 custom commands are added to it, one for each project.
It turns out you're somewhat stuck between a rock and a hard place here. The issue I think boils down to a couple of factors.
Firstly, although the docs don't make it clear, add_custom_command(TARGET ...) only works for targets created in the same directory. So the first subproject to call include(cppcheck) is the only one which can effectively add custom commands to the target ANALYZE_CODE.
A workaround for this might seem to be to move all calls to add_cppcheck from their respective subdirectories up to the top-level CMakeLists file.
include(cppcheck)
add_cppcheck(${le_first_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
add_cppcheck(${le_second_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
...
This isn't a great solution, since these really belong inside their own subdirs. But a bigger issue is that properties on source files only persist in the scope of the CMakeLists.txt in which they are added. This isn't obvious at all, but from the docs for set_source_files_properties:
Source file properties are visible only to targets added in the same directory (CMakeLists.txt).
The innards of the add_cppcheck have the following block of code:
foreach(_source ${_cppcheck_sources})
get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE)
get_source_file_property(_cppcheck_loc "${_source}" LOCATION)
if("${_cppcheck_lang}" MATCHES "CXX")
list(APPEND _files "${_cppcheck_loc}")
endif()
endforeach()
So this is checking that each source file for the given target is designated as a C++ file before adding it to the list of files to be given to cppcheck. If this function is invoked from within the CMakeLists.txt where the target is defined (i.e. the subdir) then the files all have the appropriate property and are correctly added.
However, if the function is called from the parent CMakeLists.txt, the files have lost their properties, and so none are added and cppcheck is passed an empty list!
Now for the possible fixes. There are probably few ways to get out of this hole - I can point to a couple.
You could continue with the option to always call add_cppcheck from the top-level CMake file and avoid using the source files' properties. So the problem codeblock above could be changed to something more like:
set(CxxExtensions .cpp .CPP .cc .CC .cxx .CXX)
foreach(_source ${_cppcheck_sources})
get_filename_component(Extension "${_source}" EXT)
list(FIND CxxExtensions "${Extension}" IsCxxFile)
if(IsCxxFile GREATER -1)
list(APPEND _files "${_source}")
endif()
endforeach()
You could even enforce that the function is only called from the top-level CMakeLists.txt by adding something like this at the start of the function:
if(NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
message(FATAL_ERROR "This can only be called from the top-level CMakeLists.txt")
endif()
The second fix (which I'd personally favour) is to leave the add_cppcheck calls inside the subdirs and have the function add a custom target rather than command. These targets can successfully be applied as dependencies of the top-level target ANALYZE_CODE. So for example, change the add_custom_command to something like:
add_custom_target(ANALYZE_${_name}
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "ANALYZE_${_name}: Running cppcheck on target ${_name}..."
VERBATIM)
add_dependencies(ANALYZE_CODE ANALYZE_${_name})
set_target_properties(ANALYZE_${_name} PROPERTIES FOLDER "Code Analysis")
This should cause building ANALYZE_CODE to trigger building each of the subordinate ANALYZE_... targets.
It has the downside of "polluting" the solution with a lot of extra targets, but an upside is that you could use these targets in the add_test calls (although this may be a step too far):
# CMake 2.8.0 and newer
add_test(NAME ${_name}_cppcheck_test
COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}
--target ANALYZE_${_name})

Resources