I'm trying to build a loadable kernel module using multiple source files. According to section 3.3 of https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt I've got to use obj-m for main object file and modulename-y for the rest of it.
Here's my mwe:
helpers.h
#ifndef __HELPERS_H__
#define __HELPERS_H__
void helper_print_init(void);
void helper_print_exit(void);
#endif // __HELPERS_H__
helpers.c
#include "helpers.h"
#include <linux/kernel.h>
void helper_print_init(void) {
printk("multi_file_ko_init_helper\n");
}
void helper_print_exit(void) {
printk("multi_file_ko_exit_helper\n");
}
multiFileKo.c
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
//#include "helpers.h"
static int __init multi_file_ko_init(void) {
printk("multi_file_ko_init\n");
// helper_print_init();
return 0;
}
static void __exit multi_file_ko_exit(void) {
printk("multi_file_ko_exit\n");
// helper_print_exit();
}
module_init(multi_file_ko_init);
module_exit(multi_file_ko_exit);
MODULE_LICENSE("MIT");
MODULE_AUTHOR("AUTHOR");
MODULE_DESCRIPTION("gpio");
MODULE_VERSION("0.0");
NOTE THAT multiFileKo.c does not even actually uses helpers for now. I tried to actually call those functions but for simplicity just commented things out from mwe.
Now if I compile it with kbuild like follows, using only main file, I get dmesg output as expected:
obj-m := multiFileKo.o
But when I try to compile it linked with helpers, even without actually using them as follows, dmesg remains silent even though insmod/rmmod seem to be working:
obj-m := multiFileKo.o
multiFileKo-y := helpers.o
Obviously if I uncomment everything in multiFileKo.c it does not work either. So the fact of linking additional object file seems to be breaking my module regardless of what that additional object file does.
Approach with multiFileKo-objs does not work for me either. I saw this earlier, but sure where this takes it's origin, since makefiles manual uses it only in context of host programs.
Info which lead to solution was provided by #Tsyvarev. Original info may be found in comments to first post.
obj-m := multiFileKo.o defines the name of module. It also uses multiFileKo.c as a source file by default. But this principle works for single-source-file modules only.
In case multiple source files are used to create a module, obj-m := multiFileKo.o shall define module name, but not the sources. ALL object files (referencing actual sources) then shall be listed in multiFileKo-objs := list. Source files are not allowed to have the same name which module have.
From my experiments and make utility manual I can also say that it seems that listing sources in multiFileKo-y := also works. Maybe -obj is still working due to compatibility, since make documents now advise to use -y list.
To sum up, correct approach would be:
obj-m := multiFileKo.o
multiFileKo-y := multiFileKo_main.o helpers.o
Source files:
multiFileKo_main.c // contains init and exit functions
helpers.c
Output would be stored in multiFileKo.ko
TLDR: Running ProC from Oracle instant client 12.2 on CentOS 7.3 doesn't seem to be able to properly process even a trivial input file.
Minimal input file demonstrating the problem:
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL INCLUDE oci.h;
EXEC SQL END DECLARE SECTION;
The real files obviously include my own project's header, but ultimately they pull in oci.h, which is one of the instant client SDK headers and this seems to be where the build issues are coming from.
Invocation of ProC:
The following script demonstrates the problem (again, a cut-down version of the real situation):
#!/bin/sh
export ORACLE_HOME=/some/path/instantclient_12_2
export ORACLE_SID=SomeSID
export PATH=/various/paths:${ORACLE_HOME}:${ORACLE_HOME}/sdk:${ORACLE_HOME}/bin:/some/more/paths/like:usr/bin:
export LD_LIBRARY_PATH=${ORACLE_HOME}:${ORACLE_HOME}/lib32:${ORACLE_HOME}/lib
${ORACLE_HOME}/sdk/proc \
LTYPE=LONG \
PARSE=PARTIAL \
MODE=ORACLE \
CODE=ANSI_C \
iname=foo.pc
Oracle configuration:
The contents of my pcscfg.cfg file look like this:
sys_include=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
sys_include=/usr/include
include=/some/path/instantclient_12_2/sdk/include
I've also tried various reordering, switching include and sys_include, but all seem to give the same behaviour. Adding define=__x86_64__ as seen in various online references makes no difference. I've chosen to expand out the $ORACLE_PATH in the above to make the example clearer.
Sample error output:
Using the input file defined above results in output with errors like the following (truncated to help focus the discussion):
Pro*C/C++: Release 12.2.0.1.0 - Production on Mon Sep 4 16:19:45 2017
Copyright (c) 1982, 2017, Oracle and/or its affiliates. All rights reserved.
System default option values taken from: /some/path/instantclient_12_2/precomp/admin/pcscfg.cfg
Syntax error at line 46, column 1, file /usr/include/bits/byteswap-16.h:
Error at line 46, column 1 in file /usr/include/bits/byteswap-16.h
{
1
PCC-S-02201, Encountered the symbol "{" when expecting one of the following:
; , = ( [
The contents around the line it is complaining about look like this:
static __inline unsigned short int
__bswap_16 (unsigned short int __bsx)
{ // <---- this is line 46
return __bswap_constant_16 (__bsx);
}
If I insert #include <stdlib.h> before the EXEC SQL BEGIN DECLARE SECTION line, the error message changes to this:
Syntax error at line 265, column 50, file /some/path/instantclient_12_2/sdk/include/ociextp.h:
Error at line 265, column 50 in file /some/path/instantclient_12_2/sdk/include/ociextp.h
void *ociepacm(OCIExtProcContext *with_context, size_t amount);
.................................................1
PCC-S-02201, Encountered the symbol "size_t" when expecting one of the following
:
... auto, char, const, double, enum, float, int, long,
ulong_varchar, OCIBFileLocator OCIBlobLocator,
OCIClobLocator, OCIDateTime, OCIExtProcContext, OCIInterval,
OCIRowid, OCIDate, OCINumber, OCIRaw, OCIString, register,
short, signed, sql_context, sql_cursor, static, struct,
union, unsigned, utext, uvarchar, varchar, void, volatile,
a typedef name, exec oracle, exec oracle begin, exec,
exec sql, exec sql begin, exec sql type, exec sql var,
The symbol "enum," was substituted for "size_t" to continue.
This one is more interesting because I've traced through the logic more carefully and even forcing size_t to be defined by various means, I still get the above error. But if I change the ProC invocation to use PARSE=FULL, it is successful. Unfortunately, that causes other problems with the real code and those problems have a similar nature to this one (i.e. chokes on compiler headers for things that should really have been defined by the compiler headers).
Further comments:
Looking at various solutions online, these issues are normally the result of having incorrectly set include search paths, but I've verified from the output listing that the correct headers are indeed being found. It is as though there are some compiler defines missing that GCC would normally provide but ProC isn't providing. There have been various other related examples which support this theory, giving errors on things like __INT_LEAST8_TYPE__ being unknown (which as far as I can tell GCC defines internally rather than explicitly in any of its headers).
Specific question:
ProC doesn't seem to be processing the system compiler headers correctly. Any idea why or even further things to try to help diagnose the underlying cause?
I have been able to get my application to compile correctly, I found that even though some compile problems were resolved by adding the output of the command "gcc -dM -E - < /dev/null" into a header file and including it in every Pro*C source file, new compile problems were introduced because of that and trying to resolve those new problems again introduced others so that approach was going nowhere.
In the end I started again from scratch and only included those #defines that were realy needed by the proc compiler. Also, I had to re-arrange the paths in the proc configuration file ${ORACLE_HOME}/precomp/admin/pcscfg.cfg
This is what it looks like now:
sys_include=$ORACLE_HOME/precomp/public
sys_include=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
sys_include=/usr/local/include
sys_include=/usr/include
sys_include=/usr/include/linux
ltype=short
define=__x86_64__
the reason for this is that there are several files located in the gcc include directory that are also present in some of the other directories, but those assume that all of those gcc internal defines are set as well. The system include files located in the gcc include directory sometimes differ significantly from the ones in the usual include directories that are listed below it and it would seem that proc has a lot less difficulties in parsing the ones located in the gcc 4.8.5 directory.
Next to this, the include file I created and #include into every source file proc choked on now looks this:
#ifndef __GCC4_INTERNAL_DEFINES_H__
#define __GCC4_INTERNAL_DEFINES_H__
/* Proceed only when using the Oracle Pro*C compiler on RHEL7 */
#ifdef DB_PRE_COMP
#ifdef OS_IS_RHEL7
/* These are some of the defines that gcc4 sets by itself. The Pro*C precompiler
does not know them and they are needed in order to correctly parse several
system header files. Full list of gcc4 internal defines may be obtained with
the following command: gcc -dM -E - < /dev/null */
#define __INT_LEAST8_TYPE__ signed char
#define __INT_LEAST16_TYPE__ short int
#define __INT_LEAST32_TYPE__ int
#define __INT_LEAST64_TYPE__ long int
#define __UINT_LEAST8_TYPE__ unsigned char
#define __UINT_LEAST16_TYPE__ short unsigned int
#define __UINT_LEAST32_TYPE__ unsigned int
#define __UINT_LEAST64_TYPE__ long unsigned int
#define __INT_FAST8_TYPE__ signed char
#define __INT_FAST16_TYPE__ long int
#define __INT_FAST32_TYPE__ long int
#define __INT_FAST64_TYPE__ long int
#define __UINT_FAST8_TYPE__ unsigned char
#define __UINT_FAST16_TYPE__ long unsigned int
#define __UINT_FAST32_TYPE__ long unsigned int
#define __UINT_FAST64_TYPE__ long unsigned int
#define __INTMAX_TYPE__ long int
#define __UINTMAX_TYPE__ long unsigned int
#include </usr/include/stdint.h>
#endif /* OS_IS_RHEL7 */
#endif /* DB_PRE_COMP */
#endif /* __GCC4_INTERNAL_DEFINES_H__ */
Much to my relief, I got everything to compile again with these updates. For completeness sake, proc is executed with the parse=full option, this is what I used to do under RHEL6 as well and what my application apparently needs; as part of my efforts to get it to compile I tried with partial option as well but that did not make a difference, it still choked.
This happens when you include your header with the same name as a system header, which includes stdint.h.
From Pro*C manual:
The precompiler searches directories in the following order:
the current directory
the system directory specified in a SYS_INCLUDE precompiler option
the directories specified by the INCLUDE option, in the order they are entered
the built-in directories for standard header files
For example, you may create header file db.h for your project.
If you have in your system Berkeley DB installed, then it supplies your system with it's own db.h.
As long as your db.h is situated in the same folder as preprocessed .pc file and you don't have to pass include=your_include_folder option to proc you will be ok.
If you do have separate folder for include files you are obliged to pass include=../include option to proc and Berkeley's db.h comes in place instead of db.h file from your project.
For me, I fixed this in either of these 2 ways:
Add define=ORASYS_TYPES to ${ORACLE_HOME}/precomp/admin/pcscfg.cfg
or
Add DEFINE=ORASYS_TYPES as an option to proc.
oci.h includes <oratypes.h>
And oratypes.h has:
#ifndef ORASYS_TYPES
# include <sys/types.h>
# define ORASYS_TYPES
#endif
I followed all the procedures explained so far about this matter either in this website or published notes by Dirk, Hadley or others. However, I still have problems in building my package due to the issue regarding cpp11 plugin.
I used RcppArmadillo.package.skeleton() function. I put my cpp file in the src directory. The NAMESPACE file looks as it should which contains importFrom(Rcpp, sourceCpp) line. I also edited DESCRIPTION file and in the LinkingTo section, I added RcppEigen and other packages I use. I finally ran the compileAttributes(verbose=TRUE) function in R and everything looked OK. Therefore, I think I have done everything as I should. I have to also mention that when I compile my code in R using sourceCpp(), it works perfect and is compiled with no errors!
To illustrate better what my dependencies are, I put the first block of my code here:
#include <RcppArmadillo.h>
#include <RcppNumerical.h>
#include <RcppArmadilloExtensions/sample.h>
#include <Eigen/LU>
#include <algorithm>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::depends(RcppNumerical)]]
// [[Rcpp::plugins(cpp11)]]
The problem is when I build my package and I get errors and warnings for the lines I have auto type which relates to cpp11 plugin.
After searching similar posts on this website, I concluded that I have to force my R compiler to use c++11 and there fore I edited my Makvars file located at ~/.R/Makevars and since I use MAC I added this line:
CXX=clang++ -std=c++11 to that file. However, when I do that those 3 errors go away but 50 new errors are generated as all of the Armadillo variable types, such as mat, uvec, etc are not recognized any more. So I don't know how to fix this.
I think basically putting // [[Rcpp::plugins(cpp11)]] should take care of it as the new version of Rcpp supports this plug in and probably that's why when I run sourceCpp in R I get no errors and everything looks fine. But I don't know what happens when building my package. My Rcpp version is 0.12.8 .
Thank you in advance for any sorts of help.
Plugins for both dependencies (ie other headers) and compiler options are for use by sourceCpp().
Packages do this with LinkingTo: and, for the C++11 directive, either src/Makevars or SystemRequirements. See Writing R Extensions which documents this.
I am teaching myself how to read in wav files into C++ as a part of me learning C++. I have found many resources online that recommended the following library: libsnfile library
So I followed some tutorials below in testing the basic functionality of the library, but I can't get the library to compile with Visual Studio 2010.
I have searched online for the following error, but did not find anything useful for my particular error. I downloaded the libsndfile C++ windows installer found here. I used the 32bit version since I am using the win32 C++ console version. However, my Visual Studio is 64 bit. I did the following after I downloaded the installer:
I went into Visual Studio. Under my project, I did the following:
In project properties:
1. VC++
Include >> added ...\libsnfile\include
Library >> added ...\libsnfile\lib
2. C\C++
Added the following directory as additional dependencies
...\libsnfile\lib\libsndfile-1.lib
I did this to add this third party library to my project. After this, to test, I ran the following code:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <sndfile.h>
int _tmain(int argc, _TCHAR* argv[])
{
printf("This is a test\n");
getchar();
return 0;
}
I coded that to make sure that I could access the sndfile.h in my program and everything compiled. The problem occured when I tried to implement the following code:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <sndfile.h>
int _tmain(int argc, _TCHAR* argv[])
{
printf("This is a test\n");
//This will be the length of the buffer used to hold samples while the program processes them.
//A SNDFILE is like FILE in a standard C library. Consequently, the sf_open_read and sf_open_write functions will return an
//SNDFILE* pointer when they successfully open the specified file.
SNDFILE* sf = NULL;
/*SF_INFO will obtain information of the file we wish to load into our program. */
SF_INFO info;
/*This is where the program will open the WAV file */
info.format = 0;
sf = sf_open("C:\Users\GeekyOmega\Desktop\gameon.wav", SFM_READ, &info);
if(sf == NULL)
{
printf("Failed to open the file.\n");
exit(-1);
}
getchar();
return 0;
}
I then get a system error when I click run inside visual studio when I try to run my program. It says,
The program can't start because libsnfile-1.dll is missing from your computer.
Try reinstalling the program to fix this problem.`
I tried the 64 bit windows installer and tried that, but it didn't work. Anyone understand what I am doing run? I am running Visual Studio's 2010 on Windows 7 as my dev environment.
I apologize if I am making a silly mistake, but I would deeply appreciate if anyone could help me. I tried a few hacky fixes, as I talked about above, but nothing has worked.
EDIT: I am also aware of this thread here, but this doesn't make any sense to my current issue as I am not doing any of this path stuff that they are talking about.
Warm Regards,
GeekyOmega
I fixed the issue. For future readers, this is a very common problem, I think. I placed the .dll in the debug folder of my Visual Studio project. Visual Studio couldn't see the .dll file otherwise. After this, the program fired up as expected and ran. If this does not fix the issue for you, then I suggest something else could be going on.
Always pick a title that draws in a programmer.
Anyway I'm using linux and I compiled the qt4.7.1 libs using
./configure -static -nomake demos -nomake examples -nomake tools -prefix /local/qt/qtstatic
the build and install all went fine, and I set it up in qt creator so I can build with it. Building any application works fine, however when I run the application it gives me an error.
QWidget: Must construct a QApplication before a QPaintDevice
Aborted
I understand that this means a static object is trying to use a class (QPaintDevice) that needs QApplication to be called first, and since static objects are all processed before the actual application this is obviously going to fail, The first line after my main() is the QAplication, however I know that doesn’t make a difference, My .pro does contain
CONFIGURE +=static, and I have defined static in the main program, Qt4 just doesn't like me.
How can I fix it so the static objects don't all go insane like this.
#include <QtGui/QApplication>
#include "microbrowse.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
microbrowse w;
w.show();
return a.exec();
}
is the main, but that's probably not important, the main is pretty much the same for all QT apps made by qt creator, except microbrowse is the name of whatever widget your working on. The widget microbrowse is the entire program, all this does is create the QApplication, and dimension microbrowse.
I think class microbrowse contains such a object that is not possible to be statically linked. Also check your Qt build. You should have add ./configure -relase or -debug while configuring.