can i include a file whose path is from a string variable? - c++

i think in python:
i can use:
def include_something(s):
exec('import %s'%(s))
to import package dynamically
but in c++:
void include_something(const std::string& v) {
# include v.c_str();
}
seems doestnt work.
So, is there any methods can do this? and will the futures c++ support this kind of function?

Simple answer: No, You can't
Answer with details:
You can't do this with either include or import. As You can see on the picture below, include works on preprocess time, and import works on precompile time. While c_str is running at compile time (if it is constexpr), or at run time (if casual class or function), therefore, in any case, the import(or include) will be completed before the program learns the name of the module
source of image

There is no way in C/C++ to achieve dynamic header loading.
BUT
I'll do as the following:
Create a simple PowerShell script to create a master header file, that will contain all the headers from a given directory.
$source_dir = "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\um\alljoyn_c\"
$master_headerfile = 'master.h'
Remove-Item $master_headerfile
New-Item $master_headerfile -ItemType File -Value "// Master header file`n"
Get-ChildItem $source_dir -Filter *.h |
Foreach-Object {
Add-Content $master_headerfile "#include `"$_`""
}
Output will be
Now just include this master.h in your source file.
I hope, it will help you.
Thanks :)

Related

cppcheck don't see some subfolders with error: could not find or open any of the paths given

Running cppcheck as
cppcheck.exe --enable=all --xml-version=2 2> out.xml folder\subfolder
And for some subfolders(3 out of 5) got error
error: could not find or open any of the paths given.
If I rename the folder still same error. And when I run
cppcheck.exe --enable=all --xml-version=2 2> out.xml folder
Those subfolders aren't checked as well, only 2 subfolders form this folder are checked. What could be the problem?
UPDATE: I haven't noticed that beore, but it seems that folders cppcheck don't see contains only .h/.hpp files, no .cpp
UPD:
I do can check exact file from that subfolder
cppcheck.exe --enable=all --xml-version=2 2> out.xml folder\subfolder\file.cpp
Strange..
If I navigate to that subfolder and run cppcheck from there if I didn't specify exact file I still got same error: could not find or open any of the paths given.
UPD2: I haven't noticed it before, folders cppcheck don't see contains only header files
Whenever I use CPPCheck, I use a PowerShell script to parse through each folder and sub-folder(s). Usually I would put it in an array using these parameters:
$LIST_OF_CPP_FILES = #(Get-ChildItem -Path .\ -Filter *.cpp -Recurse -File -Name) # The recurse is what goes through each sub folder and finds files with extension .cpp
$LIST_OF_C_FILES = ... *.c ...
$LIST_OF_H_FILES = ... *.h ...
Then loop through each array which now holds the files in question.
foreach($FILE in $LIST_OF_CPP_FILES)
{
&'C:\Program Files\Cppcheck\cppcheck.exe' -q --inline-suppr $FILE --force #Look at CPPCheck documentation for info on these paramters
}
Of course save this in a .ps1 file in your PWD and use Command Prompt to run it.
./CPPCheckScript.ps1
If you want to write it to a txt or xml file you can do that as well, or just have it print output in the terminal. You can use Write-Host in the PowerShell file as well.

path setting for c++ include headers for vim

My vim has path settings as shown below.
path=.,/usr/include,,
I think this is a default setting of 'path' I guess.
Because of this, g f opens c header files under the cursor.
But on C++ file C++ header files are not opened because the C++ header file location is not added to path variable of vim.
set path+=/usr/include/c++/4.6
I think that this setting on vimrc would be a solution.
But the problem is the actual directory location for C++ header file would be changed in every different linux distributions and g++ compiler versions.
How can I set path for c++ header files in a portable manner?
let g:gcpp_headers_path = system("g++ --version | grep g++ | awk '{print \"/usr/include/c++/\"$NF}'")
execute 'set path+=' . g:gcpp_headers_path
Now I am using this above:
This works with g++ environment. Not tested with other compilers.
If there's a limited number of locations, a simple conditional in ~/.vimrc will do:
if isdirectory('/usr/include/c++/4.6')
set path+=/usr/include/c++/4.6
elseif isdirectory(...
If you have a lot of different systems, and don't want to maintain all variations in a central place, you can move the system-dependent settings to a separate, local-only file, and invoke that from your ~/.vimrc, like this:
" Source system-specific .vimrc first.
if filereadable(expand('~/local/.vimrc'))
source ~/local/.vimrc
endif
I recently had the same problem, so here is my solution for documentation purposes:
1) I added the following to my .bashrc:
# add additional search paths to vim.
VIM_EXTPATHS="$HOME/.vim.extpaths"
if [ ! -e "$VIM_EXTPATHS" ] || [ "/usr/bin/cpp" -nt "$VIM_EXTPATHS" ]; then
echo | cpp -v 2>&1 | \
awk '/^#include </ { state=1 } /End of search list/ { state=0 } /^ / && state { print "set path+=" substr($0, 2) "/**2" }' > $VIM_EXTPATHS
fi
2) I added the following to my .vimrc:
" add extra paths.
let s:extpaths=expand("$HOME/.vim.extpaths")
if filereadable(s:extpaths)
execute "source ".s:extpaths
endif
On my system, the contents of the .vim.extpaths file are as follows:
set path+=/usr/lib/gcc/x86_64-linux-gnu/8/include/**2
set path+=/usr/local/include/**2
set path+=/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed/**2
set path+=/usr/include/x86_64-linux-gnu/**2
set path+=/usr/include/**2
The **2 means that ViM will search two directories deep inside these directories. Now gf will find all the C++ headers I need. If you increase the depth, searches will take a lot more time, so don't set this number too high.
#note: for #include <chrono>, ViM will go to /usr/include/boost/chrono, which, funny enough, is a directory. I wonder why go file will open a directory, maybe this should be reported as a bug. To get to the correct chrono header you have to type 2gf.
The following Vimscript code, intended for a .vimrc file, updates path to include the search paths used by the preprocessor.
if executable('gcc')
let s:expr = 'gcc -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep "^ " | sed "s/^ //"'
let s:lines = systemlist(s:expr)
for s:line in s:lines
execute 'set path+=' . fnameescape(s:line)
endfor
endif
I have similar code in my .vimrc, but with additional special-case handling.
There are specific environment variables for the compiler to examine. If you are using gcc/g++ in a linux/Unix environment, then the variables are C_INCLUDE_PATH and CPLUS_INCLUDE_PATH. If you are using bash/sh then use export VARIABLE=value or if you are using csh/tcsh then use setenv VARIABLE value or if you are using some other shell then you will need to look that up. In these examples VARIABLE is either C_INCLUDE_PATH and CPLUS_INCLUDE_PATH. I hope this helps.

grep through an explicit filelist

Stack,
We have many files in our library that were never used in subsequent projects. We are now at a development phase where we can do some good housekeeping and carefully remove unused library code. I am trying to optimize my grep command, it's current implementation is quite slow.
grep --include=*.cpp --recursive --files-with-matches <library function name> <network path to subsequent projects>
The main reason is that the projects path is expansive and the bulk of the time is spent just navigating the directory tree and applying the file mask. This grep command is called many times on the same set of project files.
Rather than navigating the directory tree every call, I would like to grep to reference a static filelist stored on my local disk.
Something akin to this:
grep --from-filelist=c:\MyProjectFileList.txt
The MyProjectFileList.txt would be:
\\server1\myproject1\main.cpp
\\server1\myproject1\func1.cpp
\\server1\myproject2\main.cpp
\\server1\myproject2\method.cpp
Grep would apply the pattern-expression to contents of each of those files. Grep output would be the fully qualified path of the project file that is uses a specific library function.
Grep commands for specific library functions that return no project files are extraneous and can be deleted.
How do you force grep to scan files from an external filelist stored in a text file?
(Thereby removing directory scanning.)
Try around a little using the 'xargs' command and pipes ("|").
Try the following:
while read line; do echo -e "$line"; done < list_of_files.txt | xargs -0 grep **YOUR_GREP_ARGS_HERE**
or in a Windows environment with Powershell installed try...
Get-Content List_of_files.txt | Foreach-Object {grep $_ GREP_ARGS_HERE}
I googled for windows args and found this:
FOR /F %k in (filelist.txt) DO grep yourgrepargs %k
(but I use linux, no idea if it works)

Automatically fix filename cases in C++ codebase?

I am porting a C++ codebase which was developed on a Windows platform to Linux/GCC. It seems that the author didn't care for the case of filenames, so he used
#include "somefile.h"
instead of
#include "SomeFile.h"
to include the file which is actually called "SomeFile.h". I was wondering if there is any tool out there to automatically fix these includes? The files are all in one directory, so it would be easy for the tool to find the correct names.
EDIT: Before doing anything note that I'm assuming you either have copies of the files off ot the side or preferably that you have a baseline version in source control should you need to roll back for any reason.
You should be able to do this with sed: Something like sed -i 's/somefile\.h/SomeFile.H/I' *.[Ch]
This means take a case-insensitive somefile (trailing /I) and do an in-place (same file) replacement (-i) with the other text, SomeFile.H.
You can even do it in a loop (totally untested):
for file in *.[Ch]
do
sed -i "s/$file/$file/I" *.[Ch]
done
I should note that although I don't believe this applies to you, Solaris sed doesn't support -i and you'd have to install GNU sed or redirect to a file and rename.
Forgive my, I'm away from my linux environment right now so I can't test this myself, but I can tell you what utilities you would need to use to do it.
Open a terminal and use cd to navigate to the correct directory.
cd ~/project
Get a list of all of the .h files you need. You should be able to accomplish this with the shell's wildcard expansion without any effort.
ls include/*.h libs/include/*.h
Get a list of all of the files in the entire project (.c, .cpp, .h, .whatever), anything that can #include "header.h". Again, wildcard expansion.
ls include/*.h libs/include/*.h *.cpp libs/*.cpp
Iterate over each file in the project with a for loop
for f in ... # wildcard file list
do
echo "Looking in $f"
done
Iterate over each header file with a for loop
for h in ... # wildcard header list
do
echo "Looking for $h"
done
For each header in each project file, use sed to search for #include "headerfilename.h", and replace with #include "HeaderFileName.h" or whatever the correct case is.
Warning: Untested and probably dangerous: This stuff is a place to start and should be thoroughly tested before use.
h_escaped=$(echo $h | sed -e 's/\([[\/.*]\|\]\)/\\&/g') # escapes characters in file name
argument="(^\s*\#include\s*\")$h_escaped(\"\s*\$)" # I think this is right
sed -i -e "s/$argument/\$1$h\$2/gip"`
Yes, I know it looks awful.
Things to consider:
Rather than going straight to running this on your production codebase, test it thoroughly first.
sed can eat files like a VCR can eat tapes.
Make a backup.
Make another backup.
This is an O(N^2) operation involving hard disk access, and if your project is large it will run slowly. If your project is not gigantic, don't bother, but if it is, consider doing something to pipe sed's output to other seds.
Your search should be case insensitive: it should match #include, #INCLUDE, #iNcLuDe, and any combination of case present in the existing header filename, as well as any amount of whitespace between the include and the header. Bonus points if you preserve whitespace.
Use Notepad++ to do a 'Find in Files' and replace.
From toolbar:
Search - Find in Files.
Then complete the 'Find what' and 'Replace with'.

Help with automated renaming in C++

Here is my issue:
I have a large library of code where all of the class names begin with Agui. For example:
class AguiWidget
{
};
class AguiBitmap
{
};
also, all the hpp and cpp files are named like this also:
AguiWidget.hpp
etc.
The library also does not use a namespace.
all of the enums begin and use Agui:
ex:
enum AguiKeyEnum
{
AGUI_KEY_SPACE,
AGUI_KEY_ENTER
};
The include guards also use ex:
AGUI_WIDGET_HPP
So,
My task is to remove all the Agui, AGUI references from the entire project (all the classes and enums), then to encapsulate all the classes into namespace agui.
What would be the easiest way to do this. I also need the hpp and cpp files to no longer have Agui in the filename.
I use MSVC 2008 as an IDE if that helps.
Thanks!
You need to use a global find and replace tool. If you have Visual Studio 2008, then it is already built-in. Once you rename all the classes and namespaces, then use another tool to rename the files or build a script to do it for you.
As a Linux user (which you aren't, but you could use Cygwin or a separate machine), I'd use the program sed to strip the prefixes. I'd start with this, then review the diffs vs. source control:
sed -i 's/Agui//g; s/AGUI_//g' *.hpp *.cpp # and maybe *.sln *.proj
Then, renaming the files:
for f in *.hpp *.cpp; do mv $f ${f#Agui}; done # or source control's mv
Then all that's left is to add namespacing. You could probably get this done using sed as well, but if the number of files is not huge I'd just do it by hand. The namespace closing braces are trivial to add though:
for f in *.hpp *.cpp; do (echo '} // namespace agui' >> $f); done
The opening braces you might want to take a little more care to add, depending on your existing code's structure.
Oh, and look, sed for Windows: http://gnuwin32.sourceforge.net/packages/sed.htm (I haven't used this).
I would suggest either using
cygwin + recursive find + script - use sed for changing names, mv to change files
or figuring how to do the equivalent in powershell.
With the right regular expressions it should work fine.
Make sure to copy the entire directory structure before editing, as it may take a few iterations to debug.