I'm trying to learn CMake using an example project that calculates the fibonacci of a given number. My project originally included a single ".c" file and header. I was able to build with CMake and run without issue. Now I'm trying to learn how to link libraries by moving my fibnoacci function into a separate ".c" file which I compile into a linkable library using CMake. It builds without issue but throws a segmentation fault when I run it. My project structure is:
fib
|
*---MathFunctions
| |
| *----CMakeLists.txt
| |
| *----myfib.h
|
*---CMakeLists.txt
|
*---fib.c
|
*---fib.h
|
*---myfib.c
|
*---Config.in.h
The CMakeLists.txt under the MathFunctions folder is empty. All of the program logic is in fib.c and myfib.c. All of the build is in the top CMakeLists.txt
fib.c:
# include "stdio.h"
# include "stdlib.h"
# include "Config.h"
#include "myfib.h"
void internalfib(int num)
{
printf("Internally defined fib\n");
int a, b;
a = 0;
b = 1;
printf( "custom fib of %d", b );
for( int i = 0; i + a <= num; b = i ) {
i = a + b;
a = b;
printf( ", %d", i );
}
}
int main( int argc, char** argv) {
fprintf(stdout,"%s Version %d.%d\n",
argv[0],
VERSION_MAJOR,
VERSION_MINOR);
#ifdef SHOW_OWNER
fprintf(stdout, "Project Owner: %s\n", OWNER);
#endif
myfib(atof( argv[1] ));
printf("\n");
return EXIT_SUCCESS;
}
myfib.c:
# include "stdio.h"
# include "stdlib.h"
void myfib(int num)
{
printf("custom myfib");
int a, b;
a = 0;
b = 1;
printf( "custom fib of %d", b );
for( int i = 0; i + a <= num; b = i ) {
i = a + b;
a = b;
printf( ", %d", i );
}
}
CMakeLists.txt:
#Specify the version being used aswell as the language
cmake_minimum_required(VERSION 2.6)
#Name your project here
project(fibonacci)
enable_testing()
set (VERSION_MAJOR 1)
set (VERSION_MINOR 0)
configure_file (
"${PROJECT_SOURCE_DIR}/Config.h.in"
"${PROJECT_BINARY_DIR}/Config.h"
)
option (SHOW_OWNER "Show the name of the project owner" ON)
#Sends the -std=c99 flag to the gcc compiler
add_definitions(-std=c99)
include_directories("${PROJECT_BINARY_DIR}")
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
add_library(MathFunctions myfib.c)
#This tells CMake to fib.c and name it fibonacci
add_executable(fibonacci fib.c)
target_link_libraries (fibonacci MathFunctions)
#test that fibonacci runs
add_test (FibonacciRuns fibonacci 5)
#Test the fibonacci of 5
add_test (FibonacciCompare5 fibonacci 5)
set_tests_properties (FibonacciCompare5 PROPERTIES PASS_REGULAR_EXPRESSION "1, 1, 2, 3, 5")
install (TARGETS fibonacci DESTINATION ${PROJECT_BINARY_DIR}/bin)
After running "..cmake" and "make" from the build folder I run:
~/dev/cworkshop/fib/build$ ./fibonacci
./fibonacci Version 1.0
Project Owner: Clifton C. Craig
Segmentation fault: 11
Where am I going wrong?
Are you actually sure you're getting a segfault because of your build system?
Your code requires input, and you do not check that input is given. From fib.c:26:
myfib(atof( argv[1] ));
If no arguments are given, your code will try to read data that you haven't provided (and segfault). If you run your code: ./fibonacci 3, you'll print myfib. I'm going to guess this is what your problem is.
Other things to consider:
when giving a portion of code, try to ensure that it's either minimal and complete, or accurately describes your problem. Large blocks of commented-out code are not relevant to the question, while in this case header files and Config.h.in (which are required to get your example to compile), are not provided.
myfib.c and myfib.h are in different folders. If myfib.c is part of the MathFunctions library, I'd put the sources into that subdirectory. This is explained in the tutorial I think you're following: this one, which has a CMakeLists.txt file containing the line:
add_library(MathFunctions mysqrt.cxx)
in the MathFunctions library.
As pointed out by #n.m in the comments, atof takes a float as input - the Fibonacci sequence is generated using an int (so atoi is more appropriate).
For your example, I would not use add_definitions to set the compiler flags. The better way to do it (project-wide) is to use set ( CMAKE_CXX_FLAGS "-O0 -g -Wall"). (There are lots of useful CMake Variables). While add_definitions works, it's not the best tool for the job you're doing. :)
Related
I am struggling to understand linking process in c. (I am new in C) When I make object a test code in my local directory (plplotExample.c and mathglExample) some complain that header are not there even though I have them in usr/local/...., except for mathglExample. The test codes are below:
plotExample.c
#include "plConfig.h"
#include "plcdemos.h"
#define NSIZE 101
int
main( int argc, char *argv[] )
{
PLFLT x[NSIZE], y[NSIZE];
PLFLT xmin = 0., xmax = 1., ymin = 0., ymax = 100.;
int i;
// Prepare data to be plotted.
for ( i = 0; i < NSIZE; i++ )
{
x[i] = (PLFLT) ( i ) / (PLFLT) ( NSIZE - 1 );
y[i] = ymax * x[i] * x[i];
}
// Parse and process command line arguments
plparseopts( &argc, argv, PL_PARSE_FULL );
// Initialize plplot
plinit();
// Create a labelled box to hold the plot.
plenv( xmin, xmax, ymin, ymax, 0, 0 );
pllab( "x", "y=100 x#u2#d", "Simple PLplot demo of a 2D line plot" );
// Plot the data that was prepared above.
plline( NSIZE, x, y );
// Close PLplot library
plend();
exit( 0 );
}
the error message is :
plplotExample.c:2:10: fatal error: plConfig.h: No such file or directory
mathglExample.c
#include <mgl2/mgl_cf.h>
int main()
{
HMGL gr = mgl_create_graph(600,400);
mgl_fplot(gr,"sin(pi*x)","","");
mgl_write_frame(gr,"test.png","");
mgl_delete_graph(gr);
}
the error message is
In file included from /usr/include/mgl2/mgl_cf.h:29:0,
from mathglExample.c:1:
/usr/include/mgl2/data_cf.h:513:17: error: expected ‘,’ or ‘;’ before ‘mgl_find_roots’
how to fix linking or should I bring all codes and libraries under one directory? I am using linux opensuse leap 15.2 and Geany as c editor.
plConfig.h has to be in the same directory as plotExample.c.
In the file /usr/include/mgl2/data_cf.h, on the line 513, at the column 17, the compiler expects a ',' or a ';' before mgl_find_roots
As already mentioned, inclusion is not linking. You have in case 1 a file not found error and in case 2 an error in the source code.
Read this on how to include header files: Source file inclusion (or since you're using linux and geany, the compiler is presumably gcc: GNU CPP Header Files)
Try to read and understand the compiler messages.
Addendum (based on your comment)
-I plplot is a relative directory. That means, the compiler is searching in your current working directory for a directory named plplot. Either use the compiler option -I /usr/include/plplot or use the following inclusion in your source files (without the -I compiler option):
#include <plplot/the_relevant_header_file.h>
As I understand it, the 'pl...' headers are part of a third party lib (that your project depends on) and is installed e.g. by the system or make, in either case, don't pick random headers (from that project) and relocate them and try to include them from that directory. Because, the headers itself might (presumably) include other headers from that lib. In such a case, use either the -I option (not recommended) or avoid the compiler option (recommended) and include from the system path as described in my example above. The reason for that is, that from your include directive (#include <plplot/...>) you're able to see, from which library you (and not only you, but most importantly others) are including the symbols from.
I have a simple example:
#include "mruby.h"
#include <mruby/compile.h>
int main()
{
mrb_int i;
mrb_value c;
mrb_state *mrb = mrb_open();
char kod[] = "def suma(a,b) (a+b).to_i end";
if (!mrb) { /* problemy */ }
mrb_load_string(mrb, kod);
for(i=0; i<9; i++)
{
c = mrb_funcall(mrb, mrb_top_self(mrb), "suma", 2,
mrb_fixnum_value(i), mrb_fixnum_value(i));
}
mrb_close(mrb);
return 0;
}
How can I compile it in static mode, without the library libmruby.a?
I only want to add /src/*.c file(s).
I don't need Array. No file access, no other gems (time, test, sprintf, random, etc.)
Which files are important and which can I pass by?
I do not need the gem compiler. I can run only bytecode if it is possible.
How can I do this?
You must run rake in the mruby source directory. You will have produce libmruby.a in the build/host/lib directory. (in a specyfic architecture)
Next you compile your program with -I option and you link your program with -lmruby specified to the linker.
Is no possible making normal static like as lua
Is it possible to write a script to run this code for different values of A;
#include <stdio.h>
#define A 3
int main (){
printf("In this version A = %d\n", A);
return(0);
}
I guess something like for loop?
Is it possible to write a script to run this code for different values of A;
Not as it is because the macro A has a fixed value defined in your code. Instead you can pass the value as an argument:
#include <stdio.h>
int main(int argc, char **argv){
if(argc == 2) {
printf("In this version A = %s\n", argv[1]);
}
return 0;
}
(The code doesn't check if its input is an integer -- which you can test if necessary).
and you can run it via script. For example, compile the above (gcc -Wall -Wextra test.c -o test) using a for loop of bash:
$ for ((i = 0; i < 10; i++)); do ./test $i; done
In this version A = 0
In this version A = 1
In this version A = 2
In this version A = 3
In this version A = 4
In this version A = 5
In this version A = 6
In this version A = 7
In this version A = 8
In this version A = 9
$
No. But you can make A a command line arg:
#include <stdio.h>
int main (int argc, char *argv[]) {
int a;
if (argc != 2 || sscanf(argv[1], "%d", &a) != 1) return 1;
printf("In this version A = %d\n", a);
return 0;
}
Compile to a binary named foo, then
foo 42
will print
In this version A = 42
You can also compile different versions by defining A in the compilation command line. From your original program, remove the #define. Then
gcc -DA=42 foo.c -o foo
./foo
will print the same as above.
DO you need run program repeated from script? why not to make program that accepts arguments from command line?
1)The main() function actually takes arguments, you can compile program once and pass different parameters, as shown in answers above
2) If you need to change some code parameters from make script, I'd say, create separate header that would contain defines and write script that would echo into that file (> for start, >> to continue writing).
3) Alternative way you can call you compiler with flag that would be equal to #define macro-command. For gcc it's -D, for example -DA=3 instead of #define A 3.
Most programs use makefile to be compiled. For that case you can script make file to use 2) or 3) Former is preferable because you do not need to pass that argument to all compilation targets, reducing time or re-compiling. There are tools for more advanced manipulations, like autoconf.
I need to find the built-in functions used in our program from a specific header file.
For example, I have the C file below:
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
printf("a = %d\n", a);
}
If I given the stdio.h header file to any command, it needs to give the output as below:
scanf
printf
Is there any built-in command to get this?
Or any options available in the gcc or cc command to get this?
If you are using GCC as compiler, you can run this command:
echo "#include <stdio.h>" | gcc -E -
This will print many lines from the stdio.h header, and from the files that are included by that header, and so on.
Some lines look like #line …, they tell you where the following lines come from.
You can analyze these lines, but extracting the functions from them (parsing) is quite complicated. But if you just want a quick, unreliable check, you could search whether these lines contain the word scanf or printf.
EDIT
As suggested in a comment, the -aux-info is more useful, but it works only when compiling a file, not when preprocessing. Therefore:
cat <<EOF >so.c
#include <stdio.h>
int main(int argc, char **argv) {
for (int i = 1; i < argc; i++) {
fprintf(stdout, "%s%c", argv[i], i < argc - 1 ? ' ' : '\n');
}
fflush(stdout);
return ferror(stdout) == -1;
}
EOF
gcc -c so.c -aux-info so.aux
Determining the function calls from your program can be done using objdump, as follows:
objdump -t so.c
The above commands give you the raw data. You still need to parse this data and combine it to only give you the data relevant to your question.
What is the simplest possible C function for starting the R interpreter, passing in a small expression (eg, 2+2), and getting out the result? I'm trying to compile with MingW on Windows.
You want to call R from C?
Look at section 8.1 in the Writing R Extensions manual. You should also look into the "tests" directory (download the source package extract it and you'll have the tests directory). A similar question was previously asked on R-Help and here was the example:
#include <Rinternals.h>
#include <Rembedded.h>
SEXP hello() {
return mkString("Hello, world!\n");
}
int main(int argc, char **argv) {
SEXP x;
Rf_initEmbeddedR(argc, argv);
x = hello();
return x == NULL; /* i.e. 0 on success */
}
The simple example from the R manual is like so:
#include <Rembedded.h>
int main(int ac, char **av)
{
/* do some setup */
Rf_initEmbeddedR(argc, argv);
/* do some more setup */
/* submit some code to R, which is done interactively via
run_Rmainloop();
A possible substitute for a pseudo-console is
R_ReplDLLinit();
while(R_ReplDLLdo1() > 0) {
add user actions here if desired
}
*/
Rf_endEmbeddedR(0);
/* final tidying up after R is shutdown */
return 0;
}
Incidentally, you might want to consider using Rinside instead: Dirk provides a nice "hello world" example on the project homepage.
In you're interested in calling C from R, here's my original answer:
This isn't exactly "hello world", but here are some good resources:
Jay Emerson recently gave a talk on R package development at the New York useR group, and he provided some very nice examples of using C from within R. Have a look at the paper from this discussion on his website, starting on page 9. All the related source code is here: http://www.stat.yale.edu/~jay/Rmeetup/MyToolkitWithC/.
The course taught at Harvard by Gopi Goswami in 2005: C-C++-R (in Statistics). This includes extensive examples and source code.
Here you go. It's the main function, but you should be able to adapt it to a more general purpose function. This example builds an R expression from C calls and also from a C string. You're on your own for the compiling on windows, but I've provided compile steps on linux:
/* simple.c */
#include <Rinternals.h>
#include <Rembedded.h>
#include <R_ext/Parse.h>
int
main(int argc, char *argv[])
{
char *localArgs[] = {"R", "--no-save","--silent"};
SEXP e, tmp, ret;
ParseStatus status;
int i;
Rf_initEmbeddedR(3, localArgs);
/* EXAMPLE #1 */
/* Create the R expressions "rnorm(10)" with the R API.*/
PROTECT(e = allocVector(LANGSXP, 2));
tmp = findFun(install("rnorm"), R_GlobalEnv);
SETCAR(e, tmp);
SETCADR(e, ScalarInteger(10));
/* Call it, and store the result in ret */
PROTECT(ret = R_tryEval(e, R_GlobalEnv, NULL));
/* Print out ret */
printf("EXAMPLE #1 Output: ");
for (i=0; i<length(ret); i++){
printf("%f ",REAL(ret)[i]);
}
printf("\n");
UNPROTECT(2);
/* EXAMPLE 2*/
/* Parse and eval the R expression "rnorm(10)" from a string */
PROTECT(tmp = mkString("rnorm(10)"));
PROTECT(e = R_ParseVector(tmp, -1, &status, R_NilValue));
PROTECT(ret = R_tryEval(VECTOR_ELT(e,0), R_GlobalEnv, NULL));
/* And print. */
printf("EXAMPLE #2 Output: ");
for (i=0; i<length(ret); i++){
printf("%f ",REAL(ret)[i]);
}
printf("\n");
UNPROTECT(3);
Rf_endEmbeddedR(0);
return(0);
}
Compile steps:
$ gcc -I/usr/share/R/include/ -c -ggdb simple.c
$ gcc -o simple simple.o -L/usr/lib/R/lib -lR
$ LD_LIBRARY_PATH=/usr/lib/R/lib R_HOME=/usr/lib/R ./simple
EXAMPLE #1 Output: 0.164351 -0.052308 -1.102335 -0.924609 -0.649887 0.605908 0.130604 0.243198 -2.489826 1.353731
EXAMPLE #2 Output: -1.532387 -1.126142 -0.330926 0.672688 -1.150783 -0.848974 1.617413 -0.086969 -1.334659 -0.313699
I don't think any of the above has answered the question - which was to evaluate 2 + 2 ;). To use a string expression would be something like:
#include <Rinternals.h>
#include <R_ext/Parse.h>
#include <Rembedded.h>
int main(int argc, char **argv) {
SEXP x;
ParseStatus status;
const char* expr = "2 + 2";
Rf_initEmbeddedR(argc, argv);
x = R_ParseVector(mkString(expr), 1, &status, R_NilValue);
if (TYPEOF(x) == EXPRSXP) { /* parse returns an expr vector, you want the first */
x = eval(VECTOR_ELT(x, 0), R_GlobalEnv);
PrintValue(x);
}
Rf_endEmbeddedR(0);
return 0;
}
This lacks error checking, obviously, but works:
Z:\>gcc -o e.exe e.c -IC:/PROGRA~1/R/R-213~1.0/include -LC:/PROGRA~1/R/R-213~1.0/bin/i386 -lR
Z:\>R CMD e.exe
[1] 4
(To get the proper commands for your R use R CMD SHLIB e.c which gives you the relevant compiler flags)
You can also construct the expression by hand if it's simple enough - e.g., for rnorm(10) you would use
SEXP rnorm = install("rnorm");
SEXP x = eval(lang2(rnorm, ScalarInteger(10)), R_GlobalEnv);
I think you can't do much better than the inline package (which supports C, C++ and Fortran):
library(inline)
fun <- cfunction(signature(x="ANY"),
body='printf("Hello, world\\n"); return R_NilValue;')
res <- fun(NULL)
which will print 'Hello, World' for you. And you don't even know where / how / when the compiler and linker are invoked. [ The R_NilValue is R's NULL version of a SEXP and the .Call() signature used here requires that you return a SEXP -- see the 'Writing R Extensions' manual which you can't really avoid here. ]
You will then take such code and wrap it in a package. We had great success with using
inline for the
Rcpp unit tests (over 200 and counting now) and some of the examples.
Oh, and this inline example will work on any OS. Even Windoze provided you have the R package building tool chain installed, in the PATH etc pp.
Edit: I misread the question. What you want is essentially what the littler front-end does (using pure C) and what the RInside classes factored-out for C++.
Jeff and I never bothered with porting littler to Windoze, but RInside did work there in most-recent release. So you should be able to poke around the build recipes and create a C-only variant of RInside so that you can feed expression to an embedded R process. I suspect that you still want something like Rcpp for the clue as it gets tedious otherwise.
Edit 2: And as Shane mentions, there are indeed a few examples in the R sources in tests/Embedding/ along with a Makefile.win. Maybe that is the simplest start if you're willing to learn about R internals.