I have a static library (C++) (say, libmylib_DARWIN.a and libmylib_LINUX.a for 2 architectures) compiled on my Mac using clang (Apple LLVM version 9.0.0 (clang-900.0.39.2) if is of any relevance).
Right now, there are two problems:
The static library (using a current build configuration) contains debug symbols
It also shows names of the object files that were used for the archive
otool -Iv libmylib_DARWIN.a
Archive : libmylib_DARWIN.a
libmylib_DARWIN.a(firstobjectfile.cpp.o)
libmylib_DARWIN.a(secondobjectfile.cpp.o)
....
I would like to remove both the debug symbols and archived filenames from this library. I wonder if there is a convenient way to do it without changing my build configuration.
will strip on Mac do it for both DARWIN- and LINUX-built libraries? Anything I should pay attention too?
strip doesn't seem to remove the archive filenames
There are some similar questions on SO; however, the ones I found deal with either iOS, Objective C, do not talk about multiplatform, and do not mention archive names.
This script implements Sigismondo's suggestion (unpacks the archive, strips each object file individually, renames them 1000.o, 1001.o, etc., and repacks). The parameters for ar crus may vary depending on your version of ar.
#!/bin/bash
# usage: repack.sh file.a
if [ -z "$1" ]; then
echo "usage: repack file.a"
exit 1
fi
if [ -d tmprepack ]; then
/bin/rm -rf tmprepack
fi
mkdir tmprepack
cp $1 tmprepack
pushd tmprepack
basename=${1##*/}
ar xv $basename
/bin/rm -f $basename
i=1000
for p in *.o ; do
strip -d $p
mv $p ${i}.o
((i++))
done
ar crus $basename *.o
mv $basename ..
popd
/bin/rm -rf tmprepack
exit 0
Is there a way to call something like clang-format --style=Webkit for an entire cpp project folder, rather than running it separately for each file?
I am using clang-format.py and vim to do this, but I assume there is a way to apply this once.
Unfortunately, there is no way to apply clang-format recursively. *.cpp will only match files in the current directory, not subdirectories. Even **/* doesn't work.
Luckily, there is a solution: grab all the file names with the find command and pipe them in. For example, if you want to format all .h and .cpp files in the directory foo/bar/ recursively, you can do
find foo/bar/ -iname *.h -o -iname *.cpp | xargs clang-format -i
See here for additional discussion.
What about:
clang-format -i -style=WebKit *.cpp *.h
in the project folder. The -i option makes it inplace (by default formatted output is written to stdout).
First create a .clang-format file if it doesn't exist:
clang-format -style=WebKit -dump-config > .clang-format
Choose whichever predefined style you like, or edit the resulting .clang-format file.
clang-format configurator is helpful.
Then run:
find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \;
Other file extensions than cpp, hpp, cc and cxx can be used in the regular expression, just make sure to separate them with \|.
I recently found a bash-script which does exactly what you need:
https://github.com/eklitzke/clang-format-all
This is a bash script that will run clang-format -i on your code.
Features:
Finds the right path to clang-format on Ubuntu/Debian, which encode the LLVM version in the clang-format filename
Fixes files recursively
Detects the most common file extensions used by C/C++ projects
On Windows, I used it successfully in Git Bash and WSL.
For the Windows users: If you have Powershell 3.0 support, you can do:
Get-ChildItem -Path . -Directory -Recurse |
foreach {
cd $_.FullName
&clang-format -i -style=WebKit *.cpp
}
Note1: Use pushd . and popd if you want to have the same current directory before and after the script
Note2: The script operates in the current working directory
Note3: This can probably be written in a single line if that was really important to you
When you use Windows (CMD) but don't want to use the PowerShell cannon to shoot this fly, try this:
for /r %t in (*.cpp *.h) do clang-format -i -style=WebKit "%t"
Don't forget to duplicate the two %s if in a cmd script.
The below script and process:
works in Linux
should work on MacOS
works in Windows inside Git For Windows terminal with clang-format downloaded and installed.
Here's how I do it:
I create a run_clang_format.sh script and place it in the root of my project directory, then I run it from anywhere. Here's what it looks like:
run_clang_format.sh
#!/bin/bash
THIS_PATH="$(realpath "$0")"
THIS_DIR="$(dirname "$THIS_PATH")"
# Find all files in THIS_DIR which end in .ino, .cpp, etc., as specified
# in the regular expression just below
FILE_LIST="$(find "$THIS_DIR" | grep -E ".*(\.ino|\.cpp|\.c|\.h|\.hpp|\.hh)$")"
echo -e "Files found to format = \n\"\"\"\n$FILE_LIST\n\"\"\""
# Format each file.
# - NB: do NOT put quotes around `$FILE_LIST` below or else the `clang-format` command will
# mistakenly see the entire blob of newline-separated file names as a SINGLE file name instead
# of as a new-line separated list of *many* file names!
clang-format --verbose -i --style=file $FILE_LIST
Using --style=file means that I must also have a custom .clang-format clang-format specifier file at this same level, which I do.
Now, make your newly-created run_clang_format.sh file executable:
chmod +x run_clang_format.sh
...and run it:
./run_clang_format.sh
Here's a sample run and output for me:
~/GS/dev/eRCaGuy_PPM_Writer$ ./run_clang-format.sh
Files found to format =
"""
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo/PPM_Writer_demo.ino
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo2/PPM_Writer_demo2.ino
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.h
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.cpp
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/timers/eRCaGuy_TimerCounterTimers.h
"""
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo/PPM_Writer_demo.ino
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo2/PPM_Writer_demo2.ino
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.h
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.cpp
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/timers/eRCaGuy_TimerCounterTimers.h
You can find my run_clang_format.sh file in my eRCaGuy_PPM_Writer repository, and in my eRCaGuy_CodeFormatter repository too. My .clang-format file is there too.
References:
My repository:
eRCaGuy_PPM_Writer repo
run_clang_format.sh file
My notes on how to use clang-format in my "git & Linux cmds, help, tips & tricks - Gabriel.txt" doc in my eRCaGuy_dotfiles repo (search the document for "clang-format").
Official clang-format documentation, setup, instructions, etc! https://clang.llvm.org/docs/ClangFormat.html
Download the clang-format auto-formatter/linter executable for Windows, or other installers/executables here: https://llvm.org/builds/
Clang-Format Style Options: https://clang.llvm.org/docs/ClangFormatStyleOptions.html
[my answer] How can I get the source directory of a Bash script from within the script itself?
Related:
[my answer] Indenting preprocessor directives with clang-format
See also:
[my answer] https://stackoverflow.com/questions/67678531/fixing-a-simple-c-code-without-the-coments/67678570#67678570
Here is a solution that searches recursively and pipes all files to clang-format as a file list in one command. It also excludes the "build" directory (I use CMake), but you can just omit the "grep" step to remove that.
shopt -s globstar extglob failglob && ls **/*.#(h|hpp|hxx|c|cpp|cxx) | grep -v build | tr '\n' ' ' | xargs clang-format -i
You can use this inside a Make file. It uses git ls-files --exclude-standard to get the list of the files, so that means untracked files are automatically skipped. It assumes that you have a .clang-tidy file at your project root.
format:
ifeq ($(OS), Windows_NT)
pwsh -c '$$files=(git ls-files --exclude-standard); foreach ($$file in $$files) { if ((get-item $$file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $$file } }'
else
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$$' | xargs clang-format -i -style=file
endif
Run with make format
Notice that I escaped $ using $$ for make.
If you use go-task instead of make, you will need this:
format:
- |
{{if eq OS "windows"}}
powershell -c '$files=(git ls-files --exclude-standard); foreach ($file in $files) { if ((get-item $file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $file } }'
{{else}}
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$' | xargs clang-format -i -style=file
{{end}}
Run with task format
If you want to run the individual scripts, then use these
# powershell
$files=(git ls-files --exclude-standard); foreach ($file in $files) { if ((get-item $file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $file } }
# bash
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$' | xargs clang-format -i -style=file
I'm using the following command to format all objective-C files under the current folder recursively:
$ find . -name "*.m" -o -name "*.h" | sed 's| |\\ |g' | xargs clang-format -i
I've defined the following alias in my .bash_profile to make things easier:
# Format objC files (*.h and *.m) under the current folder, recursively
alias clang-format-all="find . -name \"*.m\" -o -name \"*.h\" | sed 's| |\\ |g' | xargs clang-format -i"
In modern bash you can recursively crawl the file tree
for file_name in ./src/**/*.{cpp,h,hpp}; do
if [ -f "$file_name" ]; then
printf '%s\n' "$file_name"
clang-format -i $file_name
fi
done
Here the source is assumed to be located in ./src and the .clang-format contains the formatting information.
As #sbarzowski touches on in a comment above, in bash you can enable globstar which causes ** to expand recursively.
If you just want it for this one command you can do something like the following to format all .h, .cc and .cpp files.
(shopt -s globstar; clang-format -i **/*.{h,cc,cpp})
Or you can add shopt -s globstar to your .bashrc and have ** goodness all the time in bash.
As a side note, you may want to use --dry-run with clang-format the first time to be sure it's what you want.
I had similar issue with clang-format, we have a huge project with a lot of files to check and to reformat.
Scripts were a ok solutions, but there was too slow.
So, I've wrote an application that can recursively going thru files in folder and executes clang-format on them in fast multithreaded manor.
Application also supports ignore directories and files that you might not wanna touch by format (like thirdparty dirs)
You can checkout it from here: github.com/GloryOfNight/clang-format-all
I hope it would be also useful for other people.
ps: I know that app huge overkill, but its super fast at it job
A bit <O/T>, but when I googled "how to feed a list of files into clang-format" this was the top hit. In my case, I don't want to recurse over an entire directory for a specific file type. Instead, I want to apply clang-format to all the files I edited before I push my feature/bugfix branch. The first step in our pipeline is clang-format, and it almost always fails, so I wanted to run this "manually" on my changes just to take care of that step instead of nearly always dealing with a quickly failing pipeline. You can get a list of all the files you changed with
git diff <commitOrTagToCompareTo> --name-only
And borrowing from Antimony's answer, you can pipe that into xargs and finally clang-format:
git diff <commitOrTagToCompareTo> --name-only | xargs clang-format -i
Running git status will now show which files changed (git diff(tool) will show you the changes), and you can commit and push this up, hopefully moving on to more important parts of the pipeline.
The first step is to find out header and source files, we use:
find . -path ./build -prune -o -iname "*.hpp" -o -iname "*.cpp" -o -iname "*.c" -o -iname "*.h"
The -o is for "or" and -iname is for ignoring case. And in your case specifically, you may add more extensions like -o -iname "*.cc". Here another trick is to escape ./build/ directory, -path ./build -prune suggests do not descend into the given directory "./build".
Type above command you will find it still prints out "./build", then we use sed command to replace "./build" with empty char, something like:
sed 's/.\/build//' <in stream>
At last, we call clang-format to do formatting:
clang-format -i <file>
Combine them, we have:
find . -path ./build -prune -o -iname "*.hpp" -o -iname "*.cpp" -o -iname "*.cc" -o -iname "*.cxx" -o -iname "*.c" -o -iname "*.h"|sed 's/.\/build//'|xargs clang-format -i
I had similar issue where I needed to check for formatting errors, but I wanted to do it with a single clang-format invocation both on linux and windows.
Here are my one-liners:
Bash:
find $PWD/src -type f \( -name "*.h" -o -name "*.cpp" \) -exec clang-format -style=file --dry-run --Werror {} +
Powershell:
clang-format -style=file --dry-run --Werror $(Get-ChildItem -Path $PWD/src -Recurse | Where Name -Match '\.(?:h|cpp)$' | Select-Object -ExpandProperty FullName)
I was having issues getting an image to load in to Devil so I have provided exactly how I built the libs and how I am trying to use it.
Downloaded Devel source from their website.
$ unzip DevIL-1.7.8.zip
$ mkdir devil
$ cd Devil-1.7.8
+-------------------------------------------+
| Just type: |
| autoreconf -i |
| ./configure <your options here> |
| make |
| sudo make install |
+-------------------------------------------+
If I use autoreconf -i then ./configure with prefix and ilu and ilut. I get an error ..forgot.. to record it. How important is this? I have just not used it.
$ chmod +x configure
$ ./configure --prefix=/home/path/to/TestingDevil/devil --enable-ILU --enable-ILUT
$ make
$ make install
So at this point my library should be built.
I downloaded the devil simple example (simple.c) to TestingDevil/simple/simple.c
built it.
$ gcc -I ../devil/include -L ../devil/lib/ simple.c -o simple -lIL -lILU -lILUT
$ cp ../devil/lib/*.so* .
I have added an image (jpg) to test.
$ LD_LIBRARY_PATH=. ./simple image.jpg
"Could not open file...exiting"
I ran the executable from the simple directory.
simple$ ls
image.jpg libIL.so.1.1.0 libILU.so.1.1.0 libILUT.so.1.1.0 libIL.so
libILU.so libILUT.so simple libIL.so.1 libILU.so.1
libILUT.so.1 simple.c
Whats going wrong? I am using the example from devIL, it compiles and runs fine. Just can't load any files.
My System is Ubuntu 12.10 64 with build-essential installed and other dev packages for opengl dev.
Uni System is Fedora 15(?) 32. This also has exactly the same problem after building devIL in the same way.
On my home machine I installed the package libdevel-dev and that works fine.
This question does not ask about opengl, purely the devIL lib and example.
It looks like you build it withjout jpg support or you do not have jpeg libs available ?
I use ctags with vim and the OmniCppComplete plugin. Currently when generating my tags I do it individually for each library. For libc6 I use the following list of tokens / macros in a file named libc6-ignore to ignore during processing:
__attribute__
__attribute_deprecated__
__attribute_format_arg__
__attribute_format_strfmon__
__attribute_malloc__
__attribute_noinline__
__attribute_pure__
__attribute_used__
__attribute_warn_unused_result__
__wur
__THROW
__nonnull+
Am I missing any other tokens I should be ignoring and should I be using this same list or a different one when generating tags for libstdc++ and boost?
For anyone who's interested I use the following to generate my tag files:
# First make sure apt-file is install and then do:
$ sudo apt-file update
# set up tags for libc, the standard C library
$ apt-file list libc6-dev | grep -o '/usr/include/.*\.h'> ~/.vim/tags/libc6-filelist
$ ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -I./libc6-ignore -f ~/.vim/tags/libc6 -L ~/.vim/tags/libc6-filelist
# create tags for stdlibc++ and STL
$ apt-file list libstdc++6-4.4-dev | grep -E -o '/usr/include/.*\.(h|hpp)' > ~/.vim/tags/stdlibcpp-filelist
$ ctags --sort=foldcase -R --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/stdlibcpp -L ~/.vim/tags/stdlibcpp-filelist
# For Boost
$ apt-file list boost | grep -E -o '/usr/include/.*\.(h|hpp)' | grep -v '/usr/include/boost/typeof/' > ~/.vim/tags/boost-filelist
$ ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/boost -L ~/.vim/tags/boost-filelist
You can also use the modified libstdc++ library:
http://www.vim.org/scripts/script.php?script_id=2358
This contains a stripped version of the C++ header files which works for ctags.
I made a Python script that extracts all tags beginning with an underscore from a tags file. You can choose with this script which tags to exclude.
Feel free to tailor the script to meet your needs or suggest anything else:
import re
tags=open('tags','r')
output=open('exclude','w')
regex=re.compile('^_[a-zA-Z0-9_]*')
results=set()
for line in tags:
result=regex.match(line)
if(result!=None):
results.add(result.group(0))
tags.close()
for element in sorted(results):
output.write('{0}\n'.format(element))
output.close()
I have followed those instructions and I am able to get all boost boost references working i.e.
#include <iostream>
I can jump directly to iostream
However what I am still missing is to go to for example
#include <stdio.h>
Although in my generate script I have included as you mentioned i.e.
$ apt-file list libc6-dev | grep -o '/usr/include/.*\.h'> ~/.vim/tags/libc6-filelist
$ ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -I./libc6-ignore -f ~/.vim/tags/libc6 -L ~/.vim/tags/libc6-filelist
After i generate the tag "libc6" file whenever I try to go to stdio.h it is saying “E426: tag not found: stdlib”.
Here is what I have included additionally to my .vimrc in order to make all those 3 tag files visible.
set tags+=~/.vim/tags/boost
set tags+=~/.vim/tags/libc6
set tags+=~/.vim/tags/stdlibcpp
I am not an expert however I can say that this worked somehow for boost but not for libc6-dev. Can someone assist me with the solution
here is the same code as above
sudo apt-file update
# set up tags for libc, the standard C library
apt-file list libc6-dev | grep -o '/usr/include/.*\.h'> ~/.vim/tags/libc6-filelist
ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -I./libc6-ignore -f ~/.vim/tags/libc6 -L ~/.vim/tags/libc6-filelist
apt-file list libstdc++6-4.6-dev | grep -E -o '/usr/include/.*\.(h|hpp)' >> ~/.vim/tags/stdlibcpp-filelist
ctags --sort=foldcase -R --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/stdlibcpp -L ~/.vim/tags/stdlibcpp-filelist
# For Boost
apt-file list boost | grep -E -o '/usr/include/.*\.(h|hpp)' | grep -v '/usr/include/boost/typeof/' > ~/.vim/tags/boost-filelist
ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/boost -L ~/.vim/tags/boost-filelist
Sorry--I've never used ctags before--but I'll take a stab at this question.
If I understand correctly, you can use the list of keywords from GCC itself. I found this https://gist.github.com/959484 inside gcc/gcc/c-family/c-common.c. Looks like it includes reserved words for all the C (c/c++/obj-c variants). I guess some are valid for all compilers, these are for gcc of course.
As for figuring out other symbols to ignore, on OS X I'd use nm to dump the symbols of the library in question an add all symbols marked as private ('s' instead of 'S' for example) to my list of symbols to ignore. Linux has a similar library-dumping tool?
Hope that's useful.
I had my own list and never thought about adding what you've already listed!
Here's that updated ignore list for libc6 that I've come up with (Ubuntu 14.04 and GCC 4.8.4) to use as input to the -I option of ctags:
__attribute__
__attribute_deprecated__
__attribute_format_arg__+
__attribute_format_strfmon__+
__attribute_malloc__
__attribute_noinline__
__attribute_pure__
__attribute_used__
__attribute_warn_unused_result__
__attribute_alloc_size__+
__attribute_const__
__attribute_artificial__
__wur
__THROW
__THROWNL
__BEGIN_DECLS
__END_DECLS
__BEGIN_NAMESPACE_STD
__END_NAMESPACE_STD
__USING_NAMESPACE_STD+
__BEGIN_NAMESPACE_C99
__END_NAMESPACE_C99
__USING_NAMESPACE_C99+
__warndecl+
__warnattr+
__errordecl+
__flexarr=[]
__fortify_function
__REDICRECT+
__REDIRECT_NTH+
__REDIRECT_NTHNL+
__ASMNAME+
__ASMNAME2+
__nonnull+
__always_inline
__extern_inline=extern
__extern_always_inline=extern
__extension__
__restrict
__restrict_arr
I also created the following ignore list for generating a tags file for libstdc++ (GCC 4.8.2 on Ubuntu 14.04) (again, this is input to the -I option):
_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_ALGO
_GLIBCXX_END_NAMESPACE_ALGO
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
_GLIBCXX_BEGIN_EXTERN_C
_GLIBCXX_END_EXTERN_C
_GLIBCXX_VISIBILITY+
_GLIBCXX_PURE
_GLIBCXX_CONST
_GLIBCXX_NORETURN
_GLIBCXX_CONSTEXPR=constexpr
_GLIBCXX_USE_CONSTEXPR=constexpr
_GLIBCXX_THROW_OR_ABORT+
_GLIBCXX_NOEXCEPT
_GLIBCXX_USE_NOEXCEPT
_GLIBCXX_THROW+
_GLIBCXX_NOTHROW
I changed __attribute__ to be: __attribute__+ to indicate it looks like a function and should be ignored.
Of course, I have created one for Boost as well, but I think I'll refrain from posting it until someone has a need.