cmake generate assembly file then compile it into executable - c++

I'm using cmake, and let's say I have a .cpp file.
Is it possible in cmake to compile this cpp file into assembly code first, then do some other operation and after that create executable from the generated assembly?
Update:
So basically I want to compile Hello.cpp to Hello.s (later modify it, and then create the object file). However I can't generate the asm file with that code (It just creates a Hello.a static library):
add_library(Tutorial Hello.cpp)
set_target_properties(Tutorial PROPERTIES COMPILE_FLAGS "-S")
install (TARGETS Tutorial DESTINATION bin)

CMake does always generate "assembly file rules" for you. So let's say you have:
file(WRITE main.cpp "int main() { return 0; }")
add_executable(MyMain main.cpp)
You can call make for targets main.s or main.cpp.s like:
> make main.cpp.s
Compiling CXX source to assembly CMakeFiles/MyMain.dir/main.cpp.s
But if you want to automate everything, see my answer at your other question:
Call shell command after asm file generation in cmake

You can tell GCC to only generate assembly with the -S option.
You can also tell GCC to keep intermediate files with -save-temps.

Related

How to generate preprocess and assmeble code by cmake?

I am trying to get intermediate .i .s file by CMake when compiling .cpp file, but cmake default only output .o file. Is there any command to manipulate cmake to keep these intermediate file, thanks a lot!
If you are using gcc, try adding this line.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -save-temps=obj")
Which flag to use depends on the compiler you are using. Also, you should strongly prefer to inject such compiler-and-scenario-specific flags into the build externally, rather than set()-ing them inside the build.
For g++ or clang++, the following invocation would be appropriate:
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-save-temps=obj"
For MSVC it would be:
> cmake -S . -B build "-DCMAKE_CXX_FLAGS=/FA"

Failed to use gdb for an executive file generated by cmake

To do debug for C++ codes with cmake, I have a trick to add the following lines before the project (myProjectYY) line of the CMakeLists.txt file in the root directory of the source code.
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
So, after cmake and make, I have obtained the executable file mainYY, and I can simply run gdb mainYY to do the debug as I should be able to see the source codes of mainYY.cpp.
I have 2 separated projects that were already cmake and make by the others, namely a simple project (i.e. myProject1) and a complicated project (i.e. myProject2). For myProject1, the above trick works for me, i.e. after I added the above 3 lines and re-do the cmake and make again to obtain main1, I can see the source code of main1.cpp by simply executing l in gdb.
But for myProject2, I do same, i.e. I added the above 3 lines and re-do the cmake and make again to obtain main2, but in gdb there is no source code for main2.cpp. That is, gdb main2 firstly gave me Reading symbols from main2...(no debugging symbols found)...done. And then if I run l in gdb, I have No symbol table is loaded. Use the "file" command.
What are the most probable reasons for such differences between myProject1 and myProject2? How can I find out those probable reasons, and how can I do the fix such that I can debug for myProject2?
Thanks.
As you mentioned, your myProject2 is a complicated project. There could be SET( CMAKE_BUILD_TYPE Release ... FORCE ) somewhere. Check using fgrep -R "CMAKE_BUILD_TYPE" and even better, remove every definition of this everywhere.
Use cmake -DCMAKE_BUILD_TYPE=Debug instead.

CMake produces object files with .obj extension instead of .o [duplicate]

I'm struggling to get coverage information for gcov. No errors during compilation and linking, but when I run the executable, no coverage data is produced.
I'm using CMake with a separate build directory, passing flags to the compiler and linker in this way:
add_definitions(--coverage)
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
Does the executable expect the source code to be in a specific location?
What do I have to add to my CMakeLists.txt to get things going?
Kind regards,
Bjoern
CMake seems to put the code coverage (*.gcda, *.gcdo) files with the object files of your project. If your executable was named "tester" then they would appear in the following path
${CMAKE_BINARY_DIR}/CMakeFiles/tester.dir/
CMake seems to name the source files in a way that isn't very compatible with gcov though. For example if I had a source file called "mytestprog.cpp" it would be build
mytestprog.cpp.o
mytestprog.cpp.gcda
mytestprog.cpp.gcdno
where as gcov seems to expect
mytestprog.gcda
mytestprog.gcdno
I'm not really sure how to fix it. I've tried using LCov instead and that "appeared" to work but I'm not really sure if it did.
Delcypher pointed out the problem.
Solution 1: you can ask cmake to name object files as main.o instead of main.cpp.o etc. using the undocumented CMAKE_CXX_OUTPUT_EXTENSION_REPLACE switch:
cmake -DCMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON ...
Solution 2: if you do not need the .gcov files you can call lcov from the build directory:
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory out
You will find the coverage information in the out directory in html form.
Not sure where you got --coverage from, but these are the arguments I use on Linux to get coverage information using gcc and gcov:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
Here's what gcc --help --verbose has to say about those options:
-ftest-coverage Create
data files needed by "gcov"
-fprofile-arcs Insert
arc-based program profiling code
You don't need to pass --coverage to the linker. --coverage will pass -fprofile-arcs -ftest-coverage to the compiler and -lgcov to the linker.
Are you sure that it isn't creating any gcdo or gcda files? Where are you looking for these files? It should put the gcov file for each object file into the same directory as the object file. Do a find for .gcda files at the top of your build directory. If nothing shows up, gcov might not be getting linked in. Run the following command to see if it is:
nm name_of_binary | grep "gcov"
If it is getting linked in, then gcov might not have permission to write files to where you are running the executable. If it has permission, then I am stumped.

Makefile configuration for entire system

As we know, in the appliance when we use the command
make [file-name]
It automatically compiles with some flags:
-ggdb -O0 -std=c99 -Wall - Werror
I need to know in which directory the CS50 edited Makefile is located, because I want to configure my own Makefile for the entire system by which I can make any .cpp file.
When I compile c++ file with make it automatically compiles with g++ but I want to compile .cpp file with clang++ compiler, adding some essential flag such for -g for debugging -O0 for assembly code.
I'm asking how to create a Makefile for that specific reasons, if possible.
Make uses Makefiles in the current directory and Implicit-Rules. You can modify the behavior of implicit rules by changing the variables that those explicit rules use.
For example, to change the compiler for .cpp files, you could set your own CXX variable, either
in the environment (Make uses it):
CXX=clang++ make [file-name]
#OR
export CXX=clang++; make [file-name]
in a local Makefile:
CXX:=clang++
#The implicit rule, which you'll find in the link, takes care of the rest

gcov with CMake using a separate build directory

I'm struggling to get coverage information for gcov. No errors during compilation and linking, but when I run the executable, no coverage data is produced.
I'm using CMake with a separate build directory, passing flags to the compiler and linker in this way:
add_definitions(--coverage)
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
Does the executable expect the source code to be in a specific location?
What do I have to add to my CMakeLists.txt to get things going?
Kind regards,
Bjoern
CMake seems to put the code coverage (*.gcda, *.gcdo) files with the object files of your project. If your executable was named "tester" then they would appear in the following path
${CMAKE_BINARY_DIR}/CMakeFiles/tester.dir/
CMake seems to name the source files in a way that isn't very compatible with gcov though. For example if I had a source file called "mytestprog.cpp" it would be build
mytestprog.cpp.o
mytestprog.cpp.gcda
mytestprog.cpp.gcdno
where as gcov seems to expect
mytestprog.gcda
mytestprog.gcdno
I'm not really sure how to fix it. I've tried using LCov instead and that "appeared" to work but I'm not really sure if it did.
Delcypher pointed out the problem.
Solution 1: you can ask cmake to name object files as main.o instead of main.cpp.o etc. using the undocumented CMAKE_CXX_OUTPUT_EXTENSION_REPLACE switch:
cmake -DCMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON ...
Solution 2: if you do not need the .gcov files you can call lcov from the build directory:
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory out
You will find the coverage information in the out directory in html form.
Not sure where you got --coverage from, but these are the arguments I use on Linux to get coverage information using gcc and gcov:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
Here's what gcc --help --verbose has to say about those options:
-ftest-coverage Create
data files needed by "gcov"
-fprofile-arcs Insert
arc-based program profiling code
You don't need to pass --coverage to the linker. --coverage will pass -fprofile-arcs -ftest-coverage to the compiler and -lgcov to the linker.
Are you sure that it isn't creating any gcdo or gcda files? Where are you looking for these files? It should put the gcov file for each object file into the same directory as the object file. Do a find for .gcda files at the top of your build directory. If nothing shows up, gcov might not be getting linked in. Run the following command to see if it is:
nm name_of_binary | grep "gcov"
If it is getting linked in, then gcov might not have permission to write files to where you are running the executable. If it has permission, then I am stumped.