I cant compile my own version of firmware with using of system_upgrade_start function. The IoT_Demo from SDK examples is compiling with success. In my case the compiler throwing the error only on when I am using system_upgrade_start when I removing just this function(not the system_upgrade_userbin_check()) it compiles with no errors. What I need to do to make my firmware?
my user main for example:
/* main.c -- MQTT client example
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "ets_sys.h"
#include "driver/uart.h"
#include "driver/hw_timer.h"
#include "osapi.h"
#include "mqtt.h"
#include "wifi.h"
#include "debug.h"
#include "gpio.h"
#include "user_interface.h"
#include "mem.h"
#include "os_type.h"
// #include "driver/key.h"
#include "config.h"
#include "espconn.h"
#include "upgrade.h"
LOCAL void ICACHE_FLASH_ATTR
user_esp_platform_upgrade_rsp(void *arg)
{
struct upgrade_server_info *server = arg;
struct espconn *pespconn = server->pespconn;
char *action = NULL;
if (server->upgrade_flag == true) {
INFO("user_esp_platform_upgarde_successfully\n");
action = "device_upgrade_success";
} else {
INFO("user_esp_platform_upgrade_failed\n");
}
os_free(server->url);
server->url = NULL;
os_free(server);
server = NULL;
}
/******************************************************************************
* FunctionName : user_esp_platform_upgrade_begin
* Description : Processing the received data from the server
* Parameters : pespconn -- the espconn used to connetion with the host
* server -- upgrade param
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
user_esp_platform_upgrade_begin(struct espconn *pespconn, struct upgrade_server_info *server)
{
uint8 user_bin[9] = {0};
uint8 devkey[41] = {0};
server->pespconn = pespconn;
// os_memcpy(devkey, esp_param.devkey, 40);
os_memcpy(server->ip, pespconn->proto.tcp->remote_ip, 4);
#ifdef UPGRADE_SSL_ENABLE
server->port = 443;
#else
server->port = 80;
#endif
server->check_cb = user_esp_platform_upgrade_rsp;
server->check_times = 120000;
if (server->url == NULL) {
server->url = (uint8 *)os_zalloc(512);
}
if (system_upgrade_userbin_check() == UPGRADE_FW_BIN1) {
os_memcpy(user_bin, "user2.bin", 10);
} else if (system_upgrade_userbin_check() == UPGRADE_FW_BIN2) {
os_memcpy(user_bin, "user1.bin", 10);
}
os_sprintf(server->url,
"GET /v1/device/rom/?action=download_rom&version=%s&filename=%s "
"HTTP/1.0\r\nHost: %s:%d\r\n%s",
server->upgrade_version, user_bin, IP2STR(server->ip),
server->port, "devkey");
INFO("%s\n",server->url);
#ifdef UPGRADE_SSL_ENABLE
if (system_upgrade_start_ssl(server) == false) {
#else
if (system_upgrade_start(server) == false) {
#endif
INFO("upgrade is already started\n");
}
}
static void ICACHE_FLASH_ATTR app_init(void) {
}
void ICACHE_FLASH_ATTR user_init(void) {
}
compiling output:
make firmware/user1.bin
Makefile:322: warning: overriding recipe for target 'firmware'
Makefile:275: warning: ignoring old recipe for target 'firmware'
/home/fdistorted/esp8266/SDK_GCC/crosstool-NG/builds/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -Iuser -Idriver -Imqtt -Imodules -Iuser/include -Idriver/include -Imqtt/include -Imodules/include -Iinclude -I/home/fdistorted/esp8266/SDK_GCC/ESP8266_NONOS_SDK-2.1.0/include-I/home/fdistorted/esp8266/SDK_GCC/ESP8266_NONOS_SDK-2.1.0/include/json -g -Wpointer-arith -Wundef -Wl,-EL -Wno-implicit-function-declaration -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections -fno-builtin-printf -DICACHE_FLASH -DBUID_TIME=\"2017-Nov-05_23:12:26_EET\" -DMQTT_DEBUG_ON -DDEBUG_ON -D_STDINT_H -DLOCAL_CONFIG_AVAILABLE -c user/user_main.c -o build/user/user_main.o
/home/fdistorted/esp8266/SDK_GCC/crosstool-NG/builds/xtensa-lx106-elf/bin/xtensa-lx106-elf-ar cru build/esp_mqtt.a build/user/rfinit.obuild/user/user_main.o build/user/user_json.o build/driver/hw_timer.o build/driver/uart.o build/driver/key.o build/mqtt/mqtt.o build/mqtt/ringbuf.o build/mqtt/mqtt_msg.o build/mqtt/queue.o build/mqtt/proto.o build/mqtt/utils.o build/modules/config.o build/modules/wifi.o
/home/fdistorted/esp8266/SDK_GCC/crosstool-NG/builds/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -L/home/fdistorted/esp8266/SDK_GCC/ESP8266_NONOS_SDK-2.1.0/lib -Tbuild/eagle.esphttpd1.v6.ld -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -g -O2 -Wl,--start-group -lc -lgcc -lphy -lpp -lnet80211 -lwpa -lmain -llwip -lcrypto -lssl -ljson -ldriver build/esp_mqtt.a -Wl,--end-group -o build/esp_mqtt.user1.out
build/esp_mqtt.a(user_main.o): In function `user_esp_platform_upgrade_rsp':
user_main.c:(.irom0.text+0xa0): undefined reference to `system_upgrade_start'
build/esp_mqtt.a(user_main.o): In function `user_esp_platform_upgrade_begin':
/home/fdistorted/esp8266/esp_mqtt/user/user_main.c:114: undefined reference to `system_upgrade_start'
collect2: error: ld returned 1 exit status
Makefile:263: recipe for target 'build/esp_mqtt.user1.out' failed
make: *** [build/esp_mqtt.user1.out] Error 1
The -lupgrade parameter needed to be added to compiler command.
If the compiler command generates automatically the variable SDK_LIBS must have upgrade literal for example:
SDK_LIBS = c gcc phy pp net80211 wpa main lwip crypto ssl json driver upgrade
Related
I'm trying to cross-compile a simple C program to aarch64 (arm64) from a 64bit Ubuntu Linux. Can someone please help me why i'm getting this error.
It says 'cpuid.h' is not found. I've tried compiling it on the 64bit linux, it works fine. But when using aarch64-linux-gnu-gcc it is giving errors.
I'm getting the following error.
aarch64-linux-gnu-gcc -O1 -fno-stack-protector -march=armv8-a test.c -o test
test.c:4:10: fatal error: cpuid.h: No such file or directory
4 | #include <cpuid.h>
| ^~~~~~~~~
compilation terminated.
The contents of test.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cpuid.h>
// Requires that the user input the CPUID,
// plus the bytes "3" and "Q";
void succeed(char* string) {
printf("Yes, %s is correct!\n", string);
exit(0);
}
void fail(char* string) {
printf("No, %s is not correct.\n", string);
exit(1);
}
void shift_int_to_char(int i, char* buff) {
buff[0] = (i) & 0xFF;
buff[1] = (i >> 8) & 0xFF;
buff[2] = (i >> 16) & 0xFF;
buff[3] = (i >> 24) & 0xFF;
}
int main(int argc, char** argv) {
if (argc != 2) {
printf("Need exactly one argument.\n");
return -1;
}
unsigned int eax, ebx, ecx, edx;
char* buff = malloc(sizeof(char) * 15);
__get_cpuid(0, &eax, &ebx, &ecx, &edx);
shift_int_to_char(ebx, buff);
shift_int_to_char(edx, buff + 4);
shift_int_to_char(ecx, buff + 8);
buff[12] = '3';
buff[13] = 'Q';
buff[14] = '\0';
int correct = (strcmp(buff, argv[1]) == 0);
free(buff);
if (correct) {
succeed(argv[1]);
} else {
fail(argv[1]);
}
}
As explained in the comments, you need to port this program to the Aarch64 architecture, you cannot just compile the code as is. The features implemented in your SoC are exposed through the various AArch64 feature system registers or instruction set attribute registers, for example ID_AA64PFR1_EL1.
By convention, registers with names terminating with _EL1 cannot be accessed from a user-mode program running at EL0. Some support in the Operating System (running at EL1) is therefore required for reading those registers from a user-mode program - I used a Linux 5.15.0 kernel for the purpose of this answer.
On a recent Linux kernel, this can be achieved by using the HWCAP_CPUID API available in hwcaps - more details in this article , ARM64 CPU Feature Registers.
We can compile/execute the example code provided in Appendix I:
/*
* Sample program to demonstrate the MRS emulation ABI.
*
* Copyright (C) 2015-2016, ARM Ltd
*
* Author: Suzuki K Poulose <suzuki.poulose#arm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <asm/hwcap.h>
#include <stdio.h>
#include <sys/auxv.h>
#define get_cpu_ftr(id) ({ \
unsigned long __val; \
asm("mrs %0, "#id : "=r" (__val)); \
printf("%-20s: 0x%016lx\n", #id, __val); \
})
int main(void)
{
if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
fputs("CPUID registers unavailable\n", stderr);
return 1;
}
get_cpu_ftr(ID_AA64ISAR0_EL1);
get_cpu_ftr(ID_AA64ISAR1_EL1);
get_cpu_ftr(ID_AA64MMFR0_EL1);
get_cpu_ftr(ID_AA64MMFR1_EL1);
get_cpu_ftr(ID_AA64PFR0_EL1);
get_cpu_ftr(ID_AA64PFR1_EL1);
get_cpu_ftr(ID_AA64DFR0_EL1);
get_cpu_ftr(ID_AA64DFR1_EL1);
get_cpu_ftr(MIDR_EL1);
get_cpu_ftr(MPIDR_EL1);
get_cpu_ftr(REVIDR_EL1);
#if 0
/* Unexposed register access causes SIGILL */
get_cpu_ftr(ID_MMFR0_EL1);
#endif
return 0;
}
Execution:
gcc -o cpu-feature-registers cpu-feature-registers.c
./cpu-feature-registers
ID_AA64ISAR0_EL1 : 0x0000000000010000
ID_AA64ISAR1_EL1 : 0x0000000000000000
ID_AA64MMFR0_EL1 : 0x00000111ff000000
ID_AA64MMFR1_EL1 : 0x0000000000000000
ID_AA64PFR0_EL1 : 0x0000000000000011
ID_AA64PFR1_EL1 : 0x0000000000000000
ID_AA64DFR0_EL1 : 0x0000000000000006
ID_AA64DFR1_EL1 : 0x0000000000000000
MIDR_EL1 : 0x00000000410fd034
MPIDR_EL1 : 0x0000000080000000
REVIDR_EL1 : 0x0000000000000000
You now just need to identify the feature/instructions set register(s) that will provide you with the same kind of information provided by your x86_64 code.
I am trying to use the fdlibm library in C to compute sin of a large number. I used the code from this link: http://www.netlib.org/fdlibm/ and downloaded the folder "s_sin.c plus dependencies". When I run the c code in that folder "s_sin.c", I get the following error:
Undefined symbols for architecture x86_64:
"___ieee754_rem_pio2", referenced from:
_sin in s_sin-a92222.o
"___kernel_cos", referenced from:
_sin in s_sin-a92222.o
"___kernel_sin", referenced from:
_sin in s_sin-a92222.o
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any ideas how to fix this error?
Here is the code that I mentioned above:
/* #(#)s_sin.c 1.3 95/01/18 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* sin(x)
* Return sine function of x.
*
* kernel function:
* __kernel_sin ... sine function on [-pi/4,pi/4]
* __kernel_cos ... cose function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#include "fdlibm.h"
#ifdef __STDC__
double sin(double x)
#else
double sin(x)
double x;
#endif
{
double y[2],z=0.0;
int n, ix;
/* High word of x. */
ix = __HI(x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
/* sin(Inf or NaN) is NaN */
else if (ix>=0x7ff00000) return x-x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x,y);
switch(n&3) {
case 0: return __kernel_sin(y[0],y[1],1);
case 1: return __kernel_cos(y[0],y[1]);
case 2: return -__kernel_sin(y[0],y[1],1);
default:
return -__kernel_cos(y[0],y[1]);
}
}
}
The problem is you need to build libm.a from the fdlibm files. If you look at readme file it explains:
CONFIGURE
To build FDLIBM, edit the supplied Makefile or create
a local Makefile by running "sh configure"
using the supplied configure script contributed by Nelson Beebe
(note: after downloading all the files and makefile, you can simply type make and it will build libm.a)
This will create libm.a (which you can link with instead of the normal math library). After you build the library, you need only #include "fdlibm.h" in your source file and compile similar to:
gcc -Wall -Wextra -pedantic -std=c11 -Ofast -L./ -o test_s_sin test_s_sin.c -lm
This will compile your code (named test_s_sin.c above) to executable.
The reason you cannot simply build s_sin.c with gcc is if you look in s_sin.c, you will find it depends on a number of additional externally defined functions from fdlibm (which in turn depend on other source file in the library). For example in s_sin.c you have:
/* High word of x. */
ix = __HI(x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
/* sin(Inf or NaN) is NaN */
else if (ix>=0x7ff00000) return x-x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x,y);
switch(n&3) {
case 0: return __kernel_sin(y[0],y[1],1);
case 1: return __kernel_cos(y[0],y[1]);
case 2: return -__kernel_sin(y[0],y[1],1);
default:
return -__kernel_cos(y[0],y[1]);
}
Where you have the functions or macros __HI(), __kernel_sin(), __ieee754_rem_pio2(), etc.. all required by s_sin.c. These are provided by the other sources in fdlibm, but are all meant to work together as a library rather than single source files you can cherry-pick from.
I am very new in C. I just need to use one of the functions in scip. I made a make file as below:
SCIPDIR=$/Users/amin/Documents/cProgram/scipoptsuite-6.0.2/scip
include $(SCIPDIR)/make/make.project
%.o: %.c
$(CC) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CFLAGS) -c $<
all: cmain
cmain: cmain.o
$(LINKCXX) cmain.o $(LINKCXXSCIPALL) $(LDFLAGS) $(LINKCXX_o) cmain
my cmain.c file is like this:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* This file is part of the program and library */
/* SCIP --- Solving Constraint Integer Programs */
/* */
/* Copyright (C) 2002-2019 Konrad-Zuse-Zentrum */
/* fuer Informationstechnik Berlin */
/* */
/* SCIP is distributed under the terms of the ZIB Academic License. */
/* */
/* You should have received a copy of the ZIB Academic License */
/* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**#file GMI/src/cmain.c
* #brief main file for GMI cut example
* #author Marc Pfetsch
*/
/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
#include <scip/scip.h>
#include <scip/scipdefplugins.h>
/** reads parameters */
static
SCIP_RETCODE readParams(
SCIP* scip, /**< SCIP data structure */
const char* filename /**< parameter file name, or NULL */
)
{
if ( filename != NULL )
{
if ( SCIPfileExists(filename) )
{
SCIPinfoMessage(scip, NULL, "reading parameter file <%s> ...\n", filename);
SCIP_CALL( SCIPreadParams(scip, filename) );
}
else
SCIPinfoMessage(scip, NULL, "parameter file <%s> not found - using default parameters.\n", filename);
}
else if ( SCIPfileExists("scipgmi.set") )
{
SCIPinfoMessage(scip, NULL, "reading parameter file <scipgmi.set> ...\n");
SCIP_CALL( SCIPreadParams(scip, "scipgmi.set") );
}
return SCIP_OKAY;
}
/** starts SCIP */
static
SCIP_RETCODE fromCommandLine(
SCIP* scip, /**< SCIP data structure */
const char* filename /**< input file name */
)
{
/********************
* Problem Creation *
********************/
SCIPinfoMessage(scip, NULL, "read problem <%s> ...\n\n", filename);
SCIP_CALL( SCIPreadProb(scip, filename, NULL) );
/*******************
* Problem Solving *
*******************/
/* solve problem */
SCIPinfoMessage(scip, NULL, "solve problem ...\n\n");
SCIP_CALL( SCIPsolve(scip) );
SCIPinfoMessage(scip, NULL, "primal solution:\n");
SCIP_CALL( SCIPprintBestSol(scip, NULL, FALSE) );
/**************
* Statistics *
**************/
SCIPinfoMessage(scip, NULL, "Statistics:\n");
SCIP_CALL( SCIPprintStatistics(scip, NULL) );
return SCIP_OKAY;
}
/** starts user interactive mode */
static
SCIP_RETCODE interactive(
SCIP* scip /**< SCIP data structure */
)
{
SCIP_CALL( SCIPstartInteraction(scip) );
return SCIP_OKAY;
}
/** creates a SCIP instance with default plugins, evaluates command line parameters, runs SCIP appropriately,
* and frees the SCIP instance
*/
static
SCIP_RETCODE runSCIP(
int argc, /**< number of shell parameters */
char** argv /**< array with shell parameters */
)
{
SCIP* scip = NULL;
/*********
* Setup *
*********/
/* initialize SCIP */
SCIP_CALL( SCIPcreate(&scip) );
/* we explicitly enable the use of a debug solution for this main SCIP instance */
SCIPenableDebugSol(scip);
/***********************
* Version information *
***********************/
SCIPprintVersion(scip, NULL);
SCIPinfoMessage(scip, NULL, "\n");
/* include default SCIP plugins */
SCIP_CALL( SCIPincludeDefaultPlugins(scip) );
/**************
* Parameters *
**************/
if ( argc >= 3 )
{
SCIP_CALL( readParams(scip, argv[2]) );
}
else
{
SCIP_CALL( readParams(scip, NULL) );
}
/**************
* Start SCIP *
**************/
if ( argc >= 2 )
{
SCIP_CALL( fromCommandLine(scip, argv[1]) );
}
else
{
SCIPinfoMessage(scip, NULL, "\n");
SCIP_CALL( interactive(scip) );
}
/********************
* Deinitialization *
********************/
SCIP_CALL( SCIPfree(&scip) );
BMScheckEmptyMemory();
return SCIP_OKAY;
}
/** main method starting SCIP */
int main(
int argc, /**< number of arguments from the shell */
char** argv /**< array of shell arguments */
)
{
SCIP_RETCODE retcode;
retcode = runSCIP(argc, argv);
if ( retcode != SCIP_OKAY )
{
SCIPprintError(retcode);
return -1;
}
return 0;
}
Now in the directory that I have these 2 file, I run Make but it doesn't work I get error: No such file or directory
make: *** No rule to make target `Users/amin/Documents/cProgram/scipoptsuite-6.0.2/scip/make/make.project'. Stop.
I just tried to follow a instruction that someone suggested. Please help me if you can. what I have to do?
You are going about this incorrectly.
First without target the first recipe is the one called, so the all target should go first.
second: don't include that other file and delete just about everything but the directory variable and the all target
you simply need to add to the LD_FLAGS variable and the automatic rules will link for you. unless the scip project is bringing in a bunch of variables that you need I don't know why you would need to include its make file information here.
Also of note is that the current path you loaded into a variable had an incorrect leading $ sign in the assignment, and for this to link we will need to make sure its full path to libscip.so ( or libscip.a )
i.e. LD_FLAGS+=-L${DIR_containing_libscip.so} -lscip
you might also need to point to the header/include files:
CPP_FLAGS+=-I${DIR_before_includes_of_scip}/include ( if they are included as <scip/foo>. or without the /include and going up further if they are to be included just as <foo>; this depends upon the projects style. Most projects use the /include/projname pattern so as to keep the project effectively in a namespace of its own for include files to avoid collisions.
that should be it assuming everything else is built and in place and there is nothing particularly special about scip that I need to know about...
You want to separate two things
Building SCIP
Building and Linking your program.
Building SCIP
Usually one would go about and install this library using a package manager on most UNIX-like systems, or do make install to copy it into the system. Then, header files etc. will automatically be found. If you don't want to do that but rather "bundle" SCIP with your program, you usually distribute a copy or link a copy of that version for your program (copy of the code in your sourcetree under eg. "external" or using git submodules, ...). In any case though, you don't want the path to SCIP to be absolute. As an example, use this layout:
./
-- external/SCIP
-- cmain.c
-- Makefile
In the Makefile you can then set SCIPDIR like this for later use:
SCIPDIR := "./external/SCIP"
First, however, you should understand how to build manually. For that, you enter "./external/SCIP" and build the library as instructed in the Readme (often by doing something like ./configure && make && make install). If you want to automate this, you can do this from your main file. For that you can add a "phony" target (ie. a target that will not exactly create one output but build all dependencies) that we will call dep:
dep:
cd $(SCIPDIR); ./configure
$(MAKE) -C $(SCIPDIR)
.PHONY: dep
(thanks to #UpAndAdam for pointing out that you have to change the CWD before running the configure script)
For that we recursively call make for our subproject. We don't want to system-wide install the files, so we just build the library.
Building your program
We now add two pattern-rules that specify how to build and link C programs. GNU/Make (the one you're using) already has built-in suffix rules s.t. it already by default knows how to build C programs, but suffix rules are hard to deal with and you already use other GNU/Make features, so we can also use pattern-rules that are roughly equivalent and disable the built-in rules:
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
%: %.o
$(CC) $(LDFLAGS) $(CFLAGS) -o $# $^ $(LDLIBS)
.SUFFIXES:
A small note here: We compile one object file from one c file by pattern matching. I used the standard variables, CPPFLAGS (C preprocessor, not C++!), CFLAGS (C compiler & Feature flags) and listed all options before the non-option argument $< which will hold the (first) dependency listed, eg. "cmain.c". Not all C compilers allow mixing options and arguments.
For linking I do the same, but I list the libraries that we want to link with last. This is important, a classic C compiler will discard any libraries listed there if there wasn't any object earlier in the list that depends on that variable.
Now that we know how to build a generic C program, we actually want to first build SCIP, then your program and link it. For that, we'll create a new PHONY dependency, called "all", that will do exactly that:
all: dep cmain
.PHONY: dep all
However, if we now execute make all it will fail as we haven't yet specified the include path etc. For that, we set the variables that we've used before to the needed values (I guessed the specific path, as I'm on mobile):
CPPFLAGS += -I$(SCIPDIR)/include
LDFLAGS += -L$(SCIPDIR)
LDLIBS += -lscip
Putting it all together
Now this should work, more or less. One thing though is, that it's common to have all as the default target, that is, the first target listed in the Makefile. So we write:
CPPFLAGS += -I$(SCIPDIR)/include
LDFLAGS += -L$(SCIPDIR)
LDLIBS += -lscip
all: dep cmain
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
%: %.o
$(CC) $(LDFLAGS) $(CFLAGS) -o $# $^ $(LDLIBS)
dep:
cd $(SCIPDIR); ./configure.sh
$(MAKE) -C $(SCIPDIR)
.PHONY: dep all
.SUFFIXES:
Note: I'm on mobile, so I couldn't test and don't know the exact paths, but this should guide you along. Also my code here used spaces instead of tabs in the Makefile for the same reason. Be sure to replace them.
I currently started learning the Linux Device driver programming in Linux. where I found this small piece of code printing hello world using printk() function.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello World!!!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye Hello World!!!\n");
}
module_init(hello_init);
module_exit(hello_exit);
After compiling code using make command and load driver using insmod command. I'm not getting the "Hello world" printed on screen instead its printing only on the log file /var/log/kern.log. But I want printk to print on my ubuntu terminal. I'm using ubuntu(14.04). Is it possible?
It isn't possible to redirect kernel logs and massages to gnome-terminal and there you have to use dmesg.
But in a virtual terminal(open one with ctrl+F1-F6) you can redirect them to standard output.
First determine tty number by entering tty command in virtual terminal.The output may be /dev/tty(1-6).
Compile and run this code with the argument you specified.
/*
* setconsole.c -- choose a console to receive kernel messages
*
* Copyright (C) 1998,2000,2001 Alessandro Rubini
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
char bytes[2] = {11,0}; /* 11 is the TIOCLINUX cmd number */
if (argc==2) bytes[1] = atoi(argv[1]); /* the chosen console */
else {
fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
}
if (ioctl(STDIN_FILENO, TIOCLINUX, bytes)<0) { /* use stdin */
fprintf(stderr,"%s: ioctl(stdin, TIOCLINUX): %s\n",
argv[0], strerror(errno));
exit(1);
}
exit(0);
}
For example if your output for tty command was /dev/tty1then type this two command:
gcc setconsole.c -o setconsole
sudo ./setconsole 1
This will set your tty to receive kernel messages.
Then compile and run this code.
/*
* setlevel.c -- choose a console_loglevel for the kernel
*
* Copyright (C) 1998,2000,2001 Alessandro Rubini
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/klog.h>
int main(int argc, char **argv)
{
int level;
if (argc==2) {
level = atoi(argv[1]); /* the chosen console */
} else {
fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
}
if (klogctl(8,NULL,level) < 0) {
fprintf(stderr,"%s: syslog(setlevel): %s\n",
argv[0],strerror(errno));
exit(1);
}
exit(0);
}
There are 8 level of kernel messages as you specify in your code KERN_ALERT is one of them.To make console receive all of them you should run above code with 8 as arguement.
gcc setlevel.c -o setlevel
sudo ./setlevel 8
Now you can insert your module to kernel and see kernel logs in console.
By the way these codes are from ldd3 examples.
printk prints to the kernel log. There is no "screen" as far as the kernel is concerned. If you want to see the output of printk in real time, you can open a terminal and type the following dmesg -w. Note that the -w flag is only supported by recent versions of dmesg (which is provided by the util-linux package).
I tried running this sample code from fm4dd.com. But I don't know how to actually include the header files into my program.
Orignally it was like:
#include <openssl/bio.h>
But i changes it to their actual path, but an error still shows up.
#include <C:\openssl\include\openssl\bio.h>
#include <C:\openssl\include\openssl\err.h>
#include <C:\openssl\include\openssl\pem.h>
#include <C:\openssl\include\openssl\x509.h>
#include <C:\openssl\include\openssl\e_os2.h>
int main() {
const char cert_filestr[] = "./cert-file.pem";
EVP_PKEY *pkey = NULL;
BIO *certbio = NULL;
BIO *outbio = NULL;
X509 *cert = NULL;
int ret;
/* ---------------------------------------------------------- *
* These function calls initialize openssl for correct work. *
* ---------------------------------------------------------- */
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
/* ---------------------------------------------------------- *
* Create the Input/Output BIO's. *
* ---------------------------------------------------------- */
certbio = BIO_new(BIO_s_file());
outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
/* ---------------------------------------------------------- *
* Load the certificate from file (PEM). *
* ---------------------------------------------------------- */
ret = BIO_read_filename(certbio, cert_filestr);
if (! (cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) {
BIO_printf(outbio, "Error loading cert into memory\n");
exit(-1);
}
/* ---------------------------------------------------------- *
* Extract the certificate's public key data. *
* ---------------------------------------------------------- */
if ((pkey = X509_get_pubkey(cert)) == NULL)
BIO_printf(outbio, "Error getting public key from certificate");
/* ---------------------------------------------------------- *
* Print the public key information and the key in PEM format *
* ---------------------------------------------------------- */
/* display the key type and size here */
if (pkey) {
switch (pkey->type) {
case EVP_PKEY_RSA:
BIO_printf(outbio, "%d bit RSA Key\n\n", EVP_PKEY_bits(pkey));
break;
case EVP_PKEY_DSA:
BIO_printf(outbio, "%d bit DSA Key\n\n", EVP_PKEY_bits(pkey));
break;
default:
BIO_printf(outbio, "%d bit non-RSA/DSA Key\n\n", EVP_PKEY_bits(pkey));
break;
}
}
if(!PEM_write_bio_PUBKEY(outbio, pkey))
BIO_printf(outbio, "Error writing public key data in PEM format");
EVP_PKEY_free(pkey);
X509_free(cert);
BIO_free_all(certbio);
BIO_free_all(outbio);
exit(0);
}
but the following error shows up every time I try to compile it on the command prompt. Since, I'm a noob, I have no clue how to proceed from here and what to do to fix this error.
c:\openssl>gcc -lssl -lcrypto -o test test.c
In file included from test.c:1:0:
C:\openssl\include\openssl\bio.h:62:27: fatal error: openssl/e_os2.h: No such file or directory
#include <openssl/e_os2.h>
^
compilation terminated.
Edit:
I included the solution to the problem, but now a new error showed up:
c:\openssl>gcc -lssl -lcrypto -o test test.c -IC:\openssl\include\
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lssl
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lcrypto
collect2.exe: error: ld returned 1 exit status
In many cases, include-files in turn include other files. The paths of these files are specified relative, not absolute. So you have to tell your compiler, where to search for include files in general.
The -I-option is for this purpose and tells the compiler, which paths (additionally to some standard paths) are to be searched for specified include files, in your case you would use:
gcc -I C:\openssl\include
If you really need to specify an absolute include path you would use quotes, not <>, i.e.
#include "C:\foo\bar\baz.h"
but if this file includes other files, the compiler will not look specifically into C:\foo\bar for these.
Get rid of the full path names in your #include directives. That is, don't use #include <C:\openssl\include\openssl\bio.h>; rather, use:
#include <openssl\bio.h>
#include <openssl\err.h>
#include <openssl\pem.h>
#include <openssl\x509.h>
#include <openssl\e_os2.h>
And pass the include directory to gcc with -I:
gcc -I c:\openssl\include -o myfile myfile.c -lcrypto