CaptainCodeman
CaptainCodeman

Reputation: 2221

How can you compile all cpp files in a directory?

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

Answers (4)

ioaniatr
ioaniatr

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

Platipuss
Platipuss

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

Andrew
Andrew

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

Bit Fracture
Bit Fracture

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

Related Questions