Is there a way do define a global macro, like _DEBUG in VS 2013 to be global per project?
I want to use macro for conditional buld for different versions of application and avoid to include *.h.file containing the definition.
#define APP_VERSION_MAJOR 1
#define APP_VERSION_MINOR 0
#define APP_VERSION_HOTFIX 0
#define APP_VERSION_DEV a
#define APP_VER_STR_(s) #s
#define APP_VER_STR(s) APP_VER_STR_(s)
#define APP_VERSION APP_VER_STR(APP_VERSION_MAJOR) "." APP_VER_STR(APP_VERSION_MINOR) "." APP_VER_STR(APP_VERSION_HOTFIX) "." APP_VER_STR(APP_VERSION_DEV)
I would use the build system to pass the definitions to the C / C++ compiler using the -D syntax:
-DVERSION=2.0.3
Related
I have some testing code in Fortran which basically looks like
#define test1 0
#define test2 0
#define test3 0
...
#if test1
call test1()
#endif
#if test2
call test2()
#endif
#if test3
call test3()
#endif
...
At compilation, i want to change those values using -Dtest1=1.
I've seen some answers (like here) where they say you need to put
#ifndef test1
#define test1 0
#endif
But i have a lot of those and i would prefer not to add 40 lines of definition code.
Will compilation command -D flag take priority over my hard definition without the if clause?
EDIT : So i just tested it (which i should have done anyway before asking...) and compiler -D flag does not take priority over my own definition and just pulls out a warning . So any way for it to take priority and always use the compiler flags without passing through ifndef clauses?
-D effectively adds a #define at the beginning, before reading the input. So it would be just like adding an additional #define in your source code, which would naturally produce an error (or warning) about redefining the macro.
If you want to avoid that error, use the #ifndef idiom, just like everyone else does.
Not including the #ifndef guard to prevent multiple header file inclusions, does not throw compile error. Why is that?
// main.c
#include <stdio.h>
#include "declare.h"
#include "declare.h" //Shouldn't I get compiler error here
int main(){
printf("Hello World\n");
}
// declare.h
#define a 1 //just this define in declare.h file
Command used to compile: gcc main.c -std=c89
Including a header multiple times is not an error, either with or without guards.
Guards prevent you from redefining objects and functions, when you do so.
But you haven't done that. You've just redefined a macro with the same value it had before. Which is fine.
You can test this by just compiling the following file:
#define a 1
#define a 1
It's fine.
[C89: 6.8.3]: [..] An identifier currently defined as a macro without use of lparen (an object-like macro) may be redefined by another #define preprocessing directive provided that the second definition is an object-like macro definition and the two replacement lists are identical. [..]
Start putting more complex stuff in that header and you'll see a problem.
The C preprocessor macro for concatenation (##) does not seem to work on a Mac using gfortran. Using other Fortran compilers on other systems works so I am looking for a workaround for gfortran. I have to use the ## to create many variables so I can't do without them.
Example code:
#define CONCAT(x,y) x##y
program main
integer, parameter:: CONCAT(ID,2) = 3
print*,"Hello", ID_2
end program main
Compilation error with gfortran on MAC
gfortran m.F90 -o m
m.F90:5.23:
integer, parameter:: ID##2 = 3
1
Error: PARAMETER at (1) is missing an initializer
## doesn't work in gfortran (any OS, not just Mac) because it runs CPP in the traditional mode.
According to this thread the gfortran mailing list the correct operator in the traditional mode is x/**/y, so you must distinguish between different compilers:
#ifdef __GFORTRAN__
#define CONCAT(x,y) x/**/y
#else
#define CONCAT(x,y) x ## y
#endif
Others (http://c-faq.com/cpp/oldpaste.html) use this form, which behaves better when a macro passed to the CONCAT (via Concatenating an expanded macro and a word using the Fortran preprocessor):
#ifdef __GFORTRAN__
#define PASTE(a) a
#define CONCAT(a,b) PASTE(a)b
#else
#define PASTE(a) a ## b
#define CONCAT(a,b) PASTE(a,b)
#endif
The indirect formulation helps to expand the passed macro before the strings are concatenated (it is too late after).
I'm working on creating build configurations based on a previous question of mine. I've got the Build Configurations created, and I have conditional declarations for the different builds in a file called custom.h. It currently looks like this:
#pragma once
#if defined(ELITE_BUILD)
#define BUILD 3 // 1: personal, 2: select, 3: elite
#elif defined(SELECT_BUILD)
#define BUILD 2
#elif defined(PERSONAL_BUILD)
#define BUILD 1
#endif
In one of my .rc files there is an include for versionconfig.h that looks like this (somewhat redacted):
#if BUILD == 1
#define STRDESCRIPTION "Personal Edition"
#elif BUILD == 2
#define STRDESCRIPTION "Select Edition"
#elif BUILD == 3
#define STRDESCRIPTION "Elite Edition"
#pragma message(STRDESCRIPTION)
#endif
I added the #pragma command as a logging effort. After that include, the relevant parts of the .rc file looks like this (again, a bit redacted for brevity):
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", STRDESCRIPTION
END
END
END
When I attempt to compile this project I get the error error RC2104 : undefined keyword or key name: STRDESCRIPTION. I'm at a bit of a loss. The value exists, I can log it immediately after setting it, and there is no #undef command for it.
-- EDITED --
If I add placeholder defines outside of the if block the project will compile, but the values aren't showing up, so my problem appears to be related to conditional definitions. What's confusing me most at this point is that I can put a #pragma message command inside the conditional block and it's executed properly, but the values defined there are non-existent. Hoping someone can shed some light on this for me.
I found it. In Visual Studio you have to set pre-processor definitions for the Resource Files separately from the Project. As soon as I added ELITE_BUILD to the pre-processor section for the resource everything worked as expected.
Folks,
I'm using VS2010 and trying to sync the build version of my project with my Subversion repository using SubWCRev. This is all working correctly, but I can't quite get my head around one thing. My template file consists of this :
#define MAJOR_VERSION 2
#define MINOR_VERSION 2
#define MICRO_VERSION 0
#define BUILD_VERSION $WCMODS?$WCREV$+1:$WCREV$$
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
#define BUILD_VERSION_STRING QUOTE(MAJOR_VERSION.MINOR_VERSION.MICRO_VERSION.BUILD_VERSION)
Then in my application .RC file I have :
FILEVERSION MAJOR_VERSION,MINOR_VERSION,MICRO_VERSION,BUILD_VERSION
PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,MICRO_VERSION,BUILD_VERSION
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080004e4"
BEGIN
VALUE "FileVersion", BUILD_VERSION_STRING
VALUE "ProductVersion", BUILD_VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x800, 1252
END
END
As you can probably work out, I'm trying to up the build version by 1 if there's modified code so that the build version in the EXE will match the Subversion revision number when I do a release and check the code in. The problem is that BUILD_VERSION gets expanded to x+1 or x+0 which then appears in the BUILD_VERSION_STRING as "2.2.0.227+1" which is not quite what I intended.
Does anyone with a little more experience with this know a way to achieve my aim?
Thanks in advance
#define BUILD_VERSION $WCMODS?$WCREV+1$:$WCREV$$
Im my group we only automate the update of the least significant value with the svn revision number for the projects working directory. To do this we have added a pre-build step to each project that creates and then calls a batch script that does the following:
Copy $(ProjectDir)Properties\AssemblyInfo.cs to $(ProjectDir)Properties\AssemblyInfo.cs.template.
Find AssemblyVersion("X.Y.Z.ddd") in $(ProjectDir)Properties\AssemblyInfo.cs.template and replace with AssemblyVersion("X.Y.Z.$WCREV$").
Find AssemblyFileVersion("X.Y.Z.ddd") in $(ProjectDir)Properties\AssemblyInfo.cs.template and replace with AssemblyFileVersion("X.Y.Z.$WCREV$").
Run 'SubWCRev $(ProjectDir) $(ProjectDir)Properties\AssemblyInfo.cs.template $(ProjectDir)Properties\AssemblyInfo.cs'
If you use subwcrev to generate an unversioned header from your versioned template, then #include the unversioned header in your versioned .RC file, you can build for release from an unmodified work area.
Then you can just use
#define BUILD_VERSION $WCREV$
This also removes the risk of any changes creeping in between building your release EXE and checking in the code.
Could you do something like:
#define MOD_VERSION $WCMODS?1:0$
#define REVISION $WCREV$
#define BUILD_VERSION ( REVISION + MOD_VERSION )
Edit: This won't work either as pointed out in the comments!
What is the purpose of your version number? If it's to get back to the source code used to produce the binary then you might be shooting yourself in the foot a bit here. What happens if someone checks some more code into the repository at the same time as you're creating your version number? You're going to end up with your binary referencing different code.
What might be better would be to check to see if the working copy has any modifications or mixed revisions and use a specific revision number (e.g. 0xFFFFFFFF or 0) to represent this. And only use the true revision number if you used a clean tree to build the binary.
#define MAJOR_VERSION 2
#define MINOR_VERSION 2
#define MICRO_VERSION 0
#if $WCMODS?1:0$
#define BUILD_VERSION 0
#else
#define BUILD_VERSION $WCREV$
#endif