CMake: compile a program twice in a row - compilation

To be able to do many automatic optimizations, I want to be able to compile my program using the flag -fprofile-generate first, then run it to generate the profile and then re-compile the program with -fprofile-use instead.
This means I want to compile my program twice in a row, with two different CMAKE_CXX_FLAGS each time.
How can I do that using CMake?

You can build something and then run it and then build something else after execution by making use of customer targets and the "add_dependencies" command. For your gcov case you might do something like:
profile.cxx
#include <iostream>
int main(void) {
std::cout << "Hello from Generating Profile run" << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(profileExample C CXX)
# compile initial program
add_executable(profileGenerate profile.cxx)
set_target_properties(profileGenerate PROPERTIES COMPILE_FLAGS "-fprofile-
generate")
target_link_libraries(profileGenerate gcov)
add_executable(profileUse profile.cxx)
set_target_properties(profileUse PROPERTIES COMPILE_FLAGS "-fprofile-use")
target_link_libraries(profileUse gcov)
# custom target to run program
add_custom_target(profileGenerate_run
COMMAND profileGenerate
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "run Profile Generate"
SOURCES profile.cxx
)
#create depency for profileUse on profileGenerate_run
add_dependencies(profileUse profileGenerate_run)
Output showing build -> run -> build

Related

Step to pass "-std=c++11" flag in gdb regression test-suite setup

I am trying to run GDB testsuite with "-std=c++11" flag for the subtest case under "gdb.cp" folder or for the CPP related test-cases.
Currently I am performing it using DejaGnu directive "dg-options" in CPP test-case like :
// { dg-options "-std=c++11" }
But I am not confirm whether this is right way or not. Because if I check the gdb.log file, I am not seeing "-std=c++11" flag passed at compile time.
The easiest way would be, from the top-level build directory, to run the tests like:
make check-gdb RUNTESTFLAGS="CXX_FOR_TARGET='g++ --std=c++11' gdb.cp/*.exp"
GDB also supports CFLAGS_FOR_TARGET which can be set in the same way, despite being called CFLAGS these flags are appended for any compile, so you'll start to see warnings/errors about --std=c++11 being an invalid option for C tests, etc.
A final option that might be of interest would be creating a whole new DeJaGNU board file which would override the compiler flags, however, I couldn't get this working so quickly, so your mileage may vary.
You can find more information about running the tests here: https://sourceware.org/gdb/wiki/TestingGDB

CMake resources in source code for build and install

This has been on my mind for years. It is about using resource files with CMake in code such that they can be accessed when running in the build directory and when installed.
Say you have files necessary to run your program in a top-level directory called res. It contains res/file1.txt and res/file2.txt. You build this program and the resources are copied to the build directory from which the program can be run during development. Then, the program is installed with the resources into /usr/share/my_program or something and the program runs by accessing those files. The question is what to do in the source code so that the same code works when running from the build directory and when installed. I've seen several different answers for how to handle resources but each seems to have a flaw:
The program searches in some preconfigured absolute directory such as CMAKE_INSTALL_PREFIX/share/my_program and must be installed first to run, not ideal for easy use during development.
Finding some way to use relative paths to the binary but I don't see how this would work since the build tree will not mirror the installed file paths, being installed to the bin and share directories.
Differentiating between the two with a CMake variable so that it searches for a relative path in one scenario or the installed location with another. This could possibly just be the debug/release variable. It would also require rerunning CMake before installing to rebuild with the new resource paths.
Baking the files into the executable. Seems uneccessary when dealing with most resources since they could just be opened instead and may be inconvenient with large directories of files.
Is one of these the best solution? Is there something I'm not misunderstanding? I've always been under the impression programs should be able to be run from the build directory before installing to see if they work. If possible, I would like to know what both the CMake and C/C++ code would look like, such as open("my_resource_location"); and my_cmake_command(). Most answers I've seen relating to resources don't include both.
It seems to me that what you are looking for is a relocatable build.
One way to achieve this in CMake is to use configuration files to incorporate resource paths in your code. I have prepared a minimal and reproducible example to give you an idea of how it works.
First, imagine you have the following program structure on disk:
main
CMakeLists.txt
main.cpp
data
CMakeLists.txt
Resources.h.in (Thats the configuration file)
resource.txt
The resource.txt file only contains a string. The program simply opens that file, reads its content and displays it to the terminal. So you have something like:
#include <fstream>
#include <iostream>
#include <string>
#include <Resources.h>
const std::string MY_FILE = "/resource.txt";
int main(int argc, char *argv[])
{
std::string line;
std::ifstream myfile (RESOURCE_PATH + MY_FILE);
if(myfile.is_open())
{
while(std::getline(myfile,line))
{
std::cout << line << '\n';
}
myfile.close();
}
else
{
std::cout << "Unable to open file";
}
return 0;
}
Note that this file #includes a Resources.h file, but that this file does not exist in our project. However, we have a Resources.h.in configuration file that CMake will turn into a Resources.h file on generation. This generated file will then contain the resource path we need inside the RESOURCE_PATH variable. Here is what the configuration file contains:
#define RESSOURCE_PATH "#CMAKE_INSTALL_PREFIX#/#CMAKE_INSTALL_DATADIR#"
A simple #define with this strange #something# notation. On generation, CMake will make the appropriate substitution and write the result to Resource.h, which we can then consume. The main CMakeLists.txt file is pretty straight forward:
cmake_minimum_required(VERSION 3.10)
project(example)
# Sets up classic installation directories. However,
# you can override them:
include(GNUInstallDirs)
add_subdirectory(data)
add_subdirectory(main)
I use the GNUInstallDirs, which populates variables such as CMAKE_INSTALL_DATADIR, for convinience. The main/CMakeLists.txt file:
add_executable(example main.cpp)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Ressources.h.in" "Ressources.h")
target_include_directories(example
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
install(
TARGETS example
DESTINATION ${CMAKE_INSTALL_BINDIR}
)
This is where the configuration file is set up. The target_include_directories just below is added for CMake to be able to find the generated Resource.h file, which will reside in the build directory. Finally, the data/CMakeLists.txt file:
install(
FILES resource.txt
DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}
)
only has a simple installation instruction. From there, you can install as usual. Simply create a build directory and use CMake as usual. For example, if the build directory is located at the same level as the project:
mkdir ../build
cd ../build
cmake ../project
make
sudo make install
Since by default (on Linux) we have:
CMAKE_INSTALL_PREFIX=/usr/local
CMAKE_INSTALL_BINDIR=bin
CMAKE_INSTALL_DATADIR=share
The program will be installed to /usr/local/bin and the resource to /usr/local/share. Note that the Resource.h file will give you the correct path once generated by CMake. Whats is nice now, however, is that you can modify the value of CMAKE_INSTALL_PREFIX to point to somewhere else by calling CMake like so (for example, this could be a dev build directory):
cmake -DCMAKE_INSTALL_PREFIX=/home/someone/example ../project
and you will have these values instead:
CMAKE_INSTALL_PREFIX=/home/someone/example
CMAKE_INSTALL_BINDIR=bin
CMAKE_INSTALL_DATADIR=share
The Resources.h file will also be updated to point to the right location, and your resource will still be found.

How to create an artificial circular dependency between targets

I have an executable (game engine) which exports symbols (I've used set_target_properties(game PROPERTIES ENABLE_EXPORTS ON)).
I have a bunch of plugins that link to that executable:
foreach(plugin ${PLUGINS})
target_link_libraries(${plugin} game)
endforeach()
They are loaded dynamically with LoadLibrary/dlopen by the executable.
When I press F5 in Visual Studio and I start the game I don't get the changed plugins rebuilt because the game does not depend on them - it's the other way around.
I wanted to do the following:
foreach(plugin ${PLUGINS})
add_dependencies(game ${plugin})
endforeach()
but it introduces a circular dependency between each plugin and the game. How can I solve my F5 problem?
That's a "chicken-and-egg" problem since the game build will generate the import libraries needed by plugin. So you can't build plugin before game.
I've given your scenario a try and
If I force a rebuild in a POST_BUILD step, I get obviously a recursive build call:
add_custom_command(
TARGET game
POST_BUILD
COMMAND ${CMAKE_COMMAND} --build . --target ALL_BUILD --config $<CONFIG>
)
If I construct a separate target as a "runner" target, I would probably confusing others using my project:
file(WRITE nobuild.cpp "")
add_executable(game_runner nobuild.cpp)
set_source_files_properties(nobuild.cpp PROPERTIES HEADER_FILE_ONLY 1)
set_target_properties(game_runner PROPERTIES OUTPUT_NAME "game")
foreach(plugin ${PLUGINS})
add_dependencies(game_runner ${plugin})
endforeach()
So probably your suggestion of re-using the ALL_BUILD target is the best one. And for auto-generating your required .user settings you may find the following interesting:
CMake add_custom_target(): Run custom command using 'Debug->Start Debugging'
I've used the following to test your scenario:
project(TestPlugins)
file(WRITE main.cpp "int main() { return 0; }")
file(WRITE empty.cpp "")
add_executable(game main.cpp)
set_target_properties(game PROPERTIES ENABLE_EXPORTS ON)
set_target_properties(game PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_executable(plugin1 empty.cpp)
add_executable(plugin2 empty.cpp)
set(PLUGINS plugin1 plugin2)
foreach(plugin ${PLUGINS})
target_link_libraries(${plugin} game)
endforeach()

Netbeans Ubuntu C++ cannot find include files in release build but can in debug

I am creating a small command line C/C++ app to convert a binary file to a tab delimited text file after not working with C/C++ for several years. Netbeans is new to me as well. The include files below work fine when I build using 'Debug' but when using 'Release' I get the IDE error "Cannot find include file'; The files are flagged as well as lines of code. The compiler error is 'No such file or directory'.
I have other apps in the work space that do compile with the release tab set.
// these are the first code lines in the file
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
// No problem with these
#include <math.h>
#include <stdbool.h>
I don't notice any differences in properties between the apps that build correctly and this one.
Edit:
I've added the path to the includes, /usr/include for C and /usr/include/c++/4.9.2/ for C++, (I have not done this for other apps and they compile) and the error colors for the release includes went from red to yellow and only two lines in the code had red underlines. size_type and npos with the error "unable to find identifiers:
void replaceExt(std::string& s, const std::string& newExt) {
std::string::size_type i = s.rfind('.', s.length()); // size_type
if (i != std::string::npos) { //npos
s.replace(i + 1, newExt.length(), newExt);
}
}
The compiler produced this error message:
gcc -m64 -c -g -I/usr/include/c++/4.9.2 -I/usr/include -MMD -MP -MF "build/Release/GNU-Linux-x86/main.o.d" -o build/Release/GNU-Linux-x86/main.o main.c
In file included from main.c:9:0:
/usr/include/c++/4.9.2/cstdlib:41:28: fatal error: bits/c++config.h: No such file or directory
#include <bits/c++config.h>
Final Edit
It didn't appear right that NetBeans would not have the path to the standard includes so I created a new C++ project, accepted all the default preferences, and copied the all the code except main from the failed project to the new one checking to see if it would compile. Lastly I copied main and found that it builds in both release and debug with no errors.
I don't have any idea what went wrong, but I've found the fix.
It didn't appear right that NetBeans would not have the path to the standard includes so I created a new C++ project, accepted all the default preferences, and copied the all the code except main from the failed project to the new one checking to see if it would compile. Lastly I copied main and found that it builds in both release and debug with no errors.
I don't have any idea what went wrong, but I've found the fix.

CMake link shared library on Windows

There are three files, (m.c,m.h, and **main.c*).
File m.h
// m.h
int m();
File m.c
// m.c
#include <stdio.h>
#include "m.h"
int m(){
printf("Hello,m!\n");
return 0;
}
File main.c
// main.c
#include "m.h"
int main(){
return m();
}
While I prefer a shared library (m.dll), I've made the CMakeLists.txt file:
PROJECT("app1")
ADD_LIBRARY(m SHARED m.c)
ADD_EXECUTABLE(myexe main.c)
TARGET_LINK_LIBRARIES(myexe m)
The CMake configuration is done and generated done. Opening app1.sln and building with Visual Studio, it crashes as
LNK1104:Can't open file "Debug\m.lib"
It only works as STATIC at ADD_LIBRARY(). Why doesn't it work on Windows?
If I got another shared library (mylib.dll), how could I invoke its functions in my main.c and CMakeLists.txt files?
There are differences between dynamic library linking on different platforms which also needs some additional code. The good news is, that CMake can help you with this. I found the following blog post by Gernot Klingler very useful:
Creating and using shared libraries with different compilers on different operating systems
In short you need some "export prefix" defined for whatever is declared in m.h. Otherwise the build process will not generate an "import library" for statically linking named m.lib (see also CMAKE_IMPORT_LIBRARY_SUFFIX).
Here is your code with the modifications needed:
m.h
#include "m_exports.h"
int M_EXPORTS m();
m.c
#include "m.h"
#include <stdio.h>
int m(){
printf("Hello,m!\n");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
include(GenerateExportHeader)
PROJECT("app1")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}")
ADD_LIBRARY(m SHARED m.c m.h m_exports.h)
GENERATE_EXPORT_HEADER(m
BASE_NAME m
EXPORT_MACRO_NAME M_EXPORTS
EXPORT_FILE_NAME m_exports.h
STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC)
ADD_EXECUTABLE(myexe main.c)
TARGET_LINK_LIBRARIES(myexe m)
Additional References
GenerateExportHeader macro
cmake and GenerateExportHeader
How do I get CMake to create a dll and its matching lib file?
MSDN: Walkthrough: Creating and Using a Dynamic Link Library (C++)
Using WINDOWS_EXPORT_ALL_SYMBOLS might help. See an introductory article for details. In short, invoke CMake like this:
cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE
Add this in CMakeLists.txt.
if(MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
set(BUILD_SHARED_LIBS TRUE)
endif()

Resources