Makefile Mix for C and C++


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Makefile Mix for C and C++
# 1  
Old 09-19-2012
Makefile Mix for C and C++

Hi everyone,
I'm new in this forum. I hope you could help me with this code.
I'm trying to include in an ANSI C project, some (OpenCV) libraries made in C++.
When I included those libraries, the compiler threw the following error:

ardrone_testing_tool.c: (.text+0x1212) : undefined reference to `cvSURFParams'
ardrone_testing_tool.c: (.text+0x126f) : undefined reference to `cvExtractSURF'


Basically people told me to change the compiler to the g++ (if anyone think about a better solution, please tell me. However, I think I'll have to edit the Makefile of the project...). The main Makefile of the project uses some standard variables like MAKE, which calls recursively another makefile, in the folder VP_SDK/Build.

In that folder, the other makefile has some sections which calls again another makefiles to configure variables and so on. Finally it calls generic.makefile which sets the compiler and does the compilation.
The point is that now, when I changed the word gcc by g++ the compilation didn't work (the original version which had worked with the gcc).
The error that it gives is the following:

../../VLIB/video_codec.c: In function ‘int video_codec_open_private(video_controller_t*, codec_type_t, int32_t)':
../../VLIB/video_codec.c:75: error: invalid conversion from ‘void*' to ‘video_macroblock_t*'
../../VLIB/video_codec.c: In function ‘int video_codec_type_select(video_controller_t*, video_stream_t*)':
../../VLIB/video_codec.c:190: error: invalid conversion from ‘uint32_t' to ‘codec_type_t'
../../VLIB/video_codec.c:190: error: initializing argument 2 of ‘int video_codec_open_private(video_controller_t*, codec_type_t, int32_t)'
../../VLIB/video_codec.c: In function ‘int video_encode_picture(video_controller_t*, const vp_api_picture_t*, int32_t*)':
../../VLIB/video_codec.c:198: error: invalid conversion from ‘int' to ‘PixelFormat'
../../VLIB/video_codec.c: In function ‘int video_decode_picture(video_controller_t*, vp_api_picture_t*, video_stream_t*, int32_t*)':
../../VLIB/video_codec.c:237: error: invalid conversion from ‘int' to ‘PixelFormat'


That is, an error previously hadn't detected by the gcc.
So, I think maybe I should differentiate in the code the treatment of .cpp files and the other files.

Below in the post you will see some parts of the code. In the macro INTERNAL_SOURCE_EXTENSIONS, there are defined the extensions .c .S .s .cpp. You can see also that there are some other macros that depend on that... For example INTERNAL_BINARIES_COMMON_TARGET_OFILES, which after is used to do different things (and compilation of course).
Anyway, I'm thinking of doing something like duplicating some macros, to do the compilation in two parts (on one side .c .S .s and on the other .cpp).
I don't know much about makefiles, so I would like to know what do you think about that. Is that convinient to do? There is another better or easier way to make it work?
Here I show you some lines of the file generic.makefile, but I could put all the code if you think is necessary.
I will be really appreciated if you give me some help. May be for some of you is not quite difficult to see the changes that has to be made in the complete version of the code.

Code:
INTERNAL_SOURCE_EXTENSIONS= .c .S .s .cpp

INTERNAL_MKDIR=mkdir -p
INTERNAL_ECHO=echo

# (in) GENERIC_COMMAND_PREFIX
INTERNAL_CC:=$(GENERIC_COMMAND_PREFIX)gcc
INTERNAL_AR:=$(GENERIC_COMMAND_PREFIX)ar
INTERNAL_OBJCOPY:=$(GENERIC_COMMAND_PREFIX)objcopy
INTERNAL_STRIP:=$(GENERIC_COMMAND_PREFIX)strip

# (in) GENERIC_CFLAGS    # (in) GENERIC_LDFLAGS
# (in) GENERIC_ARFLAGS     # (in) GENERIC_INCLUDES
# (in) GENERIC_ADD_OFILES : for linking with     # (in) GENERIC_LIBRARY_SOURCE_DIR
# (in) GENERIC_LIBRARY_SOURCE_FILES     # (in) GENERIC_LIBRARY_TARGET_DIR : for .o files
INTERNAL_LIBRARY_SOURCE_FILES:=$(patsubst %,$(GENERIC_LIBRARY_SOURCE_DIR)/%,$(GENERIC_LIBRARY_SOURCE_FILES))
INTERNAL_LIBRARY_TARGET_OFILES:=$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),\
	$(patsubst $(GENERIC_LIBRARY_SOURCE_DIR)/%$(ext),$(GENERIC_LIBRARY_TARGET_DIR)/%.o,$(filter %$(ext),$(INTERNAL_LIBRARY_SOURCE_FILES))))

# (in) GENERIC_BINARIES_SOURCE_DIR   # (in) GENERIC_BINARIES_COMMON_SOURCE_FILES   # (in) GENERIC_BINARIES_SOURCE_ENTRYPOINTS    # (in) GENERIC_BINARIES_TARGET_DIR : for .o files

INTERNAL_BINARIES_COMMON_SOURCE_FILES:=$(patsubst %,$(GENERIC_BINARIES_SOURCE_DIR)/%,$(GENERIC_BINARIES_COMMON_SOURCE_FILES))
INTERNAL_BINARIES_COMMON_TARGET_OFILES:=$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),\
	$(patsubst $(GENERIC_BINARIES_SOURCE_DIR)/%$(ext),$(GENERIC_BINARIES_TARGET_DIR)/%.o,$(filter %$(ext),$(INTERNAL_BINARIES_COMMON_SOURCE_FILES))))
INTERNAL_BINARIES_TARGET_OENTRYPOINTS:=$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),\
	$(patsubst %$(ext),$(GENERIC_BINARIES_TARGET_DIR)/%.o,$(filter %$(ext),$(GENERIC_BINARIES_SOURCE_ENTRYPOINTS))))

===================================

Code:
ifeq ($(USE_DLL),yes)
	$(GENERIC_COMMAND_PREFIX)dlltool -e $(GENERIC_TARGET_BINARIES_DIR)/$(DLL_ID)_exports.o --export-all-symbols -l $(@:.dll=.lib) $(INTERNAL_BINARIES_COMMON_TARGET_OFILES)
	$(INTERNAL_CC) --shared -o $@ $(INTERNAL_BINARIES_COMMON_TARGET_OFILES) $(GENERIC_TARGET_BINARIES_DIR)/$(DLL_ID)_exports.o $(GENERIC_ADD_OFILES) $(GENERIC_LIB_PATHS) $(GENERIC_LIBS) $(GENERIC_LDFLAGS) $(LDFLAGS_$(subst /,_,$*))
	$(RM) $(GENERIC_TARGET_BINARIES_DIR)/$(DLL_ID)_exports.o
  else
	$(INTERNAL_CC) -o $@ $(GENERIC_BINARIES_TARGET_DIR)/$*.o $(INTERNAL_BINARIES_COMMON_TARGET_OFILES) $(GENERIC_ADD_OFILES) $(GENERIC_LIB_PATHS) $(GENERIC_LIBS) $(GENERIC_LDFLAGS) $(LDFLAGS_$(subst /,_,$*))
  endif

===================================

Code:
# Build rules for each extension
$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),$(eval $(call BUILD_OFILE_TEMPLATE,LIBRARY,$(ext))))
$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),$(eval $(call BUILD_OFILE_TEMPLATE,BINARIES,$(ext))))

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),check)
  -include $(INTERNAL_LIBRARY_DEPFILES) $(INTERNAL_BINARIES_DEPFILES)
endif
endif

Thank You all for any comments that you could give me.

Best Regards,

Hernán.
# 2  
Old 09-19-2012
When you want to reference C++ variables in C, you must declare them in C using the wrapper "extern C++ { . . . }", even by way of include file #include lines, and vice-versa with "extern C { . . . }". C++ names are mangled to indicate the type returned and, if method/subroutine/function, the number and types of arguments, for stricter type checking. The original C++ compilers were just preprocessors for the C compiler. If you look at some object code (executables and libraries) using nm, you will see the mangled names of C++ identifiers.

Your make rules need to point to different compiler commands and arguments, using different variables, e.g., not swapping CC from gcc to g++. Sometimes it simplifies things if you use a different directory, or ensure even include files have different suffixes for c++. Try not to make whole new compile lines for every file, but just modify a variable referenced in the common line for moving from one extension to the next. If object file order on linking line is getting to be a pain, remember that code is library files, static or dynamic, is not order sensitive. Even main() can be in a library if all the code in the library serves that main. One class per include file and one subroutine/method/class per non-include file, all compiled -c and non-main() .o put in libraries, is a good practice.

Last edited by DGPickett; 09-19-2012 at 11:47 AM..
# 3  
Old 09-20-2012
Thank you DGPickett for your answer.
I've been looking for the use of extern in ANSI C, and I tried several ways to code it:
Code:
extern "C++" {
      #include <opencv2/features2d/features2d.hpp>
}

But it didn't work (the compiler threw errors because of the quotation marks or the braces... I changed them by parenthesis and simple quotation marks, but It didn't work. After I found a post (*) that say that C does not define linkage to any other language (but C++ does).
So I tried with extern "C" in the c++ library, but when I compiled it threw the same compilation error...

ardrone_testing_tool.c: (.text+0x1212) : undefined reference to `cvSURFParams'
ardrone_testing_tool.c: (.text+0x126f) : undefined reference to `cvExtractSURF'


In that link, they say also that I could try with the compiler g++ (I should fix the errors I put in the last post).
What do you think about that?

Concerning the compiler, you mean to take out '.cpp' in INTERNAL_SOURCE_EXTENSIONS, and after put the .hpp file in a separated folder and call the g++ just for that folder and generate the .o ?
How can I put all the .o files all together ?

Is it OK what I'm saying? Sorry if I'm saying something that is wrong, I started just some days ago with the GNU makefile.

Thanks a lot.

(*) The forum does not allow to put links before 5 posts. Write on google "linking a C++ library to a C program" bytes
# 4  
Old 09-20-2012
What are you actually trying to do? Are you attempting to use C++ classes inside C(C doesn't have classes), or just use some external functions from C++ code?

Are you actually compiling the library, too? Perhaps you could modify it to export C symbols. That'd be simpler and more portable than trying to import C++ ones. If it's exporting functions rather than classes, it really should export them with C linkage anyway, since that'd make the library equally usable in C++ and C.
# 5  
Old 09-20-2012
extern "C" - C++ Forum

On all C++ compilers, extern "C" {} turns off mangling so C++ can call C. You use it in the C++ files only, to call C functions that have no C++ versions, i.e., when necessary.

Newer C compilers can mangle names and call C++ functions, if you declare them with extern "C++" in the C files only.

cc -c compiles something.c into (usually) something.o, an unlinked object file. If you want to link to static library somelib.a or prepare it to run-time link to dynamic library somelib.so, a second pass of cc -o something, or an internal second pass if no -c, links (actually using ld) the .o and library stuff together to an exec() friendly executable object file. Static libraries are archves from ar of *.o files, and ld copies the relevant parts of them into the statically linked executable. Dynamic libraries can be made for static ones, perhaps internally linking modules that call each other, and of course geting a new suffix and magic. Dynamic executable files just have stubs to allow a call to ld() at run time to find .so libraries in the original or $LD_LIBRARY_PATH directories, mmap() them into the memory space of the process, and set pointers to the mapped parts. All running copies of 'something' use the same *.so file mapped into the same RAM pages, except for initialized modifiable variables, which are often just initialization constants and a spec for variable space, so non-variable parts can be mapped into read-only pages. Statically linked copies of something *might* all use separate RAM copies of the code, if exec() does not use mmap(), and they roll out on separate parts of swap. Dynamic is especially wise when many programs use the same calls, so they use the same RAM & cache, and not so much swap. For instance, most C programs use libc, so it is linked by default. In dynamic mode, all C programs use the same libc.so mapped in the same RAM pages. If your dynamically linked executable goes to machines with a too different libc.so, they fail. Static linking means that never happens. Dynamic linking is for real men! Smilie You can ensure the right libraries are found with $LD_LIBRARY_PATH, just the same way you might control where 'cc' is found using $PATH.

BTW, set-uid and set-gid executables unset the $LD_LIBRARY_PATH so you need to compile them without moving the .so from run time, and often with a cc option like -R to burn in fixed library paths at compile time. This is why it is so hard to write a set-uid script -- interpreter cannot link. You have to write your own fixed path interpreter wrapper!
Login or Register to Ask a Question

Previous Thread | Next Thread

8 More Discussions You Might Find Interesting

1. AIX

Mix LDAP and LOCAL user on AIX

Hello, I'm currently trying to mix local and LDAP users on an AIX 7.1. I've triied many things. My LDAP Server in on a CentOS - OpenLDAP (which works fine with linux). I'm currently stuck on AIX at how to declare LDAP AND Local users. Here's what i did : /usr/sbin/mksecldap -c -h 'ldap03'... (15 Replies)
Discussion started by: AIX_user_324891
15 Replies

2. Programming

makefile for mix of C and C++ modules

I am trying to come up with a makefile where the target is linked with object files produced by C and C++ sources. My setup is Ubuntu/gcc: $ uname -a Linux srvr1 2.6.24-24-server #1 SMP Fri Sep 18 17:24:10 UTC 2009 i686 GNU/Linux gcc version 4.2.4 $ cat main.cpp #include <iostream>... (6 Replies)
Discussion started by: migurus
6 Replies

3. Homework & Coursework Questions

Help with Simple Multi-Level Makefile (Extremely New at Makefile)

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted! 1. The problem statement, all variables and given/known data: Basically, the prompt is make a makefile with various sub makefiles in their respective subdirectories. All code... (1 Reply)
Discussion started by: Tatl
1 Replies

4. Shell Programming and Scripting

How to mix the contents of 2 files into a new file?

Hello Everybody! My question is how can I mix for example file_a with file_b in the following method: After 2 lines of file_a put 2 lines from file_b to file_c. For example: file_a: 1 2 3 4 5 6 file_b: 11 22 (7 Replies)
Discussion started by: Levi85
7 Replies

5. Solaris

ZFS Pool Mix-up

Hi all I plan to install Solaris 10U6 on some SPARC server using ZFS as root pool, whereas I would like to keep the current setup done by VxVM: - 2 internal disks: c0t0d0 and c0t1d0 - bootable root-volume (mirrored, both disks) - 1 non-mirrored swap slice - 1 non-mirrored slices for Live... (1 Reply)
Discussion started by: blicki
1 Replies

6. UNIX for Advanced & Expert Users

Makefile problem - How to run module load in a Makefile

Hi, I'm trying to run the module load command in a Makefile and i'm getting the following error: make: module: command not found Why is this? Is there any way to run this command in a Makefile? NOTE: command - module load msjava/sunjdk/1.5.0 works fine outside of the Makefile (2 Replies)
Discussion started by: hernandinho
2 Replies

7. AIX

mix fc and tape devices

I have a problem with some partitions. In one of them I have this two fiber channel. lsdev -Cc adapter ent0 Available 03-08 10/100/1000 Base-TX PCI-X Adapter (14106902) fcs0 Available 04-08 FC Adapter fcs1 Available 05-08 FC Adapter ide0 Defined 07-08 ATA/IDE... (0 Replies)
Discussion started by: lo-lp-kl
0 Replies

8. Shell Programming and Scripting

How to grep mix of numbers and systemdate?

Hi Guys, i'm beginner in UNIX commands, need some help on this simple question: I need to make a shell script to move files to another directory, the criterias are : 1. the range of 4 last digit of the file name is 0100-0199 2. move all files that processed daily (let's say today is... (2 Replies)
Discussion started by: saltshaker
2 Replies
Login or Register to Ask a Question