I'm trying to work on a Makefile based project with Visual Studio Code. I created a task and now I can run make and see the output including a little bit of coloring inside visual studio code. However, I am not able to click on a compile error and have it take me to the corresponding line of code. I think this has to be possible, and I can't imagine it's hard, so I must be missing something obvious.
I can reproduce it with a tiny example:
main.c
#include <stdio.h>
int main(){
printf("jo\n");
unsigned int u = -999;
int x;
if ( u < x )
printf("really small\n");
asdfasdfa
#error "nononono"
}
Makefile
all:
gcc -Werror -Wall -Wextra -o main main.c
tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "make",
"type": "shell",
"command": "make",
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
I solved this very issue in the past by running gcc output (both stdout and stderr) through sed or awk that converted gcc error format into msvc error format.
Alternatively, you could try using VS Code, it supports gcc natively.
Related
I want to define an inline function in a header file (.h) which can be included by numerous source files (.c). Here is a minimal example with 1 header and 2 source files:
Header file foo.h
int ifunc(int i);
extern inline
int
ifunc(int i)
{
return i + 1;
}
Source code file: foo.c
#include <stdio.h>
#include "foo.h"
int foo2(int i);
int main()
{
printf("%d\n", foo2(1));
return 0;
}
Source code file foo2.c
#include "foo.h"
int foo2(int i)
{
return ifunc(i);
}
The problem
When I compile with optimization,
gcc -g -Wall -O2 -o foo foo.c foo2.c
$ ./foo
2
everything works fine. However when I turn off optimization, I get this error:
gcc -g -Wall -o foo foo.c foo2.c
/tmp/cc3OrhO9.o: In function `foo2':
foo2.c:5: undefined reference to `ifunc'
Can someone please explain how to fix so that I can run the code with and without -O2? I am using gcc 4.8.5.
if you replace foo.h with
static inline int ifunc(int i)
{
return i + 1;
}
Both will work.
Declaring it extern means it'll be defined somewhere else which in your original example does not happen. And the optimized build doesn't flag as an error because it already optimized it to be inline it but the non-optimized build does not find a definition in any of the .o files (since they were all compiled with ifunc being an extern as defined in foo.h).
Declaring as static inline will ensure that it is local to each file (the downside being that if it does not inline it, you'll end up with each .o that needs it having a local copy, so don't overdo it).
I am trying to compile the following code ([cuShiftOr]) to a linux box. Original code is running on Visual Studio 2013 in Windows.
My strategy is to compile all .cu files like below:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 --compile -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -fexceptions -ffunction-sections -fdata-sections -fpermissive" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -c CuShiftOr/device/hybrid.cu -o objs/CuShiftOr/device/hybrid.cu.o
Likewise for the rest.
At the final stage link everything together by running:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -std=c++11 -Icpp11-range -fexceptions -ffunction-sections -fdata-sections -fpermissive -Wnon-template-friend" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -o CuShiftOrBenchmark.a objs/CuShiftOr/device/hybrid.cu.o objs/CuShiftOr/util/op.cu.o objs/CuShiftOr/device/segment.cu.o objs/CuShiftOr/host.cu.o objs/CuShiftOr/util/timer.cu.o objs/CuShiftOr/util/file.cu.o objs/CuShiftOr/util/generator.cu.o objs/CuShiftOrBenchmark/kernel.cu.o -lm
However that leads me this undefined reference issue:
objs/CuShiftOrBenchmark/kernel.cu.o: In function `void run_benchmark<unsigned int>(std::ostream&, cushiftor::device::Handler<unsigned int>*, long, unsigned int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
tmpxft_00003ea2_00000000-4_kernel.cudafe1.cpp:(.text._Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x203): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
inside op.cuh it is defined as:
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
template<typename word>
__host__ __device__ __forceinline__ word ones(int m) {
return ~word(0) >> (bit<word>::size - m);
}
and then on kernel.cu we have:
#include "util/op.cuh"
using cushiftor::util::op::bit;
using cushiftor::util::op::bytepack;
using cushiftor::util::op::div_up;
using cushiftor::util::op::round_up;
using cushiftor::util::op::shuffle_up;
Further more compiling with Visual Studio 2013 (which works since the project was made on that) shows some instantiations that I am not sure if g++ is doing e.g:
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(209): warning C4244: 'argument' : conversion from 'int64_t' to 'cushiftor::env::datasize_t', possible loss of data
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(230) : see reference to function template instantiation 'void benchmark_with_file<word>(cushiftor::device::Handler<word> *)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(86): warning C4018: '<=' : signed/unsigned mismatch
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(132) : see reference to function template instantiation 'void run_benchmark<word>(std::ostream &,cushiftor::device::Handler<word> *,int64_t,cushiftor::env::datasize_t,int,std::string)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
Now my C++11 template knowledge is very limited but I did try to instantiate also inside the kernel.cu by adding:
template class cushiftor::util::op::bit<unsigned int>;
However to no avail... Any tips are very welcomed!
I believe this question is essentially a duplicate of this one. However simply marking it as such with no explanation may be a bit obscure. Therefore I'm going to provide a CW answer in the hopes that someone may improve it or correct me if I am wrong.
A possible MCVE derived from the code is as follows (note that I'm converting to using g++ directly rather than nvcc, as the manifestation and workarounds are the same):
$ cat test.cpp
#include <iostream>
namespace cushiftor {
namespace util {
namespace op {
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
}
}
}
#ifdef FIX2
void f(const int data){
#else
void f(const int &data){
#endif
std::cout << "size of type in bits is: " << data << std::endl;
}
using cushiftor::util::op::bit;
#ifdef FIX1
template <typename T> const int bit<T>::size;
#endif
template<typename word>
void run_benchmark() {
f(bit<word>::size);
}
int main(){
run_benchmark<unsigned>();
}
$ g++ -o test test.cpp
/tmp/ccCW51e3.o: In function `void run_benchmark<unsigned int>()':
test.cpp:(.text._Z13run_benchmarkIjEvv[_Z13run_benchmarkIjEvv]+0x5): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
$ g++ -DFIX1 -o test test.cpp
$ g++ -DFIX2 -o test test.cpp
$
This MCVE was created based on inspection of relevant code in kernel.cu, tinyformat.h, and op.cuh, in the original cuShiftOr project (and paper).
We see that if we compile the code as-is, it generates a similar error to that reported in the question.
Compiling with -DFIX2 demonstrates that taking the item in question (bit::size) as a reference argument is essential to witnessing of the issue.
Compiling with -DFIX1 eliminates the issue, and I believe is the correct approach in this case.
The explanation for this issue seems to be that the compiler may treat the static const member as a compile-time constant, unless it is "used" in the code. ("Used" has a special language-specific meaning here.) If it is "used" in the code, then the compiler must be able to take the address of it (sensible in the case of a reference parameter) and to take the address of it, the class/struct definition is not sufficient. (It is apparently only a declaration even though it appears in the class/struct definition. The declaration is sufficient for usage equivalently to a compile-time constant, but is not sufficient for the case where we wish to take the address of it.)
From here:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19) In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program
I believe the FIX1 code modification satisfies the bolded requirement above.
With the above preamble, I believe it is valid to mark this as a duplicate.
With respect to the behavior of the original project on windows, I would conjecture that compilers may have leeway in enforcement of this, and may in fact provide referenceable member symbols even when the program does not explicitly define them.
I am trying to build a static library using MinGW.
Everything was going fine until I tried to use the library and got an error saying that add_numbers is an undefined function.
Many other people have had this problem and sorted it out by moving their library to be linked after the source files were included, but that was how I had written my batch file anyway, so that was not of much help.
Here are my sources.
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
int add_numbers(int a, int b, int c);
#endif
mylib.c
#include "mylib.h"
int add_numbers(int a, int b, int c)
{
return a+b+c;
}
I'm building my .a file with the following commands
gcc --std=c89 -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
I've also tried with out specifying the standard.
There are no errors or warnings when running this command.
Next, my test program looks like this.
#include <stdio.h>
#include "mylib.h"
int main()
{
printf("The sum of 1, 2, and 3 is %d", add_numbers(1, 2, 3));
getchar();
return 0;
}
And lastly, we build the test with this command.
gcc mylibtest.c -L -lmylib -o test.exe
I've tried moving around those commands into many many different sequences, but always receiving the following error:
C:\Users\Aaron\AppData\Local\Temp\cc0ERpBi.o:mylibtest.c:(.text+0x26): undefined
reference to `add_numbers'
collect2.exe: error: ld returned 1 exit status
E:\my_first_static_library>
Any help would be very appreciated, I've read every tutorial I could find on the art of writing static libraries, as well as a good ten stackoverflow questions.
You are missing a dot after -L:
gcc mylibtest.c -L . -lmylib -o test.exe
I'm using GCC and the NVIDIA implementation of OpenCL, and online compilation instead of offline compilation.
I use this list to check which is the error I have. But nevertheless if I have an error inside my kernel the only information I have is an error value -48.
My question is: Is there a way to display the exact kernel compilation error?
If a semicolon is missing, or I have a wild pointer I would like to read so, instead of just a -48 error. Otherwise the development time is getting too slow.
I add also my Makefile:
CC=gcc
FILE=main
all:
$(CC) -c -Wall -I /usr/local/cuda/include/ $(FILE).c -o $(FILE).o
$(CC) $(FILE).o -o $(FILE) -L /usr/local/cuda/lib64/ -l OpenCL
clean:
$(RM) $(FILE) $(FILE).o
In C++, do something like:
int ErrorCode = 0;
cl_program P;
cl_device_id D;
size_t LogSize;
cl_build_status BuildStatus;
//Configure OpenCL
//Load Program Here
//Compile Program here
//Check the status of compilation
ErrorCode = clGetProgramBuildInfo(P, D, CL_PROGRAM_BUILD_STATUS, NULL, NULL, &BuildStatus);
if(BuildStatus == CL_BUILD_ERROR){
//Fetch Error
ErrorCode = clGetProgramBuildInfo(P, D, CL_PROGRAM_BUILD_LOG, NULL, NULL, &LogSize);
char Log = new Log[LogSize]; //Or use Malloc if in C
ErrorCode = clGetProgramBuildInfo(P, D, CL_PROGRAM_BUILD_LOG, LogSize, Log, NULL);
//Display Error Code here, close out OpenCL, try again, etc
}
I'm trying to run the following simple example from Xcode4:
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
namespace mpi = boost::mpi;
int main(int argc, char* argv[])
{
mpi::environment env(argc, argv);
mpi::communicator world;
std::cout << "I am process " << world.rank() << " of " << world.size()
<< "." << std::endl;
return 0;
}
I've added libboost_mpi and libboost_serialization to Xcode, and compiling using the default LLVM returns :
/usr/local/include/boost/mpi/communicator.hpp:1329:9: error: call to
implicitly-deleted copy constructor of 'boost::mpi::communicator'
: comm(comm), source(source), tag(tag), ia(comm), value(value)
^ ~~~~
However, I can compile and run using
mpic++ -I/usr/local/include main.cpp -L/usr/local/lib
-lboost_mpi -lboost_serialization
Although mpic++ seems to be calling through to LLVM:
$ mpic++
i686-apple-darwin11-llvm-g++-4.2: no input files
Anyways, I tried adding mpic++ as a compiler option in Xcode 4. I can run
$ sudo opensnoop -n Xcode | grep mpicc.xcspec
and see that the spec file is being loaded by Xcode, but I don't see any MPICC option. My spec file is fairly simple:
/**
Xcode Compiler Specification for MPICC
*/
{ Type = Compiler;
Identifier = com.apple.compilers.mpicc;
BasedOn = com.apple.compilers.gcc.4_2;
Name = “MPICC”;
Version = “Default”;
Description = “MPI GNU C/C++ Compiler 4.0″;
ExecPath = “/usr/local/bin/mpicc”;
PrecompStyle = pch;
}
and it's stored in
/Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/LLVM GCC 4.2.xcplugin/Contents/Resources/mpicc.xcspec
So this works:
link binary with:
libmpi_cxx.dylib
libmpi.dylib
libboost_mpi.dylib
libboost_serialization.dylib
Change compiler (under build options) to LLVM GCC 4.2 (hinted at by running mpic++ directly, which reports that it's using llvm gcc 4.2 internally)
Under targets, build phases, compile sources, add the compiler option "-lm" to report that you need to link with libm. Credit to #pyCthon for pointing out mpic++ --showme:link which revealed the final library that was allowing it to build successfully from the command line