Reputation: 2221
I have a number of source files in a number of folders.. Is there a way to just compile all of them in one go without having to name them?
I know that I can say
g++ -o out *.cpp
But when I try
g++ -o out *.cpp folder/*.cpp
I get an error.
What's the correct way to do this? I know it's possible with makefiles, but can it be done with just straight g++?
Upvotes: 23
Views: 68359
Reputation: 277
In case that all files contain their own main and there are not part of the same project/program, you might want to keep their original name and create one executable for each file. If this is the case, you could use awk
:
awk '{n=split(FILENAME, a, "."); outfile=sprintf("%s.out",a[n-1]); command=sprintf("g++ -I . %s -o %s", FILENAME, outfile); system(command); nextfile } ' *.cpp
For start, you use split
to separate filename and extension and store the result into an array a
. The basename is located at index n-1
and the extension is at index n
. So, we change the extension into .out
and by using sprintf
store into the outfile
variable. In the same way, we create the command to be executed by system
function in a shell.
A shortest version of the above command is:
awk '{n=split(FILENAME, a, "."); command=sprintf("g++ -I . %s -o %s.out", FILENAME, a[n-1]); system(command); nextfile } ' *.cpp
You could also modify the command to #include
additional files with -I
as suggested by @Bit Fracture.
NOTE: This solution doesn't work well if any filename contains a space or multiple dots. Before executing the command, those characters need to be replaced with an underscore for example, as described here:
find . -type f -name "* *.cpp" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
Upvotes: 0
Reputation: 78
So I ran across this and saw the vscode task above, and managed a different solution. This will get all the headers and c files from the same directory. Then will work with the F5 key.
tasks.json
{
"tasks": [
{
"type": "shell",
"label": "C/C++: gcc-7 build active file",
"command": "/usr/bin/gcc-7",
"args": [
"-I",
"${fileDirname}",
"-g",
"${fileDirname}/*.c",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
],
"version": "2.0.0"
}
Upvotes: 0
Reputation: 1
Figured it out! :) I hate the idea of having to use make or a build system just to compile my code, but I wanted to split up my code into subfolders to keep it clean and organized.
Run this (replace RootFolderName (e.g. with .
) and OutputName):
g++ -g $(find RootFolderName -type f -iregex ".*\.cpp") -o OutputName
The find command will do a recursive case-insensitive regex search (-iregex
) for files (-type f
). Placing this within $()
will then inject the results into your g++
call. Beautiful! :)
Of course, make sure you're using the command right; you can always do a test run.
For those using Visual Studio Code to compile, I had to do this in the tasks.json args: []
of a task with "command": "g++"
:
"-g",
"$(find",
"code",
"-type",
"f",
"-iregex",
"'.*\\.cpp')",
"-o",
"program"
(Otherwise it would wrap the $()
all in single quotes.)
(Thanks to: user405725 @ https://stackoverflow.com/a/9764119/1599699 comments)
Upvotes: 12
Reputation: 717
By specifying folder/*.cpp
you are telling g++ to compile cpp files in folder
. That is correct.
What you may be missing is telling the g++ where to locate additional files that those cpp files #include
.
To do this, tell your compiler to also include
that directory with -I
like this:
g++ -o out -I ./folder *.cpp folder/*.cpp
In some circumstances I have had the compiler forget what was in the root/current directory, so I manually specified it with another -I
to the current directory .
g++ -o out -I . -I ./folder *.cpp folder/*.cpp
Upvotes: 24