Hello,
Until now, I was using Makefiles, but I have decided to use CMake for the first time for a new project. The project is a framework for studying branch predictors. It should allow to generate different binaries using the source code of different branch predictors. For example, binaries that run a branch predictor over a trace and output the misprediction results, and others that compare more than one predictor. However, being a new user, I am not fully aware of what would be the best way to obtain different targets based on the same files from the framework and different source files for different predictors, while avoiding unnecessary recompilation.
The structure of the project is the following.
project
├ bp/
│ ├── predictor_a.hpp, predictor_a.cpp // sources for predictor a
│ └── predictor_b.hpp, predictor_b.cpp // sources for predictor b
├ include/
│ ├── branch_type.hpp
│ ├── trace_reader.hpp
│ ...
└ src/ -- folders with the sources of the framework.
├── simulator.cpp
├── comparator.cpp
├── trace_reader.cpp
...
The files for each predictor declare a class with a predict
function. The source files simulator.cpp
and comparator.cpp
contain a main()
function. They must instantiate some number of predictors and use them. Therefore, they must be compiled and linked with different predictors for creating different targets. Other source files, like trace_reader.cpp
, need to be compiled just once because they do not depend on the predictor.
Currently, my CMakeList is something like the following.
cmake_minimum_required(VERSION 3.10)
project(SimpleSimulator
VERSION 0.1
LANGUAGES CXX
)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
include_directories(include bp)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -O3 -march=native -mtune=native -flto"
CACHE STRING "Set C++ Compiler Flags"
FORCE
)
set(CMAKE_LINK_OPTIONS
"${CMAKE_LINK_OPTIONS} -flto"
CACHE STRING "Set Linking Options"
FORCE
)
function(add_simulator name header class)
add_executable(${name}
src/simulator.cpp
src/branch_type.cpp
src/trace_reader.cpp
)
// by using some preprocessor definitions, we are able to compile the same file with different bps.
target_compile_definitions(${name}
PUBLIC
BP_HEADER="${header}"
BP_CLASS=${class}
)
endfunction()
add_simulator(ashare ashare.hpp Ashare)
...
Basically, I wrote the simulator.cpp
file using the macros BP_HEADER and BP_CLASS which are provided during compilation and created the CMake function add_executable
which allows to declare a new target using a simulator.
The problem with this configuration is that the object files like trace_reader.cpp
are compiled for each target (while they could be reused). Additionally, I am not sure that including the dependency in the simulator.cpp
file through a macro is the best option.
How would you handle this two problems?
Thank you in advance,