How can I exclude a file from g++ compiler options - makefile

I'd like to compile most of my code with -Wconversion -Werror.
The problem is that I use a .cpp file that is open source and should not be modified, and compiling it with those flags fails because that specific .cpp file has issues with some "implicit conversions that may alter a value".
Can I somehow instruct the build to compile all other files with -Wconversion -Werror but compile that file without those flags?

The make utility provides a rich set of facilities for customizing builds and for defaulting to implicit procedures for things that are routine logic. The GNU make tutorial is a good starting point if there's a question related to the gcc toolchain.
Essentially a makefile contains the custom logic for building a project. Rules consist of an apparent target separated from the dependencies by a colon on one line, and then (possibly zero or many) recipes on succeeding lines indented by a tab character that explain steps in building that target. Bogus targets, eg. clean, may also be defined for convenience in maintaining a project.
If there's a target-specific rule, that will be used in preference to any implicit rule to build that target. Probably the OP only needs to add a target-specific rule to an existing makefile that will govern the use of compiler options (building the object from the source).

Related

How can I add command-line options file to CMake compiler flags?

GCC allows for having command-line options passed by a file by #file syntax. Using this the file should be added as prerequisite (aka dependency) to the target.
I'm not finding any reference in CMake docs about argument files, suggesting it's not supported. Or perhaps just takes a little bit more plumbing, e.g. cat file|xargs? Or some way telling CMake explicitly that the file is a prerequisite? I mean "Prerequisite" according to GNU Make terminology. If file contents change I have to rebuild. AKA dependency.
Which is it? And how does it work?
You should just be able to use target_compile_options() or CXX_<LANG>_FLAGS like you normally would.
Since the flags available for different compilers are usually different, you probably will have one for each compiler you support, in which case you can wrap your target_compile_options() calls with if() blocks based on CMAKE_CXX_COMPILER_ID or the MSVC variable, or use the CXX_COMPILER_ID or X_COMPILER_ID generator expressions to use the right file (if you have multiple files for multiple compilers) for the right compiler.
However, I've also noticed before when trying this that using file flags like this doesn't automatically add the file as a dependency to the target (the CMake won't add a rule for the target to rebuild if that file changes), so you might need to do that manually like this:
# wrap this in a function taking `target` as an argument.
get_target_property(sources ${target} SOURCES)
set_property(SOURCE ${sources}
# DIRECTORY "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}"
TARGET_DIRECTORY ${target}
APPEND PROPERTY OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/path/to/flags/file.txt"
)
The above snippet courtesy of a user in this GitHub issue. It uses the OBJECT_DEPENDS source file property to make every source file of a target depend on the compiler options file. I (and the author of that code snippet) would classify it as a workaround, since it only works for Generators that support OBJECT_DEPENDS. From the CMake docs:
Specifies a semicolon-separated list of full-paths to files on which any object files compiled from this source file depend. On Makefile Generators and the Ninja generator an object file will be recompiled if any of the named files is newer than it. Visual Studio Generators and the Xcode generator cannot implement such compilation dependencies.
I'm not sure at what level of the toolchain it would be best to request that such automatic dependency-tracking functionality be added. According some of the Ninja buildsystem maintainers in the above linked GitHub issue, (if my noob brain is understanding the words they're saying correctly :P), it's something that could be handled by compilers when they generate depfiles given a compile comand for a source file. I'm currently too scared to ask compiler maintainers if that's the case. If you're interested in digging onto the part that CMake plays in orchestrating other tools to get dependency tracking for things like header files and the creation of dependency-tracking files ("depfiles"), you can go to your CMake installation's Modules folder and grep for CMAKE_DEPFILE_FLAGS_. Then use "find in files" at https://github.dev/Kitware/CMake.
Notes: Visual Studio / MSVC's compiler calls these "command files", gcc doesn't seem to have a particular name for them, and clang calls these "configuration files". They all support similar #file syntax. I'm not sure what the history is with that, but many compilers aim to have levels of compatibility (similar interface to) with GCC.
That's all. If you're bored and want to read a bit about how CMake does header dependency detection (which is loosely related here on the topic of depfiles), see this other post of mine.

CMake: how to set COMPILE_FLAGS for header files?

I've successfully used CMake to built a shared library, but the size is not so good.
I've already tried several compile flags to cut size, etc.
set_source_files_properties(${TARGET_SOURCE_FILES} PROPERTIES COMPILE_FLAGS "-fexceptions")
Code above is used to open exception handling for single file while -fno-exceptions is added to CMAKE_CXX_FLAG. It works fine.
However, I used the same code to an *.hpp to open rtti for it while -fno-rtti is added to CMAKE_CXX_FLAGS. Unfortunately, it didn't work.
So, is there a way to add COMPILE_FLAGS to header files in CMAKE? I've viewd documentary on offical site, but still no clues.
This is not possible and probably a questionable thing to do in the first place.
Mixing different compile flags within the same binary is a dangerous game. Usually you would want all compilation units in a target to share the same compile flags, as it is very easy to mess things up subtly but terribly otherwise. However, CMake still allows you to use source file properties the way you did to do this if you are really sure what you are doing.
With header files though, things are worse. Headers do not get compiled on their own, so what you are asking for is that all source files that pull in that header will inherit the special compilation options associated with that header. But since all calls to the compiler happen based on source files, this would require to re-run CMake on every source change, check all the includes in all the source files, and adapt the compiler options accordingly. Hopefully you can now see why CMake doesn't want to do this.
What you can do though is specify those options on a per-target basis. Move your headers to an interface target and add a corresponding interface property there. Then, all targets that want to use the header will have to pull in that target as a dependency. As a consequence, all depending source files will get the special compile flags, regardless of whether they actually do include the header or not, but that's just how build systems work:
add_library(my_headers INTERFACE)
target_include_directories(my_headers INTERFACE ${PATH_TO_HEADERS})
target_compile_options(my_headers INTERFACE $<$<CXX_COMPILER_ID:GNU>:-fexceptions>)
add_executable(client a.cpp)
target_link_libraries(client PUBLIC my_headers)
In this example, a.cpp (as well as all other sources of client) will now get compiled with the -fexceptions flag.

setting up autotools to link single system library statically

I have a project, where I want to link one of system libraries statically. The project uses GNU build system.
In configure.ac I have:
AC_CHECK_LIB(foobar, foobar_init)
On development machine this library is installed in /usr/lib/x86_64-linux-gnu. It is detected, but it is linked dynamically, which causes issues, as it is not present on some machines. Linking it statically (-Wl,-Bstatic etc.) works fine, but I don't know how to set this up in autotools. I tried forcing this into Makefile.am link flags for the project, but it still gives a preference to dynamic library.
I also tried using --enable-static with ./configure, but it seems to have no effect on system libraries.
If you want to link the whole program statically, then you should pass the --disable-shared option to configure. You might or might not need also to pass --enable-static, depending on the default value for that option (which you can influence via your configure.ac file). You really should consider doing this.
You should also consider making this the installer's problem, not the build system's. Let it be the installer's responsibility to ensure that all the shared libraries needed by the program are provided by the systems where it is installed. This is very common; in fact, it is one of the inspirations for package-management systems such as yum / dnf and apt, and their underlying packaging formats.
If you insist on linking only one library statically, while linking everything else dynamically, then you'll need to jump through a few more hoops. The objective will be to emit link options that cause just that library to be linked statically, without changing other libraries' linking. With the GNU toolchain, and supposing that the program is otherwise being linked dynamically, that would be this combination of options:
-Wl,-Bstatic -lfoobar -Wl,-Bdynamic
Now consider the documentation of the AC_CHECK_LIB() macro:
Macro: AC_CHECK_LIB (library, function, [action-if-found],
[action-if-not-found], [other-libraries])
[...] action-if-found is a list of shell commands to run if the link with the library succeeds; action-if-not-found is a list of shell
commands to run if the link fails. If action-if-found is not
specified, the default action prepends -llibrary to LIBS and defines
'HAVE_LIBlibrary' (in all capitals). [...]
Note in particular the default behavior in the event that the optional arguments are not provided (your present case) -- that's not quite what you want, at least not by itself. I suggest providing at least an alternative behavior for action-if-found case, and you could consider also making configure fail in the action-if-not-found case. The latter is left as an exercise; implementing just the former might look like this:
AC_CHECK_LIB([foobar], [foobar_init], [
LIBS="-Wl,-Bstatic -lfoobar -Wl,-Bdynamic $LIBS"
AC_DEFINE([HAVE_LIBFOOBAR], [1], [Define to 1 if you have libfoobar.])
])
You should also pay attention to the order of your AC_CHECK_LIB() invocations. As its docs go on to say:
This macro is intended to support building LIBS in a right-to-left
(least-dependent to most-dependent) fashion such that library
dependencies are satisfied as a natural side effect of consecutive
tests. Linkers are sensitive to library ordering so the order in which
LIBS is generated is important to reliable detection of libraries.
If you find that you still aren't getting what you want, then have a look at the link commands that make actually executes. You need to understand what's wrong about them before you can determine how to fix the problem.
With all that said, I observe that the above treatment is basically a hack, and it makes your build system much less resilient. It introduces dependencies on GNU toolchain options (which some other toolchains may nevertheless accept), and it assumes dynamic linking is being performed overall. It may be possible to resolve those issues with additional Autoconf code, but I urge you to instead go with one of the first two alternatives I described.

Makefile linker is unable to link one of the object files

I am doing a project that includes writing a makefile. Here I have 2 different makefiles. The first one does the initial build step. In the second makefile I am trying to use the initially generated object files (paths provided) and add one more additional object file generated else where. The problem I am facing here is that the linker is unable to link this new object file to the older ones.
I am using this command to do this step.
arm-none-eabi-g++ -T ../linker.ld -nostartfiles -Xlinker --gc-sections -Wl,-Map,"map_file.map" -specs=nano.specs -o "target.elf" new_file.o all_older_files.o
Here the new_file.o is of arm_eabi version 0 and all_older_files.o is arm_eabi version 5. However, this is not giving me any error or warning. And, interesting thing is that, some of the symbols in the new_file.o are being included in the target.elf file. I have checked and checked the linker script but unable to find a solution and also, check if the eabi version is making some difference, but it is the same if I manually edit the elf file using an elf editor.
All I want is that I need to include the sections in the new_file.o in this target.elf so that I can make use of these.
I think I got this. Thank you #Notlikethat, your insight helped me. I figured out that the "--gc-sections" is ignoring the symbols and sections that weren't referenced.
However, when I tried this the first time, the sections were off by large memory portions than it should be and thought this wasn't the solution. But, later I have noticed that the initial auto-gen makefile is also doing the same removing unused sections. So I had to disable that in eclipse project setting and then remove this flag in my makefile as well. This placed the sections where it should be.
Thank you so much, this has saved me tons of time as I was fighting with this for a little longer than needed.

How do I tell ld to ignore a missing library?

I'd like to define a Makefile with implicit rules for a bunch of executables, some of which require linking against a custom-built library (let's call it libedich.a).
My problem is that I'd like to be able to build those executables that do not require libedich.a when the latter hasn't been built yet. If I simply add -ledich to the LDLIBS variable, I get errors when libedich.a doesn't exist:
/usr/bin/ld: cannot find -ledich
How do I tell ld that it's okay to continue linking when a given library doesn't exist?
A common solution is to create a dummy archive so that GCC will find it. Since the executable doesn't need any symbols from the library, it won't error out. Like this,
# create an empty archive.
ar cru libedich.a
or even simpler,
echo '!<arch>' >libedich.a
This is the downside of using one LDLIBS variable to hold all of the library dependencies and re-using it for every target, even though you know some targets only need a subset of the libraries. You have several options:
There are probably fancy IDE's and build tools out there that try to infer library dependencies from context, saving you from manually specifying them for each target.
Switch to using shared libraries.
Fix the target in your Makefile so that it depends on libedich.a (even if it doesn't need to). This will work if you are building everything anyway and don't care what order the targets proceed in.
Manually specify the library dependencies for each target in your Makefile.
The last option is my recommendation; it is more work, but eliminating the false dependencies in your Makefile will enable you to build (perhaps most of) your targets even if one of the dependencies is broken. One convenient way to do this is with target-specific variables:
targetname::LDLIBS+=-ledich
You probably also want to be aware of make --keep-going (make -k)

Resources