compile folder of cpp files into GNU's g++ using Powershell commands - c++

I'm looking for a way to pipe a full folders worth of c++ commands into g++ so that I don't have to type 25 file names into the g++ command.
I am using Powershell and thought that I could somehow use a pipeline with Get-childItem -Name -Path *.cpp. That way the whole folder could be compiled at once without the chance of me missing a file or misspelling a filename, and would be modular enough that I could just use Set-Location folderpathbefore pasting it wouldn't have to write a new makefile each time I make a linked program with a medium~large number of linked files.
Is this possible/practical or should I stick to using a makefile?
For example:
I have a elevator simulation 'borrowed' from a how to program book that has 12 header files, 12 classes saved into individual cpp files, and 1 main execution cpp in C:\Users\Noah\Desktop\ripsfromthebook\ch09\elevator.
let's assume that everything necessary for the program to work is present and if you typed in each cpp filename into a g++ command it would compile correctly into a working a.exe file.
They are named:
bell.cpp
bell.h
building.cpp
building.h
button.cpp
button.h
clock.cpp
clock.h
door.cpp
door.h
elevator.cpp
elevator.h
elevatorButton.cpp
elevatorButton.h
ElevatorSimulation.cpp
floor.cpp
floor.h
floorButton.cpp
floorButton.h
light.cpp
light.h
person.cpp
person.h
scheduler.cpp
scheduler.h
It would be great if I could use something similar to Get-ChildItem -Name -Path *.cpp | g++ -g to have all 13 ~.cpp file names be used as an input instead of having to write out this monster {see below} into the powershell commands.
Or using an array of strings to save the childItem output then run g++
$x = Get-ChildItem -name -path *.cpp
g++ -g $x -o main
would be better than this monster.
g++ -g bell.cpp building.cpp button.cpp clock.cpp door.cpp elevator.cpp elevatorButton.cpp ElevatorSimulation.cpp floor.cpp floorButton.cpp light.cpp person.cpp scheduler.cpp
short term solution I'm copy/pasting the output of Get-ChildItem into my makefile.

if your are using Cmakelists to build your library/exe you can use file() as below :
file(GLOB your_src
"relativePath/*.h"
"relativePath/*.cpp")
add_executable(your_exe ${your_src})
but it seems to be advised against
GLOB will generate a list of all files that match the globbing expressions and store it into the variable. Globbing expressions are similar to regular expressions, but much simpler. If RELATIVE flag is specified for an expression, the results will be returned as a relative path to the given path. (We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.)
source: https://cmake.org/cmake/help/v3.0/command/file.html#file

Related

GCC Compiler: Compile Multiple files with different output file names

Is it possible to compile multiple files and save the output for each files with different name ? I had only copied .cpp files from old computer to my new one.Those programs are all error free and are tested.So now i have to compile each files to get the output file.There are about 310 programs so it is really hard to compile each file separately.I usually save output file with the same file name without any extension.Is there any way to compile all files in the directory and save each files output separately. I'm looking forward for a command like this
gcc *.cpp -o *
If there are files,
filename1.cpp
filename2.cpp etc.
I want to get the output files like this :
filename1
filename2 etc.
EDIT :
Is there any way to save the timestamp of .cpp file to the output file .??
If each file should have it's own executable and they're all in the same directory you can do this:
for i in *.cpp; do g++ $i -o `basename $i .cpp`; done
To add the timestamp:
for i in *.cpp; do g++ $i -std=c++11 -o `basename $i .cpp`-`date +%Y%m%d -r $i`; done
This will produce the date in YYYYMMDD format after the filename and hyphen
To change modification date:
for i in *.cpp; do g++ $i -std=c++11 -o `basename $i .cpp`; touch -t `date +%Y%m%d%H%M -r $i` `basename $i .cpp`; done
You would do this with the "make" program, and a suitable makefile. That uses rules (some predefined), for transforming ".cpp" files into ".o" and executables. A quick check shows me that GNU make does have a default rule for .cpp to .o (long ago, it did not).
The GCC compiler is (internally) compiling one file at a time (but also has Link Time Optimization).
You want to use a builder like GNU make; adapt this example (or that one) to your needs.

SFML build all batch file

I was wondering if there was a way to alter the below code so it will build all the ".cpp" and ".h" files in a folder (+ subfolders) and specify one .exe name to be made.
#ECHO OFF
echo Building...
g++ -DSFML_STATIC main.cpp -lsfml-graphics-s -lsfml-window-s -lsfml-system-s
I know I can use CMake, but I want to know if it's possible with a batch script. If I can't do what I'm asking, can I at least specify a name for the .exe? It always comes out as "a.exe". I am using MingW.
Sorry, if this has been covered already. I searched and didn't find anything.
To specify the name for the output file, add option "-o name.exe".
To pass a large number of files to g++, you will have to use a response file like so:
#echo off
setlocal enabledelayedexpansion
for /r %%f in (*.cpp) do (
set a=%%f
set a=!a:\=/!
echo !a! >>files.tmp
)
endlocal
g++ -DSFML_STATIC #files.tmp -o bob.exe -lsfml-graphics-s -lsfml-window-s -lsfml-system-s
del files.tmp
Note that you should only give the *.cpp files to g++. It will find the .h files on its own while compiling.
I don't have a MingW setup so I wasn't able to test this completely, sorry. But the part about building the response file works at least.
Sources:
[http://www.mingw.org/wiki/MinGW_for_First_Time_Users_HOWTO]
[http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/cmd.mspx?mfr=true]
[Multiple do commands in a for loop: Echoing a string to a file and then redirecting to the command window
"a.exe" is the default name that g++ uses for executables on Windows. If you want to specify your own name, add "-o foo.exe" to the g++ command line.

How to preprocess individual source file with several #include files spread across in large project?

For getting a preprocessed output, following command is used:
g++ -E a.cpp > temp.cpp
If a.cpp has #include files not in the same folder, then we use:
g++ -I <directory> -E a.cpp > temp.cpp
Now, there are several .cpp file for which I want a preprocessed output.
Also a huge #include dependency for every .cpp file and the header file is spread in several different subdirectories; so following option is very cumbersome:
g++ -I <dir1> -I <dir2> -I <dir3> ... -E a.cpp > temp.cpp
Is there any simpler way (preferably without the use of Makefile) ?
(Assume that dir1, dir2, ... are under a single directory)
You need the same set of -I for preprocessing and for compiling.
When you actually compile the code, you surely use some set of -I parameters (probably generated by a make file).
So just use the same (or compile, and copy&paste the -I parameters).
The only alternative I see is restructuring your header directories to be in a common directory (with sub-directories, using #include <subdir/header.h>).
But this is much more work (though it may be worth the effort).
One way can be that you give the TOP directory in which all the subdirectory resides. This way you wont have to give many -I. But this will slowdown it.

Include one header file in each source file

Say you have 100s of source files (.c or .cpp) files, and you want to include some definitions, function/variable declarations in each of them. Normally in C/C++, you use header files for that purpose. But in this case you need to put #include "header.h" in each source file.
Now my question is, is there a way to include one header for all the files without putting #include "header.h" in each of the file, because it will be very tiresome to write #include "header.h" for 100s of source files.
You can use the -include flag for clang or GCC. From the man page:
-include file
Process file as if "#include "file"" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor's working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the "#include "..."" search chain as normal.
If multiple -include options are given, the files are included in the order they appear on the command line.
Example:
clang -include header.h -c file1.c
clang -include header.h -c file2.c
clang -include header.h -c file3.c
clang -o app file1.o file2.o file3.o
MSVC has the /FI flag, which is similar.
You could solve this problem using a unix pipe
find ./ -name "*.c" -or -name "*.cpp" | xargs -n 1 sed -i '1 i #include <my_header.h>'
You can't do that, although you could write a script for you to do it. A script that takes each files, and writes #include "header.h" at top. Edit: -include in gcc does this.
However, what you need is achievable in a different way through the compiler options. In gcc, with -D.
Let's say, you want the define DEBUG_LEVEL to 2 in all your source files. You can simply do this by invoking gcc like this:
gcc -DDEBUG_LEVEL=2
Note that in this case, you would need to rebuild all your project (which would have been done anyway if you had changed this definition in 1 header file to which ALL the source files depend on)
Header files are not definitions - they are declarations.
You put as few in as possible - saves the compiler work and also inter-dependencies.
You can even reduce the number further by using forward declarations in those header files.
If you are clever you can get you IDE to help you out with filling in the gaps instead of hurting your fingers.

gcov on larger projects (static libraries, ...)

I'm working on larger project which has the following directory layout:
Source
MyA
aa.cpp
ab.cpp
ac.cpp
MyB
ba.cpp
bb.cpp
bc.cpp
MyTest
testaa.cpp
testab.cpp
testac.cpp
testba.cpp
testbb.cpp
testbc.cpp
main.cpp
Build
MyA
aa.o
ab.o
ac.o
libMyA.a (static library)
MyB
ba.o
bb.o
bc.o
libMyB.a (static library)
MyTest
testaa.o
testab.o
testac.o
testba.o
testbb.o
testbc.o
MyTest (executable)
After compiling with -fprofile-arcs -ftest-coverage I execute the MyTest application inside the Build/MyTest directory. As expected there are *.gcno and *.gcda files inside the Build directory. After running gcov inside the MyTest directory different *.gcov files are produced but unfortunately not for everything inside MyA and MyB, although every function is called inside this two libraries. Tried different options but somehow I'm unable to create useful (means correct) *.gcov files with this layout.
If I copy every cpp inside one directory and repeat the steps everything works as expected and the coverage analysis is perfect.
You must specify source files as absolute paths to g++/gcc. Don't use relative paths with ".." or like "foo/bar.cpp", else you'll get errors like "geninfo: WARNING: no data found for XXXX".
Don't include any header files on the command line to g++/gcc. Else you'll get "stamp mismatch with graph file" errors.
So, following should work when having multiple directories:
g++ --coverage -DDEBUG -g3 heyo.cpp /app/helper/blah.cpp /app/libfoo/foo.cpp -o program
./program
lcov --directory . --capture --output-file app.info
genhtml --output-directory cov_htmp app.info
Or, if you're in a Makefile that uses relative paths already, it's convenient to use:
g++ --coverage -DDEBUG -g3 $(abspath heyo.cpp helper/blah.cpp ../foo/bar/baz.cpp) -o program
To be able to keep your directory structure, you need to run gcov once inside each source file folder, but use the -o option to tell gcov where the data files are.
I think it should be like this:
gcov -o ../../Build/MyA *.cpp
I have a project with a similar source file structure, but I let the compiler dump object files etc into the source folders. I then run gcov multiple times from the root folder, once for each source file, but I specify the relative path of the source file and use the -o option to specify the relative folder like this:
gcov -o Source/MyA Source/MyA/aa.cpp
If you performed your product or application testing thoroughly and manually and spent lot of effort on it. If your objective is to get code coverage report using lcov and gcov but by mistake deleted gcno files. You can regenerate gcno files by recompiling the code but it will be generated with new timestamp and gcov reports error saying "stamp mismatch with graph file" and no code coverage report will be generated. This will result in all your testing effort getting wasted.
There is a shortcut to still generate the code coverage report. This is just a workaround and should not be relied upon all the time. Its recommended to preserve *.gcno files till your testing completes.
Note down your gcc version(gcc -v) and download its source code from one of the mirror sites
Eg - ftp://gd.tuwien.ac.at/gnu/sourceware/gcc/releases/gcc-4.4.6/gcc-4.4.6.tar.bz2
After extracting downloaded file, gcc the folder structure will be as follows
gcc-4.4.6
gcc-4.4.6/gcc
If you directly go inside gcc-4.4.6/gcc and try to do ./configure and compile(make) from there then you will encounter below problem
build/genmodes -h > tmp-modes.h
/bin/sh: build/genmodes: No such file or directory
Solution is do ./configure and make from gcc-4.4.6 and no errors will be shown related to genmodes. This will compile all modules including gcc. You may have to install mpfr and gmp modules which are needed by gcc if any error shown by ./configure
goto gcc-4.4.6/gcc/gcov.c and comment below lines and then recompile with above command
/* if (tag != bbg_stamp)
{
fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
goto cleanup;
}*/
Example path of new gcov binary after compilation is gcc-4.4.6/host-x86_64-unknown-linux-gnu/gcc/gcov
Place this binary in /usr/bin and regenerate code coverage report with command as shown in below example
lcov --capture --directory ./ --output-file coverage.info ; genhtml coverage.info --output-directory /var/www/html/coverage
Now you should not get "stamp mismatch with graph file" error and you will get code coverage report properly