I have the original code that is meant to compile in Windows and Linux using gcc.
It works fine even under cygwin. Now, when I try to compile for iOS
echo $OSTYPE
darwin14
everything seems fine and a build is successfully obtained. However, when I tried to run the CUI app, a message Segmentation fault 11 is displayed.
After a couple of days searching on internet, by chance I found this link.
As a result, I made the following change in one of the *.c file
-#define _POSIX_C_SOURCE 199309
+#define _POSIX_C_SOURCE 199506
and the new build works fine. Although I am not a programmer, I am wondering what would be so significant different between these two macros? Could you comment on why such change becomes so significant.
though it is only 1 line of code,but it may make big difference,POSIX is a standard,it define the interface between OS and applications,and it has many different version(you can think it similar with a hardware USB standard , it has many version, like USB 1.0 and USB 2.0).
sometimes programmer can't determine which platform the program will be work on , it may run on Linux , may run on windows, maybe the system provide old standard interface, maybe a new one.
So , programmer add this kind of macros, write codes for many different interface,for example ,a source code like this:
#define WIN
#ifdef WIN
<part 1:1000 lines of code>
#endif
#ifdef LINUX
<part 2:1000 lines of code>
#endif
<1000 lines that not depend on system , can both run on Linux and Windows.>
the compiler will compile part 1(discard part 2), but when you change #define WIN to #define LINUX , it will contain part 2(and discard part 1) ! you may think you only changed 1 line , but the compiler may choose or discard thousands of lines (maybe even more ,maybe less, that depend on the code)
Related
I am using a SAMD21XPlained Pro board on Mac (OS Big Sur) with MPLAB X IDE v6.00 (XC32 compiler) and I am currently experiencing a problem when trying to display a message on my terminal via the printf() function.
I am a beginner in embedded programming and I try to follow this tutorial about STDIO Serial Communications : https://www.youtube.com/watch?v=3pwdpYj5s_A&t=397s
Based on this tutorial I first tried to do only a printf() but I didn't see anything on the terminal (I didn't try the scanf() for this first try).
The only thing I changed is that I included the stdio.h file and I did a second test with a baud rate 9600 (because I don't really know how to define the baud rate and I wanted to test like that).
I have read on several forums that the problem comes from the fact that the XC32 compiler uses by default the UART2 while the printf() must use the UART1 to be displayed on the terminal.
Several people suggest to include xc.h to redefine the default UART1 (__XC_UART = 1) but this seems to work only for PIC32MX µCs.
According to my research in the XC32 compiler files, the xc.h file for PIC32MX is not the same as the one for PIC32/SAM and only the one for PIC32MX defines __XC_UART.
I also tried to apply what is proposed in "Microchip Developer Help" for "Redirect stdout for Use With printf()" in the XC32 category:
https://microchipdeveloper.com/xc32:redirect-stdout
The problem is that it also seems to be only for PIC32MX µCs (the p32xxxx.h file that is included at the beginning of the code exists only for PIC32MX in the XC32 compiler).
After a few days of research, I tried many solutions proposed on different forums but I still can't find the one that works so I was wondering if you have an idea?
Thank you !
I am not a native english speaker, so please excuse any spelling or grammar mistakes
I am not a compiling expert, nor do I have any useful experience with builds and their errors
I am C# programmer and mainly working in an MS Enviroment
I only know the 3 "must know to survive in Linux commands" "./configure, make & make install" from my little Linux Experience
My Development Enviroment
I am using a Windows 7 Workstation
with Cygwin and MinGW (as Linux 'Replacement') to compile.
The Problem
I want to compile C source code on windows, which is primary written for Linux distributions.
/Configure works without problems.
If I use the command make to compile the sources, I run into following error:
Error
grib_keys.c:50:34:
error: 'alphasort' undeclared (first use in this function)
Research:
My Research proved me, that this problem already has been solved, but unfortunately, the answer isn't working for me.
Implicit declaration of scandir; alphasort is undeclared
http://ubuntuforums.org/archive/index.php/t-1653576.html
The solution says, that I only have to include following: #define _GNU_SOURCE
Which I tried, but as already stated, it doesn't work.
I included it in following files:
- grib_keys.c
- config.h
and tried to compile them with concurrent and not concurrent inclusion.
In the end, the important parts of the files looked like this:
config.h
********
/* Add #define _GNU_SOURCE to solve "'alphasort' undeclared" error */
#define _GNU_SOURCE
grib_keys.c
***********
#define _GNU_SOURCE
count = scandir(dir, &files, 0, alphasort);
What I want to achive & to know:
I want to compile the whole sourcecode of below named API, to use the binaries on a windows operating system.
Also I would like to know, whether I wrote the "#define _GNU_SOURCE"-Tag to the right place, or if I made a mistake.
Downloads:
Api
https://software.ecmwf.int/wiki/display/GRIB/Home
If you're going to declare feature-test macros such as _GNU_SOURCE, you must ensure that the preprocessor sees them before it sees any code that uses them. That generally means they have to be processed before any system headers. The best placement, therefore, is at the top of each of your C source files (not headers), before any #include directives.
With that said, you need a solution that applies to the C library you're actually using, and its development headers. For MinGW, it seems that would be Microsoft's C library, which does not appear to document an alphasort() function.
Even if you were using glibc (Cygwin's version, for instance) my glibc docs claim that the needed feature-test macro for alphasort() is either _BSD_SOURCE or _SVID_SOURCE, not _GNU_SOURCE. Since glibc 2.10, it looks like it's probably best to use _POSIX_C_SOURCE >= 200809L, or _XOPEN_SOURCE >= 700, as these reflect the fact that the function was standardized in POSIX.1-2008.
How do I determine a user's OS in terminal application, in C?
For example, in the code below, what should I replace windows and linux with?
/* pseudo code */
if(windows)
{system(cls)}
else if(linux)
{system(clear)}
else{...}
I should mention that I am a beginner at C, and need something like this so my code can work on windows and/or linux, without making separate source for each.
Typically, this is done with macros in the build system (since you have to BUILD the code for each system anyway.
e.g. gcc -DLINUX myfile.c
and then in myfile.c
#ifdef LINUX
... do stuff for linux ...
#else if defined(WINDOWS)
... do something for windows ...
#else if ... and so on.
...
#endif
(Most of the time, you can find some way that doesn't actually require the addition of a -D<something> on the command line, by using predefined macros for the tools you are using to compile for that architecture).
Alternatively, you ca do the same thing, but much quicker and better (but not 100% portable) by printing the ANSI escape sequence for "clear screen":
putstr("\033" "2J");
yes, that's two strings, because if you write "\0332J" the compile will use the character 0332, not character 033, followed by the digit 2. So two strings next to each other will do the trick.
I believe you can avoid runtime check by specializing your 'functions' during compilation. So, how about this then:
#ifdef WIN32
CLEAR = cls
#elif __linux__
CLEAR = clear
#endif
Predefs vary from compiler to compiler, so here's a good list to have: http://sourceforge.net/p/predef/wiki/OperatingSystems/
It is probably better to detect the environment at compile time rather than runtime. With compiled languages like C you aren't going to have the same compiler output running on different platforms as you would with a lanugage such as Java so you don't need to do this kind of check at runtime.
This is the header I use to work out what platform my code is being compiled on. It will define different macros depending on the OS (as well as other things).
Something like this in use:
#if defined(UTIL_PLATFORM_WINDOWS)
printf("windows\n");
#elif defined(UTIL_PLATFORM_UNIXLIKE)
printf("Unix\n");
#endif
I am developing a embedded software that is meant to run on two to three different family of micro controllers. For now we have makefiles that reads the configuration switches and does compilation.
The process is getting more and more tedious for both developers and non developers to stay updated with compile switches and build configurations. I know Linux kernel uses ncurses for generating compile configurations. I am looking for a similar tool, but cross platform. It should run on Windows and Linux. I know this will still not solve the problem but its more appealing to non developers also I can quickly share my .config file or compare it with existing. The configurations will be in specific order and a diff tool here will help.
Can anyone share their experience with similar project maintenance or a reference project (embedded and common code base for multiple micros). Just want to know best practices.
PS : Language used C, 8/16 bit micros, no OS just timer based batch scheduler (baremetal)
I have one microcontroller but several projects which get compiled from the same source code. I think my scenario is similar to yours, at least to some extent. My solution was inspired by Linux kernel, as well.
config.h
All source code which needs to get access to some configuration parameter simply includes an header file called config.h.
config.h consists of just one line:
#include <config/project.h>
project.h
I have several configuration header files, one per project. A project.h consists of macro definitions with values such as true, false, or constants:
#define CONFIG_FOO true
#define CONFIG_BAR false
#define CONFIG_TIME 100
check.c
This file checks configuration parameters for correctness:
- all parameters must be defined, even if not used or meaningful for that project
- unwanted parameter combinations are signalled
- parameter values are constrained.
#if !defined(CONFIG_FOO)
#error CONFIG_FOO not defined
#endif
#if !defined(CONFIG_BAR)
#error CONFIG_BAR not defined
#endif
#if !defined(CONFIG_TIME)
#error CONFIG_TIME not defined
#endif
#if !(CONFIG_FOO ^ CONFIG_BAR)
#error either CONFIG_FOO or CONFIG_BAR should be se
#endif
#if CONFIG_TIME > 250
#error CONFIG_TIME too big
#endif
Makefile
By instructing the compiler to output the preprocessor macros, it is possible (with a bit of sed expression) to feed the Makefile with the same parameter values gprovided for a given project.
If you don't find anything else, GNU autotools could make things a bit easier.
When I was doing multi-platform development, I used a solution like the one in my answer here. Have a specific "platform_XXX.h" for each platform, and restrict the conditional compilation to a single master "platform.h" file which selects the right subfile.
I am currently using the popen function in code that is compiled by two compilers: MS Visual Studio and gcc (on linux). I might want to add gcc (on MinGW) later.
The function is called popen for gcc, but _popen for MSVS, so i added the following to my source code:
#ifdef _MSC_VER
#define popen _popen
#define pclose _pclose
#endif
This works, but i would like to understand whether there exists a standard solution for such problems (i recall a similar case with stricmp/strcasecmp). Specifically, i would like to understand the following:
Is _MSC_VER the right flag to depend on? I chose it because i have the impression that linux environment is "more standard".
If i put these #define's in some header file, is it important whether i #include it before or after stdio.h (for the case of popen)?
If _popen is defined as a macro itself, is there a chance my #define will fail? Should i use a "new" token like my_popen instead, for that reason or another?
Did someone already do this job for me and made a good "portability header" file that i can use?
Anything else i should be aware of?
Better to check for a windows-specific define (_WIN32 perhaps) because mingw won't have it either. popen() is standardised (it's a part of the Single UNIX® Specification v2)
No; so long as the macro is defined before its first use it does not matter if _popen() is not defined until later.
No; what you have is fine even if _popen is a macro.
It's been done many times but I don't know of a freely-licensed version you can use.
The way you are doing it is fine (with the #ifdef etc) but the macro that you test isn't. popen is something that depends on your operating system and not your compiler.
I'd go for something like
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 2)
/* system has popen as expected */
#elif defined(YOUR_MACRO_TO DETECT_YOUR_OS)
# define popen _popen
# define pclose _pclose
#elif defined(YOUR_MACRO_TO DETECT_ANOTHER_ONE)
# define popen _pOpenOrSo
# define pclose _pclos
#else
# error "no popen, we don't know what to do"
#endif
_MSC_VER is the correct macro for detecting the MSVC compiler. You can use __GNUC__ for GCC.
If you are going to use popen as your macro ID, I suggest you #include it after, because of 3.
If you #include it after stdio.h, it should work AFAIK, but better safe than sorry, no? Call it portable_popen or something.
Many projects (including some of mine) have a portability header, but it's usually better to roll your own. I'm a fan of doing things yourself if you have the time. Thus you know the details of your code (easier to debug if things go wrong), and you get code that is tailored to your needs.
Not that I know of. I do stuff like this all the time, without problems.
Instead of ending up with cluttered files containing #ifdef..#else..#endif blocks, I'd prefer a version using different files for different platforms:
put the OS dependent definitions in one file per platform and #define a macro my_popen
#include this file in your platform-agnostic code
never call the OS functions directly, but the #define that you created (i.e. my_popen)
depending on your OS, use different headers for compilation (e.g. config/windows/mydefines.h on windows and config/linux/mydefines.h on linux, so set the include path appropriate and always #include "mydefines.h")
That's a much cleaner approach than having the OS decision in the source itself.
If the methods you're calling behave different between windows and linux, decide which one shall be the behavior you're using (i.e. either always windows behavior or always linux behavior) and then create wrapper methods to achieve this. For that, you'll also need not only two mydefines.h files but also to myfunctions.c files that reside in the config/OSTYPE directories.
Doing it that way, you also get advantages when it comes to diff the linux and the windows version: you could simply diff two files while doing a diff on the linux and windows blocks of the same file could be difficult.