0

Hi I'm trying to use environmental variables as part of the MSBuild process on a Gitlab runner setup to pass the CI_PIPELINE_ID and CI_COMMIT_SHA to build the application with an increment build id and commit sha to track the binaries version.

My .gitlab-ci.yml is configured as below:

variables:
  Solution: Project.sln

before_script:
  - "echo off"
  - 'call "%VS140COMNTOOLS%\vsvars32.bat"'
  - echo.
  - set
  - echo.
  - echo %HALCONROOT%|find "13" >nul
  - if errorlevel 1 (echo not13) else (set HALCONVERSION=HALCON_13)

stages:
  - build

build:
  stage: build
  script:
  - echo building...
  - 'msbuild.exe /p:Configuration="Release" /p:Platform="x64" "%Solution%"'
  tags:
  - "HALCON 13"
  except:
  - tags

What do I need to do to access the environmental variables like this in my c++ project?

#ifndef CI_COMMIT_SHA
#define COMMIT_SHA                  0
#else
#define COMMIT_SHA                  CI_COMMIT_SHA
#endif
a_dizzle
  • 43
  • 7

2 Answers2

2

You can use Settings --> CD/CD --> Secret variables to define variables you want to use in .yml, for example:

Secret variables

Then you can use it as follows:

script:
- echo $USERNAME

Regarding accessing environment variables in C++, you can try:

std::string getEnvVar( std::string const & key ) const
{
    char * val = getenv( key.c_str() );
    return val == NULL ? std::string("") : std::string(val);
}
Yu-Lin Chen
  • 559
  • 5
  • 12
  • CI_PIPELINE_ID and CI_COMMIT_SHA are already predefined https://docs.gitlab.com/ce/ci/variables/README.html. My question is how I use this with msbuild so it compiles with them by accessing the key values. – a_dizzle Dec 18 '17 at 23:51
  • @a_dizzle: modified. – Yu-Lin Chen Dec 19 '17 at 00:42
  • I'm not trying to get the key value at runtime, only when compiling. I was able to add these to the project by adding /D CI_PIPELINE_ID=$(CI_PIPELINE_ID) /D CI_COMMIT_SHA=$(CI_COMMIT_SHA) at the end of the msbuild command. However i would like not to do this if they don't exist. – a_dizzle Dec 19 '17 at 00:51
  • So you want to do something like `if $(CI_PIPELINE_ID) build_with_ci_env else build_without_ci_env`? – Yu-Lin Chen Dec 19 '17 at 00:58
  • Exactly. I almost have it working with the the /D inputs however when it is built on an environment with out these CI_PIPELINE_ID will be set to an empty string which will break STRINGIZE around the defines. My next question is how to do some thing like P99_IS_EMPTY for msbuild? – a_dizzle Dec 19 '17 at 01:07
  • Is this help? https://stackoverflow.com/questions/3781520/how-to-test-if-preprocessor-symbol-is-defined-but-has-no-value – Yu-Lin Chen Dec 19 '17 at 01:10
  • Using that give a C4003 compiler warning on EXPAND, is there a way to prevent the warnings? – a_dizzle Dec 19 '17 at 02:06
  • Solved by doing `#define DO_EXPAND(VAL) VAL ## 1 #define EXPAND(VAL) DO_EXPAND(VAL) #if !defined(CI_PIPELINE_ID) || (EXPAND(CI_PIPELINE_ID + 0) == 1) #define VERSION_BUILD 9999 #else #define VERSION_BUILD CI_PIPELINE_ID #endif` – a_dizzle Dec 19 '17 at 02:27
2

Solved by adding the following code to the C/C++ Command Line on the properties page.

/D CI_PIPELINE_ID=$(CI_PIPELINE_ID) /D CI_COMMIT_SHA=$(CI_COMMIT_SHA)

However you will now have to check if these are empty when you do not run in a CI environment with the following checks taken from How to test if preprocessor symbol is #define'd but has no value? and modified. (A + 0 is required in the EXPAND function to prevent C4003 warnings when the define is empty.

#define DO_EXPAND(VAL)  VAL ## 1
#define EXPAND(VAL)     DO_EXPAND(VAL)

#define DO_QUOTE(X)        #X
#define QUOTE(X)           DO_QUOTE(X)

#if !defined(CI_PIPELINE_ID) || (EXPAND(CI_PIPELINE_ID + 0) == 1)
#define VERSION_BUILD               9999
#else
#define VERSION_BUILD               CI_PIPELINE_ID
#endif

#if !defined(CI_COMMIT_SHA)
#define COMMIT_SHA                  ""
#else
#define COMMIT_SHA                  CI_COMMIT_SHA
#endif
a_dizzle
  • 43
  • 7