Compile a single file under CMake project?

15,957

Solution 1

You do not have to add extra custom targets to your CMake scripts, as the Makefiles generated by CMake already contain .o targets for each .cc file. E.g. if you have a source file called mySourceFile.cc, there will be a Makefile in your build directory that defines a target called <Some Path>/mySourceFile.cc.o. If you cd into your build directory, you can use grep or ack-grep to locate the Makefile that defines this target, then cd into that Makefile's directory and build it.

E.g. suppose the command ack-grep mySourceFile.cc.o prints something like:

foo/bar/Makefile
119:x/y/z/mySourceFile.o: x/y/z/mySourceFile.cc.o
123:x/y/z/mySourceFile.cc.o:
124:    # recipe for building target

Then you can build mySourceFile.cc.o by doing:

cd foo/bar && make x/y/z/mySourceFile.cc.o

Solution 2

CMake doesn't have a generic built-in way of doing this (it's an open issue), but if you're using the Ninja generator, you can can use a special Ninja syntax for building just the direct outputs of a given source file. For example, to compile just foo.o you would use:

ninja /path/to/foo.cpp^

Solution 3

Not out-of-the box. CMake does not expose those "internal" makefile rules in the main makefile.

You can do this only if you consider what kind of file structure CMake uses internally. You can e.g. for compiling a single .obj files using CMake generated makefiles call

make -f CMakeFiles/myProg.dir/build.make CMakeFiles/myProg.dir/main.cc.obj

when you have something like

cmake_minimum_required(VERSION 3.1)

project(myProg CXX)

file(WRITE "main.cc" "int main()\n{\nreturn 0;\n}") 
add_executable(myProg main.cc)

Solution 4

To build src/foo.cpp alone:

cmake --build . --target src/foo.cpp.o

Solution 5

Others have suggested ways to find the target name (ending in .cpp.o) from the .cpp filename, but if you already know the name of a target that will trigger compilation of the .cpp file and you're using ninja this suggestion should be easier.

First build the target:

ninja TriggersCppCompilationLib

Assuming your file was changed or was not yet built, ninja will print the full target name. When you see the name come up, hit enter so it is not overwritten. Then simply copy the name from the terminal (e.g. using tmux copy mode).

Share:
15,957

Related videos on Youtube

pacorrop
Author by

pacorrop

Updated on September 15, 2022

Comments

  • pacorrop
    pacorrop over 1 year

    I'm developing a C++ project which is going to be enclosed on a bigger one.

    I've seen that on the bigger project (is a Qt application and it's being generated from qmake) I am able to compile a single file from the linux command line, just entering the relative path to the specific file as an argument to make.

    On the other hand, I'm using CMake for my own project. When I modify some code for a compilation unit and I have to modify its header file, I have to wait a long time to compile its dependencies and then its own source file. But there are some situations in which I would prefer to check whether the source code in the *.cc file is compilable without errors.

    Is there a way to generate a Makefile from CMake the way qmake does this? Switching to qmake is not an option anymore.

    • John
      John almost 8 years
      Try make help on your current CMake-generated makefile. I'm pretty sure that will list how to build just a single object file.
  • mystery_doctor
    mystery_doctor almost 6 years
    Thanks for pointing that out! I also just noticed that it works well for out-of-source builds, as long as the path you specify is relative from where you are building to the original source file location
  • il--ya
    il--ya over 5 years
    you can also specify target for cmake using --target, so for example: cmake --build . --target src/foo.cpp.o
  • Andry
    Andry over 5 years
    minor correction, it will build src/foo.cpp from all targets has used this cpp
  • Jan Christoph Uhde
    Jan Christoph Uhde about 5 years
    The answer Ose provided is correct. This is not helpful. While CMake does not provide targets for each TU it well provides the information to the concrete build-systems. One has to look there.
  • usr1234567
    usr1234567 about 5 years
    This might be the case for Makefiles. nocnokneo provides a solution for Ninja. But in general, there is no way. nocnokneo even links the according open bug.
  • Ose
    Ose about 5 years
    @usr1234567 You're right to say that there's no general solution (e.g. I'd be very surprised if you can compile a single file in Visual Studio when using CMake). But the person who asked the question didn't ask for a general solution. They asked for a solution that works with make.
  • Ruslan
    Ruslan over 2 years
    You can also pass the usual options like e.g. VERBOSE=1 to cmake as you would do when building this project with make.