makefile variable inside of ifeq block is not visible - variables

I have a makefile:
SOURCES= helloworld.c
ifeq ($(OSNAME), linux)
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
OBJECTS=$(SOURCES:%.c=%.obj)
endif
#OBJECTS=$(SOURCES:%.c=%.o) #without this line print won't output anything
print:
#echo $(OBJECTS)
When I call make print (on linux and macOS), it prints empty line unless I uncomment the #OBJECTS=$(SOURCES:%.c=%.o) line.
Why is this happening? Arn't all variables global?

Hint 1):
You can print out every variable from make with the following command:
SOURCES= helloworld.c
$(info sources: $(SOURCES))
$(info osname: $(OSNAME))
$(info os: $(OS))
Hint 2)
As you can see from the output in linux it returns:
sources: helloworld.c
osname:
os:
you can see that OSNAME is not set on linux at all, so your check ifeq ($(OSNAME), linux) will always fail!
To get the OS information, checkout this link:
OS detecting makefile

I gave a test to your Makefile but to no avail. While it is possible that it should work in general, it does not seem to resemble other examples for testing OS. Hence I'm tempted to suggest that your conditionals, at least for Linux where I tested, do not evalute to true, hence the variable is not set.
Here is a rewritten example that seems to work on Linux:
SOURCES= helloworld.c
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OS),Windows_NT)
OBJECTS=$(SOURCES:%.c=%.obj)
endif
print:
#echo $(OBJECTS)
Output (for me on Linux):
db#vm1:~/projects/here> make
helloworld.o
This example was mostly inspired by the following gist:
https://gist.github.com/sighingnow/deee806603ec9274fd47

Related

How do I build/compile Fortran with MinGW gfortran via CMake?

I've got much more I've got to get figured out with CMake than just the following problem, but it's the first and simplest one which I still can't get past. I've scoured the interwebs and even borrowed the 'Mastering CMake' book from a friend, but I'm still having the hardest time... A lot of stuff exists online with regards to CMake, Fortran, and MinGW, and even combinations of two at a time. But all three together seem to be almost non-existent.
All I want to do (at this point) is get a simple Fortran program built and compiling using CMake on Windows, using MinGW's gfortran compiler.
...And I'm a CMake n00b.
This is what I've been working with so far:
CMakeLists.txt:
project(cmake_test Fortran)
add_executable(testf test.f90)
test.f90:
program test
write(*,*)"hello world"
endprogram test
I've got the MSYS2 version of MinGW, since that's the only version that the code I'm eventually going to be compiling will compile with on Windows. (Ie. when I compile it with my own Makefile in the MSYS2 shell, it compiles.)
I've got my Windows Path appended with ;C:\msys64\mingw64\bin. (I've also tried ;C:\msys64\usr\bin, but it complains about sh.exe being in the same directory, among other issues.)
Then I pop open the CMake-GUI, load in the CMakeLists above, hit Configure, specify the generator for the project to be "MinGW Makefiles", select "Use default native compilers", and get the following output:
The Fortran compiler identification is GNU 5.4.0
Check for working Fortran compiler: C:/msys64/mingw64/bin/gfortran.exe
Check for working Fortran compiler: C:/msys64/mingw64/bin/gfortran.exe -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/mingw64/bin/gfortran.exe supports Fortran 90
Checking whether C:/msys64/mingw64/bin/gfortran.exe supports Fortran 90 -- yes
Configuring done
Then I click Configure again and get:
Configuring done
Then Generate:
Generating done
In my build directory there is then a Makefile and a number of other files and directories.
I try running make in the MSYS2 shell, and I get this:
myself#COMPUTER MSYS /c/users/myself/desktop/dll_test/with_fortran_cmake/build
$ make
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\users\myself\desktop\dll_test\with_fortran_cmake\build>
That last line is a prompt. If I type stuff like make it seems to run it again and it just brings up the prompt again, within the prompt. If I hit Ctrl+C, it kills it and returns to the normal MSYS2 prompt.
So I can't figure out how to actually make it, assuming I'm even doing the CMake part right.
Question: How do I get this example code to build/compile/run given the constraints I've listed?
(What I'd actually rather do, once I get past this part, is get it to work with Visual Studio 13, since I have a C++ project being built with CMake (written mostly by someone else to whom I have limited access for questions and aid) from which I want to be able to call my Fortran. Once I get the Fortran into a library of some sort which is callable by the C++ from Visual Studio, the Fortran can pretty much just be left alone as a pre-built library. I know that editing Fortran from VS is not really much of a possibility, and I'm not interested in doing it.)
Here are the contents of the generated Makefile (note my editor replaced tabs with spaces when I copied it here):
# CMAKE generated file: DO NOT EDIT!
# Generated by "MinGW Makefiles" Generator, CMake Version 3.5
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
SHELL = cmd.exe
# The CMake executable.
CMAKE_COMMAND = "C:\Program Files (x86)\CMake\bin\cmake.exe"
# The command to remove a file.
RM = "C:\Program Files (x86)\CMake\bin\cmake.exe" -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = C:\Users\myself\Desktop\dll_test\with_fortran_cmake
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
"C:\Program Files (x86)\CMake\bin\cmake-gui.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
"C:\Program Files (x86)\CMake\bin\cmake.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles\progress.marks
$(MAKE) -f CMakeFiles\Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\myself\Desktop\dll_test\with_fortran_cmake\build\CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles\Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named testf
# Build rule for target.
testf: cmake_check_build_system
$(MAKE) -f CMakeFiles\Makefile2 testf
.PHONY : testf
# fast build rule for target.
testf/fast:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/build
.PHONY : testf/fast
test.obj: test.f90.obj
.PHONY : test.obj
# target to build an object file
test.f90.obj:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.obj
.PHONY : test.f90.obj
test.i: test.f90.i
.PHONY : test.i
# target to preprocess a source file
test.f90.i:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.i
.PHONY : test.f90.i
test.s: test.f90.s
.PHONY : test.s
# target to generate assembly for a file
test.f90.s:
$(MAKE) -f CMakeFiles\testf.dir\build.make CMakeFiles/testf.dir/test.f90.s
.PHONY : test.f90.s
# Help Target
help:
#echo The following are some of the valid targets for this Makefile:
#echo ... all (the default if no target is provided)
#echo ... clean
#echo ... depend
#echo ... testf
#echo ... edit_cache
#echo ... rebuild_cache
#echo ... test.obj
#echo ... test.i
#echo ... test.s
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0
.PHONY : cmake_check_build_system
Version information:
GNU Fortran (GCC) 5.3.0
Windows 7 Enterprise
Cmake 3.5.2
MSYS2 - I'm not sure how to find the version for this
MinGW - I'm not sure how to find the version for this
I've been through a lot of different pages online during my search, and I didn't bother keeping track of them all, but this one in particular is one I keep coming across because it seems like it's very related from the title, but the actual issue and resolution are totally not:
How can I get a basic Fortran file to compile on Windows/MinGW using CMake?
Here is a quick shell session showing how I was able to build your Fortran program using MSYS2, cmake, make, and gfortran. You should try running the same commands that I did and see if they give different outputs then investigate the reason.
The MSYSTEM variable is especially important; it is determined by what shortcut you click on when starting MSYS2.
$ echo $MSYSTEM
MINGW64
$ which cmake
/mingw64/bin/cmake
$ which gfortran
/mingw64/bin/gfortran
$ which make
/usr/bin/make
$ ls
CMakeLists.txt test.f90
$ cat CMakeLists.txt
project(cmake_test Fortran)
add_executable(testf test.f90)
$ cat test.f90
program test
write(*,*)"hello world"
endprogram test
$ mkdir build && cd build
$ cmake -G"MSYS Makefiles" ..
-- The Fortran compiler identification is GNU 6.2.0
-- Check for working Fortran compiler: D:/msys64/mingw64/bin/gfortran.exe
-- Check for working Fortran compiler: D:/msys64/mingw64/bin/gfortran.exe -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether D:/msys64/mingw64/bin/gfortran.exe supports Fortran 90
-- Checking whether D:/msys64/mingw64/bin/gfortran.exe supports Fortran 90 -- yes
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/david/Documents/scraps/test_fortran/build
$ make
Scanning dependencies of target testf
[ 50%] Building Fortran object CMakeFiles/testf.dir/test.f90.obj
[100%] Linking Fortran executable testf.exe
[100%] Built target testf
$ ./testf.exe
hello world
Edit: There IS a working solution here -- read till the end!
Thanks to David Grayson's comment on the original question, I've found a partial solution. "Partial" because it uses f95 instead of gfortran. I'm posting it because it might work for someone else, and if I'm able to figure out how to get it to work with gfortran, I'll just update it.
Turns out the main issue was a pretty simple mistake: I was using "MinGW Makefiles" instad of "MSYS Makefiles".
When I only changed that, however, I got the following output in the CMake-GUI when I clicked Configure:
CMake Error: CMake was unable to find a build program corresponding to "MSYS Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMake was unable to find a build program corresponding to "MSYS Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMAKE_Fortran_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_AR was not found, please set to archive program. Configuring incomplete, errors occurred!
To fix this, I changed my Windows Path again. I'd been using ;C:\msys64\mingw64\bin, and so I switched it to ;C:\msys64\usr\bin.
This then worked (I clicked Configure a second time, clicked Generate, and then ran make via the MSYS2 terminal in the /build directory), but as you can see in the following output, it used f95 instead of gfortran:
The Fortran compiler identification is GNU 5.3.0
Check for working Fortran compiler: C:/msys64/usr/bin/f95.exe
Check for working Fortran compiler: C:/msys64/usr/bin/f95.exe -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/usr/bin/f95.exe supports Fortran 90
Checking whether C:/msys64/usr/bin/f95.exe supports Fortran 90 -- yes
Configuring done
I'm still working to get it to use gfortran, and I'll update this solution if I figure it out.
Edit:
Okay, this is obviously more of a hack and I'm sure that there's a better solution. I renamed C:\msys64\usr\bin\f95.exe to something else (so that MSYS2 wouldn't find it as another Fortran compiler before finding gfortran). I also had to clear CMake's cache and restart it. But now it works:
The Fortran compiler identification is GNU 5.3.0
Check for working Fortran compiler: C:/msys64/usr/bin/gfortran.exe
Check for working Fortran compiler: C:/msys64/usr/bin/gfortran.exe -- works
Detecting Fortran compiler ABI info
Detecting Fortran compiler ABI info - done
Checking whether C:/msys64/usr/bin/gfortran.exe supports Fortran 90
Checking whether C:/msys64/usr/bin/gfortran.exe supports Fortran 90 -- yes
Configuring done
Working on figuring out how to do this the "correct" way.
Edit:
Okay, I'm guessing this is the more proper way to do it, as I assume it essentially does the same thing as setting environment variables on the commandline when calling CMake from there.
In the CMake-GUI, I set everything up as explained before, but before clicking Configure for the first time, I clicked the "Add Entry" button with the little plus symbol. I then set two new Cache Entries -- though only one is really necessary:
Name: CMAKE_Fortran_COMPILER
Type: FILEPATH
Value: C:\msys64\usr\bin\gfortran.exe
I also set the following, but this was only to verify that it was calling gfortran properly, as you'll see in the output below:
Name: CMAKE_VERBOSE_MAKEFILE
Type: BOOL
Value: [True]
Then, running make in the MSYS2 terminal, I got the following:
$ make
"/C/Program Files (x86)/CMake/bin/cmake.exe" -H/C/Users/myself/Desktop/dll_test/with_fortran_cmake -B/C/Users/myself/Desktop/dll_test/with_fortran_cmake/build --check-build-system CMakeFiles/Makefile.cmake 0
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/depend
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_depends "MSYS Makefiles" /C/Users/myself/Desktop/dll_test/with_fortran_cmake /C/Users/myself/Desktop/dll_test/with_fortran_cmake /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles/testf.dir/DependInfo.cmake --color=
Scanning dependencies of target testf
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/requires
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make[2]: Nothing to be done for 'CMakeFiles/testf.dir/requires'.
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
make -f CMakeFiles/testf.dir/build.make CMakeFiles/testf.dir/build
make[2]: Entering directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
[ 50%] Building Fortran object CMakeFiles/testf.dir/test.f90.obj
/C/msys64/usr/bin/gfortran.exe -c /C/Users/myself/Desktop/dll_test/with_fortran_cmake/test.f90 -o CMakeFiles/testf.dir/test.f90.obj
[100%] Linking Fortran executable testf.exe
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E remove -f CMakeFiles/testf.dir/objects.a
/C/msys64/usr/bin/ar.exe cr CMakeFiles/testf.dir/objects.a #CMakeFiles/testf.dir/objects1.rsp
/C/msys64/usr/bin/gfortran.exe -Wl,--whole-archive CMakeFiles/testf.dir/objects.a -Wl,--no-whole-archive -o testf.exe -Wl,--out-implib,libtestf.dll.a -Wl,--major-image-version,0,--minor-image-version,0
make[2]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
[100%] Built target testf
make[1]: Leaving directory '/c/Users/myself/Desktop/dll_test/with_fortran_cmake/build'
"/C/Program Files (x86)/CMake/bin/cmake.exe" -E cmake_progress_start /C/Users/myself/Desktop/dll_test/with_fortran_cmake/build/CMakeFiles 0
And the resulting program works both via the MSYS2 terminal and a Windows command prompt.
...Now I need to figure out how to get this all together with C++ in Visual Studio. Stay tuned for more SO questions! :D

How can I ignore errors on an individual CMake command in my CMakeLists.txt?

I have a project where the CMakeLists.txt attempts to read a file which may or may not be present. It is not a problem for the file to be missing and the script handles either case. This is used to tweak the compilation environment slightly if we can detect a known Linux distribution:
file (READ /etc/redhat-release RHREL)
if (RHREL MATCHES "Red Hat Enterprise Linux Server release 6*")
# tweak for RHEL6
elseif (RHREL MATCHES "Red Hat Enterprise Linux Server release 7*")
# tweak for RHEL7
else()
# either read failed, or we didn't match a known RHEL release
# fallback to reasonable defaults
endif()
The problem is that when file(READ...) fails it seems to be outputting a message using the SEND_ERROR parameter. This means that my configuration continues into the catch-all else() as I expect, but at the end of configuration CMake refuses to generate a Makefile.
How can I run file(READ) in such a way that I can cope with errors locally and prevent them from failing the entire configuration?
You can check if the file exists first (n.b. if it exists but isn't readable you will still have a problem):
if (EXISTS /etc/redhat-release)
Turning my comment into an answer
In this special case, you could also check CMAKE_HOST_SYSTEM.
The more general answer is you have to move your code into an external CMake script and call it with the all mighty execute_process() command:
FileDumpRedHatRelease.cmake
file(READ /etc/redhat-release RHREL)
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${RHREL}")
# or if you don't mind the '-- ' leading dashes with STATUS messages
# (because normal CMake messages go to stderr)
#message(STATUS "${RHREL}")
CMakeLists.txt
execute_process(
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/FileDumpRedHatRelease.cmake"
OUTPUT_VARIABLE RHREL
ERROR_QUIET
)
References
Even those references are all discussing an add_custom_command() command that could fail, you can see the usage of execute_process() and external CMake scripts in such cases:
catch return value in CMake add_custom_command?
CMake: Ignoring return codes on ADD_CUSTOM_COMMAND (hhc.exe)
0013146: ADD_CUSTOM_COMMAND has no OUTPUT / RESULT Variable

cmake check existence of compiler

I'm trying to play around with cmake to build a small C++-code.
I do not have yet g++
(I'm testing on a virtualbox OS)
When I call cmake .
I get the nasty error messages.
-- The C compiler identification is GNU 4.7.2
**-- The CXX compiler identification is unknown**
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
**CMake Error: your CXX compiler: "CMAKE_CXX_COMPILER-NOTFOUND" was not found. Please set CMAKE_CXX_COMPILER to a valid compiler path or name.
-- Configuring incomplete, errors occurred!**
Basically, this is OK. It says errors occurred, but it says too much than needed. I just want to get a precise and concise message saying "g++ ist not installed. INSTALL it please".
Is there a way to first check if g++ is installed and then give an appropriate message?
The output you gave shows that CMake attempting to be helpful to you. If it is too verbose for your taste, perhaps the simplest way to reduce it would be to capture it into a variable, then examine it.
You can save the sample CMake script below as detect_cxx_compiler.cmake, and invoke the script using cmake -P detect_cxx_compiler.cmake. The code is written in a manner intended to be helpful to CMake beginners, not for small size or processing efficiency.
cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
cmake_policy(VERSION 2.8.5)
# This cmake script (when saved as detect_cxx_compiler.cmake) is invoked by:
#
# cmake -P detect_cxx_compiler.cmake
#
# It is written for clarity, not brevity.
# First make a new directory, so that we don't mess up the current one.
execute_process(
COMMAND ${CMAKE_COMMAND} -E make_directory detection_area
WORKING_DIRECTORY .
)
# Here, we generate a key file that CMake needs.
execute_process(
COMMAND ${CMAKE_COMMAND} -E touch CMakeLists.txt
WORKING_DIRECTORY detection_area
)
# Have CMake check the basic configuration. The output is
# actually in the form that you posted in your question, but
# instead of displaying it onscreen, we save it to a variable
# so that we can select only parts of it to print later.
execute_process(
COMMAND ${CMAKE_COMMAND} --check-system-vars
OUTPUT_VARIABLE the_output
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY detection_area
)
# Eliminate the directory, including all of the files within it that
# CMake created.
execute_process(
COMMAND ${CMAKE_COMMAND} -E remove_directory detection_area
WORKING_DIRECTORY .
)
# Here, you have the entire message captured as a variable.
# Uncomment this next line to convince yourself of this.
#message(STATUS "the_output = |${the_output}|.")
# Here, we search the message to see if the C++ compiler was found or not,
# and print an arbitrary message accordingly.
string(FIND "${the_output}" "CMAKE_CXX_COMPILER-NOTFOUND" scan_result)
#message(STATUS "scan_result = |${scan_result}|.")
if(NOT(-1 EQUAL "${scan_result}"))
message(FATAL_ERROR "A C++ compiler was not detected.")
endif()
message(STATUS "A C++ compiler was detected.")
You should use GCC (Gnu Compiler Collection) frontend. You should install gcc-c++ or something similar package.

Why I cannot get Valgrind diagnostic information with CMake?

I am now running CTest with or without Valgrind in Ubuntu Linux. Firstly, I set up a CMakeLists.txt script to enable testing:
enable_testing()
include(CTest)
if(UNIX)
set(CTEST_MEMORYCHECK_COMMAND, "usr/bin/valgrind")
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS, "--trace-children=yes --leak-check=full")
endif()
add_test(NAME test
WORKING_DIRECTORY ${my_outputdirectory}
COMMAND test_exe)
When I run the test without valgrind, I use the following command:
cmake -G "CodeBlocks - Unix Makefiles"
ctest -D ExperimentalBuild
ctest -R test -D ExperimentalTest
That works fine. However, when I run the following command to invoke valgrind:
cmake -G "CodeBlocks - Unix Makefiles"
ctest -D ExperimentalBuild
ctest -R test -D ExperimentalMemChec
the following message appear:
--Processing memory checking output:
Memory checking results:
This is definitely not the diagnostic information I expect. I was wondering what I should do next. Thanks!
EDIT:
Later on, I find that the diagnostic information can be available only in the case where the memory leak happens. However, the diagnostic information is very vague in the sense that the location where the error occurs is not given. How could I obtain more detailed information?
By default, CMake does not build debug symbols for Makefile projects, so Valgrind is unable to determine the exact location of a leak in source code.
Try running cmake with
cmake -DCMAKE_BUILD_TYPE=Debug /path/to/source
which should add the compiler option for building debug symbols.
I use a python script which parses my memory leaks from valgrind it is available here.
In CMake I use the following command to add a memory test:
ADD_TEST(testName ${Test_Dir}/memtest.py ${CMAKE_CURRENT_BINARY_DIR}/testExecutable ${CMAKE_BINARY_DIR})
Such that I do not need to parse the memory leak errors direct in cmake. The python script simply executes a memory check with valgrind on the executable and returns an error if a leak was found. If a leak was found the test then fails otherwise it passes. Hope this might help you.
CMake by default uses the following command line arguments for valgrind memcheck:
--log-file=/Path/to/build-dir/Testing/Temporary/MemoryChecker.1.log \
-q --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=50
Note that the --log-file argument means that any valgrind errors ends up in that file. I find it more useful when valgrind posts the information to the stderr, so a build server like Jenkins or TeamCity can show it more easily. In order to do that, you have to set the MEMORYCHECK_COMMAND_OPTIONS variable with --log-fd=2 (and other options if you'd like) so it overrides the --log-file option.
More info here.

Can not compile simple C# application with mkbundle

I have written some console "Hello world"-like app. and have followed c# cywgwin mono mkbundle windows 7 - cannot compile file answer. But I have got:
$ mkbundle -o Fur Furries.exe --deps -z
OS is: Windows
Sources: 1 Auto-dependencies: True
embedding: C:\Monotest\Furries.exe
compression ratio: 40.43%
embedding: C:\Soft\Mono\lib\mono\4.0\mscorlib.dll
compression ratio: 34.68%
Compiling:
as -o temp.o temp.s
gcc -mno-cygwin -g -o Fur -Wall temp.c `pkg-config --cflags --libs mono-2|dos2un
ix` -lz temp.o
temp.c: In function `main':
temp.c:173: warning: implicit declaration of function `g_utf16_to_utf8'
temp.c:173: warning: assignment makes pointer from integer without a cast
temp.c:188: warning: assignment makes pointer from integer without a cast
/tmp/ccQwnxrF.o: In function `main':
/cygdrive/c/Monotest/temp.c:173: undefined reference to `_g_utf16_to_utf8'
/cygdrive/c/Monotest/temp.c:188: undefined reference to `_g_utf16_to_utf8'
collect2: ld returned 1 exit status
[Fail]
It's in Windows XP.
First of all, prepare development environment:
Install Mono. For example, you have installed it into "C:\Soft\Mono".
Install Cygwin. When selecting which packages to install select following: gcc-mingw, mingw-zlib, pkg-config, nano.
Start Cygwin Bash shell (either using a link or "bash --login -i" command).
Open "$HOME/.bashrc" with "nano" ("nano ~/.bashrc"). Don't use editors which don't preserve end-of-line-s ("CR", "LF", "CR/LF" or other), or it will corrupt the file!
Add following lines to the end of the file:
export PKG_CONFIG_PATH=/cygdrive/c/Soft/Mono/lib/pkgconfig
export PATH=$PATH:/cygdrive/c/Soft/Mono/bin
Restart Cygwin Bash shell.
After that you can compile your assemblies with "mkbundle":
Perform the following command: "mkbundle -c -o host.c -oo bundle.o --deps YourAssembly.exe <additional arguments>". You also may optionally pass "-z" to compress resultant bundle. You should get "host.c" and "bundle.o" files.
In "host.c" you should remove "_WIN32" "branch" (except "#include <windows.h>" one). It doesn't work. You may do it just by adding "#undef _WIN32" right after following lines in it:
#ifdef _WIN32
#include <windows.h>
#endif
So you'll get:
#ifdef _WIN32
#include <windows.h>
#endif
#undef _WIN32
Perform the following command: "gcc -mno-cygwin -o ResultantBundle.exe -Wall host.c `pkg-config --cflags --libs mono-2|dos2unix` bundle.o <additional arguments>". If you added a -z additional argument in step 2, you must add a -lz additional argument in this step.
You will get "ResultantBundle.exe". This is your Mono application packed as standalone executable.
It still requires "mono-2.0.dll" and some additional DLL-s and resources you depended on during development (for example, it may require GTK# native DLL-s) but it doesn't require full Mono runtime to run.
Just wanted to add that if you pass -z to mkbundle then you'll need to pass -lz to gcc. I had some issues getting an application with winforms and net access to work properly, and I had to copy machine.config from C:\Mono\etc\mono\4.0\machine.config to where my application was. I then passed --machine-config machine.config to mkbundle.
All of these steps are pretty confusing and frustrating, why is not as simple as just typing mkbundle --deps app.exe? I tried making a change to the template used by mkbundle and compiling it myself, but it wont run. I've gone as far now as to download the mono source and attempt to build the whole thing, but I doubt it will work. If anyone can explain what the hell is going on with mkbundle to make this so annoying, I'd be interested in contributing.
after you have the temp.o and temp.c, you can add them to visual c++ to make a windows application with other sources.