2

I use WSL2 from vscode to develop and build, but I am a novice linux user. I am currently developing in C and using unity for unit testing and dmalloc to check for correct memory usage.

Following the dmalloc documentation here, once the library has been installed, an alias must be created for dmalloc so that it can be configured from the command line. I use this option in the .bashrc file to create the alias:

function dmalloc { eval `command dmalloc -b $*`; }

Before running a program compiled with the dmalloc library, dmalloc must be told to place the results in a log file as follows:

dmalloc -l logfile -i 100 low

This all works well when typing the commands into the shell. However, my unit tests are run one by one from a make file. I would like dmalloc to output its results to a specific logfile for each unit test. However, since an alias is used to configure dmalloc and make does not expand aliases, dmalloc cannot be configured before each unit test is run.

Here is an example of how I would like to run the unit tests from my make file:

DIR_BUILD_TESTS := $(DIR_BUILD)tests/
TXT_TESTS := $(patsubst $(DIR_BUILD_TESTS)%.o,$(DIR_BUILD_TESTS)%.txt,$(OBJ_TESTS))

test: $(TXT_TESTS)
    @echo "-----------------------\nPASSED:\n-----------------------"
    @echo "$(PASSED)"
    @echo "-----------------------\nIGNORES:\n-----------------------"
    @echo "$(IGNORE)"
    @echo "-----------------------\nFAILURES:\n-----------------------"
    @echo "$(FAIL)"
    @echo "DONE"

$(DIR_BUILD_TESTS)%.txt: $(DIR_BUILD_TESTS)%.exe
    dmalloc -l $(subst .txt,.log,$@) -i 100 low
    -./$< > $@ 2>&1

The default target is "test" which only outputs the results from the unit tests. However, the prerequisites for test are text files containing the test outputs, the rule after test runs each built .exe file and outputs its results to a text file. This was adapted from the makefile example from the unity documentation. As you can see, I would like to configure dmalloc before running each test so that each test has a dmalloc log file associated with it. This does not work though, here is an example of the current output:

dmalloc -l ../../build/debug/tests/testNumberOne.log -i 100 low
export DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=../../build/debug/tests/testNumberOne.log
./../../build/debug/tests/testNumberOne.exe > ../../build/debug/tests/testNumberOne.txt 2>&1

According to the dmalloc documentation, if "DMALLOC_OPTIONS" displays in the output then the alias did not take effect. This is what we were expecting since we know that make does not expand aliases.

So is there a way to get the functionality which I want?

bjoubert89
  • 61
  • 5
  • what is the alias? – stark Apr 04 '23 at 11:37
  • As I understand it, adding "function dmalloc { eval `command dmalloc -b $*`; }" to the .bashrc file allows one to type "dmalloc" into the command line with options to configure dmalloc. Thus, "dmalloc" is the alias is it not? I would think that there would be a way of configuring dmalloc without the use of the alias and the alias just makes it more convenient. I don't know .bashrc syntax, so I'm not sure how one would call dmalloc without the alias. – bjoubert89 Apr 04 '23 at 11:56
  • A bash function is not a bash alias. The default shell used by make is `sh` – stark Apr 04 '23 at 12:49
  • Even beyond the fact that make uses `sh` not `bash`, the shell make invokes won't source your setup files AND shell functions and aliases are not passed through the environment to `sh`. Basically, you cannot add functions or aliases to your shell configuration file and expect to use them in a makefile recipe. – MadScientist Apr 04 '23 at 15:29

1 Answers1

0

Let me start off by clarifying some concepts about dmalloc. The dmalloc library uses the DMALLOC_OPTIONS environment variable during runtime to determine some of its behavior. Your desired dmalloc operation must be configured by altering the DMALLOC_OPTIONS environment variable before executing the program which uses the dmalloc library. Once the dmalloc utility has been installed, with no "alias" (as referred to by the dmalloc documentation) added to the .bashrc file, calling the dmalloc command with the desired configuration options will only print the command required to make the necessary changes to the DMALLOC_OPTIONS environment variable, but the variable itself will not be changed or assigned. The example below shows a dmalloc call with the required configuration options and then prints the DMALLOC_OPTIONS environment variable, the environment variable is empty.

$ dmalloc -l logfile -i 100 low
export DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=logfile
$ echo "$DMALLOC_OPTIONS"

If you call the output of the above dmalloc command and then print the value of the DMALLOC_OPTIONS environment variable, you will see that the variable has been assigned a value, shown below.

$ export DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=logfile
$ echo "$DMALLOC_OPTIONS"
debug=0x4e48503,inter=100,log=logfile

The dmalloc documentation instructs the user to add an "alias" to the shell's configuration file. For bash, the alias is shown below.

function dmalloc { eval `command dmalloc -b $*`; }

This is not actually an alias, but a function. However, in this instance it serves a similar purpose. Without going into too much detail about the function, once the function has been added to the .bashrc file, the shell will execute the output of the dmalloc command instead of the dmalloc command directly. Therefore, with the alias added, the DMALLOC_OPTIONS environment variable can be assigned by simply calling the dmalloc command with the desired options, as shown below.

dmalloc -l logfile -i 100 low

Without the alias, you would first need to run dmalloc to get the required command for assigning the variable and then assign the variable as shown below.

$ dmalloc -l logfile -i 100 low
export DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=logfile
$ export DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=logfile

So the alias basically just provides a shortcut, but is not required to used the dmalloc library.

Now back to using dmalloc in a makefile. As mentioned in the original question, make does not expand aliases or functions in the .bashrc file. However, dmalloc can be used directly to obtain the required command for DMALLOC_OPTIONS assignment and then this command can be called before executing each test. To achieve this, the makefile in the question is edited as follows:

DIR_BUILD_TESTS := $(DIR_BUILD)tests/
TXT_TESTS := $(patsubst $(DIR_BUILD_TESTS)%.o,$(DIR_BUILD_TESTS)%.txt,$(OBJ_TESTS))
DMALLOC_CONFIG = export DMALLOC_OPTIONS=debug=0x4f4ed03,inter=10,log=$(subst .$(EXT),.log,$<)

test: $(TXT_TESTS)
    @echo "-----------------------\nPASSED:\n-----------------------"
    @echo "$(PASSED)"
    @echo "-----------------------\nIGNORES:\n-----------------------"
    @echo "$(IGNORE)"
    @echo "-----------------------\nFAILURES:\n-----------------------"
    @echo "$(FAIL)"
    @echo "DONE"

$(DIR_BUILD_TESTS)%.txt: $(DIR_BUILD_TESTS)%.exe
    -$(DMALLOC_CONFIG); \
    ./$< > $@ 2>&1

The DMALLOC_CONFIG variable has been added to the makefile which contains the required command to assign the DAMLLOC_OPTIONS environment variable. The contents of the DMALLOC_CONFIG variable is called as a command before each test is run. Very important is that the command to assign the DMALLOC_OPTIONS environment variable and the command to run the test must be executed as a single recipe. This is because make creates a new shell instance for each recipe and each new shell instance will have an unassigned DMALLOC_OPTIONS environment variable. The -$(DMALLOC_CONFIG); and the ./$< > $@ 2>&1 lines are combined into a single recipe by placing a backslash (\) after -$(DMALLOC_CONFIG); line.

bjoubert89
  • 61
  • 5
  • This question had an answer which helped me solve the problem. I don't know why, but that answer has been taken down. So here is the information which I used to solve the problem. – bjoubert89 Jun 08 '23 at 11:21