I'm new to configure.ac, I'm trying to create a simple program that would only use the GNU guile library if the user invokes:
configure --with-guile
so the program would be something like:
#include "config.h"
#include <stdio.h>
#ifdef HAVE_GUILE
#include <libguile.h>
#endif
int main(int argc,char** argv) {
#ifdef HAVE_GUILE
printf("Guile supported\n");
scm_init_guile();
#else
printf("Guile not supported\n");
#endif
return 0;
}
GNU guile uses guile-config compile and guile-config link to obtain the path to the include directory and the libraries. I've not found a tutorial where the paths above are obtained via an external program.
So far my `configure.ac` is
AC_INIT(program, 1.0)
AC_PROG_CC
AC_CONFIG_HEADERS(config.h)
with_guile=no
AC_ARG_WITH(guile, [AS_HELP_STRING([--with-guile], [use gnu guile])],[],[with_guile=yes])
if test "x$with_guile" != no
then
AC_MSG_CHECKING(for Guile)
guile-config link > /dev/null || {
echo "configure: cannot find guile-config; is Guile installed?" 1>&2
exit 1
}
CFLAGS="$CFLAGS `guile-config compile`"
LDFLAGS="$LDFLAGS `guile-config link`"
AC_DEFINE([HAVE_GUILE],[1],[Guile supported])
#PKG_CHECK_MODULES([GUILE],[guile-2.0])
#AC_CHECK_HEADERS([libguile.h], [], [AC_MSG_ERROR([guile include files not found])])
#AC_CHECK_LIB([guile], [scm_with_guile], [AC_MSG_ERROR([guile library files not found])])
fi
dnl Process Makefile.in to create Makefile
AC_OUTPUT(Makefile)
I've removed AC_CHECK_HEADERS and AC_CHECK_LIB because they doesn't work (the files are not found).
Here I'm lost: how can I add the guile paths to CFLAGS and LDFLAGS, how can I generate HAVE_GUILE in config.h
current Makefile.in:
CC=#CC#
LD=#CC#
program: program.o
$(LD) -o $# $^
.PHONY: clean
clean:
rm -f program *.o
configure.ac:
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_ARG_WITH(guile, [AS_HELP_STRING([--with-guile], [use gnu guile])],
[with_guile=yes],[with_guile=no])
AS_IF([test "x$with_guile" = xyes],
[AC_CHECK_PROG([GUILE_CONFIG],[guile-config],[guile-config])
AS_IF([test -z "$GUILE_CONFIG"],[AC_MSG_FAILURE([cannot find guile-config])])
CFLAGS="$CFLAGS `$GUILE_CONFIG compile`"
LDFLAGS="$LDFLAGS `$GUILE_CONFIG link`"
AC_DEFINE([HAVE_GUILE],[1],[Guile supported])])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
is more typical. I used a Makefile.am instead of what you did:
Makefile.am:
bin_PROGRAMS = program
program_SOURCES = src/main.c
which is more typical also.
config.h has:
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Guile supported */
#define HAVE_GUILE 1
...
Makefile has:
...
CFLAGS = -g -O2 -pthread -I/usr/include/guile/2.0
...
LDFLAGS = -lguile-2.0 -lgc
Related
I'm trying to follow the check tutorial here to try and setup a test suite. My project structure is like
root
|-----src
|----- foo.h, foo.c
test
|----- root_test.h, root_test.c, foo_test.c
Makefile.am
configure.ac
My foo.h:
#ifndef FOO_H
#define FOO_H
int func();
#endif
foo.c:
#include "foo.h"
int func() { return 0; }
root_test.h:
#ifndef ROOT_TEST_H
#define ROOT_TEST_H
#include <check.h>
Suite *foo_suite();
#endif
root_test.c:
#include <check.h>
#include <stdlib.h>
#include "root_test.h"
int main() {
int fc;
SRunner *sr;
sr = srunner_create(foo_suite());
srunner_run_all(sr, CK_NORMAL);
fc = srunner_ntests_failed(sr);
srunner_free(sr);
return fc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
foo_test.c:
#include <check.h>
#include "../src/foo.h"
#include "root_test.h"
START_TEST(foo_func) { ck_assert_int_eq(func(), 0); }
END_TEST
Suite *foo_suite() {
Suite *s;
TCase *tc;
s = suite_create("Foo");
tc = tcase_create("Core");
tcase_add_test(tc, foo_func);
suite_add_tcase(s, tc);
return s;
}
My Makefile.am:
ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libroot.la
HFILES =\
src/foo.h
CFILES =\
src/foo.c
libroot_la_SOURCES = $(HFILES) $(CFILES)
TESTS = libroot_test
check_PROGRAMS = libroot_test
libroot_test_SOURCES = $(HFILES) test/root_test.h test/root_test.c test/foo_test.c
libroot_test_CFLAGS = #CHECK_CFLAGS#
libroot_test_LDADD = libroot.la #CHECK_LIBS#
noinst_PROGRAMS = libroot_test
and my configure.ac:
AC_PREREQ([2.71])
AC_INIT([libroot], [0.0.1], [swdon#users.noreply.github.com])
AC_CONFIG_AUX_DIR([build])
AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_SRCDIR([src/foo.h])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AM_PROG_AR
LT_INIT
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
My autoreconf -i and ./configure run without any issues. When I run make check I get the following output with error:
/bin/sh ./libtool --tag=CC --mode=link gcc #CHECK_CFLAGS# -g -O2 -o libroot_test test/libroot_test-libroot_test.o test/libroot_test-foo_test.o libroot.la #CHECK_LIBS#
libtool: link: gcc #CHECK_CFLAGS# -g -O2 -o .libs/libroot_test test/libroot_test-libroot_test.o test/libroot_test-foo_test.o #CHECK_LIBS# ./.libs/libroot.so -Wl,-rpath -Wl,/usr/local/lib
/usr/bin/ld: cannot find #CHECK_CFLAGS#: No such file or directory
/usr/bin/ld: cannot find #CHECK_LIBS#: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:687: libroot_test] Error 1
The #CHECK_CFLAGS# and #CHECK_LIBS# strings appearing in your Makefile.am are placeholders for the values of Autoconf output variables, but your original configure.ac does not contain anything that would set such output variables. As a result, the placeholders are carried through unchanged to generated makefiles, where they cause builds to fail with the observed error.
The Check documentation contains a section about integrating libcheck with Autotools-based build systems. Its recommendation is to use the the PKG_CHECK_MODULES provided by pkg-config. For example,
# ...
# Checks for libraries.
PKG_CHECK_MODULES([CHECK], [check >= 0.9.6])
# ...
The second macro parameter specifies the minimum acceptable version of Check, and it may be omitted if you do not wish to specify a minimum version.
Note also that older versions of PKG_CHECK_MODULES do not automatically make the relevant variables Autoconf output variables. If you were saddled with such a version and were unable to update, then you would also want to add
AC_SUBST([CHECK_CFLAGS])
AC_SUBST([CHECK_LIBS])
after PKG_CHECK_MODULES.
If you do not have pkg-config or do not want your package build to rely on it then there is also an AM_PATH_CHECK() macro provided by Check itself that can serve the purpose. That macro is deprecated, however, and therefore may be removed from some future version of Check. Refer to the documentation for more information on this macro.
Okay, so I added the AM_PATH_CHECK to my configure.ac and it's working now. My updated configure.ac:
AC_PREREQ([2.71])
AC_INIT([libccg],[0.0.1],[smadurange#users.noreply.github.com])
AC_CONFIG_AUX_DIR([build])
AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_SRCDIR([src/foo.h])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AM_PROG_AR
AM_PATH_CHECK
LT_INIT
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
error log
paging.c: In function ‘setup_paging_structures’:
paging.c:7: warning: implicit declaration of function ‘printf’
rm -f bootimg
gcc -nostdlib -static boot.o paging.o x86_desc.o i8259.o kernel.o lib.o paging.o tests.o -Ttext=0x400000 -o bootimg
paging.o: In function `setup_paging_structures':
/workdirmain/work/mp3_group_31/student-distrib/paging.c:4: multiple definition of `setup_paging_structures'
paging.o:/workdirmain/work/mp3_group_31/student-distrib/paging.c:4: first defined here
paging.o: In function `initialize_paging':
/workdirmain/work/mp3_group_31/student-distrib/paging.c:13: multiple definition of `initialize_paging'
paging.o:/workdirmain/work/mp3_group_31/student-distrib/paging.c:13: first defined here
collect2: ld returned 1 exit status
make: *** [bootimg] Error 1
Here's what my paging.h file looks like:
#ifndef _PAGING_H
#define _PAGING_H
#include "types.h"
#define TOTAL_ENTRIES 1024
extern void setup_paging_structures();
extern void initialize_paging();
#endif
Paging.c below:
#include "paging.h" //include header files
void setup_paging_structures(){
int i;
for (i = 0; i < TOTAL_ENTRIES; i++){
printf("weird");
}
return;
}
void initialize_paging(){
setup_paging_structures();
return;
}
Note, I have not called the functions yet.
The command I'm using is "sudo make" (Makefile was given to me. I'm pretty sure I'm not supposed to modify it):
# Makefile for OS project
# To build, first `make dep`, them `make`. Everything should be automatic.
# Will compile all *.c and *.S files in the current directory.
# Flags to use when compiling, preprocessing, assembling, and linking
CFLAGS+=-Wall -fno-builtin -fno-stack-protector -nostdlib
ASFLAGS+=
LDFLAGS+=-nostdlib -static
CC=gcc
#If you have any .h files in another directory, add -I<dir> to this line
CPPFLAGS+=-nostdinc -g
# This generates the list of source files
SRC=$(wildcard *.S) $(wildcard *.c) $(wildcard */*.S) $(wildcard */*.c)
# This generates the list of .o files. The order matters, boot.o must be first
OBJS=boot.o
OBJS+=$(filter-out boot.o,$(patsubst %.S,%.o,$(filter %.S,$(SRC))))
OBJS+=$(patsubst %.c,%.o,$(filter %.c,$(SRC)))
bootimg: Makefile $(OBJS)
rm -f bootimg
$(CC) $(LDFLAGS) $(OBJS) -Ttext=0x400000 -o bootimg
sudo ./debug.sh
dep: Makefile.dep
Makefile.dep: $(SRC)
$(CC) -MM $(CPPFLAGS) $(SRC) > $#
.PHONY: clean
clean:
rm -f *.o */*.o Makefile.dep
ifneq ($(MAKECMDGOALS),dep)
ifneq ($(MAKECMDGOALS),clean)
include Makefile.dep
endif
endif
edit: I added updates to my post including the actual directories, the entire error log, and the contents of the Makefile I am using. This is also for a class that I'm currently taking, hence some of the things that were automatically given to me.
I am trying to compile a minimal test shared library in FreeBSD using:
FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1)
Target: x86_64-unknown-freebsd12.0
Thread model: posix
InstalledDir: /usr/bin
test.c
#include "test.h"
int SampleFunction(int a, int b)
{
return a * b;
}
test.h
#ifndef TESTLIB_H
#define TESTLIB_H
extern int SampleFunction(int a, int b);
#endif
Makefile
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CC = cc
testlib: $(TEST_OBJS)
$(CC) -fpic -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
Output:
$ make testlib
cc -O2 -pipe -c test.c -o test.o
cc -fpic -o test.so test.o
/usr/bin/ld: error: undefined symbol: main
>>> referenced by crt1.c:76 (/usr/src/lib/csu/amd64/crt1.c:76)
>>> /usr/lib/crt1.o:(_start)
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1
Stop.
make: stopped in /usr/home/user/testlib
As well as adding -shared to the linker stage (as mentioned by Oo.oO), you probably also want to compile with the -fPIC flag as well. So if you are using the makefile implicit rules for the compiling (looks like you are) then you will probably want to add that flag to CFLAGS. I don't think you need it for the linking stage:
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CFLAGS += -fPIC
CC = cc
testlib: $(TEST_OBJS)
$(CC) -shared -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
I prefer using the OS-provided bsd.lib.mk for such building libraries. The following should do the right thing -- whatever it may be:
SHLIB_NAME= testlib
SRCS= test.c
.include <bsd.lib.mk>
(For building executables there is bsd.prog.mk, BTW.)
So here is my Makefile:
# My First Makefile
HEADERS = stdio.h
all: main.o input.o output.o
cc -o all main.o input.o output.o
main.o: main.c $(HEADERS)
cc -c main.c -o main.o
input.o: input.c $(HEADERS)
cc -c input.c -o input.o
output.o: output.c $(HEADERS)
cc -c output.c -o output.o
clean:
-rm -f *.o
-rm -f all
And below is input.c:
#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
void getChar()
{
getchar();
}
#endif
Below is output.c:
#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
void putChar(char c)
{
putchar(c);
}
#endif
Below is main.c:
#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
int main()
{
char c;
while ((c = etChar()) != '\n')
{
putChar(c);
}
}
#endif
Yet whenever I press "make" command in Terminal,
I get:
make: *** No rule to make target `stdio.h', needed by `main.o'. Stop.
cc refers to clang
What is it that I am doing wrong here?
I was trying to get used to $(ARGS) by using $(HEADERS)
but it seems that the clang compiler does not accept this.
Do you think I should use gcc instead?
It is unnecessary to write stdio.h in your Makefile. GCC will automatically search it in DEFAULT PATH (/usr/include, ....). Write header files as targes in Makefile only if you use your own header files.
# Makefile
# define CC
CC := gcc
# define final targets
TARGETS := main
# just trigger $(TARGETS)
all: $(TARGETS)
# build main from main.o, input.o, output.o
main: main.o input.o output.o
$(CC) -o $# $^
# build main.o/input.o/output.c from main.c/input.c/output.c
%.o: %.c
$(CC) -c -o $# $<
# trigger $(TARGETS), then run ./main
run: $(TARGETS)
./main
clean:
-rm $(TARGETS)
-rm *.o
# define targets which are not bound to file
.PHONY: all clean run
In your case:
"make" will look for stdio.h in the current directory, and is complaining that the header is not found.
Just to fix this, you should mention the full path where stdio.h is located, for example:
HEADERS = /usr/include/stdio.h
Ideally, if you want to check for the presence of standard headers like stdio.h, you should use tools like automake and autoconf, which generate the Makefile automatically. Here's a link which points to the autoconf documentation:
https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html
I have two .c files that both have mains. One of the files has a function that I would like to use in the other main. Is it possible to reference this other function without copying and pasting it into the other .c file?
No you don't need to copy and paste, suppose you have this
program-one.c
First program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_one_stuff();
common_function();
return 0;
}
program-two.c
Second program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_two_stuff();
common_function();
return 0;
}
You need a third .c file and a .h file, like this
common.c
Common Functions Implementation.
void common_function()
{
/* Do it here */
}
common.h
Common Functions Header.
void common_function();
You now can compile a single binary for each program consisting of two files, the program specific .c file and common.c.
The right way to do it is to have a Makefile and generate object code first, and then link the object files togeather, thus compiling each file only once.
Makefile
This is a GNU make Makefile using gcc as the compiler.
CC = gcc
CFLAGS = -Wall -Wextra -Werror -g3 -O0 # enable debug symbols and warnings
LDFLAGS = # linker flags here ...
OBJ = common.o program-one.o program-two.o
all:
$(CC) $(LDFLAGS) common.o program-one.o -o program-one
$(CC) $(LDFLAGS) common.o program-two.o -o program-two
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
#rm -fv *.o program-one program-two
EDIT: in response to your comment I would suggest the following
#define main ignore /* Or whatever name you want */
#include "the-student-implementation.c"
#undef main
int main(void)
{
/* This would be your `main()' */
return 0;
}
The best solution is what iharob suggested, but if for some reason that isn't possible, you could surround the main() in the file containing the common function with #ifdef USE_MAIN, then only define the USE_MAIN identifier in the command to build that project. When you build the other project that doesn't have USE_MAIN defined, the preprocessor will cause the second main() to be skipped, so the compiler won't be confused.
But unless this is really needed, I highly recommend splitting this into three files: main1.c, main2.c, and common.c/common.h