OCLint usage example - objective-c

I was looking for an example on how to config OCLint or how to get it running. I made a search but nothing. Here at Stack Overflow there are just 3 posts related, just naming the library and on google just the official OCLint.org
The oficial docs says:
[user#localhost ~]$ oclint -help
OVERVIEW: OCLint, a static code analysis tool for Objective-C and related languages
USAGE: oclint [options] <input files>
OPTIONS:
-D <macro> - Predefine the specified macro
-F <directory> - Add directory to framework include search path
-I <directory> - Add directory to include search path
-R <directory> - Add directory to rule loading path
-arch <arch_name> - Specify which architecture (e.g. ppc, i386, x86_64, armv7) the compilation
should targets.
-help - Display available options (-help-hidden for more)
-include <file> - Include file before parsing
-isysroot <directory> - Add directory to SYSTEM include search path
-o <file> - Write output to <file>
-rc <paramemter>=<value> - Change the baheviour of rules
-stats - Enable statistics output from program
Choose report type:
-text - Plain text report
-html - HTML formatted report
-version - Display the version of this program
-x <value> - Input language type
But I would like a better explanation about macro (-D), and which path to choose for -I, -F, -R and what should I point at. A code example as
$ oclint path/to/file.m -D something -I something -F something -R something
And the output expected from that would be great.

Basically you just give oclint whatever you give to your compiler.
Alternatively, you may want to try oclint-xcodebuild if you are not familiar with compiler flags. This is a Python script that extracts flags from your Xcode build log file. See the usage here.

Related

How to run sanitizers on whole project

I'm trying to get familiar with sanitizers as ASAN, LSAN etc and got a lot of useful information already from here: https://developers.redhat.com/blog/2021/05/05/memory-error-checking-in-c-and-c-comparing-sanitizers-and-valgrind
I am able to run all sort of sanitizers on specific files, as shown on the site, like this:
clang -g -fsanitize=address -fno-omit-frame-pointer -g ../TestFiles/ASAN_TestFile.c
ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out >../Logs/ASAN_C.log 2>&1
which generates a log with found issue. Now I would like to extend this to run upon building the project with cmake. This is the command to build it at the moment:
cmake -S . -B build
cd build
make
Is there any way I can use this script with adding the sanitizers, without having to alter the cmakelist.txt file??
For instance something like this:
cmake -S . -B build
cd build
make -fsanitize=address
./a.out >../Logs/ASAN_C.log 2>&1
The reason is that I want to be able to build the project multiple times with different sanitizers (since they cannot be used together) and have a log created without altering the cmakelist.txt file (just want to be able to quickly test the whole project for memory issues instead of doing it for each file created).
You can add additional compiler flags from command line during the build configuration:
cmake -D CMAKE_CXX_FLAGS="-fsanitize=address" -D CMAKE_C_FLAGS="-fsanitize=address" /path/to/CMakeLists.txt
If your CMakeLists.txt is configured properly above should work. If that does not work then try adding flags as environment variable:
cmake -E env CXXFLAGS="-fsanitize=address" CFLAGS="-fsanitize=address" cmake /path/to/CMakeLists.txt

Clang: Using Cmake to build a compile_commands.json for my project

I'm trying to create the compile_commands.json file by following these instructions: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
I don't see any option on the docs that allows be to build the compile_commands.json file against my own code. The command that I use when I follow the doc builds the json file, but the contents of the file contains files/directories in the llvm source directory. I'm assuming that if this file contains contents of my own project, then when I run run-clang-tidy.py (from here), then it will run clang-tidy against my own project.
So the question: How do I get Cmake to build the compile_commands.json to contain my own project?
It is unclear exactly what you want to achieve. In the link you provided, the author is building LLVM from source code, which is why the compilation database (compile_commands.json) refers to those sources.
In general to build the compilation database while building the source tree with CMake, you provide it with the -DCMAKE_EXPORT_COMPILE_COMMANDS=ON flag.
So, where the blog post you linked calls
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON path/to/llvm/sources
...you would exchange the path to the sources for your own source tree:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON this/is/my/source/tree/path
...which should generate the json-file in the current (build) directory.
As in the article, you will probably want to symlink that file to the root of your source tree and then run your tools from there.
Here's a (very) simple build script that I wrote and sometimes use. Maybe it can be helpful to you (adjust to your own needs obviously). It should be run from the root of your source tree.
#!/usr/bin/env sh
type=Debug
if ! [[ -z "$1" ]]; then
type="$1"
mkdir -p build/$type
shift
fi
# Configure build
cmake -S . -B build/$type -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=$type .
# Build
cmake --build build/$type --parallel 4 --config $type "$#"
ln -fs build/$type/compile_commands.json .

Make pattern match variables are not expanded

I'm trying to build some PDFs in a Makefile using Sphinx. The resulting PDF has broken references, so I want to fix those using pdftk.
Goal
So what I want to do for all PDFs I build is this:
# Creates the PDF files.
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken
# Go through all PDFs and fix them.
pdftk $(BUILDDIR)/pdf_broken/thepdf.pdf output $(BUILDDIR)/pdf/thepdf.pdf
Attempt with Make
So to do this with Make I have written this Makefile:
# Build PDF (results in broken references)
$(BUILDDIR)/pdf_broken/%.pdf:
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken
# This fixes the broken pdfs and produces the final result.
$(BUILDDIR)/pdf/%.pdf: $(BUILDDIR)/pdf_broken/%.pdf
mkdir -p $(BUILDDIR)/pdf/
pdftk $^ output $#
pdf: $(BUILDDIR)/pdf/%.pdf
Expected result
I'm using Pattern matching as I understand it from reading the manual:
http://www.tack.ch/gnu/make-3.82/make_91.html
Where $< as I understand it should be the prerequisite expanded so from my above example:
$(BUILDDIR)/pdf_broken/thepdf.pdf
and then $# should be the target:
$(BUILDDIR)/pdf/thepdf.pdf
So my recipe pdftk $^ output $# should run the command:
pdftk $(BUILDDIR)/pdf_broken/thepdf.pdf output $(BUILDDIR)/pdf/thepdf.pdf
Actual result
But this is not what is happening. Instead, this is run:
pdftk build/pdf_broken/%.pdf output build/pdf/%.pdf
Which obviously gives me an error:
Error: Unable to find file.
Error: Failed to open PDF file:
build/pdf_broken/%.pdf
Question
So my question is, what have I missundestood with how the pattern matching works, and how is the correct way to solve this using Make?
You should likely lookup pattern rules. In any case, it looks like you have a single command to generate all the files in the broken directory. This should have its own rule, and should likely output a dummy file to indicate it is complete. Your rule to fix the pdf files should be dependent on this dummy target being created.
It should be something like:
// get a list of expected output files:
PDF_SOURCES:=$(wildcard source/pdf/*)
PDF_OUTS:=$(patsubst $(PDF_SOURCES),source/pdf/%.pdf,$(BUILDDIR)/pdf/%.pdf);
// just for debugging:
$(info PDF_SOURCES = $(PDF_SOURCES))
$(info PDF_OUTS = $(PDF_OUTS))
// default rule
all: $(PDF_OUTS)
#echo done
// rule to build BUILDIR:
$(BUILDDIR)/pdf:
mkdir -p $#
// rule to build all broken files in one go:
// (note: generates a file .dosphynx, which is used to keep track
// of when the rule was run last. This rule will be run if the
// timestamp of any of the sources are newer.
.do_sphynx: $(PDF_SOURCES) | $(BUILDDIR)/pdf
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken
touch $#
// create a dependency of all output files on do_sphynx
$(PDF_OUTS): .do_sphynx
// patern rule to fix pdf files
$(BUILDDIR)/pdf/%.pdf : $(BUILDDIR)/pdf_broken/%.pdf
pdftk $< output $#
I've not tested this, so its possible it may have a syntax error in it..
---------------------- EDIT -------------
Ok, since $(PDF_OUTS) cannot be determined at makefile read time, perhaps you should do:
// get a list of expected output files:
PDF_SOURCES:=$(wildcard source/pdf/*)
all: .do_fix
#echo done
$(BUILDDIR)/pdf:
mkdir -p $#
.do_sphynx: $(PDF_SOURCES) | $(BUILDDIR)/pdf
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) source/pdf/ $(BUILDDIR)/pdf_broken
touch $#
.do_fix: .do_sphynx
#for src in $$(ls source/pdf/*.pdf); do \
trg=$${src/#"source/pdf"/"$(BUILD_DIR)/pdf"}; \
[[ $$src -nt $$trg ]] && \
echo "$$src ==> $$trg" && pdftk $$src output $$trg; \
done
touch $#
One note -- the -nt comparator in the if will return true if $trg does not exist, so it will cover the case where the file is missing, or the target is older than the source. Again not tested, but it should work.

What does the `-H.` option means for CMake?

This answer to a former question on CMake shows this command line:
cmake -H. -Bbuild -G "MSYS Makefiles"
What task does the -H. option perform here? cmake --help says that -H prints the help...
I am using CMake 3.2.3.
As mentioned in the linked answer, it is an undocumented option, but looking at the source code reveals its effect:
In cmake::SetArgs():
if(arg.find("-H",0) == 0)
{
directoriesSet = true;
std::string path = arg.substr(2);
path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
this->SetHomeDirectory(path);
The last call, SetHomeDirectory actually sets the source directory for the project. The -B option (also undocumented) in turn sets the binary directory.
If these options are not set, the binary directory will be the current folder where cmake is executed, and the source directory can be given as a positional argument (if not found, the source folder will also be the current working directory).
The Hitchhiker’s Guide to the CMake explains both, the legacy and new in CMake 3.13 options:
-H
This internal option is not documented but widely used by community.
and
Has been replaced in 3.13 with the official source directory flag of -S.
-B
Starting with CMake 3.13, -B is an officially supported flag,
can handle spaces correctly and can be used independently of the -S or -H options.

MinGW linking dynamic library with bad name

I am using MinGW64 (Windows 7) without MSYS and I have the following problem:
I have one dll, written in C99, which has to have the .mexw64 suffix so it can be used by Matlab. I would like to be able to link this dll form another dll (mexw64) dynamically but gcc won't allow me to link directly. I cannot do static linking, because both dlls have many functions of the same name which can be hidden by not exporting their symbols when creating the shared library.
So far, I have tried:
To create a symbolic link (with correct suffix and preffix) using mklink. This works, but I was not able to run mklink from the makefile. Maybe it is due to the fact I am not using MSYS which could have ln -s (I havent checked).
To do the copy of the first dll and correcting the suffix and prefix. This worked better than I expected, because on runtime the second dll actually uses the original .mexw64 and not the dll copy. I guess it is just because the .mexw64 is found first, but why is that .mexw64 searched in the first place? How the system know it is actually a dll?
My question is, is this correct/safe enough? Are there any other options?
Thanks for comments.
You should build a proper implib, either as a linker output or from a .def.
Linker:
$ gcc -shared -o testimpl.mexw64 testimpl.c -Wl,--out-implib,libtestimpl.a
$ dlltool -I libtestimpl.a
testimpl.mexw64
Or create a .def file, specifying an explicit LIBRARY:
$ cat testimpl.def
LIBRARY testimpl.mexw64
EXPORTS
test #1
$ dlltool -d testimpl.def -l libtestimpl.a
$ dlltool -I libtestimpl.a
testimpl.mexw64
And finally, link stuff:
$ gcc -o test.exe test.c libtestimpl.a
# or
$ gcc -o test.exe test.c -L. -ltestimpl
$ grep testimpl.mexw64 test.exe
Binary file test.exe matches