How to compile package with sub-directory includes in SCons? - makefile

scons output (split for readability), relevant commit:
scons: Building targets ...
g++ -o build/XMP/XMPCore/source/ExpatAdapter.o -c -O2 -iquote- -DUNIX_ENV=1 \
-D_FILE_OFFSET_BITS=64 -Ifixes/XMP-Toolkit -IXMP-Toolkit-SDK-CC201306/build \
-IXMP-Toolkit-SDK-CC201306/source/common -IXMP-Toolkit-SDK-CC201306/XMPCore/source \
-IXMP-Toolkit-SDK-CC201306/source/XMPFiles \
-IXMP-Toolkit-SDK-CC201306/source/XMPFiles/FileHandlers \
-IXMP-Toolkit-SDK-CC201306/source/XMPFiles/FormatSupport \
-IXMP-Toolkit-SDK-CC201306/third-party/MD5 \
-IXMP-Toolkit-SDK-CC201306/public/include \
XMP-Toolkit-SDK-CC201306/XMPCore/source/ExpatAdapter.cpp
XMP-Toolkit-SDK-CC201306/XMPCore/source/ExpatAdapter.cpp:9:77: fatal error:
public/include/XMP_Environment.h: No such file or directory
#include "public/include/XMP_Environment.h" // ! Must be the first #include!
^
It seems XMP started using relative includes in files rather than relying on compiler options. How do I handle this new include style in SCons?
(Background: When trying to compile dcp2icc (using a Makefile based on the original ReadMe.txt) I got a bunch of errors like 'strlen' is not a member of 'std', which seems to be because of an include clean-up in GCC. Rather than patch a bunch of third party libraries I decided to try a newer version of XMP.)

You should try to solve this include fail pretty much the same as you would on the command-line: by adding the missing include path, which in your case seems to be "-IXMP-Toolkit-SDK-CC201306". So, add your origXMP to the CPPPATH as well...

Related

How to force static library to include it dependencies?

I build my own static library with gcc and ar like this.
g++ \
... list of library sources ... \
... a lot of -L -l -I -D options etc... \
-c \
&& ar crf ./lib/libpackager.a *.o
Then I use this library in my app. Currently I built it like this.
g++ \
myApp.cpp \
... same -L -l -I options as in library ... \
-L. -lpackager \
-o myApp
It works, but I am little odd for me that I need to duplicate all -l and -L during building the app. Is it possible include all this library dependencies inside the library. My goal to build app like this.
g++ myApp.cpp -L. -lpackager -o myApp
Transferring comments into an answer.
Specifying the -l and -L operations when compiling to object files is irrelevant. Some versions of GCC warn about arguments that won't be used because they are link-time arguments, and linking won't be used when you include the -c flag.
The ar command doesn't know what to do with the C compiler's -l and -L arguments (it might have its own uses for the flags; one version of ar accepts but ignores -l).
So, you have to specify the dependencies when you link with the static library. That is the way life has been since the early 70s — that aspect hasn't changed yet.
Shared libraries can be built with the dependency information, but not static libraries.
As I understand it, I need to build a shared library and link it in a static way, right?
No. You either need to build and link a shared library as a shared library, or you need to accept that using a static library means you will need to specify other libraries on the command line when you use this library. There are systems to help manage such information; pkg-config is one such. AFAIK, you cannot link a shared library in a 'static way'.

Configure clang-check for c++ standard libraries

I am trying to run Ale as my linter, which in turn uses clang-check to lint my code.
$ clang-check FeatureManager.h
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "FeatureManager.h"
No compilation database found in /home/babbleshack/ or any parent directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
/home/babbleshack/FeatureManager.h:6:10: fatal error: 'unordered_map' file not found
#include <unordered_map>
^~~~~~~~~~~~~~~
1 error generated.
Error while processing /home/babbleshack/FeatureManager.h.
Whereas compiling with clang++ returns only a warning.
$ clang++ -std=c++11 -Wall FeatureManager.cxx FeatureManager.h
clang-5.0: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
There are no flags to clang-check allowing me to set compilation flags.
Took a while to figure this out, but you can do
clang-check file.cxx -- -Wall -std=c++11 -x c++
or if you are using clang-tidy
clang-tidy file.cxx -- -Wall -std=c++11 -x c++
To get both working with ALE, I added the following to my vimrc
let g:ale_cpp_clangtidy_options = '-Wall -std=c++11 -x c++'
let g:ale_cpp_clangcheck_options = '-- -Wall -std=c++11 -x c++'
If you want ALE to work for C as well, you will have to do the same for g:ale_c_clangtidy_options and g:ale_c_clangcheck_options.
I was getting stumped by a similar error message for far too long:
/my/project/src/util.h:4:10: error: 'string' file not found [clang-diagnostic-error]
#include <string>
^
I saw other questions suggesting that I was missing some critical package, but everything already seemed to be installed (and my code built just fine, it was only clang-tidy that was getting upset).
Passing -v showed that my .h file was being handled differently:
$ clang-tidy ... src/*.{h,cc} -- ... -v
...
clang-tool ... -main-file-name util.cc ... -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9 ... -x c++ ... /tmp/copy/src/util_test.cc
...
clang-tool ... -main-file-name util.h ... -x c-header /my/project/src/util.h
...
As Kris notes the key distinction is the -x c-header flag, which is because clang assumes a .h file contains C, not C++, and this in turn means that the system C++ includes weren't being used to process util.h.
But the -main-file-name flag also stood out to me as odd; why would a header file ever be the main file? While digging around I also came across this short but insightful answer that header files shouldn't be directly compiled in the first place! Using src/*.cc instead of src/*.{h,cc} avoids the problem entirely by never asking Clang to try to process a .h on its own in the first place!
This does introduce one more wrinkle, though. Errors in these header files won't be reported by default, since they're not the files you asked clang-tidy to look at. This is where the "Use -header-filter=. to display errors from all non-system headers.*" message clang-tidy prints comes in. If I pass -header-filter=src/.* (to only include my src headers and not any other header files I'm including with -I) I see the expected errors in my header files. Phew!
I'm not sure whether to prefer -x c++ or -header-filter=.* generally. A downside of -header-filter is you have to tune the filter regex, rather than just passing in the files you want to check. But on the other hand processing header files in isolation is essentially wasteful work (that I expect would add up quickly in a larger project).

Remove a compiler / linker flag from autotools configure

There is a project (Antlr3 for C) that can be built with ./configure && make && make install.
One of the flags that are used in the compilation command is -Wl,-soname -Wl,libantlr3c.so. The whole command is:
libtool: link: gcc -shared .libs/antlr3baserecognizer.o .libs/antlr3basetree.o \
.libs/antlr3basetreeadaptor.o .libs/antlr3bitset.o .libs/antlr3collections.o \
.libs/antlr3commontoken.o .libs/antlr3commontree.o .libs/antlr3commontreeadaptor.o \
.libs/antlr3commontreenodestream.o .libs/antlr3convertutf.o .libs/antlr3cyclicdfa.o \
.libs/antlr3debughandlers.o .libs/antlr3encodings.o .libs/antlr3exception.o \
.libs/antlr3filestream.o .libs/antlr3inputstream.o .libs/antlr3intstream.o \
.libs/antlr3lexer.o .libs/antlr3parser.o .libs/antlr3rewritestreams.o \
.libs/antlr3string.o .libs/antlr3tokenstream.o .libs/antlr3treeparser.o \
-m64 -Wl,-soname -Wl,libantlr3c.so -o .libs/libantlr3c.so
How can I remove only the -Wl,-soname -Wl,libantlr3c.so part?
I understand that the compiler and linker flags can be overridden with CFLAGS and LDFLAGS in the configure command. According to this link, it's something like
./configure CFLAGS=blah LDFLAGS=blah
Although I understand that they can/should be used as environment variables, something like
CFLAGS=BLAH LDFLAGS=blah ./configure
However, I think that those uses would try to override all the CFLAGS or LDFLAGS. I only want to exclude the -soname flag (which, I understand, -Wl, means that the compiler passes a flag to the linker.
None of my attempts with things like LDFLAGS=-soname= or CFLAGS="-Wl,soname -Wl,", and variations of them, were successful so far.
From this question it looks as if it was possible to remove flags from within a Makefile, but I can't see that being applicable to overriding flags from the command line with the configure command. It's also possible to provide these variables to the make command instead of the configure command, but that wasn't successful either.
Note, it wouldn't make sense for me to change the Makefile, since it's generated out of the configure command.
You cannot remove -soname because it's part of the way you build a shared library with GCC, and comes straight from libtool. Since you can't really build a shared object for ELF without a soname (well, you can, but it's not really useful) libtool won't let you remove that.
You probably are better off declaring what you try to achieve, because I have a feeling it has nothing really to do with -soname in that case.

rebar compile fails with bitcask - "errno.h": no such file

I am new to Erlang, so i am going through Joe Armstrong's book "Programming Erlang". In chapter 25 there's an example on how to work with rebar. I followed the instructions and created a Makefile
all:
test -d deps || rebar get-deps
rebar compile -v
#erl -noshell -pa './deps/bitcask/ebin' -pa './ebin' -s myapp start
and rebar.config
{deps, [
{bitcask, ".*", {git, "git://github.com/basho/bitcask.git", "master"}}
]}.
Getting the dependencies works, but compiling fails.
The verbose output tells me that this command fails
cmd: cc -c $CFLAGS -g -Wall -fPIC -I"/usr/lib/erlang/lib/erl_interface-3.7.18/include" -I"/usr/lib/erlang/erts-6.2/include" c_src/bitcask_nifs.c -o c_src/bitcask_nifs.o
with this error
/home/user/folder/deps/bitcask/c_src/bitcask_nifs.c:22:19: fatal error: errno.h: No such file or directory
But
find /usr/include -name errno.h
gives me
/usr/include/x86_64-linux-gnu/asm/errno.h
/usr/include/asm/errno.h
/usr/include/linux/errno.h
/usr/include/asm-generic/errno.h
So I was asking myself..
what am I missing?
how can I tell rebar about the depencies on the C libraries and where to find them?
why isn't this configured correctly in the Makefile of bitcask?
Maybe I was searching for the wrong terms, but I couldn't find any solution in the internets.
Many thanks in advance
There are two thing to consider
rebar options
You can set options for compiling C code with port_env option in rebar.config.
comiling deps
Since bitstack is your dependency, it is not compiled with yours rebar config, but with it's own. So if you would like to change anything, you would have to modify the bitcask file.
Fortunately, if you look into config their writen all C compilation is done with environment variable $ERL_CFLAGS. And again, in rebar source code you can see that this flag is responsible for include paths in your compilation.
So easist way would be extending $ERL_CFLAGS in your Makefile before compilation, with something like this
all: ERL_CFLAGS = "$ERL_CFLAGS -I /usr/include/linux/errno.h"
all:
test -d deps || rebar get-deps
rebar compile -v
#erl -noshell -pa './deps/bitcask/ebin' -pa './ebin' -s myapp start
Just make sure that this include works for you, and that you are not overwriting any flags you are using.

How to overrule default gcc options to the linker?

On my system when I compile something (with bfin-linux-uclibc-g++ but that is irrelevant), I get hundreds of warnings (not in my own code base) with respect to one of the compiler flags. I want to disable it.
fde encoding in src/SpiMessageUtil.o(.eh_frame) prevents .eh_frame_hdr table being created.
This orginates from a default gcc flag which is handed over to the linker, which is easy to check by adding '-v' to the compilation step:
COLLECT_GCC_OPTIONS=... --eh-frame-hdr ...
I would like to get rid of this option, which is indeed by default defined:
bfin-linux-uclibc-g++ -dumpspecs | grep frame-hdr
%{!static:--eh-frame-hdr}\
%{mfdpic: -m elf32bfinfd -z text} %{shared} %{pie} \
%{static:-dn -Bstatic} %{shared:-G -Bdynamic} \
%{!shared: %{!static: %{rdynamic:-export-dynamic} \
%{!dynamic-linker:-dynamic-linker \
%{mglibc:%{muclibc:%e-mglibc and -muclibc used together;:%e-mglibc not supported for this target};:/lib/ld-uClibc.so.0 \
}}}\
%{static}} -init __init -fini __fini
How can I override this option? I cannot use -Wl,--no-eh-frame-hdr, because there is nothing like that defined.
You can dynamically dump GCC's specs, remove this switch from there and use it when linking, i.e.:
g++ -dumpspecs | sed -e 's,--eh-frame-hdr,,g' > better_specs
g++ -specs=better_specs -o target file1.o file2.o -llib1...
This would replace the specs inline, while keeping original compiler intact.
If you keep your own Makefiles, this could also be handled with something like:
$(TARGET): $(OBJS) | better_specs
$(LINK.o) $(OUTPUT_OPTION) -specs=$| $^
better_specs:
$(CXX) -dumpspecs | sed -e 's,--eh-frame-hdr,,g' > $#
This approach could be also used with configure scripts, provided that you generate better_specs before, you could just use ./configure CXX='g++ -specs=/path/to/better_specs'.
I just got started with back-porting some code to an old system with a bfin controller and ran into the problem with these terribly annoying warnings - 1000s at a time. I didn't find a way to just deactivate the output.
But there are 2 "ways to go" that work:
Fix the source and rebuild the tool-chain:
Remove the code that creates the output in elf-eh-frame.c in the function _bfd_elf_discard_section_eh_frame:
(*info->callbacks->einfo)
(_("%P: fde encoding in %B(%A) prevents .eh_frame_hdr"
" table being created.\n"), abfd, sec);
Patch the ld binary
Take a look at the ld-Binary and patch the binary directly.
I dumped the data segment (.rodata) with objdump to find the address of the string. Then (after creating a disassembly with objdump) I searched where that string was used and replaced the call to the function that creates the output with two NoOps (0xFF 0xD3 -> 0x90 0x90).
Linker still creates the same output, but no more messages.

Resources